链接结构LDR PEB

时间:2015-07-20 09:26:36

标签: assembly structure shellcode

我需要通过PEB获取kernel32.dll的地址,当我尝试通过双向链接列表访问_LDR_DATA_TABLE_ENTRY结构时,事情变得复杂,这个列表给出了_PEB_LDR_DATA结构,这些列表是:

+0x00c InLoadOrderModuleList : _LIST_ENTRY
+0x014 InMemoryOrderModuleList : _LIST_ENTRY
+0x01c InInitializationOrderModuleList : _LIST_ENTRY

比如说InMemoryOrderModuleListy选中列表LDR_DATA_TABLE_ENTRY需要访问结构,那必须通过Flink show来完成,其结构如下:

0:000> dt ntdll!_LIST_ENTRY
   +0x000 Flink            : Ptr32 _LIST_ENTRY
   +0x004 Blink            : Ptr32 _LIST_ENTRY

简而言之,不知道选择列表是否会是InMemoryOrderModuleList并直接指向第一个输入LDR_DATA_TABLE_ENTRY,因为这个列表是" LIST_ENTRY类型" Flink成员,偏移量为0,并指向该表。

这是我尝试理解的代码,它获取了kernel32的地址:

xor ebx, ebx            //clear ebx
mov ebx, fs:[ 0x30 ]    //get a pointer to the PEB
mov ebx, [ ebx + 0x0C ] //get PEB->Ldr
mov ebx, [ ebx + 0x14 ] //get PEB->Ldr.InMemoryOrderModuleList.Flink(1st entry) **here**       
mov ebx, [ ebx ]        //get the next entry(2nd entry)
mov ebx, [ ebx ]        //get the next entry(3rd entry)
mov ebx, [ ebx + 0x10 ] //get the 3rd entries base address(kernel32.dll)

如第14行所示"此处"是什么让我感到困惑,因为移动的0x14只是我选择了InMemoryOrderModuleList列表的类型,但你可以在第一局中的评论中看到通过推出Flink所运用的那些。

我等待您的确认,提前谢谢!

2 个答案:

答案 0 :(得分:3)

假设PEB处于1000h。

此处列出了PEB的第一个成员及其在内存中的地址

typedef struct _PEB {
  /* 1000h + 000h = 1000h */    BYTE Reserved1[2];
  /* 1000h + 002h = 1002h */    BYTE BeingDebugged;
  /* 1000h + 003h = 1003h */    BYTE Reserved2[1];
  /* 1000h + 004h = 1004h */    PVOID Reserved3[2];
  /* 1000h + 00ch = 100ch */    PPEB_LDR_DATA Ldr;
  ...
} PEB, *PPEB;

Ldr成员是指针,假设它指向2000h,  即PEB_LDR_DATA位于2000h。

现在来自MSDN,PEB_LDR_DATA具有这种结构(官方文档中省略了许多成员)

typedef struct _PEB_LDR_DATA {
  /* 2000h + 000h = 2000h */ BYTE       Reserved1[8];
  /* 2000h + 008h = 2008h */ PVOID      Reserved2[3];
  /* 2000h + 014h = 2014h */ LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

正如您所看到的,成员InMemoryOrderModuleList 不是指针是结构,因此LIST_ENTRY的所有成员都嵌入到PEB_LDR_DATA结构中。<登记/> 这意味着在InMemoryOrderModuleList的地址处有LIST_ENTRY的第一个成员,此成员为Flink,位于2014h。

Here the expanded structure

typedef struct _PEB_LDR_DATA {
  /* 2000h + 000h = 2000h */ BYTE       Reserved1[8];
  /* 2000h + 008h = 2008h */ PVOID      Reserved2[3];
  /* 2000h + 014h = 2014h */ LIST_ENTRY InMemoryOrderModuleList;
       /* 2000h + 014h = 2014h */ LIST_ENTRY* InMemoryOrderModuleList.Flink
       /* 2000h + 018h = 2018h */ LIST_ENTRY* InMemoryOrderModuleList.Blink
} PEB_LDR_DATA, *PPEB_LDR_DATA;

注意现在FlinkBlink成员指针

现在假设InMemoryOrderModuleList.Flink指向3000h 在3000h处有一个LIST_ENTRY结构,这是第一个条目。

假设此结构Flink成员指向4000h,这是第二个条目 假设最后一个结构Flink成员指向5000h,这是第三个条目。

现在除了PEB_LDR_DATA中的列表头部之外,每个LIST_ENTRY实际上都是LDR_DATA_TABLE_ENTRY,这是可能的,因为后者与前者具有兼容的内存布局。
因此,当您访问感兴趣的条目时,您可以访问LDR_DATA_TABLE_ENTRY结构的成员。

由于第三个条目是5000h而LDR_DATA_TABLE_ENTRY具有此布局

typedef struct _LDR_DATA_TABLE_ENTRY {
    /* 5000h + 000h = 5000h */  PVOID Reserved1[2];
    /* 5000h + 008h = 5008h */  LIST_ENTRY InMemoryOrderLinks;
    /* 5000h + 010h = 5010h */  PVOID Reserved2[2];
    /* 5000h + 018h = 5018h */  PVOID DllBase;
    ...
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

丑陋的MS Paint情况图片

Linked list layout

查看汇编代码

xor ebx, ebx            //An useless instruction
mov ebx, fs:[ 0x30 ]    //get a pointer to the PEB
;EBX is now  1000h

mov ebx, [ ebx + 0x0C ] //get PEB->Ldr
;This read from 100ch and EBX gets 2000h

mov ebx, [ ebx + 0x14 ] //get PEB->Ldr.InMemoryOrderModuleList.Flink(1st entry)
;This read from 2014h and EBX gets 3000h   

mov ebx, [ ebx ]        //get the next entry(2nd entry)
;This read from 3000h and EBX gets 4000h  

mov ebx, [ ebx ]        //get the next entry(3rd entry)
;This read from 4000h and EBX gets 5000h  

mov ebx, [ ebx + 0x10 ] //get the 3rd entries base address(kernel32.dll)
;This read from 5010h, it seems that this DOES NOT read the correct member! 
;Should be at offset 18h

答案 1 :(得分:0)

这是因为InMemoryOrderModuleList列表是LIST_ENTRY类型,其第一个成员是Flink,其位移 0x00

0:000> dt ntdll!_LIST_ENTRY
   **+0x000** Flink            : Ptr32 _LIST_ENTRY
   +0x004 Blink            : Ptr32 _LIST_ENTRY

nMemoryOrderModuleList是一个双向链表,其第一个成员是Flink,其位移是0x00 ......这意味着如果我选择列表InMemoryOrderModuleList将直接指向InMemoryOrderModuleList成员_LDR_DATA_TABLE_ENTRY表?而不是_LDR_DATA_TABLE_ENTRY表的开头?

如果我不太懂英语,我很抱歉,抱歉