论坛首页 安全工具分享区 阅读主题

[原创]调试技巧 | 从 Win7 到 Win10,DLL引用计数查看全攻略

324 浏览 0 回复
#1 楼主 2026-06-01 21:08:59
前言有两种常用的方式可以查看 dll 的引用计数。在 windbg 中通过 !dlls 命令查看 dll 的引用计数。!dlls 输出结果中包含 LoadCount 字段。注意: 不同版本的 windbg 使用的 !exts.dlls 命令解析方式不同,低版本的 windbg 在解析 win10 上运行程序的 dll 引用计数,解析结果很可能是错的。手动解析 PEB 中的 PEB_LDR_DATA 中的模块加载列表数据查看 dll 的引用计数。Win7 及之前系统:
找到 PEB 中的 PEB_LDR_DATA (Ldr 字段),遍历其 InLoadOrderModuleList 链表。链表项为 _LDR_DATA_TABLE_ENTRY 结构,其中的 LoadCount 字段即为引用计数。Win8 及之后系统:
结构发生变化,需在 _LDR_DATA_TABLE_ENTRY 中找到 DdagNode 字段(它是一个指向 _LDR_DDAG_NODE 的指针),该结构中的 LoadCount 字段为当前引用计数。win7 查看方法进程的 PEB 中保存了 PEB_LDR_DATA,对应的字段名为 ldr,可以通过 dt _PEB @$peb -b ldr 命令查看 ldr 的内容。0:000> dt _PEB @$peb -b ldr
ntdll!_PEB
  +0x00c Ldr : 0x77290200
ldr 中有三个链表,分别是 InLoadOrderModuleList,InMemoryOrderModuleList 和 InInitializationOrderModuleList0:000> dt ntdll!_PEB_LDR_DATA 0x77290200
  +0x000 Length           : 0x30
  +0x004 Initialized      : 0x1 ''
  +0x008 SsHandle         : (null)
  +0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x6b27a0 - 0x6b34b0 ]    //<----
  +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x6b27a8 - 0x6b34b8 ]    //<----
  +0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x6b2840 - 0x6b34c0 ]    //<----
  +0x024 EntryInProgress  : (null)
  +0x028 ShutdownInProgress : 0 ''
  +0x02c ShutdownThreadId : (null)
每个链表项的类型是 LDR_DATA_TABLE_ENTRY,结构如下:0:000> dt _LDR_DATA_TABLE_ENTRY 0x6b27a0
ntdll!_LDR_DATA_TABLE_ENTRY
  +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x6b2830 - 0x7729020c ]
  +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x6b2838 - 0x77290214 ]
  +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
  +0x018 DllBase          : 0x00fa0000 Void
  +0x01c EntryPoint       : 0x00fb1109 Void
  +0x020 SizeOfImage      : 0x1b000
  +0x024 FullDllName      : _UNICODE_STRING "C:\Users\bcn\Desktop\WaitDllUnloadExe.exe"
  +0x02c BaseDllName      : _UNICODE_STRING "WaitDllUnloadExe.exe"
  +0x034 Flags            : 0x4000
  +0x038 LoadCount        : 0xffff    //<----
  +0x03a TlsIndex         : 0
  +0x03c HashLinks        : _LIST_ENTRY [ 0x77294818 - 0x77294818 ]
  +0x03c SectionPointer   : 0x77294818 Void
  +0x040 CheckSum         : 0x77294818
  +0x044 TimeDateStamp    : 0x696f76bc
  +0x044 LoadedImports    : 0x696f76bc Void
  +0x048 EntryPointActivationContext : (null)
  +0x04c PatchInformation : (null)
  +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x6b27f0 - 0x6b27f0 ]
  +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x6b27f8 - 0x6b27f8 ]
  +0x060 StaticLinks      : _LIST_ENTRY [ 0x6b3568 - 0x6b3488 ]
  +0x068 ContextInformation : 0x771cc924 Void
  +0x06c OriginalBase     : 0
  +0x070 LoadTime         : _LARGE_INTEGER 0x0
可以通过如下命令显示出每个 dll 的引用计数。!list -t nt!_LIST_ENTRY.FLink -x "dt nt!_LDR_DATA_TABLE_ENTRY LoadCount BaseDllName @$extret" 0x76ff5da0+0x00c,其中 0x77b80200 为 ldr 的基址。命令解释关于以上命令的 AI 解释如下:!list专门用于遍历链表的 Windbg 扩展命令可以遍历 LIST_ENTRY 结构定义的双向链表-t nt!_LIST_ENTRY.FLink-t 指定链表节点的类型nt!_LIST_ENTRY.FLink 指定链表结构体中的前向指针字段表示链表通过 FLink 字段连接-x选项及其参数-x "dt nt!_LDR_DATA_TABLE_ENTRY LoadCount BaseDllName @$extret"
-x 表示对每个链表节点执行指定的命令执行的命令是:dt nt!_LDR_D

...(已截断)

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-290038.htm

暂无回复,快来抢沙发吧!

请登录后参与讨论

立即登录 注册账号