前言有两种常用的方式可以查看 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
[原创]调试技巧 | 从 Win7 到 Win10,DLL引用计数查看全攻略
324 浏览
0 回复
暂无回复,快来抢沙发吧!