Windows
PE 文件结构图
PEB 结构
32位及64位TEB、PEB详解
x86/x64 PE文件头详解
本文档使用 MrDoc 发布
-
+
首页
PEB 结构
- 该文章记录的有点混乱,更加具体详细下参考网站下【32位及64位TEB、PEB详解】 **该结构在不同版本的 Windows 下不同!具体可以参考 https://www.vergiliusproject.com/** ### 参考链接 > https://bbs.kanxue.com/thread-266678.htm > https://blog.csdn.net/CSNN2019/article/details/113113347 > https://blog.csdn.net/simon798/article/details/107128069 > https://blog.csdn.net/zhoujiaxq/article/details/23169587 ### 定义   Windows XP SP3 ```c typedef struct _PEB { // Size: 0x1D8 000h UCHAR InheritedAddressSpace; 001h UCHAR ReadImageFileExecOptions; 002h UCHAR BeingDebugged; //Debug运行标志 003h UCHAR SpareBool; 004h HANDLE Mutant; 008h HINSTANCE ImageBaseAddress; //程序加载的基地址 00Ch struct _PEB_LDR_DATA *Ldr //Ptr32 _PEB_LDR_DATA 010h struct _RTL_USER_PROCESS_PARAMETERS *ProcessParameters; 014h ULONG SubSystemData; 018h HANDLE DefaultHeap; 01Ch KSPIN_LOCK FastPebLock; 020h ULONG FastPebLockRoutine; 024h ULONG FastPebUnlockRoutine; 028h ULONG EnvironmentUpdateCount; 02Ch ULONG KernelCallbackTable; 030h LARGE_INTEGER SystemReserved; 038h struct _PEB_FREE_BLOCK *FreeList 03Ch ULONG TlsExpansionCounter; 040h ULONG TlsBitmap; 044h LARGE_INTEGER TlsBitmapBits; 04Ch ULONG ReadOnlySharedMemoryBase; 050h ULONG ReadOnlySharedMemoryHeap; 054h ULONG ReadOnlyStaticServerData; 058h ULONG AnsiCodePageData; 05Ch ULONG OemCodePageData; 060h ULONG UnicodeCaseTableData; 064h ULONG NumberOfProcessors; 068h LARGE_INTEGER NtGlobalFlag; // Address of a local copy 070h LARGE_INTEGER CriticalSectionTimeout; 078h ULONG HeapSegmentReserve; 07Ch ULONG HeapSegmentCommit; 080h ULONG HeapDeCommitTotalFreeThreshold; 084h ULONG HeapDeCommitFreeBlockThreshold; 088h ULONG NumberOfHeaps; 08Ch ULONG MaximumNumberOfHeaps; 090h ULONG ProcessHeaps; 094h ULONG GdiSharedHandleTable; 098h ULONG ProcessStarterHelper; 09Ch ULONG GdiDCAttributeList; 0A0h KSPIN_LOCK LoaderLock; 0A4h ULONG OSMajorVersion; 0A8h ULONG OSMinorVersion; 0ACh USHORT OSBuildNumber; 0AEh USHORT OSCSDVersion; 0B0h ULONG OSPlatformId; 0B4h ULONG ImageSubsystem; 0B8h ULONG ImageSubsystemMajorVersion; 0BCh ULONG ImageSubsystemMinorVersion; 0C0h ULONG ImageProcessAffinityMask; 0C4h ULONG GdiHandleBuffer[0x22]; 14Ch ULONG PostProcessInitRoutine; 150h ULONG TlsExpansionBitmap; 154h UCHAR TlsExpansionBitmapBits[0x80]; 1D4h ULONG SessionId; 1d8h AppCompatFlags : _ULARGE_INTEGER 1e0h AppCompatFlagsUser : _ULARGE_INTEGER 1e8h pShimData : Ptr32 Void 1ech AppCompatInfo : Ptr32 Void 1f0h CSDVersion : _UNICODE_STRING 1f8h ActivationContextData : Ptr32 Void 1fch ProcessAssemblyStorageMap :Ptr32 Void 200h SystemDefaultActivationContextData : Ptr32 Void 204h SystemAssemblyStorageMap : Ptr32 Void 208h MinimumStackCommit : Uint4B } PEB, *PPEB; ```   Win7 ```c ntdll!_PEB +0x000 InheritedAddressSpace : UChar +0x001 ReadImageFileExecOptions : UChar +0x002 BeingDebugged : UChar +0x003 BitField : UChar +0x003 ImageUsesLargePages : Pos 0, 1 Bit +0x003 IsProtectedProcess : Pos 1, 1 Bit +0x003 IsLegacyProcess : Pos 2, 1 Bit +0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit +0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit +0x003 SpareBits : Pos 5, 3 Bits +0x004 Mutant : Ptr32 Void +0x008 ImageBaseAddress : Ptr32 Void +0x00c Ldr : Ptr32 _PEB_LDR_DATA +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS +0x014 SubSystemData : Ptr32 Void +0x018 ProcessHeap : Ptr32 Void +0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION +0x020 AtlThunkSListPtr : Ptr32 Void +0x024 IFEOKey : Ptr32 Void +0x028 CrossProcessFlags : Uint4B +0x028 ProcessInJob : Pos 0, 1 Bit +0x028 ProcessInitializing : Pos 1, 1 Bit +0x028 ProcessUsingVEH : Pos 2, 1 Bit +0x028 ProcessUsingVCH : Pos 3, 1 Bit +0x028 ProcessUsingFTH : Pos 4, 1 Bit +0x028 ReservedBits0 : Pos 5, 27 Bits +0x02c KernelCallbackTable : Ptr32 Void +0x02c UserSharedInfoPtr : Ptr32 Void +0x030 SystemReserved : [1] Uint4B +0x034 AtlThunkSListPtr32 : Uint4B +0x038 ApiSetMap : Ptr32 Void +0x03c TlsExpansionCounter : Uint4B +0x040 TlsBitmap : Ptr32 Void +0x044 TlsBitmapBits : [2] Uint4B +0x04c ReadOnlySharedMemoryBase : Ptr32 Void +0x050 HotpatchInformation : Ptr32 Void +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void +0x058 AnsiCodePageData : Ptr32 Void +0x05c OemCodePageData : Ptr32 Void +0x060 UnicodeCaseTableData : Ptr32 Void +0x064 NumberOfProcessors : Uint4B +0x068 NtGlobalFlag : Uint4B +0x070 CriticalSectionTimeout : _LARGE_INTEGER +0x078 HeapSegmentReserve : Uint4B +0x07c HeapSegmentCommit : Uint4B +0x080 HeapDeCommitTotalFreeThreshold : Uint4B +0x084 HeapDeCommitFreeBlockThreshold : Uint4B +0x088 NumberOfHeaps : Uint4B +0x08c MaximumNumberOfHeaps : Uint4B +0x090 ProcessHeaps : Ptr32 Ptr32 Void +0x094 GdiSharedHandleTable : Ptr32 Void +0x098 ProcessStarterHelper : Ptr32 Void +0x09c GdiDCAttributeList : Uint4B +0x0a0 LoaderLock : Ptr32 _RTL_CRITICAL_SECTION +0x0a4 OSMajorVersion : Uint4B +0x0a8 OSMinorVersion : Uint4B +0x0ac OSBuildNumber : Uint2B +0x0ae OSCSDVersion : Uint2B +0x0b0 OSPlatformId : Uint4B +0x0b4 ImageSubsystem : Uint4B +0x0b8 ImageSubsystemMajorVersion : Uint4B +0x0bc ImageSubsystemMinorVersion : Uint4B +0x0c0 ActiveProcessAffinityMask : Uint4B +0x0c4 GdiHandleBuffer : [34] Uint4B +0x14c PostProcessInitRoutine : Ptr32 void +0x150 TlsExpansionBitmap : Ptr32 Void +0x154 TlsExpansionBitmapBits : [32] Uint4B +0x1d4 SessionId : Uint4B +0x1d8 AppCompatFlags : _ULARGE_INTEGER +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER +0x1e8 pShimData : Ptr32 Void +0x1ec AppCompatInfo : Ptr32 Void +0x1f0 CSDVersion : _UNICODE_STRING +0x1f8 ActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +0x1fc ProcessAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +0x200 SystemDefaultActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +0x204 SystemAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +0x208 MinimumStackCommit : Uint4B +0x20c FlsCallback : Ptr32 _FLS_CALLBACK_INFO +0x210 FlsListHead : _LIST_ENTRY +0x218 FlsBitmap : Ptr32 Void +0x21c FlsBitmapBits : [4] Uint4B +0x22c FlsHighIndex : Uint4B +0x230 WerRegistrationData : Ptr32 Void +0x234 WerShipAssertPtr : Ptr32 Void +0x238 pContextData : Ptr32 Void +0x23c pImageHeaderHash : Ptr32 Void +0x240 TracingFlags : Uint4B +0x240 HeapTracingEnabled : Pos 0, 1 Bit +0x240 CritSecTracingEnabled : Pos 1, 1 Bit +0x240 SpareTracingBits : Pos 2, 30 Bits ```   Win7 下的结构更大 ### PEB 的重要结构 ```c +0x002 BeingDebugged : UChar +0x008 ImageBaseAddress : Ptr32 Void +0x00c Ldr : Ptr32 _PEB_LDR_DATA +0x018 ProcessHeap : Ptr32 Void +0x068 NtGlobalFlag : Uint4B ```   **BeingDebugged**    kernel32.dll 中有一个函数如下: ```c BOOL WINAPI IsDebuggerPresent() ```    该 API 用来判断当前进程是否处于调试状态,并返回判断结果。而该 API 就是通过检测 PEB.BeingDebugged 成员来确定是否正在调试程序(是,则返回 1;否,则返回 0)。Win7 中,IsDebuggerPresent()是在 Kernelbase.dll 中实现的。而在 Windows XP 及以前版本的操作系统中,它是在 kernel32.dll 中。Win10 中也是在 Kernel32.dll 中。   **ImageBaseAddress**    ImageBaseAddress 成员用来表示进程的 ImageBase。Windows 用 GetModuleHandle 函数获取 ImageBase: ```c HMODULE WINAPI GetModuleHandle( __in_opt LPCTSTR lpModuleName ) ```    函数返回值被存在 EAX 中。   **Ldr**    Ldr 成员是指向了 **_PEB_LDR_DATA** 结构体指针。如下: ```c ypedef struct _PEB_LDR_DATA { ULONG Length; // 00h BOOLEAN Initialized; // 04h PVOID SsHandle; // 08h LIST_ENTRY InLoadOrderModuleList; // 0ch 模块链表,以加载顺序排序 LIST_ENTRY InMemoryOrderModuleList; // 14h 模块链表,以内存位置排序 LIST_ENTRY InInitializationOrderModuleList; // 1ch 模块链表,以初始化顺序排序 EntryInProgress //Ptr32 Void ShutdownInProgress //Uchar ShutdownThreadId //Ptr32 Void } PEB_LDR_DATA, *PPEB_LDR_DATA; // 24h ```    当模块(DLL)加载到进程后,通过 ldr 成员可以直接获得该模块的加载基地址。    _PEB_LDR_DATA 结构体成员中有 3 个 **LIST_ENTRY** 类型的成员 (InLoadOrderModuleList;InMemoryOrderModuleList; InInitializationOrderModuleList; ),LIST_ENTRY 结构体的定义如下所示: ```c typedef struct _LIST_ENTRY{ struct _LIST_ENTRY *Flink; // 指向下一个节点 struct _LIST_ENTRY *Blink; // }LIST_ENTRY,*LIST_ENTRY ```    从上面可看出,_LIST_ENTRY 结构体提供了双向链表机制。而链表中保存了 **_LDR_DATA_TABLE_ENTRY** 结构体的信息。 ```c //0x78 bytes (sizeof) Win7 下 struct _LDR_DATA_TABLE_ENTRY { struct _LIST_ENTRY InLoadOrderLinks; //0x0 struct _LIST_ENTRY InMemoryOrderLinks; //0x8 struct _LIST_ENTRY InInitializationOrderLinks; //0x10 VOID* DllBase; //0x18 VOID* EntryPoint; //0x1c ULONG SizeOfImage; //0x20 struct _UNICODE_STRING FullDllName; //0x24 struct _UNICODE_STRING BaseDllName; //0x2c ULONG Flags; //0x34 USHORT LoadCount; //0x38 USHORT TlsIndex; //0x3a union { struct _LIST_ENTRY HashLinks; //0x3c struct { VOID* SectionPointer; //0x3c ULONG CheckSum; //0x40 }; }; union { ULONG TimeDateStamp; //0x44 VOID* LoadedImports; //0x44 }; struct _ACTIVATION_CONTEXT* EntryPointActivationContext; //0x48 VOID* PatchInformation; //0x4c struct _LIST_ENTRY ForwarderLinks; //0x50 struct _LIST_ENTRY ServiceTagLinks; //0x58 struct _LIST_ENTRY StaticLinks; //0x60 VOID* ContextInformation; //0x68 ULONG OriginalBase; //0x6c union _LARGE_INTEGER LoadTime; //0x70 }; ```    每个加载到进程中的 DLL 模块都有与之对应的 _LDR_DATA_TABLE_EBTRY 结构体,这些结构体相互链接,最终形成 _LIST_ENTRY 双向链表。    需要注意的是,_PEB_LDR_DATA 结构体中存在 3 种链表。也就说,存在多个 _LDR_DATA_TABLE_ENTRY 结构体,有三种链接方式可以把它们链接起来。    借用下前人的图:    **ProcessHeap**    x64 中 ProcessHeap 在 PEB 的偏移是 0x30.    x86 中 ProcessHeap 在 PEB 的偏移是 0x18.    **ProcessHeap 是指向 HEAP 结构体的指针,在 HEAP 结构体中的两个成员 Flags 和 Force Flags 。**进程运行正常时,Heap.Flags 的成员值为0x2,HEAP.ForceFlags 成员的值为0x0    HeapFlags    对于 x64 系统,vista 以上版本的 HeapFlags 位于 *ProcessHeap + 0x70,剩余低版本的 windows 中的 HeapFlags 位于 *ProcessHeap+ 0x14。    对于 x86 系统 vista 以上版本的 HeapFlags 位于 *ProcessHeap + 0x40,剩余低版本的 windows 中的 HeapFlags 位于 *ProcessHeap + 0x0c。    如果 HeapFlags 的值**大于 2**说明程序处于调试状态。示例代码如下: ```c // 环境 - win10 x64 ULONG64 ul_processHeap = (ULONG64)(__readgsqword(0x60) + 0x30); ULONG64 ul_heapFlags = (ULONG64)(*ul_processHeap + 0x70); if(*ul_heapFlags > 2){ cout << "发现调试器" << endl; } else{ cout << "没有调试器" << endl; } ```    HeapForceFlags    对于 x64 系统,vista 以上版本的 HeapForceFlags位于 *ProcessHeap+ 0x74,剩余低版本的 windows 中的 HeapForceFlags 位于 *ProcessHeap+ 0x18。    对于 x86 系统 vista 以上版本的 HeapForceFlags 位于 *ProcessHeap + 0x44,剩余低版本的 windows 中的 HeapForceFlags 位于 *ProcessHeap + 0x10。    如果 HeapForceFlags 的值**大于 0 **则说明处于调试状态。 ```c // 环境 - win10 x64 ULONG64 ul_processHeap = (ULONG64)(__readgsqword(0x60) + 0x30); ULONG64 ul_heapForceFlags = (ULONG64)(*ul_processHeap + 0x74); if(*ul_heapForceFlags > 0){ cout << "发现调试器" << endl; } else{ cout << "没有调试器" << endl; } ```   **NtGlobalFlag**    通常程序没有被调试时,NtGlobalFlag成员值为0,如果进程被调试这个成员通常值为0x70(代表下述标志被设置):    FLG_HEAP_ENABLE_TAIL_CHECK(0X10)    FLG_HEAP_ENABLE_FREE_CHECK(0X20)    FLG_HEAP_VALIDATE_PARAMETERS(0X40)
别卷了
2024年8月8日 15:08
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码