【发布时间】:2017-03-30 14:35:27
【问题描述】:
我的目标是挂钩来自特定 dll 及其依赖项的所有 LoadLibrary 调用(可能会延迟导入)。以下是我尝试解决此任务的方法:
-
使用
DONT_RESOLVE_DLL_REFERENCES标志加载此dll。1.1。将此算法递归地应用于 dll 的子模块。
- 手动填写此 dll 的导入表。
- 挂钩所有
LoadLibraryA、LoadLibraryW等函数,只是修补导入表。 - 使用
DLL_PROCESS_ATTACH标志手动调用此dll 的DllMain。
最后一步我遇到了问题。如果我手动调用DllMain,那么所有内部LoadLibrary 调用都将从我的模块的地址空间(而不是从dll 的地址空间)执行,并且我在step3 中的所有钩子都不会调用。
而且我不想在我的主模块中挂钩 LoadLibrary 调用,因为还有其他代码调用 LoadLibrary 而我不会产生这样的副作用。
所以我的问题是我应该如何调用 DllMain 以强制它不使用主模块中的LoadLibrary?是因为延迟进口吗?还是只是因为我打电话给DllMain?或者也许这个任务有更好的解决方案?
这是我运行 dll 的方式:
void PEUtility::runDllMain(HMODULE module)
{
typedef BOOL(WINAPI *DllMainFunPtr)(HMODULE, DWORD, LPVOID);
auto header = ImageNtHeader(module);
auto dllMain = (DllMainFunPtr)(header->OptionalHeader.AddressOfEntryPoint + (DWORD_PTR)module);
dllMain(module, DLL_PROCESS_ATTACH, NULL);
}
这是我填写导入表的方式:my question about how I'm filling import table
LoadLibrary hooking 类似于 Import Table 填充。
更新
我添加了一些来自 ApiMonitor 的屏幕截图,以证明 LoadLibrary("...mso20win32client.dll") 是从不同的模块调用的,然后我加载父库 olmapi32.dll(这取决于 mso20win32client.dll)使用上面描述的所有这些东西,然后我就打电话给LoadLibrary:
当我使用上述方法时(使用DONT_RESOLVE_DLL_REFERENCES、DllMain 等)(注意最后一行:mso20win32client.dll 是从 mapi32ex64.dll 加载的 - 我的主模块):
当我只是调用 LoadLibrary("OLMAPI32.dll") 时(注意最后一行:mso20win32client.dll 是从 olmapi32.dll 加载的 - 我想使用我的方法加载的 dll):
【问题讨论】:
-
有趣的是另一个 DLL 如何从您的模块中调用 LoadLibrary。你有点困惑。你自己加载dll的方式不正确。例如,在这种情况下,您不处理 Dll 中的清单,不创建激活上下文。而且,如果说 DLL 没有导入 LoadLibrary,而是使用 GetProcAddress 来获取这个 proc?你到底在做什么?我的意思是目标目标。
header->OptionalHeader.AddressOfEntryPoint你也没有检查 0 -
@RnMn,我是否正确理解使用
DONT_RESOLVE_DLL_REFERENCES加载库并为特定库调用 DllMain 对于清单和上下文来说是不够的?至于GetProcAddress- 我正在挂钩kernel32LoadLibrary 函数,我猜这个库总是出现在 dll 的导入表中。无论如何,我正在挂钩预定义的 dll 集,并且这些 dll 中没有一个不使用GetProcAddress。 -
是的,当您使用
DONT_RESOLVE_DLL_REFERENCES时,未处理 dll 清单。喜欢和tls。 -
为了了解发生了什么,您需要使用调试器并且仅使用调试器。任何 apimonitor 都不够
标签: c++ hook dllimport portable-executable dllmain