重命名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是如何正确获取信息的,还有其他替代方法吗?
一种方法是直接从进程内存中读取数据,而不使用任何枚举模块列表的Win32函数:
- 使用
OpenProcess
打开进程的句柄 - 调用
NtQueryInformationProcess
获取ProcessBasicInformation
信息类型,读取_PROCESS_BASIC_INFORMATION
结构的PebBaseAddress
属性(进程环境块地址) - 使用
ReadProcessMemory
从目标进程内存读取PE块(读取ldrData
部分) - 浏览内存中已加载模块的列表。看见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