本论坛为只读模式,仅供查阅,不能注册新用户,不能发帖/回帖,有问题可发邮件 xikug.xp (^) gmail.com
查看: 6604|回复: 8

用_LdrpHashTable来列举进程dll [复制链接]

Rank: 1

发表于 2010-1-6 22:29:54 |显示全部楼层
ntdll.dll中保存着LdrpHashTable这个hash链表,hash链表中的每个元素是_list_entry,8字节,通过它

可以枚举进程中的dll,这个链表是通过
lkd> dt _LDR_DATA_TABLE_ENTRY
nt!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY
   +0x008 InMemoryOrderLinks : _LIST_ENTRY
   +0x010 InInitializationOrderLinks : _LIST_ENTRY
   +0x018 DllBase          : Ptr32 Void
   +0x01c EntryPoint       : Ptr32 Void
   +0x020 SizeOfImage      : Uint4B
   +0x024 FullDllName      : _UNICODE_STRING
   +0x02c BaseDllName      : _UNICODE_STRING
   +0x034 Flags            : Uint4B
   +0x038 LoadCount        : Uint2B
   +0x03a TlsIndex         : Uint2B
   +0x03c HashLinks        : _LIST_ENTRY
   +0x03c SectionPointer   : Ptr32 Void
   +0x040 CheckSum         : Uint4B
   +0x044 TimeDateStamp    : Uint4B
   +0x044 LoadedImports    : Ptr32 Void
   +0x048 EntryPointActivationContext : Ptr32 Void
   +0x04c PatchInformation : Ptr32 Void

中的+0x03c HashLinks        : _LIST_ENTRY来链接起的。

http://www.langouster.com/HTML/77.html上已经相应的检测代码,但是具体细节没有说明。

关注下ntdll中对LdrpHashTable的引用,在ida中对LdrpHashTable查找,发现有3个函数对它有操作,

第1个:
.text:7C941571 ; __stdcall LdrpInitializeProcess(x, x, x, x, x)
.text:7C941571 _LdrpInitializeProcess@20 proc near     ; CODE XREF: _LdrpInitialize(x,x,x)

+6114p

。。。。。
。。。。。
初始化hash链表
.text:7C941571
.text:7C941790                 push    20h    //总共32个元素
.text:7C941792                 pop     ecx
.text:7C941793                 mov     eax, offset _LdrpHashTable
.text:7C941798                 mov     [ebp+var_70], ecx
.text:7C94179B
.text:7C94179B loc_7C94179B:                           ; CODE XREF: LdrpInitializeProcess(x,x,x,x,x)+233j
.text:7C94179B                 mov     [eax+4], eax //每个节点头的flink,blink都指向自身
.text:7C94179E                 mov     [eax], eax
.text:7C9417A0                 add     eax, 8
.text:7C9417A3                 dec     ecx
.text:7C9417A4                 jnz     short loc_7C94179B
。。。。。
。。。。。


第2个:

__stdcall LdrpInsertMemoryTableEntry(x)
.text:7C93BFC4 _LdrpInsertMemoryTableEntry@4 proc near ; CODE XREF: LdrpMapDll(x,x,x,x,x,x)

-B8p
.text:7C93BFC4                                         ; LdrpInitializeProcess(x,x,x,x,x)+65Fp ...
.text:7C93BFC4
.text:7C93BFC4 arg_0           = dword ptr  8
.text:7C93BFC4
.text:7C93BFC4                 mov     edi, edi
.text:7C93BFC6                 push    ebp
.text:7C93BFC7                 mov     ebp, esp
.text:7C93BFC9                 push    ebx
.text:7C93BFCA                 push    esi
.text:7C93BFCB                 push    edi
.text:7C93BFCC                 mov     eax, large fs:18h
.text:7C93BFD2                 mov     eax, [eax+30h]
.text:7C93BFD5                 mov     ebx, [eax+0Ch]  ; ldr
.text:7C93BFD8                 mov     esi, [ebp+arg_0] ; 参数1,为一个_LDR_DATA_TABLE_ENTRY指针
.text:7C93BFDB                 mov     eax, [esi+30h]  ;
/*
lkd> dt _LDR_DATA_TABLE_ENTRY -b  BaseDllName
.text:7C93BFDB                                         ; nt!_LDR_DATA_TABLE_ENTRY
.text:7C93BFDB                                         ;    +0x02c BaseDllName : _UNICODE_STRING
.text:7C93BFDB                                         ; lkd> dt _UNICODE_STRING
.text:7C93BFDB                                         ; nt!_UNICODE_STRING
.text:7C93BFDB                                         ;    +0x000 Length           : Uint2B
.text:7C93BFDB                                         ;    +0x002 MaximumLength    : Uint2B
.text:7C93BFDB                                         ;    +0x004 Buffer           : Ptr32 Uint2B
*/

.text:7C93BFDE                 movzx   eax, word ptr [eax] ; 路径前四个字节入栈
.text:7C93BFE1                 push    eax
.text:7C93BFE2                 lea     edi, [esi+3Ch]  ; dt _LDR_DATA_TABLE_ENTRY
.text:7C93BFE2                                         ; +0x03c HashLinks        : _LIST_ENTRY
.text:7C93BFE5                 call    _RtlUpcaseUnicodeChar@4 ; 首字母大写,返回第1个字母,'A'为0x0x41
./*
.text:7C93BFE5                                         ; dt _PEB_LDR_DATA
.text:7C93BFE5                                         ; nt!_PEB_LDR_DATA
.text:7C93BFE5                                         ;    +0x000 Length           : Uint4B
.text:7C93BFE5                                         ;    +0x004 Initialized      : UChar
.text:7C93BFE5                                         ;    +0x008 SsHandle         : Ptr32 Void
.text:7C93BFE5                                         ;    +0x00c InLoadOrderModuleList : _LIST_ENTRY
.text:7C93BFE5                                         ;    +0x014 InMemoryOrderModuleList : _LIST_ENTRY
.text:7C93BFE5                                         ;    +0x01c InInitializationOrderModuleList : _LIST_ENTRY
.text:7C93BFE5                                         ;    +0x024 EntryInProgress  : Ptr32 Void
*/

.text:7C93BFEA                 dec     eax             ; 以0为基准
.text:7C93BFEB                 and     eax, 1Fh        ; 索引号转换,不会超过32,'a'-->0,'b'-->1.....
.text:7C93BFEE                 lea     eax, _LdrpHashTable[eax*8] ; 得到hash某头节点,下面是将节点插入链表操作
.text:7C93BFF5                 mov     ecx, [eax+4]
.text:7C93BFF8                 mov     [edi], eax
.text:7C93BFFA                 mov     [edi+4], ecx
.text:7C93BFFD                 mov     [ecx], edi
.text:7C93BFFF                 mov     [eax+4], edi
.text:7C93C002                 lea     eax, [ebx+0Ch]  ; 当前ldr的+0x00c InLoadOrderModuleList,下面是将节点插入链表操作
.text:7C93C005                 mov     ecx, [eax+4]
.text:7C93C008                 mov     [esi], eax
.text:7C93C00A                 mov     [esi+4], ecx
.text:7C93C00D                 mov     [ecx], esi
.text:7C93C00F                 mov     [eax+4], esi
.text:7C93C012                 lea     ecx, [ebx+14h]  ; 当前ldr的+0x014 InMemoryOrderModuleList,下面是将节点插入链表操作
.text:7C93C015                 mov     edx, [ecx+4]
.text:7C93C018                 lea     eax, [esi+8]
.text:7C93C01B                 pop     edi
.text:7C93C01C                 mov     [eax], ecx
.text:7C93C01E                 mov     [eax+4], edx
.text:7C93C021                 pop     esi
.text:7C93C022                 mov     [edx], eax
.text:7C93C024                 mov     [ecx+4], eax
.text:7C93C027                 pop     ebx
.text:7C93C028                 pop     ebp
.text:7C93C029                 retn    4
.text:7C93C029 _LdrpInsertMemoryTableEntry@4 endp

上面这个函数7C93BFF5处开始的代码,正是langouster文章中的特征值
else if(dwMajorVersion==5 && dwMinorVersion==1)//xp
{
  pSign=(CONST BYTE *)"\x8B\x48\x04\x89\x07\x89\x4F\x04\x89\x39\x89";
  SignLen=11;
}
然后就可以得到_LdrpHashTable了。


最后一个函数LdrpCheckForLoadedDll中的相关代码就交给大家完成了^ ^。

下面是我小修改后编译的程序(几乎没改动,感谢原作者),可以看到输出的dll的名字是按a,b,c,d。。。的链表排列的。

欢迎指正。

参考文献:
http://www.langouster.com/HTML/77.html
http://blog.donews.com/zwell/archive/2005/10/21/596302.aspx
感谢原文作者

ListModuleByLdrpHashTable.rar

10 KB, 下载次数: 911

Rank: 1

发表于 2010-1-7 16:29:49 |显示全部楼层
支持!!!!

Rank: 2

发表于 2010-1-7 16:39:40 |显示全部楼层
貌似老外也放了个类似的
忘记在哪儿看过的

Rank: 1

发表于 2010-2-6 22:24:29 |显示全部楼层
好文,只有来捧场迟了,当初我也是分析GetModuleHandle如何枚举模块时偶然发现还存在着这样一份列表。
现在这世道,已经越来越分不清隐藏模块与堆代码的差别了。

Rank: 2

发表于 2010-2-6 23:11:24 |显示全部楼层
先来膜拜一下,漫漫看了

Rank: 1

发表于 2010-10-19 03:58:01 |显示全部楼层
支持  刚想看看peb 呢这个更方便

Rank: 2

发表于 2010-10-19 16:24:24 |显示全部楼层
先收藏

Rank: 1

发表于 2013-4-23 17:05:07 |显示全部楼层
不错, 收藏了

Rank: 1

发表于 2013-5-3 17:47:36 |显示全部楼层
刚好有用到, 收藏下
您需要登录后才可以回帖 登录 | 立即加入

Archiver|手机版|第8个男人 - 论坛为只读模式,仅供查阅

GMT+8, 2019-6-26 17:03 , Processed in 0.026551 second(s), 11 queries .

Design by pvo.cn

© 2011 Pvo Inc.

回顶部