You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用CreateRemoteThread+LoadLibrary向64位Windows进程注入DLL时返回退出码0失败的原因排查

CreateRemoteThread+LoadLibrary向64位Windows进程注入DLL时返回退出码0失败的原因排查

看起来你的问题核心出在字符编码不匹配上,这是64位DLL注入中非常容易踩的坑,咱们一步步拆解问题和修复方案:

1. 最直接的原因:LoadLibraryW 与 ANSI 路径不兼容

你的代码里犯了一个关键的类型不匹配错误:

  • 你传入的DLL路径是const char*类型的ANSI窄字符串,用strlen计算长度,通过WriteProcessMemory写入的也是窄字符字节。
  • 但你通过GetProcAddress获取的是LoadLibraryW的地址——这是LoadLibrary的宽字符版本,它期望接收的是LPCWSTR(宽字符指针)参数。

当远程线程执行LoadLibraryW时,会把你写入的ANSI字节序列当作宽字符解析,这会导致路径完全乱码(比如原本的F:\...会被解析成完全无意义的宽字符组合),自然找不到目标DLL,最终返回0。

2. 快速修复方案

你有两种选择来解决这个编码不匹配问题:

方案一:改用 LoadLibraryA(适配ANSI路径)

既然你用的是ANSI格式的路径,直接获取LoadLibraryA的地址即可,和你的参数类型完全匹配:

// 替换原来的pLoadLibrary赋值代码
LPVOID pLoadLibrary = reinterpret_cast<LPVOID>(
    GetProcAddress(
        GetModuleHandleA("kernel32.dll"), // 用A版本的GetModuleHandle
        "LoadLibraryA"                    // 取LoadLibraryA的地址
    )
);

方案二:切换为宽字符路径(适配LoadLibraryW)

如果想使用宽字符版本,需要把整个路径处理逻辑改成宽字符:

// 1. 把DLL路径改成宽字符
const wchar_t* DLLpath = L"F:\\project\\LearnMaliciouCode\\RemoteThreadInjector\\x64\\Debug\\DLL\\Dll3.dll";

// 2. 注入函数中调整内存分配、写入的逻辑:
pRemoteMem = VirtualAllocEx(
    hProcess, NULL, 
    (wcslen(DLLpath)+1) * sizeof(wchar_t), // 宽字符每个占2字节
    MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE
);

if (!WriteProcessMemory(
    hProcess, pRemoteMem, 
    DLLpath, 
    (wcslen(DLLpath)+1) * sizeof(wchar_t), 
    nullptr
)) {
    std::cerr << "[!] WriteProcessMemory failed: " << GetLastError() << std::endl;
    return FALSE;
}

// 3. 继续使用LoadLibraryW
LPVOID pLoadLibrary = reinterpret_cast<LPVOID>(
    GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW")
);

3. 其他需要注意的细节

除了编码问题,还有几个点可以优化或检查:

  • 最小权限原则:你现在用的PROCESS_ALL_ACCESS权限过大,系统可能在某些场景下拒绝该权限请求。建议使用最小必要权限:PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,这样更稳妥。
  • 错误处理的误区:你在GetExitCodeThread后调用GetLastError()是无效的!GetLastError()是线程局部存储的,当前进程的错误码和远程线程的错误码完全无关。如果想知道远程进程中LoadLibrary失败的具体原因,需要在DLL的DLL_PROCESS_ATTACH中记录错误(比如写入日志文件),而不是在注入器中获取当前进程的GetLastError()
  • 路径的绝对/相对问题:确保你传入的是绝对路径,远程进程的工作目录可能和注入器不同,相对路径容易导致找不到DLL(不过你已经用了绝对路径,这点没问题)。

4. 验证修复效果

修改后重新编译注入器和DLL,再次执行注入,应该就能看到LoadLibrary返回非0值,DLL成功加载。

内容来源于stack exchange

火山引擎 最新活动