我是靠谱客的博主 危机秋天,最近开发中收集的这篇文章主要介绍获取Kernel32基地址的几种方法-相关结构,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

 

一、几个重要的数据结构,可以通过windbg的dt命令查看其详细信息

_PEB、_PEB_LDR_DATA、_LDR_DATA_TABLE_ENTRY

二、技术原理

1、通过fs:[30h]获取当前进程的_PEB结构

2、通过_PEB的Ldr成员获取_PEB_LDR_DATA结构

3、通过_PEB_LDR_DATA的InMemoryOrderModuleList成员获取_LIST_ENTRY结构

4、通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构,注意:这里的Flink指向的是_LDR_DATA_TABLE_ENTRY结构中的InMemoryOrderLinks成员,因此需要计算真正的_LDR_DATA_TABLE_ENTRY起始地址,我们可以用CONTAINING_RECORD来计算。

5、输出_LDR_DATA_TABLE_ENTRY的BaseDllName或FullDllName成员信息。

三、代码实现(基于XP sp2 系统)

 
//EnumInLoadModule.c  
//compile:cl EnumInLoadModule.c  
#include <windows.h>  

#define CONTAINING_RECORD(address, type, field) ((type *)( /  
(PCHAR)(address) - /  
(ULONG_PTR)(&((type *)0)->field)))  

typedef struct _UNICODE_STRING {  
    USHORT  Length;  
    USHORT  MaximumLength;  
    PWSTR  Buffer;  
} UNICODE_STRING, *PUNICODE_STRING;  

typedef struct _PEB_LDR_DATA  
{  
    DWORD Length;  
    UCHAR Initialized;  
    PVOID SsHandle;  
    LIST_ENTRY InLoadOrderModuleList;  
    LIST_ENTRY InMemoryOrderModuleList;  
    LIST_ENTRY InInitializationOrderModuleList;  
    PVOID EntryInProgress;  
}PEB_LDR_DATA,*PPEB_LDR_DATA;  

typedef struct _LDR_DATA_TABLE_ENTRY  
{  
    LIST_ENTRY InLoadOrderLinks;  
    LIST_ENTRY InMemoryOrderLinks;  
    LIST_ENTRY InInitializationOrderLinks;  
    PVOID DllBase;  
    PVOID EntryPoint;  
    DWORD SizeOfImage;  
    UNICODE_STRING FullDllName;  
    UNICODE_STRING BaseDllName;  
    DWORD Flags;  
    WORD LoadCount;  
    WORD TlsIndex;  
    LIST_ENTRY HashLinks;  
    PVOID SectionPointer;  
    DWORD CheckSum;  
    DWORD TimeDateStamp;  
    PVOID LoadedImports;  
    PVOID EntryPointActivationContext;  
    PVOID PatchInformation;  
}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;  

其中,InLoadOrderModuleList(xp下第一个结点XXX.exe 第二个是ntdll.dll, win7:ntdll.dll,kernel32.dll)、InMemoryOrderModuleList(1.xx.exe 2.ntdll.dll win7:xx.exe,ntdll.dll)、InInitializationOrderModuleList(xp下第一个结点一般是ntdll.dll,第二个是 kernel32.dll win7:ntdll,kernelbase.dll)就是进程当前已加载模块的链表,只是按照不同的方式排序。EnumProcessModules是通过InMemoryOrderModuleList链表枚举的,而根据Win2k代码,ToolHelp32函数是通过InLoadOrderModuleList枚举。这三个_LIST_ENTRY都是在一个RTL_PROCESS_MODULE_INFORMATION结构中的成员。这个结构在2k代码中有引用,不过没有确切的定义
typedef struct _PEB  
{  
    UCHAR InheritedAddressSpace;  
    UCHAR ReadImageFileExecOptions;  
    UCHAR BeingDebugged;  
    UCHAR SpareBool;  
    PVOID Mutant;  
    PVOID ImageBaseAddress;  
    PPEB_LDR_DATA Ldr;
    //......  
}PEB,*PPEB;  

int main(void)  
{  
    PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;  
    PLIST_ENTRY pListEntryStart = NULL,pListEntryEnd = NULL;  
    PPEB_LDR_DATA pPebLdrData = NULL;  
    PPEB pPeb = NULL;  

    //故意加载一些DLL,以便测试!  
    LoadLibrary("ResLibDemo");  
    __asm  
    {  
        //1、通过fs:[30h]获取当前进程的_PEB结构  
        mov eax,dword ptr fs:[30h];  
        mov pPeb,eax  
    }  

    //2、通过_PEB的Ldr成员获取_PEB_LDR_DATA结构  
    pPebLdrData = pPeb->Ldr;  

    //3、通过_PEB_LDR_DATA的InMemoryOrderModuleList成员获取_LIST_ENTRY结构  
    pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;  

    //查找所有已载入到内存中的模块  
    do  
    {  
        //4、通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构  
        pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY,InMemoryOrderLinks);  

        //5、输出_LDR_DATA_TABLE_ENTRY的BaseDllName或FullDllName成员信息  
        printf("%S/n",pLdrDataEntry->BaseDllName.Buffer);  

        pListEntryStart = pListEntryStart->Flink;  

    }while(pListEntryStart != pListEntryEnd);  
}  

/* 
output: 
EnumInLoadModule.exe 
ntdll.dll 
kernel32.dll 
ResLibDemo.dll 
... 

*/

 

typedef struct _LDR_DATA_TABLE_ENTRY
 {
    
     LIST_ENTRY InLoadOrderLinks;
     LIST_ENTRY InMemoryOrderLinks;
     LIST_ENTRY InInitializationOrderLinks;
     PVOID DllBase;
     PVOID EntryPoint;
     ULONG SizeOfImage;
     UNICODE_STRING FullDllName;
     UNICODE_STRING BaseDllName;
     ULONG Flags;
     USHORT LoadCount;
     USHORT TlsIndex;
     union
     {  
         LIST_ENTRY HashLinks;
         struct
         {
             PVOID SectionPointer;
             ULONG CheckSum;
         };
     };
     ULONG TimeDateStamp;
    
 } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

 

///

 xp下

0:000> dt _peb 7ffde000
ntdll!_PEB
   +0x000 InheritedAddressSpace : 0 ''
   +0x001 ReadImageFileExecOptions : 0 ''
   +0x002 BeingDebugged    : 0x1 ''
   +0x003 SpareBool        : 0 ''
   +0x004 Mutant           : 0xffffffff
   +0x008 ImageBaseAddress : 0x00400000
   +0x00c Ldr              : 0x00251ea0 _PEB_LDR_DATA
   +0x010 ProcessParameters : 0x00020000 _RTL_USER_PROCESS_PARAMETERS
   +0x014 SubSystemData    : (null)
   +0x018 ProcessHeap      : 0x00150000
   +0x01c FastPebLock      : 0x7c9a0620 _RTL_CRITICAL_SECTION
   +0x020 FastPebLockRoutine : 0x7c921000
   +0x024 FastPebUnlockRoutine : 0x7c9210e0
   +0x028 EnvironmentUpdateCount : 1
   //.............

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 - 0x252a80 ]             //下面用到,指向一个 _LDR_DATA_TABLE_ENTRY的首地址
   +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x251ee8 - 0x252a88 ]       //下面用到,指向一个 _LDR_DATA_TABLE_ENTRY的InMemoryOrderLinks地址
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x251f58 - 0x2529d0 ]  //下面用到,指向一个 _LDR_DATA_TABLE_ENTRY的InInitializationOrderLinks地址
   +0x024 EntryInProgress  : (null)
0:000> dt _LDR_DATA_TABLE_ENTRY 0x251ee0
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x251f48 - 0x251eac ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x251f50 - 0x251eb4 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x018 DllBase          : 0x00400000
   +0x01c EntryPoint       : 0x00415667
   +0x020 SizeOfImage      : 0x88000
   +0x024 FullDllName      : _UNICODE_STRING "C:Documents and SettingsAdministrator桌面Dbgview.exe"
   +0x02c BaseDllName      : _UNICODE_STRING "Dbgview.exe"
   +0x034 Flags            : 0x5000
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x7c99e298 - 0x7c99e298 ]
   +0x03c SectionPointer   : 0x7c99e298
   +0x040 CheckSum         : 0x7c99e298
   +0x044 TimeDateStamp    : 0x4ddfd5aa
   +0x044 LoadedImports    : 0x4ddfd5aa
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
0:000> dt _LDR_DATA_TABLE_ENTRY 0x251f48
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
   +0x01c EntryPoint       : 0x7c9320f8
   +0x020 SizeOfImage      : 0x96000
   +0x024 FullDllName      : _UNICODE_STRING "C:WINDOWSsystem32ntdll.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "ntdll.dll"
   +0x034 Flags            : 0x85004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x7c99e2e8 - 0x7c99e2e8 ]
   +0x03c SectionPointer   : 0x7c99e2e8
   +0x040 CheckSum         : 0x7c99e2e8
   +0x044 TimeDateStamp    : 0x4d00f280
   +0x044 LoadedImports    : 0x4d00f280
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
0:000> dt _LDR_DATA_TABLE_ENTRY 0x251ee8-0x8  //(计算根据偏移得到首地址)
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x251f48 - 0x251eac ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x251f50 - 0x251eb4 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x018 DllBase          : 0x00400000
   +0x01c EntryPoint       : 0x00415667
   +0x020 SizeOfImage      : 0x88000
   +0x024 FullDllName      : _UNICODE_STRING "C:Documents and SettingsAdministrator桌面Dbgview.exe"
   +0x02c BaseDllName      : _UNICODE_STRING "Dbgview.exe"
   +0x034 Flags            : 0x5000
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x7c99e298 - 0x7c99e298 ]
   +0x03c SectionPointer   : 0x7c99e298
   +0x040 CheckSum         : 0x7c99e298
   +0x044 TimeDateStamp    : 0x4ddfd5aa
   +0x044 LoadedImports    : 0x4ddfd5aa
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)

0:000> dt _LDR_DATA_TABLE_ENTRY 0x251f50-0x8 //(计算根据偏移得到首地址)
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
   +0x01c EntryPoint       : 0x7c9320f8
   +0x020 SizeOfImage      : 0x96000
   +0x024 FullDllName      : _UNICODE_STRING "C:WINDOWSsystem32ntdll.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "ntdll.dll"
   +0x034 Flags            : 0x85004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x7c99e2e8 - 0x7c99e2e8 ]
   +0x03c SectionPointer   : 0x7c99e2e8
   +0x040 CheckSum         : 0x7c99e2e8
   +0x044 TimeDateStamp    : 0x4d00f280
   +0x044 LoadedImports    : 0x4d00f280
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
0:000> dt _LDR_DATA_TABLE_ENTRY 0x251f58-0x10
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
   +0x01c EntryPoint       : 0x7c9320f8
   +0x020 SizeOfImage      : 0x96000
   +0x024 FullDllName      : _UNICODE_STRING "C:WINDOWSsystem32ntdll.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "ntdll.dll"
   +0x034 Flags            : 0x85004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x7c99e2e8 - 0x7c99e2e8 ]
   +0x03c SectionPointer   : 0x7c99e2e8
   +0x040 CheckSum         : 0x7c99e2e8
   +0x044 TimeDateStamp    : 0x4d00f280
   +0x044 LoadedImports    : 0x4d00f280
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
0:000> dt _LDR_DATA_TABLE_ENTRY 0x252020-0x10
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x2520d0 - 0x251f48 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x2520d8 - 0x251f50 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x252328 - 0x251f58 ]
   +0x018 DllBase          : 0x7c800000
   +0x01c EntryPoint       : 0x7c80b64e
   +0x020 SizeOfImage      : 0x11e000
   +0x024 FullDllName      : _UNICODE_STRING "C:WINDOWSsystem32kernel32.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "kernel32.dll"
   +0x034 Flags            : 0x85004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x7c99e2d0 - 0x7c99e2d0 ]
   +0x03c SectionPointer   : 0x7c99e2d0
   +0x040 CheckSum         : 0x7c99e2d0
   +0x044 TimeDateStamp    : 0x506bc5dd
   +0x044 LoadedImports    : 0x506bc5dd
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)


 

///

 

win7下 上面windbg 手工方式一样,只是运行结果略有一同,下面给出程序 实现的方式。

VOID GetPebModule()
{
	PBYTE pPeb;
	PPEB_LDR_DATA pLdr , tttt;
	PLDR_DATA_TABLE_ENTRY pLdrData;

	__asm
	{
		MOV EAX, FS:[0x18]
		MOV EAX, [EAX + 0x30]

		MOV pPeb, EAX  
	}

	pLdr = (PPEB_LDR_DATA)(*(DWORD*)(pPeb + 0x0C));

	tttt = pLdr;

	printf("nInLoadOrderModuleList:n");

	pLdrData = (PLDR_DATA_TABLE_ENTRY)pLdr->InLoadOrderModuleList.Flink;

	for ( ; (pLdr->InLoadOrderModuleList.Flink) != (pLdrData->InLoadOrderLinks.Flink); )
	{
		wprintf(L"%srn", (pLdrData->FullDllName.Buffer));
		wprintf(L"%srn", (pLdrData->BaseDllName.Buffer));
		pLdrData = (PLDR_DATA_TABLE_ENTRY)(pLdrData->InLoadOrderLinks.Flink);
	}


	printf("nnInInitializationOrderModuleList:n");

	pLdr = tttt;

	pLdrData = (PLDR_DATA_TABLE_ENTRY)CONTAINING__RECORD(tttt->InInitializationOrderModuleList.Flink, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);

	for ( ; (tttt->InInitializationOrderModuleList.Flink) != (pLdrData->InInitializationOrderLinks.Flink); )
	{
		wprintf(L"%srn", (pLdrData->FullDllName.Buffer));
		wprintf(L"%srn", (pLdrData->BaseDllName.Buffer));
		pLdrData = (PLDR_DATA_TABLE_ENTRY)CONTAINING__RECORD(pLdrData->InInitializationOrderLinks.Flink, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);

	}

	printf("nnInMemoryOrderModuleList:n");
	pLdrData = (PLDR_DATA_TABLE_ENTRY)CONTAINING__RECORD(pLdr->InMemoryOrderModuleList.Flink, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

	for ( ; (pLdr->InMemoryOrderModuleList.Flink) != (pLdrData->InMemoryOrderLinks.Flink); )
	{
		wprintf(L"%srn", (pLdrData->FullDllName.Buffer));
		wprintf(L"%srn", (pLdrData->BaseDllName.Buffer));
		pLdrData = (PLDR_DATA_TABLE_ENTRY)CONTAINING__RECORD(pLdrData->InMemoryOrderLinks.Flink, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

	}

	return ;
}


/*

输出:

nInLoadOrderModuleList:

C:WindowsSYSTEM32ntdll.dll
ntdll.dll
C:Windowssystem32kernel32.dll
kernel32.dll
C:Windowssystem32KERNELBASE.dll
KERNELBASE.dll

 

InInitializationOrderModuleList:
C:WindowsSYSTEM32ntdll.dll
ntdll.dll
C:Windowssystem32KERNELBASE.dll
KERNELBASE.dll
C:Windowssystem32kernel32.dll
kernel32.dll

 

InMemoryOrderModuleList:
d:DesktopHsdaosUIHsdaostrunkBinVstest.exe
Vstest.exe
C:WindowsSYSTEM32ntdll.dll
ntdll.dll
C:Windowssystem32kernel32.dll
kernel32.dll
C:Windowssystem32KERNELBASE.dll
KERNELBASE.dll

*/

  ///

用shellcode获取Kernel32基地址的几种方法

 

win7下

 __asm
 {
  push    eax
  mov     eax, fs:[30h]  //PEB 址,  mov  eax, fs:[18h] 这个获得TEB地址
  mov     eax, [eax + 0Ch]
  mov     eax, [eax + 1Ch]
  mov     eax, [eax]
  mov     eax, [eax]
  mov     eax, [eax + 8]
  mov   hModule, eax
  pop     eax
 }

 

mov eax, fs:[0] //为_EXCEPTION_REGISTRATION_RECORD的地址,exceptionList

 

 __asm
 {
  push    eax
  mov     eax, fs:[18h] //TEB地址

  mov     eax, [eax + 30h ] //PEB地址
  mov     eax, [eax + 0Ch]
  mov     eax, [eax + 1Ch]
  mov     eax, [eax]
  mov     eax, [eax]
  mov     eax, [eax + 8]
  mov   hModule, eax
  pop     eax
 }

 

 

XP 下

 __asm
 {
  push    eax
  mov     eax, fs:[30h]
  mov     eax, [eax + 0Ch]
  mov     eax, [eax + 1Ch]
  mov     eax, [eax]
  mov     eax, [eax + 8]
  mov   hModule, eax
  pop     eax
 }

 

 

1、CreateProcess函数在完成装载应用程序后,会先将一个返回地址压入到堆栈顶端,而这个返回地址恰好在Kernel32.dll中,利用这个原理我们可以顺着这个返回地址按64KB大小往地址搜索,那么我们一定可以找到Kernel32模块的基地址,废话少说,代码如下:

GetK32Base:
    mov eax, [esp+04h]     ;得到kernel32的返回地址
    and eax, ffff0000h
Search:
    cmp WORD ptr [eax], IMAGE_DOS_SIGNATURE   ;判断是否为ImageBase
    jnz @f
    mov edx, [eax+3ch]
    add edx, eax
    cmp WORD ptr [edx], IMAGE_NT_SIGNATURE   ;判断是否为PE头
    jnz @f
    ret
@@:
    dec eax     ;按64KB递减搜索
    xor ax, ax
    cmp eax, 70000000h
    ja Search
    ret

2、通过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]     ;指向下一个节点
mov eax,[eax+18h]    ;Kernel.dll的基地址   
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+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


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

最后

以上就是危机秋天为你收集整理的获取Kernel32基地址的几种方法-相关结构的全部内容,希望文章能够帮你解决获取Kernel32基地址的几种方法-相关结构所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(29)

评论列表共有 0 条评论

立即
投稿
返回
顶部