我是靠谱客的博主 安静大叔,最近开发中收集的这篇文章主要介绍TEB和PEBTEB(Thread Environment Block,线程环境块)什么是PEB?,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

TEB(Thread Environment Block,线程环境块)

线程环境块中存放着进程中所有线程的各种信息

TEB的访问方法

ntdll.NtCurrentTeb() 函数用来返回当前线程的TEB结构体指针

NtCurrentTeb() 函数所返回的结构体指针即为 fs:[0x18] 的值,里面的值即为TEB的结构体指针,fs:[0]的值即为TEB的起始地址

nt!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : Ptr32 Void
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : Ptr32 Void
   +0x02c ThreadLocalStoragePointer : Ptr32 Void
   +0x030 ProcessEnvironmentBlock : Ptr32 _PEB
   +0x034 LastErrorValue   : Uint4B
   +0x038 CountOfOwnedCriticalSections : Uint4B
   +0x03c CsrClientThread  : Ptr32 Void
   +0x040 Win32ThreadInfo  : Ptr32 Void
   +0x044 User32Reserved   : [26] Uint4B
   +0x0ac UserReserved     : [5] Uint4B
   +0x0c0 WOW32Reserved    : Ptr32 Void
   +0x0c4 CurrentLocale    : Uint4B
   +0x0c8 FpSoftwareStatusRegister : Uint4B
   +0x0cc SystemReserved1  : [54] Ptr32 Void
   +0x1a4 ExceptionCode    : Int4B
   +0x1a8 ActivationContextStack : _ACTIVATION_CONTEXT_STACK
   +0x1bc SpareBytes1      : [24] UChar
   +0x1d4 GdiTebBatch      : _GDI_TEB_BATCH
   +0x6b4 RealClientId     : _CLIENT_ID
   +0x6bc GdiCachedProcessHandle : Ptr32 Void
   +0x6c0 GdiClientPID     : Uint4B
   +0x6c4 GdiClientTID     : Uint4B
   +0x6c8 GdiThreadLocalInfo : Ptr32 Void
   +0x6cc Win32ClientInfo  : [62] Uint4B
   +0x7c4 glDispatchTable  : [233] Ptr32 Void
   +0xb68 glReserved1      : [29] Uint4B
   +0xbdc glReserved2      : Ptr32 Void
   +0xbe0 glSectionInfo    : Ptr32 Void
   +0xbe4 glSection        : Ptr32 Void
   +0xbe8 glTable          : Ptr32 Void
   +0xbec glCurrentRC      : Ptr32 Void
   +0xbf0 glContext        : Ptr32 Void
   +0xbf4 LastStatusValue  : Uint4B
   +0xbf8 StaticUnicodeString : _UNICODE_STRING
   +0xc00 StaticUnicodeBuffer : [261] Uint2B
   +0xe0c DeallocationStack : Ptr32 Void
   +0xe10 TlsSlots         : [64] Ptr32 Void
   +0xf10 TlsLinks         : _LIST_ENTRY
   +0xf18 Vdm              : Ptr32 Void
   +0xf1c ReservedForNtRpc : Ptr32 Void
   +0xf20 DbgSsReserved    : [2] Ptr32 Void
   +0xf28 HardErrorsAreDisabled : Uint4B
   +0xf2c Instrumentation  : [16] Ptr32 Void
   +0xf6c WinSockData      : Ptr32 Void
   +0xf70 GdiBatchCount    : Uint4B
   +0xf74 InDbgPrint       : UChar
   +0xf75 FreeStackOnTermination : UChar
   +0xf76 HasFiberData     : UChar
   +0xf77 IdealProcessor   : UChar
   +0xf78 Spare3           : Uint4B
   +0xf7c ReservedForPerf  : Ptr32 Void
   +0xf80 ReservedForOle   : Ptr32 Void
   +0xf84 WaitingOnLoaderLock : Uint4B
   +0xf88 Wx86Thread       : _Wx86ThreadState
   +0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void
   +0xf98 ImpersonationLocale : Uint4B
   +0xf9c IsImpersonating  : Uint4B
   +0xfa0 NlsCache         : Ptr32 Void
   +0xfa4 pShimData        : Ptr32 Void
   +0xfa8 HeapVirtualAffinity : Uint4B
   +0xfac CurrentTransactionHandle : Ptr32 Void
   +0xfb0 ActiveFrame      : Ptr32 _TEB_ACTIVE_FRAME
   +0xfb4 SafeThunkCall    : UChar
   +0xfb5 BooleanSpare     : [3] UChar

详细的介绍常用的结构体成员及作用

1

+0x000 NtTib            : _NT_TIB

TEB的结构体的第一个成员NtTib即为我们常说的TIB   TIB(Thread Information Block,线程信息块)

typedef struct _NT_TIB          //sizeof  1ch  
{  
 00h   struct _EXCEPTION_REGISTRATION_RECORD  *ExceptionList; 
 04h   PVOID                            StackBase;
 08h   PVOID                            StackLimit;
 0ch   PVOID                            SubSystemTib;  
       union {  
           PVOID                FiberData;  
 10h       DWORD                Version;  
       };  
 14h   PVOID                            ArbitraryUserPointer;  
 18h   struct _NT_TIB                   *Self; 
}NT_TIB;
  • ExceptionList:即为指向_EXCEPTION_REGISTRATION_RECORD结构体的链表指针(SEH)
  • StackBase:这里为线程堆栈顶部
  • StackLimit :这里为线程堆栈底部
  • Self:这为_NT_TIB结构体的自引用指针,即为NtCurrentTeb() 函数所读出的TEB结构体指针

2

+0x020 ClientId         : _CLIENT_ID

nt!_CLIENT_ID
   +0x000 UniqueProcess    : Ptr64 Void
   +0x008 UniqueThread     : Ptr64 Void

UniqueProcess:这个为当前进程的的Pid,可用函数 GetCurrentProcessId() 访问当前结构体成员获取进程标识符:

可以看到TEB+0x20即为 UniqueProcess 的成员变量。
  • UniqueThread: 这个为当前进程的的Tid,可用函数 GetCurrentThreadId() 访问当前结构体成员获取线程标识符:

可以看到TEB+0x20即为 UniqueThread 的成员变量。

3

+0x030 ProcessEnvironmentBlock : Ptr32 _PEB

这个即为PEB结构体的指针,所以说一般 fs:[0x30] 即为PEB的起始地址。

什么是PEB?

PEB( Process Envirorment Block ,进程环境块)
PEB是存放着进程信息的结构体
https://msdn.microsoft.com/en-us/library/aa813706.aspx

线程TEB结构体中,每个TEB+0x30(fs:[0x30])中都指向同一个地址(TEB.ProcessEnvironmentBlock)So。我们可以用fs:[0x30]来访问PEB的结构体地址

这里我们可以看到 [TEB.ProcessEnvironmentBlock] = =   fs:[0x30],而EP中 EBX寄存器默认为PEB的结构体地址

nt!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x003 SpareBool        : UChar
   +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 FastPebLockRoutine : Ptr32 Void
   +0x024 FastPebUnlockRoutine : Ptr32 Void
   +0x028 EnvironmentUpdateCount : Uint4B
   +0x02c KernelCallbackTable : Ptr32 Void
   +0x030 SystemReserved   : [1] Uint4B
   +0x034 AtlThunkSListPtr32 : Uint4B
   +0x038 FreeList         : Ptr32 _PEB_FREE_BLOCK
   +0x03c TlsExpansionCounter : Uint4B
   +0x040 TlsBitmap        : Ptr32 Void
   +0x044 TlsBitmapBits    : [2] Uint4B
   +0x04c ReadOnlySharedMemoryBase : Ptr32 Void
   +0x050 ReadOnlySharedMemoryHeap : 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 Void
   +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 ImageProcessAffinityMask : 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 Void
   +0x1fc ProcessAssemblyStorageMap : Ptr32 Void
   +0x200 SystemDefaultActivationContextData : Ptr32 Void
   +0x204 SystemAssemblyStorageMap : Ptr32 Void
   +0x208 MinimumStackCommit : Uint4B

+0x002 BeingDebugged    : UChar

这个结构体成员大家应该都懂,表示当前进程是否处于调试状态,也就是函数 IsDebuggerPresent() 所访问的结构体成员.

这里我看可以看到先是取出PEB的结构体地址,在取出PEB.BeingDebugged  结构体成员然后返回

+0x008 ImageBaseAddress : Ptr32 Void

这个结构体成员我们也经常用到,也就是自身的 ImageBase ,和PE结构中的 IMAGE_OPTIONAL_HEADER.ImageBase 。
可用函 GetModuleHandle (0) 获取自身模块句柄来访问这个结构体成员:

+0x00c Ldr              : Ptr32 _PEB_LDR_DATA

这个结构体成员就很复杂了,它是指向 _PEB_LDR_DATA 的结构体指针,当DLL加载到进程,可从 PEB.Ldr 中获取该模块的基址和其他信息:

ntdll!_PEB_LDR_DATA  
   +0x000 Length            //结构体大小 
   +0x004 Initialized      //进程是否初始化完成
   +0x008 SsHandle 
   +0x00c InLoadOrderModuleList : _LIST_ENTRY
   +0x014 InMemoryOrderModuleList : _LIST_ENTRY
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY  
   +0x024 EntryInProgress
   +0x028 ShutdownInProgress
   +0x02c ShutdownThreadId

InLoadOrderModuleList、InMemoryOrderModuleList、InInitializationOrderModuleList 这三个结构体成员都是指向LIST_ENTRY的结构体指针,我们查询下这个数据结构:

nt!_LIST_ENTRY
   +0x000 Flink            : Ptr64 _LIST_ENTRY
   +0x008 Blink            : Ptr64 _LIST_ENTRY

可以看出这是一个双向链表,每条链表都指向名为 LDR_DATA_TABLE_ENTRY 的结构体指针:

nt!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY
   +0x010 InMemoryOrderLinks : _LIST_ENTRY
   +0x020 InInitializationOrderLinks : _LIST_ENTRY
   +0x030 DllBase          : Ptr64 Void
   +0x038 EntryPoint       : Ptr64 Void
   +0x040 SizeOfImage      : Uint4B
   +0x048 FullDllName      : _UNICODE_STRING
   +0x058 BaseDllName      : _UNICODE_STRING
   +0x068 FlagGroup        : [4] UChar
   +0x068 Flags            : Uint4B
   +0x068 PackagedBinary   : Pos 0, 1 Bit
   +0x068 MarkedForRemoval : Pos 1, 1 Bit
   +0x068 ImageDll         : Pos 2, 1 Bit
   +0x068 LoadNotificationsSent : Pos 3, 1 Bit
   +0x068 TelemetryEntryProcessed : Pos 4, 1 Bit
   +0x068 ProcessStaticImport : Pos 5, 1 Bit
   +0x068 InLegacyLists    : Pos 6, 1 Bit
   +0x068 InIndexes        : Pos 7, 1 Bit
   +0x068 ShimDll          : Pos 8, 1 Bit
   +0x068 InExceptionTable : Pos 9, 1 Bit
   +0x068 ReservedFlags1   : Pos 10, 2 Bits
   +0x068 LoadInProgress   : Pos 12, 1 Bit
   +0x068 LoadConfigProcessed : Pos 13, 1 Bit
   +0x068 EntryProcessed   : Pos 14, 1 Bit
   +0x068 ProtectDelayLoad : Pos 15, 1 Bit
   +0x068 ReservedFlags3   : Pos 16, 2 Bits
   +0x068 DontCallForThreads : Pos 18, 1 Bit
   +0x068 ProcessAttachCalled : Pos 19, 1 Bit
   +0x068 ProcessAttachFailed : Pos 20, 1 Bit
   +0x068 CorDeferredValidate : Pos 21, 1 Bit
   +0x068 CorImage         : Pos 22, 1 Bit
   +0x068 DontRelocate     : Pos 23, 1 Bit
   +0x068 CorILOnly        : Pos 24, 1 Bit
   +0x068 ChpeImage        : Pos 25, 1 Bit
   +0x068 ReservedFlags5   : Pos 26, 2 Bits
   +0x068 Redirected       : Pos 28, 1 Bit
   +0x068 ReservedFlags6   : Pos 29, 2 Bits
   +0x068 CompatDatabaseProcessed : Pos 31, 1 Bit
   +0x06c ObsoleteLoadCount : Uint2B
   +0x06e TlsIndex         : Uint2B
   +0x070 HashLinks        : _LIST_ENTRY
   +0x080 TimeDateStamp    : Uint4B
   +0x088 EntryPointActivationContext : Ptr64 _ACTIVATION_CONTEXT
   +0x090 Lock             : Ptr64 Void
   +0x098 DdagNode         : Ptr64 _LDR_DDAG_NODE
   +0x0a0 NodeModuleLink   : _LIST_ENTRY
   +0x0b0 LoadContext      : Ptr64 _LDRP_LOAD_CONTEXT
   +0x0b8 ParentDllBase    : Ptr64 Void
   +0x0c0 SwitchBackContext : Ptr64 Void
   +0x0c8 BaseAddressIndexNode : _RTL_BALANCED_NODE
   +0x0e0 MappingInfoIndexNode : _RTL_BALANCED_NODE
   +0x0f8 OriginalBase     : Uint8B
   +0x100 LoadTime         : _LARGE_INTEGER
   +0x108 BaseNameHashValue : Uint4B
   +0x10c LoadReason       : _LDR_DLL_LOAD_REASON
   +0x110 ImplicitPathOptions : Uint4B
   +0x114 ReferenceCount   : Uint4B
   +0x118 DependentLoadFlags : Uint4B
   +0x11c SigningLevel     : UChar

每个进程中的DLL加载进来都有与之对于的 _LDR_DATA_TABLE_ENTRY 结构体,这些结构相互链接就形成了双向链表

+0x018 ProcessHeap      : Ptr32 Void

这个结构体成员就是进程堆的句柄,也就是指向结构体HEAP的指针,我们查询下结构体成员:

nt!_HEAP
   +0x000 Segment          : _HEAP_SEGMENT
   +0x000 Entry            : _HEAP_ENTRY
   +0x010 SegmentSignature : Uint4B
   +0x014 SegmentFlags     : Uint4B
   +0x018 SegmentListEntry : _LIST_ENTRY
   +0x028 Heap             : Ptr64 _HEAP
   +0x030 BaseAddress      : Ptr64 Void
   +0x038 NumberOfPages    : Uint4B
   +0x040 FirstEntry       : Ptr64 _HEAP_ENTRY
   +0x048 LastValidEntry   : Ptr64 _HEAP_ENTRY
   +0x050 NumberOfUnCommittedPages : Uint4B
   +0x054 NumberOfUnCommittedRanges : Uint4B
   +0x058 SegmentAllocatorBackTraceIndex : Uint2B
   +0x05a Reserved         : Uint2B
   +0x060 UCRSegmentList   : _LIST_ENTRY
   +0x070 Flags            : Uint4B
   +0x074 ForceFlags       : Uint4B
   +0x078 CompatibilityFlags : Uint4B
   +0x07c EncodeFlagMask   : Uint4B
   +0x080 Encoding         : _HEAP_ENTRY
   +0x090 Interceptor      : Uint4B
   +0x094 VirtualMemoryThreshold : Uint4B
   +0x098 Signature        : Uint4B
   +0x0a0 SegmentReserve   : Uint8B
   +0x0a8 SegmentCommit    : Uint8B
   +0x0b0 DeCommitFreeBlockThreshold : Uint8B
   +0x0b8 DeCommitTotalFreeThreshold : Uint8B
   +0x0c0 TotalFreeSize    : Uint8B
   +0x0c8 MaximumAllocationSize : Uint8B
   +0x0d0 ProcessHeapsListIndex : Uint2B
   +0x0d2 HeaderValidateLength : Uint2B
   +0x0d8 HeaderValidateCopy : Ptr64 Void
   +0x0e0 NextAvailableTagIndex : Uint2B
   +0x0e2 MaximumTagIndex  : Uint2B
   +0x0e8 TagEntries       : Ptr64 _HEAP_TAG_ENTRY
   +0x0f0 UCRList          : _LIST_ENTRY
   +0x100 AlignRound       : Uint8B
   +0x108 AlignMask        : Uint8B
   +0x110 VirtualAllocdBlocks : _LIST_ENTRY
   +0x120 SegmentList      : _LIST_ENTRY
   +0x130 AllocatorBackTraceIndex : Uint2B
   +0x134 NonDedicatedListLength : Uint4B
   +0x138 BlocksIndex      : Ptr64 Void
   +0x140 UCRIndex         : Ptr64 Void
   +0x148 PseudoTagEntries : Ptr64 _HEAP_PSEUDO_TAG_ENTRY
   +0x150 FreeLists        : _LIST_ENTRY
   +0x160 LockVariable     : Ptr64 _HEAP_LOCK
   +0x168 CommitRoutine    : Ptr64     long 
   +0x170 StackTraceInitVar : _RTL_RUN_ONCE
   +0x178 CommitLimitData  : _RTL_HEAP_MEMORY_LIMIT_DATA
   +0x198 FrontEndHeap     : Ptr64 Void
   +0x1a0 FrontHeapLockCount : Uint2B
   +0x1a2 FrontEndHeapType : UChar
   +0x1a3 RequestedFrontEndHeapType : UChar
   +0x1a8 FrontEndHeapUsageData : Ptr64 Wchar
   +0x1b0 FrontEndHeapMaximumIndex : Uint2B
   +0x1b2 FrontEndHeapStatusBitmap : [129] UChar
   +0x238 Counters         : _HEAP_COUNTERS
   +0x2b0 TuningParameters : _HEAP_TUNING_PARAMETERS

程序正常运行时,ProcessHeap.Flags的值为2 , ProcessHeap. ForceFlags 的值为0,也常用于反调试。
ProcessHeap结构体成员指向的HEAP结构体指针可用函数 GetProcessHeap()获取:

+0x068 NtGlobalFlag     : Uint4B

再调试状态时,PEB.NtGlobalFlag 的值为0x70 ,这个值我也不清楚 只记得几个Flages的值进行 OR(位或) 的结果

 

最后

以上就是安静大叔为你收集整理的TEB和PEBTEB(Thread Environment Block,线程环境块)什么是PEB?的全部内容,希望文章能够帮你解决TEB和PEBTEB(Thread Environment Block,线程环境块)什么是PEB?所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部