如何修复NtCreateThreadEx搭配LdrLoadDll注入DLL到自身而非目标进程的问题
问题根源
你代码的核心错误有三处:
- 调用
NtCreateThreadEx时直接在本地进程执行了LdrLoadDll((wchar_t*)0, 0, &name, &Module),你实际传给远程线程的是该函数本地执行后的返回值,而非LdrLoadDll的函数入口地址,所以DLL直接被加载到注入器自身进程。 - 你定义的
UNICODE_STRING结构体存储在本地进程栈空间,结构体指针、结构体内部的Buffer指针都指向本地进程内存,远程线程拿到地址后无法读取到合法的DLL路径。 - 你定义的
_LdrLoadDll函数原型错误,LdrLoadDll返回值为NTSTATUS而非HMODULE。
最简修复方案
你只需要调整逻辑,把LdrLoadDll地址直接作为远程线程入口、同时把路径和UNICODE_STRING结构都写入目标进程内存即可,修正后的完整代码如下:
#include <windows.h> #include <winternl.h> #pragma comment(lib, "ntdll.lib") EXTERN_C NTSYSAPI NTSTATUS NTAPI NtCreateThreadEx(PHANDLE, ACCESS_MASK, LPVOID, HANDLE, LPTHREAD_START_ROUTINE, LPVOID, BOOL, SIZE_T, SIZE_T, SIZE_T, LPVOID); // 修正LdrLoadDll的函数原型 typedef NTSTATUS(__stdcall* _LdrLoadDll)( wchar_t* PathToFile, unsigned long Flags, PUNICODE_STRING ModuleFileName, PHMODULE ModuleHandle ); _LdrLoadDll LdrLoadDll; int main() { DWORD targetProcId = 10340; // 待注入进程ID wchar_t targetDllPath[255] = L"C:\\DllTest32.dll"; // 待注入DLL路径 size_t pathByteLen = (wcslen(targetDllPath) + 1) * sizeof(wchar_t); HANDLE targetOpened = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetProcId); // 在目标进程分配UNICODE_STRING结构体 + 路径的总内存 LPVOID remoteMem = VirtualAllocEx(targetOpened, 0, sizeof(UNICODE_STRING) + pathByteLen, MEM_COMMIT, PAGE_READWRITE); // 构造UNICODE_STRING结构:Buffer指向同一块内存中路径存储的偏移位置 UNICODE_STRING name; name.Buffer = (PWSTR)((LPBYTE)remoteMem + sizeof(UNICODE_STRING)); name.Length = (USHORT)(wcslen(targetDllPath) * sizeof(wchar_t)); name.MaximumLength = (USHORT)pathByteLen; // 把结构体和路径依次写入目标进程 WriteProcessMemory(targetOpened, remoteMem, &name, sizeof(UNICODE_STRING), NULL); WriteProcessMemory(targetOpened, name.Buffer, targetDllPath, pathByteLen, NULL); LdrLoadDll = (_LdrLoadDll)GetProcAddress(GetModuleHandleA("ntdll.dll"), "LdrLoadDll"); HANDLE rt; NtCreateThreadEx( &rt, PROCESS_ALL_ACCESS, NULL, targetOpened, (LPTHREAD_START_ROUTINE)LdrLoadDll, // 直接传函数地址,不要在本地调用 remoteMem, // 参数是目标进程中的UNICODE_STRING指针 FALSE, 0, 0, 0, NULL); // 资源清理可选步骤 WaitForSingleObject(rt, INFINITE); VirtualFreeEx(targetOpened, remoteMem, 0, MEM_RELEASE); CloseHandle(rt); CloseHandle(targetOpened); return 0; }
内容的提问来源于stack exchange,提问作者Gorilka
相关产品推荐
相关产品推荐

