You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用LdrInitShimEngineDynamic()捕获进程内DLL加载事件及生效范围

问题

如何在自有应用中使用LdrInitShimEngineDynamic(),让自身.exe的指定函数在以下场景下收到通知:

  • 自行通过LoadLibrary()等方式将DLL动态加载到进程时
  • 他人通过CreateRemoteThread()等方式向当前进程加载DLL时
    要求通知触发时机满足:
  • 发生在DllMain()及DLL入口点执行之前
  • DLL的基重定位与导入表已完成解析
    同时需明确:该函数是捕获整个系统的DLL加载事件,还是仅针对当前进程?
实现方案与说明

1. LdrInitShimEngineDynamic()的使用步骤

LdrInitShimEngineDynamic()是ntdll.dll提供的加载器垫片引擎初始化接口,要实现需求需按以下步骤操作:

  • 定义自定义垫片回调:编写符合垫片引擎要求的回调函数,原型需匹配加载器的调用规范,示例原型如下:
    VOID WINAPI MyDllLoadCallback(PCUNICODE_STRING DllName, PVOID DllBase);
    
    该函数会在指定时机被加载器调用,参数包含被加载DLL的名称和基地址。
  • 获取函数地址:通过GetProcAddress从ntdll.dll中获取LdrInitShimEngineDynamic的函数指针(该函数未公开在官方头文件中)。
  • 初始化并注册垫片:调用LdrInitShimEngineDynamic,传入自定义垫片的配置(如垫片标识、回调函数指针等),让加载器将我们的垫片纳入其加载流程。

2. 触发时机验证

结合Win7 x64下NT加载器的调用流程(翻译后如下):

LoadLibraryExW()
LdrLoadDll()
LdrpLoadDll()
LdrpLoadDllInternal()
LdrpProcessWork()
LdrpMapDllFullPath()
LdrpMapDllNtfileName()
LdrpMapDllWithSectionHandle()
LdrpMinimalMapModule()
LdrpMapViewOfSection()
LdrpCompleteMapModule()
LdrpRelocateImage()
LdrpProtectAndRelocateImage();
LdrpSetProtection()
LdrpRelocateImageWithBias()    <-- DLL基重定位完成
LdrpProcessMappedModule()
LdrpCorProcessImports()
LdrpMapAndSnapDependency()    <-- DLL导入表解析完成
LdrpPrepareImportAddressTableForSnap()
LdrpPrepareModuleForExecution()
LdrpInitializeGraphRecurse()
LdrpInitializeNode()
LdrpCallInitRoutine()    <-- 此处调用自定义垫片,随后执行DllMain

可以看到:

  • 垫片回调会在LdrpCallInitRoutine中被触发,此时DLL的基重定位和导入表解析均已完成
  • 触发时机早于DllMain的执行,完全符合需求

3. 作用范围说明

LdrInitShimEngineDynamic()仅作用于调用该函数的当前进程,无法捕获整个系统的DLL加载事件。它是将垫片注入当前进程的加载器流程中,仅监控当前进程内的所有DLL加载操作——不管是自身调用LoadLibrary的主动加载,还是外部通过CreateRemoteThread注入的被动加载,都会被垫片回调捕获。

内容的提问来源于stack exchange,提问作者George Robinson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 05:07:16