我正在尝试获取给定进程正在使用的DLL列表,我试图通过VirtualQueryEx实现这一点。我的问题是它只返回了我的部分DLL列表而不是所有这些(我可以在给定的进程中使用Process Explorer或使用VirtualQuery查看列表)。
以下是代码:
char szBuf[MAX_PATH * 100] = { 0 };
PBYTE pb = NULL;
MEMORY_BASIC_INFORMATION mbi;
HANDLE h_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, iPID);
while (VirtualQueryEx(h_process, pb, &mbi, sizeof(mbi)) == sizeof(mbi)) {
int nLen;
char szModName[MAX_PATH];
if (mbi.State == MEM_FREE)
mbi.AllocationBase = mbi.BaseAddress;
if ((mbi.AllocationBase == hInstDll) ||
(mbi.AllocationBase != mbi.BaseAddress) ||
(mbi.AllocationBase == NULL)) {
// Do not add the module name to the list
// if any of the following is true:
// 1. If this region contains this DLL
// 2. If this block is NOT the beginning of a region
// 3. If the address is NULL
nLen = 0;
} else {
nLen = GetModuleFileNameA((HINSTANCE) mbi.AllocationBase,
szModName, _countof(szModName));
}
if (nLen > 0) {
wsprintfA(strchr(szBuf, 0), "\n%p-%s",
mbi.AllocationBase, szModName);
}
pb += mbi.RegionSize;
}
我的结果是szBuf
。
此函数是DLL文件的一部分,因此我很难调试。
现在DLL被编译为x64二进制文件,我将它用于x64进程。
P.S我知道EnumProcessModules并且我没有使用它有一个原因(太长了:)。
答案 0 :(得分:1)
GetModuleFileName()仅为您提供 进程中加载的模块的名称,而不是其他进程。它会偶然给你一些命中,Windows操作系统DLL将被加载到同一个地址,因此具有相同的模块句柄值。
您需要使用GetModuleFileNameEx(),以便传递进程句柄。
请注意您的代码发布的基本缺陷,您没有做任何事情来确保您可以安全地在另一个进程上使用VirtualQueryEx()。这要求您挂起所有线程,以便在迭代时不能分配内存,这是调试器所做的事情。 EnumProcessModules也是必需的。失败模式很讨厌,它是随机的,很容易让你的循环卡住,一遍又一遍地重复相同的地址。这就是CreateToolHelp32Snapshot()函数存在的原因,重点是“快照”。