重命名DLL时出现进程模块列表问题

本文关键字:模块 列表 问题 进程 DLL 重命名 | 更新日期: 2023-09-27 18:20:33

我使用CreateToolhelp32Snaphot方法列出特定进程中加载的所有模块特定DLL,但我刚刚注意到,如果重命名加载的DLL,它仍然使用初始名称(可能是进程中加载DLL时的名称)列出。这是一个已知的问题吗?

MODULEENTRY32 modEntry = new MODULEENTRY32();
modEntry.dwSize = (UInt32)Marshal.SizeOf(typeof(MODULEENTRY32));
handleToSnapshot = CreateToolhelp32Snapshot((uint)SnapshotFlags.Module | (uint)SnapshotFlags.Module32, procId);
if (Module32First(handleToSnapshot, ref modEntry))
{
    do
    {
        Console.WriteLine(modEntry.szExePath);
    }
    while (Module32Next(handleToSnapshot, ref modEntry));
}

我还尝试使用EnumProcessModulesEx+GetModuleFileNameEx,也得到了相同的结果。我想知道Process Explorer是如何正确获取信息的,还有其他替代方法吗?

重命名DLL时出现进程模块列表问题

一种方法是直接从进程内存中读取数据,而不使用任何枚举模块列表的Win32函数:

  1. 使用OpenProcess打开进程的句柄
  2. 调用NtQueryInformationProcess获取ProcessBasicInformation信息类型,读取_PROCESS_BASIC_INFORMATION结构的PebBaseAddress属性(进程环境块地址)
  3. 使用ReadProcessMemory从目标进程内存读取PE块(读取ldrData部分)
  4. 浏览内存中已加载模块的列表。看见http://sandsprite.com/CodeStuff/Understanding_the_Peb_Loader_Data_List.html了解一些解释

这是我所知道的获取模块列表的最低级的方法,我确信Process Explorer也做了类似的事情。

但请注意,正确编码确实很痛苦,因为您必须处理64位问题:要使用的内存地址不同,WOW64之类的。。。等等。最后但并非最不重要的是:当你使用C#时,祝你好运,能获得所有这些(有时是未记录的)结构/函数的正确P/Invoke签名:)


编辑:正如下面的评论中所说,这是一种获取进程加载的模块列表的替代低级方法。但我不确定这是否会提供您在重命名模块时描述的行为。

我建议你深入研究Process Hacker的源代码,这是一个与Process Explorer非常相似的开源项目。我测试了PH,它的行为和你描述的一样。注意:这只是C代码,而不是C#。看看KProcessHacker目录,它是执行所有操作的驱动程序的代码。

在NTFS中,filename是存储在主文件表中的元数据变量。MFT还包含一个文件ID。当您更改文件名时,它不会更改文件ID。标识符唯一标识文件。

文件的打开句柄不是通过文件名来跟踪的,而是通过这个唯一标识符来跟踪的。

ProcessHacker、Process Explorer和其他工具将使用FILE_INTERNAL_INFORMATION枚举器从内核使用NtQueryInformationFile

此结构包含成员变量IndexNumber,它是唯一的文件标识符。

如果你想做同样的事情,你需要在内核中做同样的事:

查找进程加载的模块,获取文件句柄,使用句柄通过NtQueryInformationFile 获取IndexNumber