题外话:上一篇文章中的 PEB法查找kerner32地址的方法 对TEB、PEB 、PE结构 知识要求很高,确实在写汇编代码时候小编
感觉自己能力,信手啪啪一顿乱撸,结果一运行,非法访问了,没办法翻阅前人的文章,贴来,但是,感到很羞愧,故有此文章
对 此过程 ,认真学习、分析下
正题:
TEB结构
//
// Thread Environment Block (TEB)
//
typedef struct _TEB
{
NT_TIB Tib; /* 00h */
PVOID EnvironmentPointer; /* 1Ch */
CLIENT_ID Cid; /* 20h */
PVOID ActiveRpcHandle; /* 28h */
PVOID ThreadLocalStoragePointer; /* 2Ch */
struct _PEB *ProcessEnvironmentBlock; /* 30h */
ULONG LastErrorValue; /* 34h */
ULONG CountOfOwnedCriticalSections; /* 38h */
PVOID CsrClientThread; /* 3Ch */
struct _W32THREAD* Win32ThreadInfo; /* 40h */
ULONG User32Reserved[0x1A]; /* 44h */
ULONG UserReserved[]; /* ACh */
PVOID WOW32Reserved; /* C0h */
LCID CurrentLocale; /* C4h */
ULONG FpSoftwareStatusRegister; /* C8h */
PVOID SystemReserved1[0x36]; /* CCh */
LONG ExceptionCode; /* 1A4h */
struct _ACTIVATION_CONTEXT_STACK *ActivationContextStackPointer; /* 1A8h */
UCHAR SpareBytes1[0x28]; /* 1ACh */
GDI_TEB_BATCH GdiTebBatch; /* 1D4h */
CLIENT_ID RealClientId; /* 6B4h */
PVOID GdiCachedProcessHandle; /* 6BCh */
ULONG GdiClientPID; /* 6C0h */
ULONG GdiClientTID; /* 6C4h */
PVOID GdiThreadLocalInfo; /* 6C8h */
ULONG Win32ClientInfo[]; /* 6CCh */
PVOID glDispatchTable[0xE9]; /* 7C4h */
ULONG glReserved1[0x1D]; /* B68h */
PVOID glReserved2; /* BDCh */
PVOID glSectionInfo; /* BE0h */
PVOID glSection; /* BE4h */
PVOID glTable; /* BE8h */
PVOID glCurrentRC; /* BECh */
PVOID glContext; /* BF0h */
NTSTATUS LastStatusValue; /* BF4h */
UNICODE_STRING StaticUnicodeString; /* BF8h */
WCHAR StaticUnicodeBuffer[0x105]; /* C00h */
PVOID DeallocationStack; /* E0Ch */
PVOID TlsSlots[0x40]; /* E10h */
LIST_ENTRY TlsLinks; /* F10h */
PVOID Vdm; /* F18h */
PVOID ReservedForNtRpc; /* F1Ch */
PVOID DbgSsReserved[0x2]; /* F20h */
ULONG HardErrorDisabled; /* F28h */
PVOID Instrumentation[]; /* F2Ch */
PVOID SubProcessTag; /* F64h */
PVOID EtwTraceData; /* F68h */
PVOID WinSockData; /* F6Ch */
ULONG GdiBatchCount; /* F70h */
BOOLEAN InDbgPrint; /* F74h */
BOOLEAN FreeStackOnTermination; /* F75h */
BOOLEAN HasFiberData; /* F76h */
UCHAR IdealProcessor; /* F77h */
ULONG GuaranteedStackBytes; /* F78h */
PVOID ReservedForPerf; /* F7Ch */
PVOID ReservedForOle; /* F80h */
ULONG WaitingOnLoaderLock; /* F84h */
ULONG SparePointer1; /* F88h */
ULONG SoftPatchPtr1; /* F8Ch */
ULONG SoftPatchPtr2; /* F90h */
PVOID *TlsExpansionSlots; /* F94h */
ULONG ImpersionationLocale; /* F98h */
ULONG IsImpersonating; /* F9Ch */
PVOID NlsCache; /* FA0h */
PVOID pShimData; /* FA4h */
ULONG HeapVirualAffinity; /* FA8h */
PVOID CurrentTransactionHandle; /* FACh */
PTEB_ACTIVE_FRAME ActiveFrame; /* FB0h */
PVOID FlsData; /* FB4h */
UCHAR SafeThunkCall; /* FB8h */
UCHAR BooleanSpare[]; /* FB9h */
} TEB, *PTEB;
PEB结构
typedef struct _PEB
{
UCHAR InheritedAddressSpace; // 00h
UCHAR ReadImageFileExecOptions; // 01h
UCHAR BeingDebugged; // 02h
UCHAR Spare; // 03h
PVOID Mutant; // 04h
PVOID ImageBaseAddress; // 08h
PPEB_LDR_DATA Ldr; // 0Ch
PRTL_USER_PROCESS_PARAMETERS ProcessParameters; // 10h
PVOID SubSystemData; // 14h
PVOID ProcessHeap; // 18h
PVOID FastPebLock; // 1Ch
PPEBLOCKROUTINE FastPebLockRoutine; // 20h
PPEBLOCKROUTINE FastPebUnlockRoutine; // 24h
ULONG EnvironmentUpdateCount; // 28h
PVOID* KernelCallbackTable; // 2Ch
PVOID EventLogSection; // 30h
PVOID EventLog; // 34h
PPEB_FREE_BLOCK FreeList; // 38h
ULONG TlsExpansionCounter; // 3Ch
PVOID TlsBitmap; // 40h
ULONG TlsBitmapBits[0x2]; // 44h
PVOID ReadOnlySharedMemoryBase; // 4Ch
PVOID ReadOnlySharedMemoryHeap; // 50h
PVOID* ReadOnlyStaticServerData; // 54h
PVOID AnsiCodePageData; // 58h
PVOID OemCodePageData; // 5Ch
PVOID UnicodeCaseTableData; // 60h
ULONG NumberOfProcessors; // 64h
ULONG NtGlobalFlag; // 68h
UCHAR Spare2[0x4]; // 6Ch
LARGE_INTEGER CriticalSectionTimeout; // 70h
ULONG HeapSegmentReserve; // 78h
ULONG HeapSegmentCommit; // 7Ch
ULONG HeapDeCommitTotalFreeThreshold; // 80h
ULONG HeapDeCommitFreeBlockThreshold; // 84h
ULONG NumberOfHeaps; // 88h
ULONG MaximumNumberOfHeaps; // 8Ch
PVOID** ProcessHeaps; // 90h
PVOID GdiSharedHandleTable; // 94h
PVOID ProcessStarterHelper; // 98h
PVOID GdiDCAttributeList; // 9Ch
PVOID LoaderLock; // A0h
ULONG OSMajorVersion; // A4h
ULONG OSMinorVersion; // A8h
ULONG OSBuildNumber; // ACh
ULONG OSPlatformId; // B0h
ULONG ImageSubSystem; // B4h
ULONG ImageSubSystemMajorVersion; // B8h
ULONG ImageSubSystemMinorVersion; // C0h
ULONG GdiHandleBuffer[0x22]; // C4h
PVOID ProcessWindowStation; // ???
} PEB, *PPEB;
typedef struct _PEB_LDR_DATA
{
ULONG Length; // +0x00
BOOLEAN Initialized; // +0x04
PVOID SsHandle; // +0x08
LIST_ENTRY InLoadOrderModuleList; // +0x0c
LIST_ENTRY InMemoryOrderModuleList; // +0x14
LIST_ENTRY InInitializationOrderModuleList;// +0x1c
} PEB_LDR_DATA,*PPEB_LDR_DATA; // +0x24
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
原理:在NT内核系统中fs寄存器指向TEB结构,TEB+0x30处指向PEB结构,PEB+0x0c处指向PEB_LDR_DATA结构,
PEB_LDR_DATA+0x1c处存放一些动态链接库地址,第一个指向ntdl.dll,第二个就是kernel32.dll的基地址了
// sty_teb_peb_ker32.cpp : Defines the entry point for the application.
// #include "stdafx.h" int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
_asm
{ mov eax, fs:[0x30] ;PEB的地址
mov eax, [eax + 0x0c] ;Ldr的地址
mov esi, [eax + 0x1c] ;Flink地址
lodsd
mov eax, [eax + 0x08] ;eax就是kernel32.dll的地址
}
return ;
}
以上代码生成exe,ollydby调试(我发现这种WinMain生成的exe 更容易发现入口)
当我们走到这一步时,数据窗上面的那个地方提示我们 FS:[0000030]=[7FFDF030]=7FFD5000
可以推测FS就在7FFDF000处,在数据窗体上Alt + G 弹出输入窗口,填入7ffdf000 回车
来到了7FFDF000地址,这就是传说中的TEB了,开头那个12FFB0应该是SEH的入口吧(待考证)
那么7FFDF030 = FS:[30h] 处存放的就是PEB结构体的地址了即7FFD5000 ,我们继续 Alt+G 输入7FFD5000
上图就是PEB结构体了,其中0ch处指向就是PEB_LDR_DATA 结构的所在了,其地址是241ea0
我们继续Alt + G 输入241ea0 回车 ,查看下PEB_LDR_DATA 结构
上图就是PEB_LDR_DATA 结构了,其中在1ch 存放着 LIST_ENTRY InInitializationOrderModuleList
而 LIST_ENTRY 的定义为
1 typedef struct _LIST_ENTRY {
2 struct _LIST_ENTRY *Flink;
3 struct _LIST_ENTRY *Blink;
4 } LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY; 此结构就是链表就是 dll信息的链表;xp下第一个链表是ntdll.dll 第二个是kernel32.dll的,win7下
下第一个链表是ntdll.dll 第二个是kernelbase.dll的,第三个才是kernel32的。
所以1ch处存放这指向 Flink 的地址,其中Flink也是个指向另一个相同结构的指针
我们继续查看241f58h处的结构
继续查看242020处
在此地址偏移8h的地方存放着kernel32的地址 7c800000h
继续跟进来到7c800000h处
开头MZ标志,3ch处E8, E8h处的PE 是否想起了SEH法搜索kernel32地址法,没错
此为PE结构呀!
梳理下过程:
1: 首先通过段选择字FS在内存中找到的当前线程环境变量TEB;
2: 线程环境结构块偏移位置30h的地方存放着指向进程环境块PEB的指针;
3: 线程环境中便宜位置0ch处的地方存放着指向PEB_LDR_DATA结构体的指针
4: PEB_LDR_DATA结构体偏移位置1ch处的地方存放着指向模块初始化链表的头指针InInitalizationOrderModuleList.
5:模块初始化链表InInitializationOrderModuleList 中按顺序存放着PE载入运行时初始化模块的信息,第一个链表节点是ntdll.dll,第二个链表节点就是kernel32.dll.
6:找到属于kernel32.dll的节点后,在其基础上再偏移0x08就是kernel32.dll在内存中的加载基地址。
7:从kernel32.dll的加载基础算起,偏移3ch的地方就是其PE头。
8:PE头偏移78h的地方存放着指向函数导出表的指针。
困了今天到此结束,明天有事不能开电脑了,又赶上周末,抽空再说吧!
----------------------------------------------------
| QQ252738331
| Q群: 104132152(群名称是缓冲区溢出|汇编|逆向)
----------------------------------------------------