【问题标题】:Set hook on LoadLibrary which was called from DllMain of hooked delayed-dll在从挂钩延迟 dll 的 DllMain 调用的 LoadLibrary 上设置挂钩
【发布时间】:2017-03-30 14:35:27
【问题描述】:

我的目标是挂钩来自特定 dll 及其依赖项的所有 LoadLibrary 调用(可能会延迟导入)。以下是我尝试解决此任务的方法:

  1. 使用DONT_RESOLVE_DLL_REFERENCES 标志加载此dll。

    1.1。将此算法递归地应用于 dll 的子模块。

  2. 手动填写此 dll 的导入表。
  3. 挂钩所有LoadLibraryALoadLibraryW 等函数,只是修补导入表。
  4. 使用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_REFERENCESDllMain 等)(注意最后一行: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 - 我正在挂钩kernel32 LoadLibrary 函数,我猜这个库总是出现在 dll 的导入表中。无论如何,我正在挂钩预定义的 dll 集,并且这些 dll 中没有一个不使用GetProcAddress
  • 是的,当您使用 DONT_RESOLVE_DLL_REFERENCES 时,未处理 dll 清单。喜欢和tls。
  • 为了了解发生了什么,您需要使用调试器并且仅使用调试器。任何 apimonitor 都不够

标签: c++ hook dllimport portable-executable dllmain


【解决方案1】:

对于偶然发现此问题的未来读者(他们的目标是在库加载和调用其 init 例程之间做一些事情,例如挂钩或更改某些代码),请查看以下答案:https://reverseengineering.stackexchange.com/a/6023

基本上你可以把LdrpCallInitRoutine挂在ntdll.dll中,系统用来调用DLL入口点:

BOOLEAN NTAPI LdrpCallInitRoutine(PDLL_INIT_ROUTINE EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 2011-11-02
    • 1970-01-01
    • 2020-08-13
    相关资源
    最近更新 更多