检测何时卸载模块(DLL)

jay*_*lee 11 c c++ windows winapi

有没有办法以编程方式检测何时从进程中卸载模块(特别是DLL)?

我没有DLL源,所以我不能改变它的DLL入口点.我也无法轮询DLL当前是否已加载,因为DLL可能会被卸载然后在轮询之间重新加载.

结果:

我最终使用jimharks解决方案绕过dll入口点并捕获DLL_PROCESS_DETACH.我发现绕行FreeLibrary()也可以工作,但是必须添加代码来检测模块实际卸载的时间或者引用计数是否正在减少.Necrolis关于找到引用计数的链接对于这样做的方法很方便.

我应该注意到,如果MSDetours中存在绕道而没有实际从内存中卸载模块,我遇到了问题.

Nec*_*lis 10

一个非常糟糕的方式(由星际争霸2使用),是让你的程序附加到自己然后监视dll卸载调试事件(http://msdn.microsoft.com/en-us/library/ms679302(VS. 85).aspx),否则你需要IAT钩子FreeLibrary,FreeLibraryEx在进程或hotpatch中,kernel32中的函数监视传递的名称和全局引用计数.


wj3*_*j32 7

如果您使用的是Vista或更高版本,请尝试使用LdrRegisterDllNotification.它确实需要使用GetProcAddress从ntdll.dll中查找函数地址,但这是正确的方法.

  • 它不比OP试图做的那样"私密".请更清楚地解释您对Native API的奇怪厌恶. (4认同)

jim*_*ark 4

也许比 Necrolis 更好的方法是使用Microsoft Research 的 Detours 包来挂钩 dll 的入口点以监视 DLL_PROCESS_DETACH 通知。

您可以使用以下函数找到给定 HMODULE(由 LoadLibrary 返回)的入口点:

#include <windows.h>
#include <DelayImp.h>


PVOID GetAddressOfEntryPoint(HMODULE hmod)
{
    PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)hmod;
    PIMAGE_NT_HEADERS pinth = (PIMAGE_NT_HEADERS)((PBYTE)hmod + pidh->e_lfanew);
    PVOID pvEntry = (PBYTE)hmod + pinth->OptionalHeader.AddressOfEntryPoint;

    return pvEntry;
}
Run Code Online (Sandbox Code Playgroud)

您的入口点替换可以采取直接操作或增加您在主循环中或对您重要的地方检查的计数器。(并且几乎肯定应该调用原始入口点。)

更新:感谢@LeoDavidson 在下面的评论中指出了这一点。Detours 4.0 现在使用自由的 MIT 许可证进行许可。

我希望这有帮助。

  • @LeoDavidson [Detours (4.x)](https://github.com/Microsoft/Detours) 现在已根据 MIT 许可证获得自由许可。过去,我也曾因 Detours 的许可条件而望而却步。但这似乎不再是一个问题。 (2认同)