在检查 Microsoft Word 的加载模块时,我遇到了一些非常奇怪的事情。我写了一个小程序来输出所有加载的 DLL 的位置。这是输出:
当我试图在我的 PC 上找到这些模块时,我无法在给定位置找到它们,而是在另一个位置:
我无法弄清楚为什么 DLL 的路径不同,而且我在 Google 中也找不到任何相关内容,尽管我怀疑它与 VFS 相关。
也就是说,Process Explorer 设法以某种方式显示了 DLL 的原始位置。
谁能告诉我 Process Explorer 如何做到这一点,以及如何在我的代码中实现相同的结果?
---------------- 编辑 ----------------
我也尝试过注入(inject) DLL 并遍历 WINWORD 的 LDR,但我仍然看不到原始 DLL 的位置。
Sysinternal 的 ListDlls 实用程序也不显示原始 DLL 的位置。 至于现在,只有 Process Explorer 显示正确的位置。
最佳答案
Office 2016 使用 App-V 来重定向和虚拟化它的一些路径。这使查找 DLL 变得有点复杂。 Process Explorer 使用稍微复杂的1 方法来查找 DLL。一般过程是:
- 使用
TH32CS_SNAPMODULE
和TH32CS_SNAPMODULE32
标志创建一个 Tool Help 32 快照。 - 使用
Module32First
和Module32Next
获取有关进程中模块的信息。 - 要解析 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/