您的位置:首页 > 其它

peb获取kernel32基址,用第一和第二种

2013-10-15 13:01 197 查看
通过PEB枚举当前进程空间中用户模块列表也可以获取Kernel32模块的基地址,fs:[0]指向TEB,fs:[30h]指向PEB,PEB偏移0ch是LDR指针,以下可以分别通过加载顺序、内存顺序、初始化顺序获取Kernel32模块的基地址,这里以初始化顺序为例:

未公开的LDR_MODULE数据结构如下:

typedef struct _LDR_MODULE

{

LIST_ENTRY InLoadOrderModuleList; // +0x00

LIST_ENTRY InMemoryOrderModuleList; // +0x08

LIST_ENTRY InInitializationOrderModuleList; // +0x10

PVOID BaseAddress; // +0x18

PVOID EntryPoint; // +0x1c

ULONG SizeOfImage; // +0x20

UNICODE_STRING FullDllName; // +0x24

UNICODE_STRING BaseDllName; // +0x2c

ULONG Flags; // +0x34

SHORT LoadCount; // +0x38

SHORT TlsIndex; // +0x3a

LIST_ENTRY HashTableEntry; // +0x3c

ULONG TimeDateStamp; // +0x44

// +0x48

} LDR_MODULE, *PLDR_MODULE;

以下是WinDbg显示的PEB_LDR_DATA的数据结构

+0x00c Ldr : Ptr32 to struct _PEB_LDR_DATA, 7 elements, 0x28 bytes

+0x000 Length : Uint4B

+0x004 Initialized : UChar

+0x008 SsHandle : Ptr32 to Void

+0x00c InLoadOrderModuleList : struct _LIST_ENTRY, 2 elements, 0x8 bytes

+0x000 Flink : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

+0x004 Blink : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

+0x014 InMemoryOrderModuleList : struct _LIST_ENTRY, 2 elements, 0x8 bytes

+0x000 Flink : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

+0x004 Blink : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

+0x01c InInitializationOrderModuleList : struct _LIST_ENTRY, 2 elements, 0x8 bytes

+0x000 Flink : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

+0x004 Blink : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

+0x024 EntryInProgress : Ptr32 to Void

通过上面两个结构我们可以通过3种方式获取Kernel32模块的基地址

1)加载顺序的方式:

GetK32Base:

assume fs:nothing

push esi

xor eax,eax

mov eax,fs:[eax+30h] ;指向PEB的指针

mov eax,[eax+0ch] ;指向PEB_LDR_DATA的指针

mov esi,[eax+0ch] ;根据PEB_LDR_DATA得出InLoadOrderModuleList的Flink字段

lodsd

mov eax, [eax] ;指向下一个节点 ;第一个节点为ntdll.dll,第二个为kernel32.dll

mov eax,[eax+18h] ;Kernel.dll的基地址 + 距离baseaddress的距离

pop esi

ret

2)内存顺序的方式:

GetK32Base:

assume fs:nothing

push esi

xor eax,eax

mov eax,fs:[eax+30h] ;指向PEB的指针

mov eax,[eax+0ch] ;指向PEB_LDR_DATA的指针

mov esi,[eax+14h] ;根据PEB_LDR_DATA得出InMemoryOrderModuleList的Flink字段

lodsd

mov eax, [eax] ;指向下一个节点

mov eax,[eax+10h] ;Kernel.dll的基地址

pop esi

ret

3)初始化顺序的方式:

GetK32Base:

assume fs:nothing

push esi

xor eax,eax

mov eax,fs:[eax+30h] ;指向PEB的指针

mov eax,[eax+0ch] ;指向PEB_LDR_DATA的指针

mov esi,[eax+1ch] ;根据PEB_LDR_DATA得出InInitializationOrderModuleList的Flink字段

lodsd

mov eax,[eax] ;win7以上版本+这个

mov eax,[eax+08h] ;Kernel.dll的基地址

pop esi

ret

3、通过遍历SEH链的方法,在SEH链中查找成员prev的值为0xFFFFFFFFh的EXCEPTION_REGISTER结构。该结构中的handler值是系统异常处理例程,总是位于kernerl32.dll中。当前线程的TIB保存在fs段选择器指定的数据段的0偏移处,所以fs:[0] 的地方就是TIB结构中的ExceptionList字段。而ExceptionList指向一个EXCEPTION_REGISTRATION结构,SEH异常处理回调函数的入口地址就是由EXCEPTION_REGISTRATION结构指定。

TIB结构如下:

NT_TIB STRUCT

ExceptionList dd ?

StackBase dd ?

StackLimit dd ?

SubSystemTib dd ?

union

FiberData dd ?

Version dd ?

ends

ArbitraryUserPointer dd ?

Self dd ?

NT_TIB ENDS

EXCEPTION_REGISTRATION STRUCT

prev dd ? ;前一个EXCEPTION_REGISTRATION结构的地址

handler dd ? ;异常处理回调函数地址

EXCEPTION_REGISTRATION ends

GetK32Base:

assume fs:nothing

xor esi, esi

mov esi, fs:[esi]

lodsd

@@:

inc eax

jz @f

dec eax

xchg esi, eax

lodsd

jmp @b

@@:

lodsd

@@:

dec eax

xor ax, ax

cmp DWORD ptr [eax], 5A4D

jnz @b

ret

结束语:技术可以做正义的事,也可以做邪恶的事,关键是看什么人掌握这些技术
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: