【发布时间】:2016-05-16 19:08:07
【问题描述】:
有一个键盘钩子是这样安装的:
s_hKeyboardHook = ::SetWindowsHookEx(WH_KEYBOARD, KeyboardHookProc, nullptr, ::GetCurrentThreadId());
(这是一个想要拦截发送到其主机(64 位)的键盘事件的插件,即使主机没有以正常方式向其插件提供键盘事件。我没有主机的源代码,虽然我有插件的源代码。)
键盘钩子程序成功运行并返回后,程序崩溃。崩溃发生在 Windows 的 ZwCallbackReturn() 内部,执行 syscall 指令。例外是0XC0000005(访问冲突)。只有在按下触发某些特定逻辑的特定键时才会发生崩溃。
我无法诊断这次崩溃,真的需要一些帮助。我确信问题出在 hook proc 中的一大段代码中。我遇到的麻烦是了解崩溃发生的位置以及基本上放置断点以抢占它的位置。
附加信息:
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 指令本身不会产生异常:寄存器看起来很正常,我猜如果它崩溃了堆栈会保持不变。所以我认为,在这条指令开始转换回内核模式之后,从“用户回调”(钩子过程调用)起源的地方,内核继续运行得很好。最终它应该将控制权返回给用户区 -GetMessage() 我想)。然后在路上,我认为,堆栈被破坏,程序崩溃。但不幸的是,在堆栈损坏之前,我无法指示我的 Visual C++ 调试器在执行的第一个用户模式指令时中断。我尝试在TranslateMessage() 和DispatchMessage() 中安装条件断点,它们最有可能在GetMessage() 之后立即运行,但它们不会在最后一个良好的用户模式指令和崩溃之间触发。
【问题讨论】:
-
The crash only happens if a particular key is pressed which triggers some particular logic- 这对我们来说有点模糊,无法辨别可能是什么问题。 -
如果你把所有的逻辑从你的钩子中剥离出来并立即返回,它还会崩溃吗?如果没有,你知道去哪里找。
-
插件是否与主机运行在同一个进程中?如果是,我假设插件是一个显式加载的 DLL。是否有可能正在卸载插件 DLL,也许是为了响应按键?
-
是的,我确信问题出在 hook proc 中的一大段代码中。我遇到的麻烦是了解崩溃发生的位置以及基本上放置断点以抢占它的位置。
标签: windows winapi hook setwindowshookex