当特定 API 映射到进程中时,我试图找到一种方法来解析它的内存地址和 DLL 文件名。大多数问题都可以通过 DLL 中的导入/导出表以及分析映射模块的导入地址表来解决。这适用于大多数功能。

但问题发生在一些 forwarded functions 上。这种函数的一个例子恰好是我的 Windows 10 系统上的 DeleteProcThreadAttributeList。因此,例如,如果我使用此类函数构建一个测试 32 位进程,或者更好,让我们使用 cmd.exe 镜像中的 32 位版本的 c:\windows\syswow64\cmd.exe,然后尝试分析其导入表。事实证明,这个函数是从 API Set 导入的,虚拟名称是 API-MS-WIN-CORE-PROCESSTHREADS-L1-1-2.DLL :

c++ - 如何解决转发的 WinAPI 的循环依赖?-LMLPHP

要找到它重定向到的实际文件,我执行以下操作:

HMODULE hMM = ::LoadLibraryEx(L"API-MS-WIN-CORE-PROCESSTHREADS-L1-1-2.DLL",
    NULL, DONT_RESOLVE_DLL_REFERENCES);
WCHAR buffModPath[MAX_PATH];
::GetModuleFileNameEx(::GetCurrentProcess(), hMM, buffModPath, _countof(buffModPath));
::FreeLibrary(hMM);

这给了我 buffModPath 作为 C:\Windows\System32\KERNEL32.DLL

由于我是从 32 位进程调用它,我现在检查 c:\windows\syswow64\KERNEL32.DLL 模块的导出表:

c++ - 如何解决转发的 WinAPI 的循环依赖?-LMLPHP

这表明 DeleteProcThreadAttributeList 被转发到 api-ms-win-core-processthreads-l1-1-0.DeleteProcThreadAttributeList

好的,然后我再次使用我的方法来解决虚拟 api-ms-win-core-processthreads-l1-1-0.dll API 集的重定向:
HMODULE hMM = ::LoadLibraryEx(L"api-ms-win-core-processthreads-l1-1-0.dll",
    NULL, DONT_RESOLVE_DLL_REFERENCES);
WCHAR buffModPath[MAX_PATH];
::GetModuleFileNameEx(::GetCurrentProcess(), hMM, buffModPath, _countof(buffModPath));
::FreeLibrary(hMM);

这给了我 C:\Windows\System32\KERNEL32.DLL ,这让我回到了我开始的地方。

那么我如何像 OS 模块加载器那样解决这种对实际 DLL 地址/入口点的循环依赖呢?

最佳答案

我认为如果你 GetProcAddress 这些导出中的一个应该是一个黑匣子,那么无论发生什么。

PEB 在 Windows 7+ 中有一个 ApiSetMap 成员,它包含加载器使用的集合信息。此数据的格式至少更改了 3 次,但映射不仅仅是从“API-*.dll”到“*32.dll”。

你可以阅读这个概念 here 的微软专利。

关于c++ - 如何解决转发的 WinAPI 的循环依赖?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48184822/

10-11 22:09
查看更多