LoadLibrary在目标进程未执行是因为注入需让目标进程自行加载DLL:须用VirtualAllocEx写入路径、GetModuleHandle+GetProcAddress获取LoadLibrary地址、CreateRemoteThread触发调用,且路径须为绝对路径;跨架构注入会因Windows硬限制直接失败;DllMain中禁止调用阻塞或隐式加载API,否则导致进程冻结;管理员权限下注入失败多因PPL等保护机制拦截。

为什么 LoadLibrary 在目标进程里根本没执行?
因为直接调用 LoadLibrary 只在当前进程有效,注入的本质是让目标进程自己去加载你的 DLL——你得把路径字符串和函数地址“塞进去”,再让它调用自己的 LoadLibraryA 或 LoadLibraryW。
常见错误是:本地调用一次 LoadLibrary 就以为注入成功了,结果目标进程毫无反应。这不是 DLL 问题,是压根没跑进目标进程的地址空间。
- 必须用
VirtualAllocEx在目标进程申请内存,写入 DLL 路径字符串 - 必须用
GetModuleHandleA("kernel32.dll")拿到本机LoadLibraryA地址,再通过GetProcAddress获取真实入口(注意:这个地址在目标进程中大概率可用,因 kernel32 是默认映射) - 必须用
CreateRemoteThread让目标进程跳转过去执行,参数就是上面申请的字符串地址 - 路径必须是目标进程能访问的绝对路径(比如
"C:\temp\hook.dll"),不能用相对路径或环境变量
32 位 DLL 注入到 64 位进程会怎样?
直接失败,CreateRemoteThread 返回 0,GetLastError() 是 ERROR_INVALID_PARAMETER。Windows 不允许跨架构远程线程创建——这是硬限制,不是权限或签名问题。
判断方法很简单:用 IsWow64Process 检查目标进程是否为 Wow64(即 32 位进程运行在 64 位系统),再对比你自己的模块位数(sizeof(void*) == 8)。两者不一致就别试了。
立即学习“C++免费学习笔记(深入)”;
- 64 位程序只能注入 64 位 DLL,32 位程序只能注入 32 位 DLL
- 没有“自动转换”或“兼容模式”——连
VirtualAllocEx都会拒绝跨架构地址空间操作 - 如果必须跨架构(比如调试场景),得用间接方式:启动对应位数的 helper 进程,再由它完成注入(复杂且易被拦截)
DllMain 里做太多事会导致注入卡死
目标进程会在挂起状态下执行你的 DllMain,而 Windows 对此阶段有严格限制:不能调用 LoadLibrary、CreateThread、WaitForSingleObject 等可能引发同步问题的 API。一旦违反,进程就僵在 LOAD_LIBRARY_AS_DATAFILE 类似状态,甚至蓝屏(尤其在系统关键进程上)。
典型现象是:注入函数返回成功,但目标进程 UI 冻结、CPU 占用飙升、任务管理器显示“无响应”。这时候十有八九是 DllMain 里触发了隐式加载或等待。
-
DllMain中只做最轻量的事:保存hInstance、初始化几个全局指针、设个原子标志 - 所有实际逻辑(如 Hook、注册回调、开线程)必须放到单独函数里,用
CreateThread或异步定时器触发(注意:线程必须在DLL_PROCESS_ATTACH后立即 detach,避免阻塞主线程) - 不要在
DllMain里调用任何第三方 SDK、日志库、网络函数——它们内部很可能用了临界区或加载其他 DLL
为什么管理员权限下还是注入失败?
不是权限不够,而是目标进程开了保护机制。从 Windows 8.1 开始,Protected Process Light (PPL) 和 Win10 的 Exploit Protection 会拦截远程线程创建,哪怕你是 SYSTEM 也不行。典型目标:杀毒软件主进程、Edge/Chrome 渲染器、Windows Defender 相关服务。
错误现象通常是:CreateRemoteThread 返回 NULL,GetLastError() 是 ERROR_ACCESS_DENIED,而不是常见的 ERROR_NOT_FOUND 或 ERROR_INVALID_HANDLE。
- 先用
GetProcessMitigationPolicy检查目标进程是否启用了ProcessExtensionPointDisablePolicy或ProcessSignaturePolicy - 绕过 PPL 几乎不可能(需要内核驱动或未公开漏洞),普通用户态注入应主动跳过这类进程
- 某些安全软件会 HOOK
NtCreateThreadEx并静默拒绝——此时需结合 ETW 或 Sysmon 日志确认是否被拦截
真正稳定的注入,从来不是靠“怎么突破”,而是清楚知道哪些进程不该碰、哪些路径必须绝对可靠、哪些 API 在 DllMain 里连碰都不能碰。



















