使用VirtualQueryEx枚举远程进程中的模块不会返回所有模块

时间:2012-12-26 13:46:34

标签: c winapi dll virtualalloc

我正在尝试获取给定进程正在使用的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并且我没有使用它有一个原因(太长了:)。

1 个答案:

答案 0 :(得分:1)

GetModuleFileName()仅为您提供 进程中加载​​的模块的名称,而不是其他进程。它会偶然给你一些命中,Windows操作系统DLL将被加载到同一个地址,因此具有相同的模块句柄值。

您需要使用GetModuleFileNameEx(),以便传递进程句柄。

请注意您的代码发布的基本缺陷,您没有做任何事情来确保您可以安全地在另一个进程上使用VirtualQueryEx()。这要求您挂起所有线程,以便在迭代时不能分配内存,这是调试器所做的事情。 EnumProcessModules也是必需的。失败模式很讨厌,它是随机的,很容易让你的循环卡住,一遍又一遍地重复相同的地址。这就是CreateToolHelp32Snapshot()函数存在的原因,重点是“快照”。