題外話:上一篇文章中的 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
----------------------------------------------------