4

当加载它们的系统范围的钩子被卸载时,如何从所有进程中正确卸载 DLL?

来自MSDN

您可以使用 UnhookWindowsHookEx 释放全局挂钩过程,但该函数不会释放包含挂钩过程的 DLL。这是因为全局挂钩过程在桌面中每个应用程序的进程上下文中被调用,从而导致对所有这些进程的 LoadLibrary 函数的隐式调用。由于无法为另一个进程调用 FreeLibrary 函数,因此无法释放 DLL。在显式链接到 DLL 的所有进程都已终止或调用 FreeLibrary 并且调用挂钩过程的所有进程都已恢复 DLL 外部的处理后,系统最终会释放 DLL。

所以我正在寻找的是一种检测钩子何时脱钩的方法,然后FreeLibrary从所有被钩子的进程中调用。卸载钩子时,是否有任何其他方法可以立即卸载 DLL?

4

2 回答 2

5

Hook dll 在它们的消息循环中被卸载。强制它们通过消息循环有助于卸载它们。

在 UnhookWindowsHookEx 之后添加这个以强制唤醒所有消息循环:

DWORD dwResult;
SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, SMTO_ABORTIFHUNG|SMTO_NOTIMEOUTIFNOTHUNG, 1000, &dwResult);

但是,我仍然不时遇到问题。我不知道它是从哪里来的。我想一个锁定的进程可能会阻止 dll 卸载,但我没有证据证明这一点。

于 2010-11-02T09:50:29.283 回答
1

一般来说,如果FreeLibrary不需要调用,您应该使用全局窗口挂钩。如果您确实想这样做,您可以使用 DLL 注入(参见例如http://www.codeproject.com/KB/threads/winspy.aspxhttp://www.codeproject.com/KB/system/hooksys。 aspx)关于CreateRemoteThreadLoadLibrary技术。在这种情况下,您可以在远程过程中做您想做的事情。您可以结合使用这两种技术。

如果您只想调用FreeLibrary来更新 DLL,您可以通过另一种方式执行此操作。每个加载的 DLL 都可以重命名(例如在 cmd.exe 中)为临时名称,您可以MoveFileEx使用MOVEFILE_DELAY_UNTIL_REBOOT标志调用。然后您就可以复制和使用新版本的 DLL。下次重新启动计算机时,旧的 DLL 将被删除。

于 2010-07-02T11:36:27.027 回答