本文探讨fs 是否等于fs:0
fs是段选择子,16位。
fs:x 是段寻址,寻找到的地址为32位,此值为fs指向的段段内偏移x处的地址。
根据已知FS:0指向TEB
以此源码为例,windbg双调。
.386
.model flat,stdcall
option casemap:none
.code
start:
int 3
nop
nop
end start
windbg捕获断点
kd> !teb
TEB at 7ffde000
ExceptionList: 0012ffe0
StackBase: 00130000
StackLimit: 0012e000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 7ffde000
EnvironmentPointer: 00000000
ClientId: 00000404 . 00000528
RpcHandle: 00000000
Tls Storage: 00000000
PEB Address: 7ffdf000
LastErrorValue: 0
LastStatusValue: 0
Count Owned Locks: 0
HardErrorMode: 0
为了dump 描述表GDT,查看GDTR寄存器,当然还有fs寄存器
kd> rm ?
1 - Integer state (32-bit) or
2 - Integer state (64-bit), 64-bit takes precedence
4 - Floating-point state
8 - Segment registers
10 - MMX registers
20 - Debug registers and, in kernel, CR4
40 - SSE XMM registers
80 - CR0, CR2 and CR3
100 - Descriptor and task state
kd> rm 100|1
kd> r
eax=00000000 ebx=7ffdf000 ecx=0012ffb0 edx=7c92e4f4 esi=00360036 edi=00360033
eip=00401000 esp=0012ffc4 ebp=0012fff0 iopl=0 nv up ei pl zr na pe nc
gdtr=8003f000 gdtl=03ff idtr=8003f400 idtl=07ff tr=0028 ldtr=0000
001b:00401000 cc int 3
查看fs寄存器
kd> .formats fs
Evaluate expression:
Hex: 0000003b
Decimal: 59
Octal: 00000000073
Binary: 00000000 00000000 00000000 00111011
Chars: ...;
Time: Thu Jan 01 08:00:59 1970
Float: low 8.26766e-044 high 0
Double: 2.91499e-322
fs的结构划分:
按照intel文档的说明,最低的2位表示将要访问的段的权限级为0,第3位这里是0,表示将要访问的段的段描述符从全局描述符表(即GDT)里面取得,剩下的高13位是所为索引值用的
16位fs按照说明应该分为:(0000000000111)(0)(11)
对应结构为(高13位-GDT索引值) (第3位-段描述符获取位置) (低2位-段权限)
GDT中每个索引所占地址为qword
kd> r gdtr
gdtr=8003f000
kd> dw gdtr+7*8 l4
8003f038 0fff e000 f3fd 7f40
段描述符(qword)与段地址相关的部分:
第4个word的高8位为段起始地址的高8位,第3个word的低8位为段起始地址的高 8-15位,第2个word为段起始地址的低16位
cpu从后往前扫 7f40 取7f, f3fd取fd,e000取e000
我们关心的地址结构为:32bit=8+8+16=(7f)+(fd)+(e000)=7ffde000
kd> dq gdtr+7*8 l1
8003f038 7f40f3fd`e0000fff 7f-fd-e000
kd> dd 7ffde000 l1
7ffde000 0012ffe0
kd> !teb
TEB at 7ffde000
ExceptionList: 0012ffe0
StackBase: 00130000
StackLimit: 0012e000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 7ffde000
EnvironmentPointer: 00000000
ClientId: 00000404 . 00000528
RpcHandle: 00000000
Tls Storage: 00000000
PEB Address: 7ffdf000
LastErrorValue: 0
LastStatusValue: 0
Count Owned Locks: 0
HardErrorMode: 0
也就是说:fs:0 的过程为:
1.寻找gdt起始地址 通过gdtr
2.通过fs寻找到在gdt中的地址, 以fs的高13位为索引,地址为gdtr+index*8
3.得到的地址存放的是段描述符,该描述符长度为QWORD。
4.得到fs:0地址。从段地址符中取出高8位+高24位~到低12位前 (8+24)
时间: 2024-11-05 13:28:14