您的位置:首页 > 其它

获取Kernel32基地址的几种方法-相关结构

2013-04-01 17:20 337 查看
一、几个重要的数据结构,可以通过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成员信息。

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


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

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

typedefstruct_UNICODE_STRING{
USHORTLength;
USHORTMaximumLength;
PWSTRBuffer;
}UNICODE_STRING,*PUNICODE_STRING;

typedefstruct_PEB_LDR_DATA
{
DWORDLength;
UCHARInitialized;
PVOIDSsHandle;
LIST_ENTRYInLoadOrderModuleList;
LIST_ENTRYInMemoryOrderModuleList;
LIST_ENTRYInInitializationOrderModuleList;
PVOIDEntryInProgress;
}PEB_LDR_DATA,*PPEB_LDR_DATA;

typedefstruct_LDR_DATA_TABLE_ENTRY
{
LIST_ENTRYInLoadOrderLinks;
LIST_ENTRYInMemoryOrderLinks;
LIST_ENTRYInInitializationOrderLinks;
PVOIDDllBase;
PVOIDEntryPoint;
DWORDSizeOfImage;
UNICODE_STRINGFullDllName;
UNICODE_STRINGBaseDllName;
DWORDFlags;
WORDLoadCount;
WORDTlsIndex;
LIST_ENTRYHashLinks;
PVOIDSectionPointer;
DWORDCheckSum;
DWORDTimeDateStamp;
PVOIDLoadedImports;
PVOIDEntryPointActivationContext;
PVOIDPatchInformation;
}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;

其中,InLoadOrderModuleList(xp下第一个结点XXX.exe第二个是ntdll.dll,win7:ntdll.dll,kernel32.dll)、InMemoryOrderModuleList(1.xx.exe2.ntdll.dllwin7:xx.exe,ntdll.dll)、InInitializationOrderModuleList(xp下第一个结点一般是ntdll.dll,第二个是kernel32.dllwin7:ntdll,kernelbase.dll)就是进程当前已加载模块的链表,只是按照不同的方式排序。EnumProcessModules是通过InMemoryOrderModuleList链表枚举的,而根据Win2k代码,ToolHelp32函数是通过InLoadOrderModuleList枚举。这三个_LIST_ENTRY都是在一个RTL_PROCESS_MODULE_INFORMATION结构中的成员。这个结构在2k代码中有引用,不过没有确切的定义

typedefstruct_PEB
{
UCHARInheritedAddressSpace;
UCHARReadImageFileExecOptions;
UCHARBeingDebugged;
UCHARSpareBool;
PVOIDMutant;
PVOIDImageBaseAddress;
PPEB_LDR_DATALdr;

//......
}PEB,*PPEB;

intmain(void)
{
PLDR_DATA_TABLE_ENTRYpLdrDataEntry=NULL;
PLIST_ENTRYpListEntryStart=NULL,pListEntryEnd=NULL;
PPEB_LDR_DATApPebLdrData=NULL;
PPEBpPeb=NULL;

//故意加载一些DLL,以便测试!
LoadLibrary("ResLibDemo");
__asm
{
//1、通过fs:[30h]获取当前进程的_PEB结构
moveax,dwordptrfs:[30h];
movpPeb,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
...


*/

typedefstruct_LDR_DATA_TABLE_ENTRY

{

LIST_ENTRYInLoadOrderLinks;

LIST_ENTRYInMemoryOrderLinks;

LIST_ENTRYInInitializationOrderLinks;

PVOIDDllBase;

PVOIDEntryPoint;

ULONGSizeOfImage;

UNICODE_STRINGFullDllName;

UNICODE_STRINGBaseDllName;

ULONGFlags;

USHORTLoadCount;

USHORTTlsIndex;

union

{

LIST_ENTRYHashLinks;

struct

{

PVOIDSectionPointer;

ULONGCheckSum;

};

};

ULONGTimeDateStamp;

}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

xp下

0:000>dt_peb7ffde000

ntdll!_PEB

+0x000InheritedAddressSpace:0''

+0x001ReadImageFileExecOptions:0''

+0x002BeingDebugged:0x1''

+0x003SpareBool:0''

+0x004Mutant:0xffffffff

+0x008ImageBaseAddress:0x00400000

+0x00cLdr:0x00251ea0_PEB_LDR_DATA

+0x010ProcessParameters:0x00020000_RTL_USER_PROCESS_PARAMETERS

+0x014SubSystemData:(null)

+0x018ProcessHeap:0x00150000

+0x01cFastPebLock:0x7c9a0620_RTL_CRITICAL_SECTION

+0x020FastPebLockRoutine:0x7c921000

+0x024FastPebUnlockRoutine:0x7c9210e0

+0x028EnvironmentUpdateCount:1

//.............

0:000>dt_PEB_LDR_DATA0x00251ea0

ntdll!_PEB_LDR_DATA

+0x000Length:0x28

+0x004Initialized:0x1''

+0x008SsHandle:(null)

+0x00cInLoadOrderModuleList:_LIST_ENTRY[0x251ee0
-0x252a80]//下面用到,指向一个_LDR_DATA_TABLE_ENTRY的首地址

+0x014InMemoryOrderModuleList:_LIST_ENTRY[0x251ee8-0x252a88]//下面用到,指向一个_LDR_DATA_TABLE_ENTRY的InMemoryOrderLinks地址

+0x01cInInitializationOrderModuleList:_LIST_ENTRY[
0x251f58-0x2529d0]//下面用到,指向一个_LDR_DATA_TABLE_ENTRY的InInitializationOrderLinks地址

+0x024EntryInProgress:(null)

0:000>dt_LDR_DATA_TABLE_ENTRY0x251ee0

ntdll!_LDR_DATA_TABLE_ENTRY

+0x000InLoadOrderLinks:_LIST_ENTRY[0x251f48-0x251eac]

+0x008InMemoryOrderLinks:_LIST_ENTRY[0x251f50-0x251eb4]

+0x010InInitializationOrderLinks:_LIST_ENTRY[0x0-0x0]

+0x018DllBase:0x00400000

+0x01cEntryPoint:0x00415667

+0x020SizeOfImage:0x88000

+0x024FullDllName:_UNICODE_STRING"C:\DocumentsandSettings\Administrator\桌面\Dbgview.exe"

+0x02cBaseDllName:_UNICODE_STRING"Dbgview.exe"

+0x034Flags:0x5000

+0x038LoadCount:0xffff

+0x03aTlsIndex:0

+0x03cHashLinks:_LIST_ENTRY[0x7c99e298-0x7c99e298]

+0x03cSectionPointer:0x7c99e298

+0x040CheckSum:0x7c99e298

+0x044TimeDateStamp:0x4ddfd5aa

+0x044LoadedImports:0x4ddfd5aa

+0x048EntryPointActivationContext:(null)

+0x04cPatchInformation:(null)

0:000>dt_LDR_DATA_TABLE_ENTRY0x251f48

ntdll!_LDR_DATA_TABLE_ENTRY

+0x000InLoadOrderLinks:_LIST_ENTRY[0x252010-0x251ee0]

+0x008InMemoryOrderLinks:_LIST_ENTRY[0x252018-0x251ee8]

+0x010InInitializationOrderLinks:_LIST_ENTRY[0x252020-0x251ebc]

+0x018DllBase:0x7c920000

+0x01cEntryPoint:0x7c9320f8

+0x020SizeOfImage:0x96000

+0x024FullDllName:_UNICODE_STRING"C:\WINDOWS\system32\ntdll.dll"

+0x02cBaseDllName:_UNICODE_STRING"ntdll.dll"

+0x034Flags:0x85004

+0x038LoadCount:0xffff

+0x03aTlsIndex:0

+0x03cHashLinks:_LIST_ENTRY[0x7c99e2e8-0x7c99e2e8]

+0x03cSectionPointer:0x7c99e2e8

+0x040CheckSum:0x7c99e2e8

+0x044TimeDateStamp:0x4d00f280

+0x044LoadedImports:0x4d00f280

+0x048EntryPointActivationContext:(null)

+0x04cPatchInformation:(null)

0:000>dt_LDR_DATA_TABLE_ENTRY
0x251ee8-0x8//(计算根据偏移得到首地址)

ntdll!_LDR_DATA_TABLE_ENTRY

+0x000InLoadOrderLinks:_LIST_ENTRY[0x251f48-0x251eac]

+0x008InMemoryOrderLinks:_LIST_ENTRY[0x251f50-0x251eb4]

+0x010InInitializationOrderLinks:_LIST_ENTRY[0x0-0x0]

+0x018DllBase:0x00400000

+0x01cEntryPoint:0x00415667

+0x020SizeOfImage:0x88000

+0x024FullDllName:_UNICODE_STRING"C:\DocumentsandSettings\Administrator\桌面\Dbgview.exe"

+0x02cBaseDllName:_UNICODE_STRING"Dbgview.exe"

+0x034Flags:0x5000

+0x038LoadCount:0xffff

+0x03aTlsIndex:0

+0x03cHashLinks:_LIST_ENTRY[0x7c99e298-0x7c99e298]

+0x03cSectionPointer:0x7c99e298

+0x040CheckSum:0x7c99e298

+0x044TimeDateStamp:0x4ddfd5aa

+0x044LoadedImports:0x4ddfd5aa

+0x048EntryPointActivationContext:(null)

+0x04cPatchInformation:(null)

0:000>dt_LDR_DATA_TABLE_ENTRY0x251f50-0x8
//(计算根据偏移得到首地址)

ntdll!_LDR_DATA_TABLE_ENTRY

+0x000InLoadOrderLinks:_LIST_ENTRY[0x252010-0x251ee0]

+0x008InMemoryOrderLinks:_LIST_ENTRY[0x252018-0x251ee8]

+0x010InInitializationOrderLinks:_LIST_ENTRY[0x252020-0x251ebc]

+0x018DllBase:0x7c920000

+0x01cEntryPoint:0x7c9320f8

+0x020SizeOfImage:0x96000

+0x024FullDllName:_UNICODE_STRING"C:\WINDOWS\system32\ntdll.dll"

+0x02cBaseDllName:_UNICODE_STRING"ntdll.dll"

+0x034Flags:0x85004

+0x038LoadCount:0xffff

+0x03aTlsIndex:0

+0x03cHashLinks:_LIST_ENTRY[0x7c99e2e8-0x7c99e2e8]

+0x03cSectionPointer:0x7c99e2e8

+0x040CheckSum:0x7c99e2e8

+0x044TimeDateStamp:0x4d00f280

+0x044LoadedImports:0x4d00f280

+0x048EntryPointActivationContext:(null)

+0x04cPatchInformation:(null)

0:000>dt_LDR_DATA_TABLE_ENTRY0x251f58-0x10

ntdll!_LDR_DATA_TABLE_ENTRY

+0x000InLoadOrderLinks:_LIST_ENTRY[0x252010-0x251ee0]

+0x008InMemoryOrderLinks:_LIST_ENTRY[0x252018-0x251ee8]

+0x010InInitializationOrderLinks:_LIST_ENTRY[0x252020-0x251ebc]

+0x018DllBase:0x7c920000

+0x01cEntryPoint:0x7c9320f8

+0x020SizeOfImage:0x96000

+0x024FullDllName:_UNICODE_STRING"C:\WINDOWS\system32\ntdll.dll"

+0x02cBaseDllName:_UNICODE_STRING"ntdll.dll"

+0x034Flags:0x85004

+0x038LoadCount:0xffff

+0x03aTlsIndex:0

+0x03cHashLinks:_LIST_ENTRY[0x7c99e2e8-0x7c99e2e8]

+0x03cSectionPointer:0x7c99e2e8

+0x040CheckSum:0x7c99e2e8

+0x044TimeDateStamp:0x4d00f280

+0x044LoadedImports:0x4d00f280

+0x048EntryPointActivationContext:(null)

+0x04cPatchInformation:(null)

0:000>dt_LDR_DATA_TABLE_ENTRY0x252020-0x10

ntdll!_LDR_DATA_TABLE_ENTRY

+0x000InLoadOrderLinks:_LIST_ENTRY[0x2520d0-0x251f48]

+0x008InMemoryOrderLinks:_LIST_ENTRY[0x2520d8-0x251f50]

+0x010InInitializationOrderLinks:_LIST_ENTRY[0x252328-0x251f58]

+0x018DllBase:0x7c800000

+0x01cEntryPoint:0x7c80b64e

+0x020SizeOfImage:0x11e000

+0x024FullDllName:_UNICODE_STRING"C:\WINDOWS\system32\kernel32.dll"

+0x02cBaseDllName:_UNICODE_STRING"kernel32.dll"

+0x034Flags:0x85004

+0x038LoadCount:0xffff

+0x03aTlsIndex:0

+0x03cHashLinks:_LIST_ENTRY[0x7c99e2d0-0x7c99e2d0]

+0x03cSectionPointer:0x7c99e2d0

+0x040CheckSum:0x7c99e2d0

+0x044TimeDateStamp:0x506bc5dd

+0x044LoadedImports:0x506bc5dd

+0x048EntryPointActivationContext:(null)

+0x04cPatchInformation:(null)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

VOIDGetPebModule()
{
PBYTEpPeb;
PPEB_LDR_DATApLdr,tttt;
PLDR_DATA_TABLE_ENTRYpLdrData;

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

MOVpPeb,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"%s\r\n",(pLdrData->FullDllName.Buffer));
wprintf(L"%s\r\n",(pLdrData->BaseDllName.Buffer));
pLdrData=(PLDR_DATA_TABLE_ENTRY)(pLdrData->InLoadOrderLinks.Flink);
}

printf("\n\nInInitializationOrderModuleList:\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"%s\r\n",(pLdrData->FullDllName.Buffer));
wprintf(L"%s\r\n",(pLdrData->BaseDllName.Buffer));
pLdrData=(PLDR_DATA_TABLE_ENTRY)CONTAINING__RECORD(pLdrData->InInitializationOrderLinks.Flink,LDR_DATA_TABLE_ENTRY,InInitializationOrderLinks);

}

printf("\n\nInMemoryOrderModuleList:\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"%s\r\n",(pLdrData->FullDllName.Buffer));
wprintf(L"%s\r\n",(pLdrData->BaseDllName.Buffer));
pLdrData=(PLDR_DATA_TABLE_ENTRY)CONTAINING__RECORD(pLdrData->InMemoryOrderLinks.Flink,LDR_DATA_TABLE_ENTRY,InMemoryOrderLinks);

}

return;
}


/*

输出:

nInLoadOrderModuleList:

C:\Windows\SYSTEM32\ntdll.dll

ntdll.dll

C:\Windows\system32\kernel32.dll

kernel32.dll

C:\Windows\system32\KERNELBASE.dll

KERNELBASE.dll

InInitializationOrderModuleList:

C:\Windows\SYSTEM32\ntdll.dll

ntdll.dll

C:\Windows\system32\KERNELBASE.dll

KERNELBASE.dll

C:\Windows\system32\kernel32.dll

kernel32.dll

InMemoryOrderModuleList:

d:\Desktop\HsdaosUI\Hsdaos\trunk\Bin\Vstest.exe

Vstest.exe

C:\Windows\SYSTEM32\ntdll.dll

ntdll.dll

C:\Windows\system32\kernel32.dll

kernel32.dll

C:\Windows\system32\KERNELBASE.dll

KERNELBASE.dll

*/

///////////////////////////////////////////////////////////////////////////////////////////////////

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

win7下

__asm

{

pusheax

moveax,fs:[30h]//PEB址,moveax,fs:[18h]这个获得TEB地址

moveax,[eax+0Ch]

moveax,[eax+1Ch]

moveax,[eax]

moveax,[eax]

moveax,[eax+8]

movhModule,eax

popeax

}

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

__asm

{

pusheax

moveax,fs:[18h]//TEB地址

moveax,[eax+30h]//PEB地址

moveax,[eax+0Ch]

moveax,[eax+1Ch]

moveax,[eax]

moveax,[eax]

moveax,[eax+8]

movhModule,eax

popeax

}

XP下

__asm

{

pusheax

moveax,fs:[30h]

moveax,[eax+0Ch]

moveax,[eax+1Ch]

moveax,[eax]

moveax,[eax+8]

movhModule,eax

popeax

}

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

GetK32Base:

moveax,[esp+04h];得到kernel32的返回地址

andeax,ffff0000h

Search:

cmpWORDptr[eax],IMAGE_DOS_SIGNATURE;判断是否为ImageBase

jnz@f

movedx,[eax+3ch]

addedx,eax

cmpWORDptr[edx],IMAGE_NT_SIGNATURE;判断是否为PE头

jnz@f

ret

@@:

deceax;按64KB递减搜索

xorax,ax

cmpeax,70000000h

jaSearch

ret

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

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

typedefstruct_LDR_MODULE

{

LIST_ENTRYInLoadOrderModuleList;//+0x00

LIST_ENTRYInMemoryOrderModuleList;//+0x08

LIST_ENTRYInInitializationOrderModuleList;//+0x10

PVOIDBaseAddress;//+0x18

PVOIDEntryPoint;//+0x1c

ULONGSizeOfImage;//+0x20

UNICODE_STRINGFullDllName;//+0x24

UNICODE_STRINGBaseDllName;//+0x2c

ULONGFlags;//+0x34

SHORTLoadCount;//+0x38

SHORTTlsIndex;//+0x3a

LIST_ENTRYHashTableEntry;//+0x3c

ULONGTimeDateStamp;//+0x44

//+0x48

}LDR_MODULE,*PLDR_MODULE;

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

+0x00cLdr:Ptr32tostruct_PEB_LDR_DATA,7elements,0x28bytes

+0x000Length:Uint4B

+0x004Initialized:UChar

+0x008SsHandle:Ptr32toVoid

+0x00cInLoadOrderModuleList:struct_LIST_ENTRY,2elements,0x8bytes

+0x000Flink:Ptr32tostruct_LIST_ENTRY,2elements,0x8bytes

+0x004Blink:Ptr32tostruct_LIST_ENTRY,2elements,0x8bytes

+0x014InMemoryOrderModuleList:struct_LIST_ENTRY,2elements,0x8bytes

+0x000Flink:Ptr32tostruct_LIST_ENTRY,2elements,0x8bytes

+0x004Blink:Ptr32tostruct_LIST_ENTRY,2elements,0x8bytes

+0x01cInInitializationOrderModuleList:struct_LIST_ENTRY,2elements,0x8bytes

+0x000Flink:Ptr32tostruct_LIST_ENTRY,2elements,0x8bytes

+0x004Blink:Ptr32tostruct_LIST_ENTRY,2elements,0x8bytes

+0x024EntryInProgress:Ptr32toVoid

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

1)加载顺序的方式:

GetK32Base:

assumefs:nothing

pushesi

xoreax,eax

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

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

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

lodsd

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

moveax,[eax+18h];Kernel.dll的基地址

popesi

ret

2)内存顺序的方式:

GetK32Base:

assumefs:nothing

pushesi

xoreax,eax

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

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

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

lodsd

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

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

popesi

ret

3)初始化顺序的方式:

GetK32Base:

assumefs:nothing

pushesi

xoreax,eax

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

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

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

lodsd

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

popesi

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_TIBSTRUCT

ExceptionListdd?

StackBasedd?

StackLimitdd?

SubSystemTibdd?

union

FiberDatadd?

Versiondd?

ends

ArbitraryUserPointerdd?

Selfdd?

NT_TIBENDS

EXCEPTION_REGISTRATIONSTRUCT

prevdd?;前一个EXCEPTION_REGISTRATION结构的地址

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

EXCEPTION_REGISTRATIONends

GetK32Base:

assumefs:nothing

xoresi,esi

movesi,fs:[esi]

lodsd

@@:

inceax

jz@f

deceax

xchgesi,eax

lodsd

jmp@b

@@:

lodsd

@@:

deceax

xorax,ax

cmpDWORDptr[eax],5A4D

jnz@b

ret

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