题外话:上一篇文章中的 PEB法查找kerner32地址的方法 对TEB、PEB 、PE结构 知识要求很高,确实在写汇编代码时候小编
感觉自己能力,信手啪啪一顿乱撸,结果一运行,非法访问了,没办法翻阅前人的文章,贴来,但是,感到很羞愧,故有此文章
对 此过程 ,认真学习、分析下
正题:
TEB结构
1 // 2 // Thread Environment Block (TEB) 3 // 4 typedef struct _TEB 5 { 6 NT_TIB Tib; /* 00h */ 7 PVOID EnvironmentPointer; /* 1Ch */ 8 CLIENT_ID Cid; /* 20h */ 9 PVOID ActiveRpcHandle; /* 28h */ 10 PVOID ThreadLocalStoragePointer; /* 2Ch */ 11 struct _PEB *ProcessEnvironmentBlock; /* 30h */ 12 ULONG LastErrorValue; /* 34h */ 13 ULONG CountOfOwnedCriticalSections; /* 38h */ 14 PVOID CsrClientThread; /* 3Ch */ 15 struct _W32THREAD* Win32ThreadInfo; /* 40h */ 16 ULONG User32Reserved[0x1A]; /* 44h */ 17 ULONG UserReserved[5]; /* ACh */ 18 PVOID WOW32Reserved; /* C0h */ 19 LCID CurrentLocale; /* C4h */ 20 ULONG FpSoftwareStatusRegister; /* C8h */ 21 PVOID SystemReserved1[0x36]; /* CCh */ 22 LONG ExceptionCode; /* 1A4h */ 23 struct _ACTIVATION_CONTEXT_STACK *ActivationContextStackPointer; /* 1A8h */ 24 UCHAR SpareBytes1[0x28]; /* 1ACh */ 25 GDI_TEB_BATCH GdiTebBatch; /* 1D4h */ 26 CLIENT_ID RealClientId; /* 6B4h */ 27 PVOID GdiCachedProcessHandle; /* 6BCh */ 28 ULONG GdiClientPID; /* 6C0h */ 29 ULONG GdiClientTID; /* 6C4h */ 30 PVOID GdiThreadLocalInfo; /* 6C8h */ 31 ULONG Win32ClientInfo[62]; /* 6CCh */ 32 PVOID glDispatchTable[0xE9]; /* 7C4h */ 33 ULONG glReserved1[0x1D]; /* B68h */ 34 PVOID glReserved2; /* BDCh */ 35 PVOID glSectionInfo; /* BE0h */ 36 PVOID glSection; /* BE4h */ 37 PVOID glTable; /* BE8h */ 38 PVOID glCurrentRC; /* BECh */ 39 PVOID glContext; /* BF0h */ 40 NTSTATUS LastStatusValue; /* BF4h */ 41 UNICODE_STRING StaticUnicodeString; /* BF8h */ 42 WCHAR StaticUnicodeBuffer[0x105]; /* C00h */ 43 PVOID DeallocationStack; /* E0Ch */ 44 PVOID TlsSlots[0x40]; /* E10h */ 45 LIST_ENTRY TlsLinks; /* F10h */ 46 PVOID Vdm; /* F18h */ 47 PVOID ReservedForNtRpc; /* F1Ch */ 48 PVOID DbgSsReserved[0x2]; /* F20h */ 49 ULONG HardErrorDisabled; /* F28h */ 50 PVOID Instrumentation[14]; /* F2Ch */ 51 PVOID SubProcessTag; /* F64h */ 52 PVOID EtwTraceData; /* F68h */ 53 PVOID WinSockData; /* F6Ch */ 54 ULONG GdiBatchCount; /* F70h */ 55 BOOLEAN InDbgPrint; /* F74h */ 56 BOOLEAN FreeStackOnTermination; /* F75h */ 57 BOOLEAN HasFiberData; /* F76h */ 58 UCHAR IdealProcessor; /* F77h */ 59 ULONG GuaranteedStackBytes; /* F78h */ 60 PVOID ReservedForPerf; /* F7Ch */ 61 PVOID ReservedForOle; /* F80h */ 62 ULONG WaitingOnLoaderLock; /* F84h */ 63 ULONG SparePointer1; /* F88h */ 64 ULONG SoftPatchPtr1; /* F8Ch */ 65 ULONG SoftPatchPtr2; /* F90h */ 66 PVOID *TlsExpansionSlots; /* F94h */ 67 ULONG ImpersionationLocale; /* F98h */ 68 ULONG IsImpersonating; /* F9Ch */ 69 PVOID NlsCache; /* FA0h */ 70 PVOID pShimData; /* FA4h */ 71 ULONG HeapVirualAffinity; /* FA8h */ 72 PVOID CurrentTransactionHandle; /* FACh */ 73 PTEB_ACTIVE_FRAME ActiveFrame; /* FB0h */ 74 PVOID FlsData; /* FB4h */ 75 UCHAR SafeThunkCall; /* FB8h */ 76 UCHAR BooleanSpare[3]; /* FB9h */ 77 } TEB, *PTEB;
PEB结构
1 typedef struct _PEB 2 { 3 UCHAR InheritedAddressSpace; // 00h 4 UCHAR ReadImageFileExecOptions; // 01h 5 UCHAR BeingDebugged; // 02h 6 UCHAR Spare; // 03h 7 PVOID Mutant; // 04h 8 PVOID ImageBaseAddress; // 08h 9 PPEB_LDR_DATA Ldr; // 0Ch 10 PRTL_USER_PROCESS_PARAMETERS ProcessParameters; // 10h 11 PVOID SubSystemData; // 14h 12 PVOID ProcessHeap; // 18h 13 PVOID FastPebLock; // 1Ch 14 PPEBLOCKROUTINE FastPebLockRoutine; // 20h 15 PPEBLOCKROUTINE FastPebUnlockRoutine; // 24h 16 ULONG EnvironmentUpdateCount; // 28h 17 PVOID* KernelCallbackTable; // 2Ch 18 PVOID EventLogSection; // 30h 19 PVOID EventLog; // 34h 20 PPEB_FREE_BLOCK FreeList; // 38h 21 ULONG TlsExpansionCounter; // 3Ch 22 PVOID TlsBitmap; // 40h 23 ULONG TlsBitmapBits[0x2]; // 44h 24 PVOID ReadOnlySharedMemoryBase; // 4Ch 25 PVOID ReadOnlySharedMemoryHeap; // 50h 26 PVOID* ReadOnlyStaticServerData; // 54h 27 PVOID AnsiCodePageData; // 58h 28 PVOID OemCodePageData; // 5Ch 29 PVOID UnicodeCaseTableData; // 60h 30 ULONG NumberOfProcessors; // 64h 31 ULONG NtGlobalFlag; // 68h 32 UCHAR Spare2[0x4]; // 6Ch 33 LARGE_INTEGER CriticalSectionTimeout; // 70h 34 ULONG HeapSegmentReserve; // 78h 35 ULONG HeapSegmentCommit; // 7Ch 36 ULONG HeapDeCommitTotalFreeThreshold; // 80h 37 ULONG HeapDeCommitFreeBlockThreshold; // 84h 38 ULONG NumberOfHeaps; // 88h 39 ULONG MaximumNumberOfHeaps; // 8Ch 40 PVOID** ProcessHeaps; // 90h 41 PVOID GdiSharedHandleTable; // 94h 42 PVOID ProcessStarterHelper; // 98h 43 PVOID GdiDCAttributeList; // 9Ch 44 PVOID LoaderLock; // A0h 45 ULONG OSMajorVersion; // A4h 46 ULONG OSMinorVersion; // A8h 47 ULONG OSBuildNumber; // ACh 48 ULONG OSPlatformId; // B0h 49 ULONG ImageSubSystem; // B4h 50 ULONG ImageSubSystemMajorVersion; // B8h 51 ULONG ImageSubSystemMinorVersion; // C0h 52 ULONG GdiHandleBuffer[0x22]; // C4h 53 PVOID ProcessWindowStation; // ??? 54 } PEB, *PPEB;
1 typedef struct _PEB_LDR_DATA 2 { 3 ULONG Length; // +0x00 4 BOOLEAN Initialized; // +0x04 5 PVOID SsHandle; // +0x08 6 LIST_ENTRY InLoadOrderModuleList; // +0x0c 7 LIST_ENTRY InMemoryOrderModuleList; // +0x14 8 LIST_ENTRY InInitializationOrderModuleList;// +0x1c 9 } PEB_LDR_DATA,*PPEB_LDR_DATA; // +0x24
1 typedef struct _LIST_ENTRY { 2 struct _LIST_ENTRY *Flink; 3 struct _LIST_ENTRY *Blink; 4 } 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的基地址了
1 // sty_teb_peb_ker32.cpp : Defines the entry point for the application. 2 // 3 4 #include "stdafx.h" 5 6 int APIENTRY WinMain(HINSTANCE hInstance, 7 HINSTANCE hPrevInstance, 8 LPSTR lpCmdLine, 9 int nCmdShow) 10 { 11 // TODO: Place code here. 12 _asm 13 { 14 15 16 mov eax, fs:[0x30] ;PEB的地址 17 mov eax, [eax + 0x0c] ;Ldr的地址 18 mov esi, [eax + 0x1c] ;Flink地址 19 lodsd 20 mov eax, [eax + 0x08] ;eax就是kernel32.dll的地址 21 } 22 return 0; 23 }
以上代码生成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(群名称是缓冲区溢出|汇编|逆向)
| 微博: http://t.qq.com/zhenw0
----------------------------------------------------