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

通过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


结束语:技术可以做正义的事,也可以做邪恶的事,关键是看什么人掌握这些技术


你可能感兴趣的:(api,hook)