从Windows键盘挂接程序返回后崩溃

有一个像这样安装的键盘钩子:

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

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

键盘挂钩程序成功运行并返回后,程序崩溃。 这个崩溃发生在Windows的ZwCallbackReturn()内部,执行syscall指令。 例外情况是0XC0000005 (访问冲突)。 只有当某个特定的按键被按下才会触发某些特定的逻辑。

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

我被卡在诊断这个崩溃,可以真的使用一些帮助。 我相信问题出在钩子过程中的这一大块代码中。 我遇到的问题是了解崩溃发生的位置以及基本放置断点的位置以抢占它。


附加信息:

1)钩子程序确实很重,有很多阻塞,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指令本身不会产生异常:寄存器看起来很理智,我猜如果它崩溃,堆栈将保持不变。 所以我认为,在这条指令启动后返回到内核模式,从“用户回调”(钩子程序调用)开始,内核继续运行得很好。 最终它应该返回到userland - GetMessage()我假设)。 然后在路上,我认为堆栈被破坏,程序崩溃。 但不幸的是,我无法指示我的Visual C ++调试器在执行第一个用户模式指令时破坏堆栈损坏之前。 我尝试在TranslateMessage()DispatchMessage()安装条件断点,这些断点最有可能在GetMessage()后面运行,但它们不会在最后一次良好的用户模式指令和崩溃之间触发。


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

因此,在最终调用所有钩子之后,控制权返回到第一个钩子程序,该程序不再存在。 而崩溃正试图执行一个无效的地址。

链接地址: http://www.djcxy.com/p/61741.html

上一篇: Crash after returning from Windows keyboard hook procedure

下一篇: My MouseHook is blocking the hook notifications of other applications