简体   繁体   中英

Detect the unloading of DLLs

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM