【问题标题】:Getting process's loaded modules which does not really exist获取进程的加载模块,但实际上并不存在
【发布时间】:2016-06-22 18:48:13
【问题描述】:

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

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

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

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

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

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

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

  2. Sysinternal 的 ListDlls 实用程序也不显示原始 DLL 位置。 就目前而言,只有 Process Explorer 显示正确的位置。

【问题讨论】:

  • @alk:如果这些是软/硬链接,它们将是用户可见的。
  • @alk,这些不是链接。
  • dumpbin /imports winword.exe 建议 Office 2016 正在使用 App-V
  • @theB,进程资源管理器如何获取正确路径?

标签: c++ c windows debugging winapi


【解决方案1】:

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

  1. 使用TH32CS_SNAPMODULETH32CS_SNAPMODULE32 标志创建工具帮助32 快照。
  2. 使用Module32FirstModule32Next 获取有关进程中模块的信息。
  3. 要解析符号链接(在我的 Office 2016 上为 App-V dll 提供),打开文件,然后使用 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++ conole 应用程序中对该代码进行了测试,而没有向进程中注入线程。我的安装与您的安装略有不同,因此可能存在一些下落不明的边缘情况,但从实验中可以看出 Process Explorer 正在使用这种方法,并且我得到的所有 DLL 都实际存在于报告的地方。
  • 谢谢老兄。你真的帮了我
  • 无关,但我对 Office 现在使用 App-V 感到有点震惊。我想不出一个很好的理由,你能吗?可能与许可有关...还记得 Office 曾经是一套用于提高生产力的有用应用吗?
  • @CodyGray 我唯一能想到的是他们正在使用 App-V 来抽象出既是商店应用程序又是收缩包装产品的怪异之处。也就是说,我仍然认为这是解决问题的复杂方法。我原以为只需添加一个使用适当更改的 DLL 搜索路径的模块加载器就足够了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-29
  • 1970-01-01
  • 1970-01-01
  • 2012-04-23
  • 1970-01-01
  • 2022-01-11
相关资源
最近更新 更多