检测DLL的卸载 [英] Detect the unloading of DLLs

查看:127
本文介绍了检测DLL的卸载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个特殊的要求,我相信没有别的办法,
就是:检测卸载DLL。我google了,发现
一个四岁的SO <关于这个。我选择了相同的
解决方案:Hook FreeLibrary



当代码进入 MyFreeLibrary ,我将以相同的方式钩住
的入口点(inline-hook)。在
MyEntryPoint 中,我将首先调用原始入口点,然后
检查原因参数 - 如果值等于
DLL_PROCESS_DETACH ,这意味着此DLL的清理工作是
刚刚完成,它将被卸载从地址空间。
在这一点上,我有机会做我的工作。它的工作原理。



那就是这样吗?不幸的是,它还没有完成。一个非常重要的
的东西被忽略:依赖。



例如, a.dll code> b.dll 和 c.dll 。当您加载
a.dll b.dll c.dll将首先加载(初始化)。这个
是因为 b.dll c.dll 在$ b $的导入表中列出b a.dll ,它们是 a.dll 的依赖关系。同样,当您卸载
a.dll b.dll c如果参考
计数减少到零,也可以卸载.dll
。我不知道
加载器如何找到DLL的依赖关系并卸载它们的细节。
MSDN 页面 FreeLibrary 没有说关于这一点,我很高兴
了解这一点,但我没有找到信息。



所以主要的问题是如何检测依赖关系的卸载
的一个DLL模块。我想有同样的机会做我的工作。



可能的解决方案可能是导入表,从导入中找出DLL的
依赖关系表,并从他们的导入表中找出依赖关系的
依赖关系,
找出所有的依赖关系,勾选所有的入口点,我不会
知道,听起来很疯狂我在这里需要一些建议。

解决方案

我为旧的SO问题提供了答案。你现在写:


而在MyEntryPoint中,我将首先调用原始入口点,然后检查原因参数 - 如果该值等于DLL_PROCESS_DETACH,这意味着这个DLL的清理工作刚刚完成,它将从地址空间中卸载。


你发现这不是真的。但是最简单的修复是什么?如果你发现原因是DLL_PROCESS_DETACH,你测试hModule是否仍然有效?请参阅:



如何判断Windows模块句柄是否仍然有效?



您可以跳过挂起DLL进入点,不检查DLL_PROCESS_DETACH,并且始终只是测试hModule是否仍然有效。这使我意识到,最好在调用原始FreeLibrary之前检查hModule是否有效,然后测试一个有效到无效的转换:

  if(moduleWasValid&!moduleStillValid)
{
//处理模块卸载
}

我希望这有帮助。


I have a special requirement, and I believe there is no other way, that is: Detect the unloading of DLLs. I googled it and found out a four-years old SO about this. I have chosen the same solution: Hook FreeLibrary.

When code goes into MyFreeLibrary, I will hook the entry point of the specified module in the same way (inline-hook). And in MyEntryPoint, I will call the original entry point first, then check the reason argument - if the value equals to DLL_PROCESS_DETACH, it means that the cleanup work of this DLL is just done, and it's going to be unloaded from the address space. At this point, I have the chance do my job. It works.

So that's it ? Unfortunately, it's not finished. A very important thing is overlooked: dependency.

For example, a.dll links against b.dll and c.dll. When you load a.dll, b.dll and c.dll will be loaded (be initialized) first. This is because b.dll and c.dll are listed in the import table of a.dll, they are dependencies of a.dll. Similarly, when you unload a.dll, b.dll and c.dll may be also unloaded if their reference count decreased to zero. I don't know the detail about how the loader finds out the dependencies of a DLL and unload them, The MSDN page of FreeLibrary didn't talk about this, I'm glad to understand this but I did't find the information.

So the main problem is how to detect the unloading of dependencies of a DLL module. I want to have the same chance to do my job.

A possible solution may be the import table, find out the dependencies of a DLL from its import table, and find out the dependencies of dependencies from their import table and so on, find out all the dependencies, hook all the entry points, I don't know, It sounds crazy, I need some advice here.

解决方案

I contributed answers to the old SO question. You now write:

And in MyEntryPoint, I will call the original entry point first, then check the reason argument - if the value equals to DLL_PROCESS_DETACH, it means that the cleanup work of this DLL is just done, and it's going to be unloaded from the address space.

You've discovered this isn't true. But what's the simplest fix? What if after you find the reason is DLL_PROCESS_DETACH, you test if the hModule is still valid? See:

How can I tell if a Windows module handle is still valid?

You may be able to skip hooking the DLL entry point, not check for DLL_PROCESS_DETACH and always just test if the hModule is still valid. Which makes me realize, it would be better to check if the hModule is valid before calling the original FreeLibrary, and after and test for a valid to invalid transition:

if (moduleWasValid && !moduleStillValid)
{
    // process module unloaded
}

I hope this helps.

这篇关于检测DLL的卸载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆