(2) [保护模式]段描述符

本文详细解析了段选择子和段描述符在x86架构中的作用和结构,包括段选择子的index、TI、RPL字段,以及段描述符的Base、Limit、P、G、D/B、type、DPL等属性。内容涵盖段寄存器填充、向上拓展与向下拓展、一致代码段与非一致代码段的区别,还有隐式堆栈访问规则。通过实例展示了如何使用windbg调试工具查询GDT表。
摘要由CSDN通过智能技术生成


如果文中有错误,还请指正

1. 段选择子

首先我们来看段选择子构成

在这里插入图片描述
图片取自 intel白皮书三卷 Vol. 3A 3-7

上面的那些位到底代表着什么呢?

  1. index : 这个表示的是一个指向GDT表的索,而GDT表中存放的就是我们所想看到的段描述符了 (因特尔没有使用LDT表),我将如何使用index查询GDT表放在了最后

    原文中写道:这是一个指向GDT表或LDT表的索引 (GDT表的位置(base address)由GDTR寄存器存放,LDT表的位置(base address)由LDTR寄存器存放)

  2. TI (table indicator flag) : 如图所示,TI == 0时,会到GDT表中查询段描述符,TI == 1时,到LDT表中查询 (windows 的TI永远都是0)

  3. RPL (Requested Privilege Level) : 请求权限级别,下文DPL一同讲解

那么该如何拆分一个段选择子呢?

  • 例1: 0x0023 = 0000 0000 0010 0011 B,稍微划分一下 0000 0000 00100 0 11,所以index = 100 B = 4,TI = 0,RPL = 11 B = 3
  • 例2: 0x0008 = 0000 0000 0000 1000 B,index = 1, TI = 0,RPL = 0
  • 例3: 0x002B = 0000 0000 0010 1011 B,index = 5, TI = 0,RPL = 3

2. 段描述符

先看这张图,这就是段描述符的样子啦
接下来会对这张图进行循序渐进地解释。
为了描述的连续性,我将一些次要的东西放在了最后

在这里插入图片描述
图片取自 intel白皮书三卷 Vol. 3A 3-10

struct 段寄存器 {
	WORD  selector;
	WORD  attibute;
	DWORD base;
	DWORD limit;
}
  • Base Address : 一共32位,直接存放到段寄存器相应的Base段即可
  • Segment Limit : ( 16 - 19 ) 位 + ( 0 - 15 ) 位,可表示位数为 0x0 - 0xFFFFF (共计20位,那么如何使用20位的 Segment Limit 来填充32位的 Limit 呢,请看G位)

  • P (segment-present) : 这个描述符是否有效, P == 1有效, P == 0无效

如果P == 0那么这个段描述符就没有什么意义了,一个有效的描述符P一定是1


  • G (granularity) : 用于填充32位的Limit
    • 当G ==1时,Limit = 0xFFF + Segment Limit << 0xC
    • 当G == 0时,Limit = 0x0 + Segment Limit.

我将如何填充段寄存器隐藏位写在了最后

> 举个例子 :
> - G = 1,Segment Limit = 0x12345 
>  Limit  = 0xFFF + Segment Limit << 0xC = 0xFFF + 0x12345 << 0xC = 0x12345==FFF==
> - G = 0,Segment Limit = 0x12345 
>  Limit  = 0x00000000 + Segment Limit = 0x00000000 + 0x12345 = 0x==000==12345

  • type : 下面的表描述的就是type这四个字节了,看不懂的话可以看下面对于S位的解释

在这里插入图片描述
图片取自 intel白皮书 Vol. 3A 3-12 (不是我用那本,我用的书,图不太直观,所以我更喜欢上面这张)

type位是与S位息息相关的,下面仅仅写出了当 S == 0 时的 type 位含义

  • S (descriptor type) : 系统段描述符
    • S == 1时,代表这是代码段数据段的描述符
      • 第11位 == 0 时,代表的是数据段的描述符
        • (第8位)
          A == 0 时,代表没有被访问过
          A == 1 时,代表没有被访问过
        • (第9位)
          W == 0 时,代表不可写,
          W == 1 时,代表可写
        • (第10位)
          E == 0 时,代表向上拓展
          E == 1 时,代表向下拓展
      • 第11位 == 1 时,代表的是代码段的描述符
        • (第8位) A同上
        • (第9位)
          R == 0 时,代表不可读,
          R == 1 时,代表可读
        • (第10位)
          E == 0 时,代表一致代码段
          E == 1 时,代表非一致代码段
    • S == 0 时,代表这是系统段的描述符
      这里涉及到调用门中断门陷阱门,任务段

  • D/B
    • 对CS段的影响
      • D/B == 0,默认16位寻址
      • D/B == 1,默认32位寻址
    • 对SS段的影响
    • 对数据段向下拓展的影响
      • D/B == 0,向下拓展的范围是除了Limit之外的0 - 64K空间
      • D/B == 1,向下拓展的范围是除了Limit之外的0 - 4G空间

有关于隐式堆栈访问向下拓展,点击跳转到文章尾部查看


  • DPL (descriptor privilege level) : 访问该段所需要的特权级别
    注:CPL (current privilege level) : 当前特权级别 (CS寄存器中存放的低2位就是CPL,如:当前的CS寄存器中的值为 0x1B = 0001 1011B,所以CPL = 3)
 mov ax, 0x000B 	//0000 0000 0000 1011  RPL = 3
 mov ds, ax 		//ax指向的段描述符的DPL = 0

数值越大权限越低,windows分为 ring 0 和 ring 3,ring 0为系统层,ring 3为用户层
当且仅当 CPL <= DPL && RPL <= DPL 时,语句才能正常执行,也就是说低权限不能访问高权限


AVL : Available and Reserved Bit (简单理解就是 保留位,通常设为0)

白皮书中写道:Bit 20 of the second doubleword of the segment descriptor is available for use by system software. (第二个双字的第20位段描述符可供系统软件使用)


L : 64位扩展使用,兼容模式下(32位程序)为0,L为1则D一定为0
(感兴趣可以查白皮书 Vol. 3A 3-13)


注解:

段选择子index的使用

  1. 打开虚拟机,并使用windbg进行调试
  2. 进入桌面后点击break按钮暂停调试
    在这里插入图片描述
  3. 输入指令 dq gdtr L20,其中dq指令表示显示内存地址 gdtr 开始后20个地址,并以8字节为一组
    同样的,我们也可以输入r gdtr来查看gdtr寄存器里的值,这个值指向GDT表,所以我们可以使用dq 0x8003f000 来查看GDT表 (对应dq指令,我们还可以使用 dd, db 指令分别按查询dword查询和按byte查询)
    在这里插入图片描述
  4. 我们选择一个段选择子0x2B作为演示,0x2B = 00101 0 11 B,其中index = 5,所以查GDT表中下标为5的一个8字节,
    在这里插入图片描述

查GDT表填充段寄存器

我们沿用上面的index = 5,所以查到的段描述符为 80008b04`200020ab,然后查表,首先填充
attribute : 80 008b 04`200020ab,所以 attribute = 008b
base : 80 008b 04 ` 2000 20ab,所以 base = 80042000
limit : 80 0 0 8b04`2000 20ab,所以 limit = 000 020ab (G = 0)

index = 2, 00 c f 93 00 ` 0000 ffff
attribute : cf93,base : 00000000,limit : fffff fff (G = 1)


向上拓展与向下拓展

在这里插入图片描述

课件里的图片,搬过来用了

  • 图片中左边的是向上拓展,代表的是只有红色部分的Limit是可访问
  • 图片中右边的是向下拓展,同样是只有红色部分能够访问,相当于除了Limit的地址不能访问,其他地址都能访问,相当于对Limit取反操作的地址有效

一致代码段与非一致代码段

  • 一致代码段:当前特权级别为低权限也可以直接访问高权限代码段,比如ring 3直接访问ring 0中的一致代码段,但高权限不允许访问低权限
    条件:CPL >= DPL
  • 非一致代码段:必须拥有相同等级的特权才能访问
    条件:CPL == DPL && RPL <= DPL

隐式堆栈访问

当使用push, pop, call等操作时,会对寄存器进行一些修改的操作,例如push eax,相当于 sub esp, 4mov [esp], eax 这里的esp并没有显式写出来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值