为何SetWindowsHookEx无MessageBox调用时无法正常工作?
问题描述
我正在跟着一篇文章推进到“Writing a Simple Hook Payload”章节,基于给定代码实现了一个键盘钩子DLL,代码如下:
#define WIN32_LEAN_AND_MEAN #include <windows.h> #include <sstream> #include "inject_payload_disablekeyinput.h" LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) { return 1; } HHOOK hhk; // This is our hook handle BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpvReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { hhk = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hinstDLL, 0); //MessageBox(NULL, "DLL loaded", "Woohoo", 0); //Line A break; } case DLL_PROCESS_DETACH: UnhookWindowsHookEx(hhk); break; } return true; }
执行注入命令:
$ LoadLibrary_Injector.exe notepad.exe "F:\render-with-notepad\Render-With-Notepad\x64\Debug\Inject_Payload_DisableKeyInput.dll" PID Found: 13660 Success! remote thread started in process 13660
现象:
- 注释Line A时,记事本仍能接收所有按键输入,钩子未生效;
- 取消注释Line A后,钩子对所有进程生效。
⚠️ 警告:尝试此代码可能需要注销Windows账户或重启机器才能解除钩子效果。
请问为何MessageBox调用会导致这种差异?
原因分析
这是因为全局钩子的生效依赖于DLL被注入到目标进程的消息循环线程中,而LoadLibrary注入默认是在目标进程的一个临时远程线程中执行的,这个线程在DllMain执行完毕后就会退出。
具体逻辑如下:
- 无
MessageBox的情况:DllMain里调用SetWindowsHookEx注册了全局键盘钩子,但注册完成后,临时远程线程立刻退出。此时记事本的主UI线程(负责处理消息循环的核心线程)还没有加载这个DLL,钩子回调KeyboardProc根本不会被触发,自然无法拦截按键输入。 - 加入
MessageBox的情况:MessageBox是模态对话框,它会启动自己的消息循环。在DLL_PROCESS_ATTACH阶段弹出MessageBox,会让临时远程线程进入消息循环并等待用户操作,这个过程中Windows的钩子机制会强制将该DLL注入到所有存在消息循环的进程(包括记事本的主UI线程)。等用户关闭MessageBox后,即便临时线程退出,DLL已经被加载到记事本的主线程中,钩子就能正常拦截按键了。
补充说明:全局WH_KEYBOARD钩子要求钩子DLL被加载到每个接收键盘消息的进程的消息循环线程中,LoadLibrary注入仅完成了将DLL加载到目标进程的一个临时线程的操作,没有触发布局到主UI线程的逻辑,而MessageBox的消息循环刚好触发了这个关键的加载过程。
内容的提问来源于stack exchange,提问作者user746461
相关产品推荐
相关产品推荐

