You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 03:54:00