Windows XP 段保护(一)
ʕ •ᴥ•ʔ ɔ:
1 什么是保护模式
R3--SDK
R0--WDK
X86 CPU的3个工作模式:实模式、保护模式和虚拟8086模式。
现在的操作系统都是基于保护模式。
保护模式的两个重要机制:段的机制、页的机制。
保护模式:保护对内存的访问、保护某些指令的执行(特权指令 )
段的机制非常复杂,了解段机制就要先了解段寄存器。
2 段寄存器
段寄存器一共有八个:ES、CS、SS、DS、FS、GS、LDTR(Windows没有使用)、TR。
- 每个段寄存器有96位其中GS、LDTR这两寄存器Windows没有使用。
- LDT表Windows也没有使用。
- 只有16位的可见部分:
Selecter
。
2.1 段寄存器的结构
可以通过结构体表示为如下:
1 | struct SegMent |
汇编读写一个地址:
1 | mov dword ptr ds:[0x00123456],eax |
读写的地址实际上是ds.Base+0x123456
。
实际所有地址的读写都是这个结构:XS.Base+Offset
2.2 段寄存器的属性
段寄存器的读写:
- mov ax,ds //只能读16位可见部分
- mov ds,ax //写入是96位
- 可以通过MOV指令进行读写(LDTR和TR除外)
- CS是可读、可执行、但不可写
1 | int var = 1; |
这里的GS就是FS。
3 段描述符
GDT表存的是段描述符,每个段描述符是64位(8字节)
这里涉及到两张表:GDT(全局描述符表)与 LDT(局部描述符表)。Windows用的是GDT表,LDT表几乎没用。
段描述符结构:(Intel手册卷3A)
段描述符表的位置、大小信息存在GDTR位寄存器中,GDTR寄存器共6字节:
低2字节:段描述符表的大小
高4字节:段描述符表的起始地址
L8:表示输出的组数为8。
3.1 段描述符属性所在位置
Atrribute:高4字节中,8~23位
Base:
- 高4字节中,24~31位,0~7位
- 低4字节中,16~31位
Limit:
- 高4字节中,16~19位
- 低4字节中,0~15位
3.2 段描述查找练习
1 | kd> r gdtr |
4 段选择子
段选择子是一个16位数,该数决定了取gdt表中查哪一个数据。这个值就是MOV DS,AX给的AX的值,从这个值中取赋值剩下的80位(96-16)。
RPL共2位,值越小权限越大。值为0x00、0x11,对应于Windows使用的0环、3环。
加载段描述符至段寄存器(其他几个汇编指令修改段寄存器)
除了MOV指令,我们还可以使用LES、LSS、LDS、LFS、LGS指令修改寄存器。
CS不能通过上述的指令进行修改,CS为代码段,CS的改变会导致EIP的改变,要改CS,必须要保证CS与EIP一起改。
1 | char buffer[6]; |
注意:RPL<=DPL(在数值上)
RPL是段选择子的权限,DPL是段描述符的权限,数值越大权限越小。
5 段描述符的P,G位
P位
- P = 1 段描述符有效
- P = 0 段描述符无效
通过指令将段描述符加载至段寄存器中,先检查P位,如果为0,那么该段描述符无效,其他检查都不做了。
G位
G位决定Limit的大小范围。D/B位对数据段来说决定地址空间大小。
- 当G=0时,Limit的范围是0x00000000-0x000FFFFF,其中,段描述符的20位在低位,高位补0。
- 当G=1时,Limit的范围是0x00000FFF-0xFFFFFFFF,其中,段描述符的20位在高位,低位补F。
6 段描述符的S、Type域
分析一个段描述符:
- 先看P位
- 再看S位(S = 1 代码段或者数据段描述符,S = 0 系统段描述符)
6.1 S位
S=1,表示代码段/数据段;
S=0,表示系统段。
S位决定着Type域的含义。
DPL两种情况:00、11
也就是 00cf9300`0000ffff 的十六进制高四字节第5个数只能为9或F才表示一个有效(P=1)的段描述符CODE/DATA
- S = 1,CODE/DATA
- 0x1001:DPL = 0x00
- 0x1111:DPL = 0x11
- S = 0,系统段描述符
- 0x1000:DPL = 0x00
- 0x1110:DPL = 0x11
6.2 Type域
TYPE域共4位,可以通过查表来确定其含义。(S=1,CODE/DTA、S=0系统段描述符)
- 当S = 1时,段描述符表示CODE/DATA。
- 当S = 0时,段描述符是一个系统段描述符。
S = 1,Type=0x1xxx,CODE代码段描述符
CODE:
- A:段描述符是否被使用过
- 1:使用过
- 0:未使用过
- R:是否可读
- 1:可读
- 0:不可读
- C:一致位
- 1:一致代码段
- 0:非一致代码段
S = 0,Type=0x0xxx,DATA数据段描述符
DATA:
A:段描述符是否被使用过
- 1:使用过
- 0:未使用过
W:是否可写
- 1:可写
- 0:不可写
E:拓展位
1:向下拓展,有效地址为右边红色(红色为64KB或4GB)
0:向上拓展,有效地址为左边红色(Windows使用,红色为64KB或4GB)
6.3 练习
1、判断哪些是系统段描述符?哪些是代码或者数据段描述符?
2、判断哪些是代码段描述符?哪些是数据段描述符?
3、查分几个数据段:EWA
4、查分几个代码段:CRA
5、查分几个系统段描述符,分析属性
先看P位,再看S位。
7 段描述符的D/B位
D/B位对数据段来说决定地址空间大小。
情况一:对CS段的影响(加载:MOV CS, AX)
D = 1 采用32位寻址方式
D = 0 采用16位寻址方式
情况二:对SS段的影响(加载:MOV SS, AX)
D = 1 隐式堆栈访问指令(如:PUSH POP CALL等会修改ESP) 使用32位堆栈指针寄存器ESP
D = 0 隐式堆栈访问指令(如:PUSH POP CALL等会修改SP) 使用16位堆栈指针寄存器SP
指令前缀67:改变默认寻址方式,但不是改D/B位,若默认是32寻址,则改为16位寻址。若默认是16寻址,则改为32位寻址。
情况三:对数据段DS、ES的影响(加载:MOV DS, AX)
D = 1 段上限为4GB 0xFFFFFFFF
D = 0 段上限为64KB 0xFFFF