白名单Hook检测无法阻止DLL注入,因其滞后、易绕过且误杀率高;有效防御需在入口拦截(如Hook OpenProcess)和内存属性控制(如VirtualProtectEx)上下功夫。

不能靠“白名单Hook检测”阻止DLL注入——它既不实时、也不可靠,反而容易被绕过或误杀合法模块。
为什么白名单检测在运行时几乎无效
所谓“白名单Hook检测”,通常是遍历当前进程已加载的模块(EnumProcessModules),比对模块路径或签名是否在预设列表中。但问题在于:
- 注入发生后才扫描,
LoadLibrary已执行、DllMain已跑完,代码早已驻留内存并可能完成钩子安装 - 攻击者可把 DLL 放在系统目录(如
C:\Windows\System32)、重命名成msvcp140.dll等合法名,轻松绕过路径白名单 - 签名验证需调用
WinVerifyTrust,但很多合法软件(尤其国产工具)根本没签名;强制校验会导致自身崩溃或启动失败 - 模块枚举本身可被隐藏——注入者早一步 Hook
EnumProcessModules或修改 PEB 的Ldr链表,你的白名单逻辑就连“坏人”都看不到
真正能起效的防御层:入口拦截 + 内存属性控制
防御目标不是“发现已注入的DLL”,而是“让注入动作在第一步就失败”。关键点在进程启动初期和敏感 API 调用链上:
- 在
DllMain的PROCESS_ATTACH阶段,立即调用SetThreadInformation(Windows 10 1809+)禁用当前线程的ThreadMemoryPriority和ThreadRestrictCallerAccess,这会阻止后续WriteProcessMemory和VirtualAllocEx成功 - 用
VirtualProtectEx主动将关键模块(如kernel32.dll中LoadLibraryA、CreateRemoteThread的入口)设为PAGE_EXECUTE_READ,再 Hook 自己的调用点做参数校验——不是查“谁在调用”,而是查“调用者栈帧是否来自本进程合法模块” - 在主线程初始化时,用
NtQueryInformationProcess检查ProcessImageFileName和ProcessCommandLine,若发现命令行含可疑参数(如-inject、--dll),直接退出——很多自动化注入器依赖命令行传参启动目标进程
Inline Hook OpenProcess 是最务实的防线
几乎所有注入器第一步都是调用 OpenProcess 获取目标句柄。Hook 它比 Hook LoadLibrary 更前置、更难绕过:
立即学习“C++免费学习笔记(深入)”;
- Hook 必须在进程启动后 100ms 内完成,否则注入器可能已抢先进入;推荐在
DllMain的PROCESS_ATTACH里用CreateThread启一个高优先级线程立即 Patch - 判断逻辑别只看
dwDesiredAccess是否含PROCESS_ALL_ACCESS——攻击者会降权请求;重点检查dwProcessId是否等于当前进程 ID,且调用者模块不在白名单(此时白名单才有意义:只允许你自己的模块调用) - 返回
NULL并设GetLastError()为ERROR_ACCESS_DENIED,任务管理器、Process Hacker、甚至部分杀软 UI 都会静默失败,不会弹窗报错
真正的难点不在 Hook 本身,而在确保你的 Hook 代码不被反向 Patch —— 注入器发现你 Hook 了 OpenProcess,下一步就会尝试 WriteProcessMemory 去覆写你的跳转指令。所以必须配合 VirtualProtect 锁死你自己的代码页,并在每次调用前用 memcmp 校验指令字节是否被篡改。这层保护,比任何白名单扫描都实在。


















