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() 访问当前结构体成员获取进程标识符:
- UniqueThread: 这个为当前进程的的Tid,可用函数 GetCurrentThreadId() 访问当前结构体成员获取线程标识符:
可以看到TEB+0x20即为 UniqueThread 的成员变量。
3
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB
这个即为PEB结构体的指针,所以说一般 fs:[0x30] 即为PEB的起始地址。
什么是PEB?
线程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(位或) 的结果
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/211132.html原文链接:https://javaforall.net
