TEB不在系统内核空间,而是应用层中的结构

线程环境块(Thread Environment Block)

包含了系统频繁使用的一些与线程相关的数据

进程中的每个线程都对应一个TEB

一个进程的所有TEB都存放在从0x7FFDE000开始的线性内存中

每4kb为一个完整的TEB

结构体定义

MSDN

typedef struct _TEB {
  PVOID Reserved1[12];
  PPEB  ProcessEnvironmentBlock;
  PVOID Reserved2[399];
  BYTE  Reserved3[1952];
  PVOID TlsSlots[64];
  BYTE  Reserved4[8];
  PVOID Reserved5[26];
  PVOID ReservedForOle;
  PVOID Reserved6[4];
  PVOID TlsExpansionSlots;
} TEB, *PTEB;

这个并不完整qwq,在不同OS中用windbg导出完整的

Windows XP SP3

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

借助winDbg的符号文件,查看了PEB结构体的所有成员。

WIN7

image-20240721190506040 image-20240721190522786 image-20240721190531906

重要成员

在用户模式调试中起重要作用的成员有2个,如下

+0x000 NtTib            : _NT_TIB
  ………………………………………………………………………………
   +0x030 ProcessEnvironmentBlock : Ptr32 _PEB
  • ProcessEnvironmentBlock成员:

    先看Offset 30处的ProcessEnvironmentBlock成员,它是指向PEB(Process Environment Block,进程环境块)结构体指针。PEB是进程环境块,每个进程对应1个PEB结构体。

  • NtTib成员

    TEB结构体的第一个成员为_NT_TIB结构体(TIB是Thread Information Block的简称,意为“线程信息块”),_NT_TIB结构体的定义如下所示:

    typedef struct _NT_TIB          //sizeof  1ch
    {
     00h   struct _EXCEPTION_REGISTRATION_RECORD  *ExceptionList;          //SEH链入口
     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结构自身的线性地址
    }NT_TIB;
     
    typedef     NT_TIB      *PNT_TIB;

ExceptionList成员指向_EXCEPTION_REGISTRATION_RECORD结构体组成的链表,它用于Windows OS的SEH。Self成员是_NT_TIB结构体的自引用指针,也是TEB结构体的指针(因为TEB结构体的第一个成员就是_NT_TIB结构体)。那么我们如何在用户模式下访问到TEB结构体呢?只有访问它才能使用相应信息。

TEB访问方法

使用windbg很容易访问

关键是如何在用户模式下访问TEB

Ntdll.NtCurrentTeb()API用来返回当前线程的TEB结构体地址。

打开od进行跟踪后

在这里插入图片描述

NtCurrentTeb函数的内部代码就两行代码,返回FS:[18]地址值。

观察上图中TEB结构体的地址(33E000),发现它与FS段寄存器所指的段内存的基址是一样的。即TEB与FS段寄存器有着联系

其实,FS段寄存器指示当前线程的TEB结构体。

IA-32系统中进程的虚拟内存大小为4GB,因而需要32位的指针才能访问整个内存空间,但是FS寄存器的大小只有16位,那么它如何表示进程内存空间的TEB结构体的地址呢?实际上,FS寄存器并非直接指向TEB结构体的地址它持有SDT 的索引,而该索引持有实际TEB地址。

SDT位于内核区域,其地址存储在特殊的寄存器GDTR(Global Descriptior Table Register,全局描述符表寄存器)中。

GDTR寄存器里面存放一个地址值,即SDT值,找到地址值所在的位置后,然后加上FS段寄存器里面的值(16位寄存器)后,得到一个内存单元,这个内存单元里面存放了一个指针,这个指针指向了TEB结构体的地址,TEB结构体的地址=[FS+SDT],下图可助理解

在这里插入图片描述

这里的段寄存器跟王爽老师里面所说的段寄存器作用不太一样,这里可以把FS段寄存器值看做是一个 偏移值 就好,而起始点存储在GDTR寄存器里面

总结

TEB起始地址=[SDT+FS]

FS:[0x18]=TEB起始地址
(_ NT _TIB结构体的最后一个Self成员恰好位于从TEB结构体的0x18位置,Self指针变量指向 _ NT _TIB结构体的起始地址,也就是TEB的起始地址)

FS:[0x18]=TEB.NtTib.Self=address of TIB=address of TEB = FS:0

FS:[0x30]=PEB起始地址

FS:[0x30]=TEB.ProcessEncironmentBlock=address of PEB

FS:[0]=SEH起始地址
TIB结构体的第一个成员就是ExceptionList是SEH链的入口