P位
p = 1时段描述符有效,p = 0时段描述符无效
Base
Base被分成了三个部分,按照实际拼接即可
G位
如果G = 0 说明描述符中Limit的单位是字节,如果是G = 1 ,那么limit的描述的单位是页也就是4kb
S位
S = 1 表示代码段或者数据段描述符,s = 0表示系统描述符
Type域
S位会决定是下面哪种表格,当s = 1 时,说明此时是数据段
其中这张表里面Read可读,Write可写,Execute可执行,accessed被访问过,expand-down表示向下扩展,conformimg表示一致位,这几个里面一致位如果是1,那么就说明这个段所指的内存是纯段没有页的,但是现在的操作系统基本上都有分页,故不再赘述
重点可以说下向下拓展
左边是正常的向上拓展,即base到Limit这一段距离的内存有效,右边是base到Limit这一段距离无效,也就是向下拓展,总的来说,向下拓展就是段所指的这部分内存无效
下面是验证
打开Windbg,可以看见此时ds对应的描述符为00cff300`0000ffff(0x23,也就是index为4)
1: kd> r gdtr
gdtr=807d4c20
1: kd> dq 807d4c20
ReadVirtual: 807d4c20 not properly sign extended
807d4c20 00000000`00000000 00cf9b00`0000ffff
807d4c30 00cf9300`0000ffff 00cffb00`0000ffff
807d4c40 00cff300`0000ffff 80008b7c`f75020ab
807d4c50 8040937c`c0003748 0040f300`00004000
807d4c60 0000f200`0400ffff 00000000`00000000
807d4c70 8000897d`1ac00068 8000897d`1b300068
807d4c80 00000000`00000000 00000000`00000000
807d4c90 800092b9`900003ff 00000000`00000000
还是老样子,把这个描述符移到段选择子对应4b(index号为9)的位置,同时将Type域的值置为6,也就是多加上一个expand-down
1: kd> eq 807d4c68 00cff600`0000ffff
WriteVirtual: 807d4c68 not properly sign extended
1: kd> dq 807d4c20
ReadVirtual: 807d4c20 not properly sign extended
807d4c20 00000000`00000000 00cf9b00`0000ffff
807d4c30 00cf9300`0000ffff 00cffb00`0000ffff
807d4c40 00cff300`0000ffff 80008b7c`f75020ab
807d4c50 8040937c`c0003748 0040f300`00004000
807d4c60 0000f200`0400ffff 00cff600`0000ffff//被修改的在这里
807d4c70 8000897d`1ac00068 8000897d`1b300068
807d4c80 00000000`00000000 00000000`00000000
807d4c90 800092b9`900003ff 00000000`00000000
我们随便找个程序,通过汇编来改动ds的值,下图里面已经修改了ds的值
再运行一步,就跳到了Win的错误(KiUserExceptionDispatcher),这就是报错了
DB位
DB位对不同段的影响不同
对CS段的影响
D = 1 采用32位的寻址方式,D = 0 采用16位的寻址方式
对SS段的影响
D = 1 时,隐式堆栈访问指令(PUSH ,POP,CALL)使用32位堆栈指针寄存器ESP,D = 0时,使用SP
这里两个影响也可以通过修改描述符,但是道理和Type域那里是一样的,就没有必要多来几次了
DPL
描述符特权级别,规定了访问该段所需要的特权级别
AVL
AVL指示是否可以供系统软件使用