当特定 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
:
要找到它重定向到的实际文件,我执行以下操作:
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
模块的导出表:这表明
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/