首页
社区
课程
招聘
[求助]pe怎么获取hashtable这个链表
发表于: 2015-9-18 12:24 6416

[求助]pe怎么获取hashtable这个链表

2015-9-18 12:24
6416
PLIST_ENTRY GetLdrpHashTableAddress()
{
  DWORD i;
  HANDLE hModule;
  PLIST_ENTRY LdrpHashTable;
  PIMAGE_DOS_HEADER DosHeader;
  PIMAGE_NT_HEADERS NtHeader;
  PIMAGE_SECTION_HEADER SectionHeader;
  
  //hashtable是保存在ntdll这个模块的.data的一个地址的偏移
  hModule=GetModuleHandle("ntdll.dll");

  //得到ntdll的pe文件头结构
  DosHeader=(PIMAGE_DOS_HEADER)hModule;
  NtHeader=(PIMAGE_NT_HEADERS)((PUCHAR)hModule+DosHeader->e_lfanew);
  SectionHeader=IMAGE_FIRST_SECTION(NtHeader);
  
  //
  // Retrieve .data section
  // 
  //开始搜索section
  for(i=0; i<NtHeader->FileHeader.NumberOfSections; i++)
  {
    //printf("Section : %s\n", SectionHeader[i].Name);
    if(*(PDWORD)&SectionHeader[i].Name=='tad.') //.dat
    {  
      printf("Data section : 0x%x\n", (DWORD)hModule+SectionHeader[i].VirtualAddress);
      break;
    }
  }
  //得到hashtable
       //这里的为什么 +0x260,0x260怎么得到的?
  LdrpHashTable=(PLIST_ENTRY)((PUCHAR)hModule+SectionHeader[i].VirtualAddress+0x260);
  
  return LdrpHashTable;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
2
这里看不出任何理由,因此可以判断这个0x260毫无疑问是个硬编码而已
在我的XP SP3上,这个值是0x280,所以没有通用性

想要完美得到这个HashTable的地址,其实可以通过它的定义把它的地址“算”出来
以我的XP SP3为例,在windbg中观察到以下信息:

先找到PEB,这个不难,再找其中的Ldr,这几个偏移好像万年不变
0:000> dt _PEB 7ffdf000
ntdll!_PEB
   +0x000 InheritedAddressSpace : 0 ''
   +0x001 ReadImageFileExecOptions : 0 ''
   +0x002 BeingDebugged    : 0x1 ''
   +0x003 SpareBool        : 0 ''
   +0x004 Mutant           : 0xffffffff Void
   +0x008 ImageBaseAddress : 0x00400000 Void
   +0x00c Ldr              : 0x00251ea0 _PEB_LDR_DATA

0:000> dt _PEB_LDR_DATA 0x00251ea0 
ntdll!_PEB_LDR_DATA
   +0x000 Length           : 0x28
   +0x004 Initialized      : 0x1 ''
   +0x008 SsHandle         : (null) 
   +0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x251ee0 - 0x253990 ]
   +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x251ee8 - 0x253998 ]
   +0x01c [COLOR="Red"][B]InInitializationOrderModuleList [/B][/COLOR]: _LIST_ENTRY [ 0x251f58 - 0x2538e0 ]
   +0x024 EntryInProgress  : (null) 
 

Ldr+0xC开始,其实是个LDR_DATA_TABLE_ENTRY结构,这三个链表中的节点是一样的,但是顺序不一样,我们看第三个InInitializationOrderModuleList ,按初始化顺序,第一个被初始化的当然是ntdll.dll

0:000> dt nt!_LDR_DATA_TABLE_ENTRY 0x251f58-10
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x252010 - 0x251ee0 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x252018 - 0x251ee8 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x252020 - 0x251ebc ]
   +0x018 DllBase          : 0x7c920000 Void
   +0x01c EntryPoint       : 0x7c9320f8 Void
   +0x020 SizeOfImage      : 0x96000
   +0x024 FullDllName      : _UNICODE_STRING "C:\windows\system32\ntdll.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "ntdll.dll"
   +0x034 Flags            : 0x85004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   [COLOR="Red"][B]+0x03c HashLinks        : _LIST_ENTRY [ 0x25384c - 0x7c99e2e8 ] //就是这个Link[/B][/COLOR]   
   +0x03c SectionPointer   : 0x0025384c Void
   +0x040 CheckSum         : 0x7c99e2e8
   +0x044 TimeDateStamp    : 0x4d00f280
   +0x044 LoadedImports    : 0x4d00f280 Void
   +0x048 EntryPointActivationContext : (null) 
   +0x04c PatchInformation : (null) 


上面加红的就是这个Link了,考虑到LdrpHashTable的定义如下:
#define LDRP_HASH_TABLE_SIZE 32
#define LDRP_HASH_MASK       (LDRP_HASH_TABLE_SIZE-1)
#define LDRP_COMPUTE_HASH_INDEX(wch) ( (RtlUpcaseUnicodeChar((wch)) - (WCHAR)'A') & LDRP_HASH_MASK )
LIST_ENTRY LdrpHashTable[LDRP_HASH_TABLE_SIZE];


可以看到Hash算法其实就是模块名称的首字母大写之后减去'A',然后与32取余
然后挂入一个双链表数组中(没学过数据结构的请自行补课, 经典结构)

那么现在的情况是,已经知道了模块ntdll.dll的首节点,来反推数组的首地址,我们按算法算一下:
'N '- ' A' = 13 
13 * sizeof(LIST_ENTRY)= 13 * 8 = 104 = 0x68

0x7c99e2e8 - 0x68 = 0x7c99e280 


那么0x7c99e280  就是LdrpHashTable的地址了
来验证一下:
0:000> x ntdll!*hashtable*
7c99e280 ntdll!LdrpHashTable = <no type information>


至于编码实现,楼主就自己去实现吧。
虽然这里面也用到了几个硬编码,不过这几个是微软万年不变的,放心用好了
2015-9-19 13:26
0
雪    币: 234
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
achillis 这里看不出任何理由,因此可以判断这个0x260毫无疑问是个硬编码而已 在我的XP SP3上,这个值是0x280,所以没有通用性 想要完美得到这个HashTable的地址,其实可以通过它的定义把 ...
,顶起
2022-5-27 21:41
0
游客
登录 | 注册 方可回帖
返回
//