检测DLL的卸载 [英] Detect the unloading of DLLs
问题描述
我有一个特殊的要求,我相信没有其他方法,
是:检测卸载DLL。我google了一下,发现了
一个四岁的SO,关于这一点。我选择了相同的
解决方案:Hook FreeLibrary
。
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
.
当代码进入 MyFreeLibrary
,我将以相同的方式(inline-hook)挂钩
的指定模块的入口点。在
MyEntryPoint
中,我将首先调用原始入口点,然后
检查 reason
argument - 如果值等于
DLL_PROCESS_DETACH
,这意味着这个DLL的清理工作是
刚刚完成,它将被卸载从地址空间。
在这一点上,我有机会做我的工作。它工作。
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.
这是吗?不幸的是,它还没有完成。一个非常重要的
事情被忽略:dependency。
So that's it ? Unfortunately, it's not finished. A very important thing is overlooked: dependency.
例如, a.dll
code> b.dll 和 c.dll
。当您加载
a.dll
, b.dll
和 c.dll
将首先加载(初始化)。这个
是因为$ b $的导入表中列出了 b.dll
和 c.dll
b a.dll
,它们是 a.dll
的依赖项。类似地,当卸载
a.dll
, b.dll
和 c .dll
也可以卸载,如果它们的引用
计数减少到零。我不知道
加载程序如何发现DLL的依赖项并卸载它们的细节,
FreeLibrary 没有讨论的库/ windows / desktop / ms683152%28v = vs.85%29.aspxrel =nofollow> MSDN 页这个,我很高兴的
理解这个,但我没有找到信息。
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.
所以主要的问题是如何检测卸载依赖关系
的DLL模块。我想有相同的机会来完成我的工作。
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.
一个可能的解决方案可能是导入表,找出DLL的
依赖关系表,并从其导入表等找出依赖关系的
依赖关系,
找出所有的依赖关系,钩住所有入口点,我不
知道,这听起来很疯狂,我需要一些建议。
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.
推荐答案
我为旧的SO问题提供了答案。你现在写:
I contributed answers to the old SO question. You now write:
在MyEntryPoint中,我将首先调用原始入口点,然后检查reason参数 - 如果值等于DLL_PROCESS_DETACH,这意味着这个DLL的清理工作刚刚完成,它将从地址空间中卸载。
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.
发现这不是真的。但是最简单的修复是什么?如果在找到原因是DLL_PROCESS_DETACH之后,如果hModule仍然有效,会怎么样?请参阅:
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:
您可以跳过挂接DLL入口点,不检查DLL_PROCESS_DETACH,总是只是测试hModule是否仍然有效。这让我意识到,最好在调用原始FreeLibrary之前检查hModule是否有效,然后测试一个有效到无效的转换:
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
}
我希望这有帮助。
这篇关于检测DLL的卸载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!