1

我正在尝试获取给定进程正在使用的 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 进程。

PS 我知道 EnumProcessModules 并且我没有使用它是有原因的(太长了:)。

4

1 回答 1

1

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

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

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

于 2012-12-26T15:33:44.140 回答