代码运行在RING0(系统地址空间)和RING3(用户地址空间)时,FS段寄存器分别指向GDT(全局描述符表)中不同段:在RING3下,FS段值是0x3B(这是WindowsXP下值;在Windows2000下值为0x38。差别就是在XP下RPL=3);运行在RING0下时,FS段寄存器值是0x30。下面以XP为例说说。

 

一.          RING3下的FS

 

当代码运行在Ring3下时,FS值为指向的段是GDT中的0x38段(RPL为3)。该段的长度为4K,基地址为当前线程的线程环境块(TEB),所以该段也被称为“TEB段”。

WINXPSP1及以前的Windows2000等系统中,进程环境块(PEB)的地址固定为0X7FFDF000,该进程的第一个线程的TEB地址为0X7FFDE000,第二个TEB的地址为0X7FFDD000…..但是自从WindowsXP SP2开始PEB和TEB的地址都是随机映射的(详见博文:MiCreatePebOrTeb函数注释)。

 

下图是WindowsXP SP3下的TEB结构(大小为0XFB8):

 

nt!_TEB

   +0x000 NtTib            : _NT_TIB

      +0x000 ExceptionList    : Ptr32

      +0x004 StackBase        : Ptr32

      +0x008 StackLimit       : Ptr32

      +0x00c SubSystemTib     : Ptr32

      +0x010 FiberData        : Ptr32

      +0x010 Version          : Uint4B

      +0x014 ArbitraryUserPointer : Ptr32

      +0x018 Self             : Ptr32  <——

   +0x01c EnvironmentPointer : Ptr32

   +0x020 ClientId         : _CLIENT_ID

      +0x000 UniqueProcess    : Ptr32

      +0x004 UniqueThread     : Ptr32

   +0x028 ActiveRpcHandle  : Ptr32

   +0x02c ThreadLocalStoragePointer : Ptr32

   +0x030 ProcessEnvironmentBlock : Ptr32  <——

   +0x034 LastErrorValue   : Uint4B

   +0x038 CountOfOwnedCriticalSections : Uint4B

   +0x03c CsrClientThread  : Ptr32

   +0x040 Win32ThreadInfo  : Ptr32

……

 

FS:[0X18]就是TEB所在的地址;FS:[0X30]就是PEB所在的地址。由于每个线程的TEB不尽相同,所以GDT中0X30描述符的基地址会随着线程的切换而改变的。我们来看看在什么地方变换的.看