gpt4 book ai didi

c++ - 如何从另一个进程中解开全局钩子(Hook)?

转载 作者:行者123 更新时间:2023-11-27 23:43:07 26 4
gpt4 key购买 nike

<分区>

这是我当前的设置:我有一个 C++ DLL,它在全局范围内将其中一个函数 Hook 到计算机上运行的每个进程。 Hook 是在 DLLMain 中使用 SetWindowsHookEx winapi 函数完成的,我正在 Hook 到 WH_CBTWH_SHELL事件。我还有一个 C# 应用程序,它使用 p/invoke (LoadLibrary()) 加载 DLL,这会触发从 DLLMain 安装 Hook 。 DLL 中的处理程序通过命名管道向 C# 应用程序发送事件信息。

基于我在 microsoft documentary 上阅读的内容,这些事件将在目标进程的线程上处理,并且必须由独立的 C++ DLL 安装(不像 WH_MOUSE_LL 和 WH_KEYBOARD_LL 可以由任何应用程序安装,甚至是 straight from a C# app using p/invoke )。

到目前为止一切正常;托管应用程序正在按应有的方式接收数据。当我关闭应用程序时,问题出现了,因为处理程序仍然 Hook ,因此 DLL 文件正在使用中,无法删除。

由于处理程序未在我的应用程序中运行,而是注入(inject)到我计算机上运行的其他进程中,因此 C# 应用程序不能简单地调用 UnhookWindowsHookExFreeLibrary,因为事件处理程序的指针属于其他进程。

问题:

我如何从托管应用程序中触发取消 Hook 例程,以确保 DLL 不再被任何进程使用?

这是我尝试过的:

我想出的唯一解决方案是创建一个退出事件(使用 CreateEvent),每次处理程序收到 WH_CBTWH_SHELL 消息,它检查是否设置了退出事件,在这种情况下,它从它所属的进程中脱钩并在处理消息之前返回。

这种方法的问题是,在我关闭我的应用程序并卸载 DLL 之后,我必须等到其余进程至少收到一次 WH 事件,这样属于它们的处理程序才能自行解除 Hook 。

这是 DLL 的代码:

#include <windows.h>
#include <sstream>

HANDLE hTERM;
HHOOK hCBT;
HHOOK hShell;

void __declspec(dllexport) InstallHooks(HMODULE h);
void __declspec(dllexport) RemoveHooks();

int Continue()
{
return WAIT_TIMEOUT == WaitForSingleObject(hTERM, 0);
}

LRESULT FAR PASCAL _cbtProc(int c, WPARAM w, LPARAM l)
{
if (!Continue()) { RemoveHooks(); return 0; }
// Handling the message ...
return CallNextHookEx(0, c, w, l);
}

LRESULT FAR PASCAL _shellProc(int c, WPARAM w, LPARAM l)
{
if (!Continue()) { RemoveHooks(); return 0; }
// Handling the message ...
return CallNextHookEx(0, c, w, l);
}

void InstallHooks(HMODULE h)
{
hTERM = OpenEvent(EVENT_ALL_ACCESS, 0, __TEXT("{0C3ED513-F38C-4996-8130-F9A3C93D890B}"));
if (!Continue())
return;
hCBT = SetWindowsHookEx(WH_CBT, _cbtProc, h, 0);
hShell = SetWindowsHookEx(WH_SHELL, _shellProc, h, 0);
}

void RemoveHooks()
{
UnhookWindowsHookEx(hCBT);
UnhookWindowsHookEx(hShell);
if (hTERM) CloseHandle(hTERM); hTERM = 0;
}

int FAR PASCAL DllMain(HMODULE h, DWORD r, void* p)
{
switch (r)
{
case DLL_PROCESS_ATTACH: InstallHooks(h); break;
case DLL_PROCESS_DETACH: RemoveHooks(); break;
default: break;
}
return 1;
}

托管 C# 应用程序的源代码没有什么特别之处,因为它唯一做的就是在启动时调用 LoadLibrary,处理来自管道的消息,最后设置需要时使用其他 p/invoke 调用退出事件。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com