【发布时间】:2013-07-17 08:13:29
【问题描述】:
我正在尝试实现 API Hooking 机制。
到目前为止,我所拥有的是一个通过SetWindowsHookEx 调用注入其他进程的 DLL,以及一些用于实现挂钩本身的代码。
例如,我可以成功地跨多个不同的应用程序挂钩 MessageBoxA 调用(这不是最终目标)。
我需要做的是挂钩一些图形功能,尤其是文本输出功能,因为我需要能够进行屏幕抓取。
现在 - 我知道我需要哪些文本输出功能(TextOutA/W、ExtTextOutA/W 用于我尝试访问的应用程序),并且我知道我需要将 Begin/EndPaint 或 Get/ReleaseDC 挂接到将DC 与窗口句柄匹配,并确定文本输出是否在我感兴趣的窗口上。
我的问题是,虽然我可以毫无问题地挂钩文本输出函数、消息框等,但 GetDC 和 BeginPaint 一样会导致严重崩溃。
代码很长,所以我会发布我遇到的问题,但如果有帮助,我可以发布更多。
大致框架如下;
function CustomBeginPaint(hWnd: HWND; var lpPaint: TPaintStruct): HDC;
begin
UninstallHook();
Result := BeginPaint(hWnd, lpPaint );
InstallHook();
end;
即使是这个非常简单的函数也经常失败,返回零。
我完全无法解释发生了什么,因为hWnd 始终是 1309192,尽管在多台机器上尝试过。
【问题讨论】:
-
您说调用 GetDC 和 BeginPaint 时遇到“硬崩溃”,然后您说调用 BeginPaint 的引用函数返回零 - 如果崩溃,它如何返回零?另外,“硬崩溃”是什么意思-应用程序崩溃,系统崩溃,蓝屏死机?您使用的是哪个操作系统?您的应用程序是 32 位还是 64 位?您是在连接 32 位还是 64 位进程?如果没有更多信息,这感觉就像一个难以回答的问题。
-
请编辑您的问题并添加您的 Delphi 版本的 TAG。你的目标是 Win64 还是 Win32 ?
-
另外,如果
BeginPaint返回零/空,那是因为你给了它一个错误的 HWND。 HWND 始终相同是值得怀疑的——这真的不应该被期望。CustomBeginPaint在哪里调用?如果是直接钩子回调,你是如何设置钩子的?你能展示你的前向声明吗? -
取消钩子和重新钩子不是线程安全的。如果应用程序有多个 GUI 线程(VCL 不支持它,但您可以加载具有自己的 GUI 线程的 DLL),这可能会崩溃或导致有趣的错误。