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

为何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执行完毕后就会退出。

具体逻辑如下:

  1. 无MessageBox的情况:DllMain里调用SetWindowsHookEx注册了全局键盘钩子,但注册完成后,临时远程线程立刻退出。此时记事本的主UI线程(负责处理消息循环的核心线程)还没有加载这个DLL,钩子回调KeyboardProc根本不会被触发,自然无法拦截按键输入。
  2. 加入MessageBox的情况:MessageBox是模态对话框,它会启动自己的消息循环。在DLL_PROCESS_ATTACH阶段弹出MessageBox,会让临时远程线程进入消息循环并等待用户操作,这个过程中Windows的钩子机制会强制将该DLL注入到所有存在消息循环的进程(包括记事本的主UI线程)。等用户关闭MessageBox后,即便临时线程退出,DLL已经被加载到记事本的主线程中,钩子就能正常拦截按键了。

补充说明:全局WH_KEYBOARD钩子要求钩子DLL被加载到每个接收键盘消息的进程的消息循环线程中,LoadLibrary注入仅完成了将DLL加载到目标进程的一个临时线程的操作,没有触发布局到主UI线程的逻辑,而MessageBox的消息循环刚好触发了这个关键的加载过程。


内容的提问来源于stack exchange,提问作者user746461

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 03:52:31