我需要通过PEB访问kernel32.dll的地址,当我试图通过一个双链接列表访问_LDR_DATA_TABLE_ENTRY结构时,情况变得复杂起来,这个列表给了我_PEB_LDR_DATA结构,这些列表如下:
+0x00c InLoadOrderModuleList : _LIST_ENTRY
+0x014 InMemoryOrderModuleList : _LIST_ENTRY
+0x01c InInitializationOrderModuleList : _LIST_ENTRY例如,InMemoryOrderModuleListy selected LDR_DATA_TABLE_ENTRY需要访问结构,这必须通过Flink显示实现,其结构如下:
0:000> dt ntdll!_LIST_ENTRY
+0x000 Flink : Ptr32 _LIST_ENTRY
+0x004 Blink : Ptr32 _LIST_ENTRY简而言之,不知道select列表是否会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)如行中所示,“这里”是给我带来困惑的原因,因为移动的0x14只会选择InMemoryOrderModuleList列表的类型,但正如您在第一局的评论中所看到的那样,使用Flink练习的方式。
我正在等待您的确认,谢谢您的提前!
发布于 2015-07-20 10:47:35
假设PEB在1000小时。
这里列出了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成员是指针,假设它指向2000 H,即PEB_LDR_DATA位于2000 H。
现在,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,位于204。
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;Note表示,现在的Flink和Blink成员是指针。
现在假设InMemoryOrderModuleList.Flink指向3000h。
在3000 h有一个LIST_ENTRY结构,这是第一个条目。
假设这个结构Flink成员指向4000 h,这是第二个条目。
还假设最后一个结构Flink成员指向5000 h,这是第三个条目。
现在,除了PEB_LDR_DATA中的列表头之外,每个LIST_ENTRY实际上都是一个LDR_DATA_TABLE_ENTRY,这是可能的,因为后者具有与前者兼容的内存布局。
因此,您到达感兴趣项时,您可以访问LDR_DATA_TABLE_ENTRY结构的成员。
因为第三个条目位于5000小时,并且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;一幅描绘局势的丑陋图画

检查程序集代码
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发布于 2015-07-20 11:27:38
这是因为InMemoryOrderModuleList列表是LIST_ENTRY类型,它的第一个成员是Flink,其位移是0x00?
0:000> dt ntdll!_LIST_ENTRY
**+0x000** Flink : Ptr32 _LIST_ENTRY
+0x004 Blink : Ptr32 _LIST_ENTRYnMemoryOrderModuleList是一个双链表,其第一个成员是Flink,其位移为0x00。这意味着,如果我选择列表,InMemoryOrderModuleList将直接指向InMemoryOrderModuleList成员_LDR_DATA_TABLE_ENTRY表?而不是_LDR_DATA_TABLE_ENTRY表的开头?
如果我不太懂英语,我很抱歉,对不起
https://stackoverflow.com/questions/31512952
复制相似问题