c++ - 获取实际不存在的进程加载模块

标签 c++ c windows debugging winapi

在检查 Microsoft Word 的加载模块时,我遇到了一些非常奇怪的事情。我写了一个小程序来输出所有加载的 DLL 的位置。这是输出:

Loaded modules using snapshot's WinApi

当我试图在我的 PC 上找到这些模块时,我无法在给定位置找到它们,而是在另一个位置:

The DLL's actual location

我无法弄清楚为什么 DLL 的路径不同,而且我在 Google 中也找不到任何相关内容,尽管我怀疑它与 VFS 相关。

也就是说,Process Explorer 设法以某种方式显示了 DLL 的原始位置。

谁能告诉我 Process Explorer 如何做到这一点,以及如何在我的代码中实现相同的结果?

---------------- 编辑 ----------------

  1. 我也尝试过注入(inject) DLL 并遍历 WINWORD 的 LDR,但我仍然看不到原始 DLL 的位置。

  2. Sysinternal 的 ListDlls 实用程序也不显示原始 DLL 的位置。 至于现在,只有 Process Explorer 显示正确的位置。

最佳答案

Office 2016 使用 App-V 来重定向和虚拟化它的一些路径。这使查找 DLL 变得有点复杂。 Process Explorer 使用稍微复杂的1 方法来查找 DLL。一般过程是:

  1. 使用 TH32CS_SNAPMODULETH32CS_SNAPMODULE32 标志创建一个 Tool Help 32 快照。
  2. 使用Module32FirstModule32Next获取有关进程中模块的信息。
  3. 要解析 App-V dll 在我的 Office 2016 上存在的符号链接(symbolic link),请打开文件,然后使用 GetFinalPathNameByHandle获取解析路径。 (请注意,这将是包含前导 \\?\ 的路径,但这很容易删除。)

示例实现:

// Obtain the Process ID however you like. I used GetWindowThreadProcessId.
if (processId != 0)
{
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processId);
    if (snapshot != INVALID_HANDLE_VALUE)
    {
        MODULEENTRY32W moduleInfo = { 0 };
        moduleInfo.dwSize = sizeof(MODULEENTRY32W);

        BOOL ok = Module32FirstW(snapshot, &moduleInfo);
        if (!ok)
        {
            // The read failed, handle the error here.
        }
        do
        {
            HANDLE hFile = CreateFileW(moduleInfo.szExePath, 
                                       0, 
                                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 
                                       NULL, 
                                       OPEN_EXISTING, 
                                       FILE_ATTRIBUTE_NORMAL, 
                                       NULL);
            if (hFile)
            {
                WCHAR realPath[MAX_PATH];
                DWORD result = GetFinalPathNameByHandleW(hFile, 
                                                         realPath, 
                                                         MAX_PATH, 
                                                         FILE_NAME_NORMALIZED);
                if (result > 0)
                {
                    wcout << L"Module: " << realPath << endl;
                }

                CloseHandle(hFile);
            }
            else
            {
                wcout << L"Module Name: " << moduleInfo.szExePath << endl;
            }
        } while (Module32NextW(snapshot, &moduleInfo));

        CloseHandle(snapshot);
    }
}

1 请注意,Process Explorer 是由 Sysinternals 编写的,并且可能使用了较低级别的信息。此方法确实解析了我 2016 年安装的 DLL。

关于c++ - 获取实际不存在的进程加载模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37976044/

相关文章:

android - 如何在 Android 中从文件读取 OpenCV Mat 对象?

c++ - vtkAxis - 从轴符号中删除小数点

c - c中的循环声明

c++ - 复制具有线程安全规则建议的非const参数的构造函数?

c++ - std::hash ofr 的返回值 (x86/x64)

c - 如何根据另一个序列重新排列 char 数组(这是一个按升序排序的 float 组)?

c++ - 与 GCC 的 -Wreturn-type 等效的 Visual Studio 警告是什么?

windows - 无法使用 pkcs12 文件连接到 RabbitMq Broker

c - 尝试删除文件时获取权限被拒绝错误

c++ - 以编程方式在 Windows 上隐藏应用程序