获取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系统)
*/
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手工方式一样,只是运行结果略有一同,下面给出程序实现的方式。
/*
输出:
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
结束语:技术可以做正义的事,也可以做邪恶的事,关键是看什么人掌握这些技术
_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
结束语:技术可以做正义的事,也可以做邪恶的事,关键是看什么人掌握这些技术
相关文章推荐
- 获取JAVA[WEB]项目相关路径的几种方法
- 获取JAVA[WEB]项目相关路径的几种方法
- [转]获取JAVA[WEB]项目相关路径的几种方法
- 获取JAVA[WEB]项目相关路径的几种方法(转载)
- 获取JAVA[WEB]项目相关路径的几种方法
- 获取Kernel32基地址的几种方法
- mybatis中获取SqlSessionFactory的几种方法及其相关使用
- 转:获取JAVA[WEB]项目相关路径的几种方法
- 获取JAVA项目相关路径的几种方法
- 获取Kernel32基地址的几种方法
- 获取JAVA[WEB]项目相关路径的几种方法
- 获取JAVA[WEB]项目相关路径的几种方法
- 获取JAVA[WEB]项目相关路径的几种方法
- 获取JAVA[WEB]项目相关路径的几种方法
- 获取JAVA[WEB]项目相关路径的几种方法
- 获取Kernel32基地址的几种方法
- 获取客户端网卡MAC地址的几种方法
- C#基于OLEDB获取Excel文件表结构信息的方法
- spring获取webapplicationcontext,applicationcontext几种方法详解
- 获取SQL Server元数据的几种方法