windows - 从 Windows 键盘 Hook 程序返回后崩溃

标签 windows winapi hook setwindowshookex

有一个键盘钩子(Hook)安装如下:

s_hKeyboardHook = ::SetWindowsHookEx(WH_KEYBOARD, KeyboardHookProc, nullptr, ::GetCurrentThreadId());

(这是一个想要拦截发送到其主机(64 位)的键盘事件的插件,即使主机没有以正常方式向其插件提供键盘事件。我没有主机的源代码,虽然我有插件的源代码。)

键盘钩子(Hook)程序成功运行并返回后,程序崩溃。崩溃发生在 Windows 的 ZwCallbackReturn() 内部,执行 syscall 指令。异常(exception)情况是 0XC0000005(访问冲突)。仅当按下触发某些特定逻辑的特定键时才会发生崩溃。

This is how it looks like in the debugger (animated gif)

我一直在诊断这次崩溃,确实需要一些帮助。我确信问题出在钩子(Hook)过程中的这一大块代码中。我遇到的困难是理解崩溃发生的位置以及基本上在哪里放置断点来抢占它。


其他信息:

1) 钩子(Hook)过程确实非常繁重,有大量的阻塞、I/O 和内存使用(在快速机器上它在几秒钟内完成)。也许这就是问题的一部分。

2) 如果编译为 32 位,崩溃后的堆栈看起来更有趣,但我怀疑它是否可信:

2a71f510()  Unknown
ExecuteHandler2@20()    Unknown
ExecuteHandler@20() Unknown
_RtlDispatchException@8()   Unknown
_KiUserExceptionDispatcher@8()  Unknown
2a10f24a()  Unknown
_DispatchHookW@16() Unknown
_CallHookWithSEH@16()   Unknown
___fnHkINDWORD@4()  Unknown
_KiUserCallbackDispatcher@12()  Unknown
_LdrAddLoadAsDataTable@20() Unknown
AfxInternalPumpMessage() Line 153   C++
AfxWinMain(0x00000000, 0x00000020, 0x00000001, 1638280) Line 47 C++
@BaseThreadInitThunk@12()   Unknown

前 5 行重复了很多次。


这是我迄今为止尝试过的。据我了解,syscall 指令本身不会生成异常:寄存器看起来很正常,而且我猜如果堆栈崩溃,堆栈将保持不变。所以我认为,在这条指令启动转换回内核模式之后,从“用户回调”(钩子(Hook)过程调用)的起源处,内核继续正常运行。最终它应该将控制权返回给用户态 -GetMessage() 我猜)。然后,我认为,堆栈会损坏并且程序崩溃。但不幸的是,我无法指示我的 Visual C++ 调试器在堆栈损坏之前在执行的第一个用户模式指令处中断。我尝试在 TranslateMessage()DispatchMessage() 中安装条件断点,它们最有可能在 GetMessage() 之后立即运行,但它们没有在最后一个良好的用户模式指令和崩溃之间不会触发。

最佳答案

发生崩溃是因为键盘钩子(Hook)过程不是钩子(Hook)链中的第一个。它是通过 CallNextHookEx() 从钩子(Hook)链中的前一个钩子(Hook)调用的。之前的钩子(Hook)是由 DLL 注册的,该 DLL 在“我们的”键盘钩子(Hook)内卸载。

因此,在所有的钩子(Hook)最终被调用之后,控制权返回到第一个钩子(Hook)过程,而这个钩子(Hook)过程已经不存在了。崩溃是因为尝试执行无效地址。

关于windows - 从 Windows 键盘 Hook 程序返回后崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37261407/

相关文章:

windows - 卸载 Visual Studio 2015 Community - 禁用卸载按钮?

ruby-on-rails - 找不到生成器 mongoid :config

c - 如果WriteFile同步完成,是否发出信号通知事件

c++ - 如何通过 DhcpSAPI 启用 DHCP 子网

delphi - 当鼠标被钩住时,窗口接收无限量的消息

python:如何枚举本地Windows组成员

python - 使用 win32api 将 key 发布到记事本不起作用

winapi GetSystemTimes函数不填lpIdleTime/lpKernelTime/lpUserTime

c++ - 为 WH_MOUSE 设置 WindowsHookEx

c# - 即使应用程序未聚焦,也可以 Hook /检测 Windows 语言更改