Windows保护模式学习笔记(一)—— 段寄存器&GDT表

  • 保护模式
  • 参考书籍:
  • 一、段寄存器
    • 段寄存器的结构
    • 段寄存器的读写
    • 段寄存器的属性
      • 1)探测Attribute:
      • 2)探测Base:
      • 3)探测Limit:
  • 二、GDT表与LDT表
    • GDT表
      • 1)段描述符
        • 段描述符的属性
        • 段描述符与段寄存器结构的对应关系
      • 2)段选择子
    • 加载段描述符到段寄存器
    • 段权限检查
      • 1) CPU分级概念
      • 2) 进程特权级别
        • 当前特权级(CPL)
        • 请求特权级(RPL)
      • 3)数据段的权限检查

保护模式

X86 CPU的三个模式:实模式保护模式虚拟8086模式

参考书籍:

《Intel白皮书第三卷》

一、段寄存器

什么是段寄存器?

当我们用汇编读写某一个地址时:

mov dword ptr ds:[0x123456], eax

我们真正读写的地址是:

ds.base + 0x123456

段寄存器有几个,有哪些?

有八个,分别是:

ES CS SS DS FS GS LDTR TR

段寄存器的结构

结构图表示:


结构体表示:

struct SegMent
{WORD Selector;     // 段选择子 16位 可见WORD Atrributes;  // 段属性 16位 不可见DWORD Base            // 段起始地址 32位 不可见DWORD Limit         // 段大小 32位 不可见
}

段寄存器的读写

读:MOV AX,ES
写:MOV DS,AX
注意:段寄存器在的时候只读16位,但的时候会写入96位!
思考:如何证明向段寄存器写入时写了96位?

段寄存器的属性

属性图:

图中红色字体部分在不同环境中可能不同

1)探测Attribute:

在编辑器中尝试编译并执行以下代码:

int var = 0;
__asm
{mov ax,ss          // 此处不能为CS CS可读 可执行 但不可写mov ds,axmov dword ptr ds:[var],eax
}

编译器能成功编译上述代码,并且程序运行过程中没有报错


再在编辑器中尝试编译并执行以下代码:

int var = 0;
__asm
{mov ax,cs          // SS 改成了 CSmov ds,axmov dword ptr ds:[var],eax
}

编译器能成功编译上述代码,但程序运行过程中报错

上面的两个例子说明段寄存器的Attribute在写入时会被更改!

2)探测Base:

在编辑器中尝试编译并执行以下代码:

int var = 1;
__asm
{                   mov ax,fs               mov gs,ax               mov eax,gs:[0]      // 不要使用DS 否则编译不过去mov dword ptr ds:[var],eax // = mov edx,dword ptr ds:[0x7FFDF000]
}

编译器能成功编译上述代码,并且程序运行过程中没有报错

说明段寄存器的Base在写入时会被更改!

3)探测Limit:

int var = 1;
__asm
{                   mov ax,fs               mov gs,ax               mov eax,gs:[0x1000]// 访问的地址相当于下面这行注释的代码 但DS的Limit是0xFFFFFFFF// mov eax,dword ptr ds:[0x7FFDF000+0x1000]mov dword ptr ds:[var],eax
}

编译器能成功编译上述代码,但程序运行过程中报错
这是因为 FS 段寄存器的 Limit 为 0xFFF,而我们输入的段偏移为0x1000

思考:段寄存器在写入时,只给了16位,剩下的80位填什么?数据从哪里来?

二、GDT表与LDT表

GDT:全局描述符表
LDT :局部描述符表

当我们执行类似MOV DS, AX指令时,CPU会查表,根据AX的值来决定查找GDT还是LDT,查找表的什么位置,以及查出多少数据

GDT表

工具:WinDbg

gdtr是一个寄存器,存储了GDT表所在位置
gdtl也是一个寄存器,存储了GDT表的大小

在内存中查看GDT表

第一排的数据为内存地址,红框中的数据才是真正的内存数据,即GDT表
我们已经知道如何查看GDT表了,但是如果想要看懂这张表,得先学习段描述符段选择子

1)段描述符

描述:GDT表中存储的元素称为段描述符
大小:每个段描述符占用空间为8个字节

为了更方便观察,在WinDbg中使用dq命令查看GDT表:

段描述符结构图:

段描述符高位在前低位在后
例如GDT表的第二项:00cf9b00`0000ffff
00cf9b00对应结构图的高四字节(上面一行),0000ffff对应结构图的低四字节(下面一行)

段描述符的属性

P位
P = 1:段描述符有效
P = 0:段描述符无效

段描述符加载时,首先看P位是否为1

G位
G=0:段寄存器的Limit元素单位为字节,最大值为0x000FFFFF
G=1:段寄存器的Limit元素单位为4KB,最大值为0xFFFFFFFF

S位
S = 1:段描述符为代码段数据段描述符
S = 0:段描述符为系统段描述符

Type域
S = 1时,即段描述符为代码段或数组段描述符时,Type域结构图如下:

第11位为0:段描述符为数据段描述符
第11位为1:段描述符为代码段描述符
A位:若该代码段/数据段未被访问过,则值为0,否则为1
W位:若为1,表示该段可写
E位:若为0,则向上拓展,若为1,则向下拓展
图例:

向上拓展:有效范围为fs.Base ~ fs.Base+Limit
向下拓展:有效范围除了fs.Base ~ fs.Base+Limit

R位:若为1,表示该段可读
C位:一致位。若为1,则是一致代码段;若为0,则是非一致代码段


S = 0时,即段描述符为系统段描述符时,Type域结构图如下:

D\B位
情况1:对CS段的影响

D=1:采用32位寻址方式
D=0:采用16位寻址方式

情况2:对SS段的影响

D=1:隐式堆栈访问指令(如:PUSH POP CALL)使用32位堆栈指针寄存器ESP
D=0:隐式堆栈访问指令(如:PUSH POP CALL)使用16位堆栈指针寄存器SP

情况3:向下拓展的数据段

D=1:段上限为4GB
D=0:段上限为64KB


DPL
描述:

DPL存储在段描述符中,规定了访问所在段描述符所需要的特权级别是多少
DPL数值越大,访问所在段描述符所需要的权限越低
注意:在Windows中,DPL只会出现两种情况,要么全为0,要么全为1

例:
若AX指向的段描述符的DPL=0,但当前程序的CPL=3,那么这条指令是不会成功的!

段描述符与段寄存器结构的对应关系

Attribute:位于段描述符高四字节的第8-23位
Base:由三部分组成
第一部分:位于段描述符高四字节的第24-31位
第二部分:位于段描述符高四字节的第0-7位
第三部分:位于段描述符低四字节的第16-31位
Limit:由两部分组成
第一部分:位于段描述符高四字节的第16-19位
第二部分:位于段描述符低四字节的第0-15位

2)段选择子

描述:

段选择子是一个16位的段描述符,该描述符指向了定义该段的段描述符

段选择子结构图:

字段说明
RPL:请求特权级别
TI:TI=0 查GDT表;TI=1 查LDT表
Index:处理器将索引值乘以8在加上GDT或者LDT的基地址,就是要加载的段描述符

加载段描述符到段寄存器

除了MOV指令,还可以使用LES、LSS、LDS、LFS、LGS指令修改段寄存器
注意:不存在LCS指令,因为CS不可写

例:

char buffer[6];
__asm
{           les ecx,fword ptr ds:[buffer] //高2个字节给es,低四个字节给ecx
}

实验:为buffer赋值,并成功执行以上代码
注意:RPL<=DPL(在数值上)

段权限检查

1) CPU分级概念

平时我们称应用程序为3环,系统程序为0环,前面这句话只与CPU有关,与操作系统无关

思考:如何判断某个程序处于哪一环?

2) 进程特权级别

当前特权级(CPL)

描述:

段寄存器 CS 的后两位比特位称为当前特权级
注意:段选择子SS和CS的后两位比特位相同

如:
→ CS = 0x001B
→ 0x001B = 二进制:0000 0000 0001 1011
→ 二进制:11 = 十进制:3
→ 因此:当前进程处于3环

请求特权级(RPL)

描述:

RPL是段选择子结构中的一部分
RPL是针对段选择子而言的,每个段的选择子都有自己的RPL
RPL表示用什么权限去访问一个段

例:

MOV AX,0008
MOV DS,AX
与
MOV AX,000B
MOV DS,AX
指向的是同一个段描述符,但RPL不同

3)数据段的权限检查

检查:CPL<= DPL并且 RPL<= DPL(数值上的比较)

例:

当CPL = 0时执行以下指令:MOV AX,000B          // RPL=3,请求权限为3MOV DS,AX            // 假设ax指向的段描述符的DPL=0
上述指令虽然满足了CPL<=DPL,但RPL>DPL,因此执行失败

注意:代码段和系统端描述符的检查方式不一样

思考:既然已经有CPL(当前特权级别)了,为什么还要有RPL(请求特权级别)
回答:我们本可以用“读写”的权限去打开一个文件,但为了避免出错,有些时候我们使用“只读”的权限去打开

Windows保护模式学习笔记(一)—— 段寄存器GDT表相关推荐

  1. Windows保护模式学习笔记(五)—— 任务段任务门

    Windows保护模式学习笔记(五)-- 任务段&任务门 要点回顾 任务段 TSS (Task-state segment ) TR段寄存器 TR段寄存器的读写 TSS段描述符 实验:加载自定 ...

  2. Windows保护模式学习笔记(二)—— 代码跨段跳转

    Windows保护模式学习笔记(二)-- 代码跨段跳转 要点回顾 代码跨段跳转 执行流程 1)段选择子拆分 2)查表得到段描述符 3)权限检查 4)加载段描述符 5)代码执行 6)总结 一致代码段(共 ...

  3. Windows保护模式学习笔记(十二)—— 控制寄存器

    Windows保护模式学习笔记(十二)-- 控制寄存器 控制寄存器 Cr0寄存器 Cr2寄存器 Cr4寄存器 控制寄存器 描述: 控制寄存器有五个,分别是:Cr0 Cr1 Cr2 Cr3 Cr4 Cr ...

  4. Windows保护模式学习笔记(六)—— 10-10-12分页

    Windows保护模式学习笔记(六)-- 10-10-12分页 基本概念 4GB内存空间 有效地址-线性地址-物理地址 有效地址与线性地址 物理地址 控制寄存器:Cr3 10-10-12分页 实验:通 ...

  5. Windows保护模式学习笔记(三)—— 长调用/短调用/调用门

    Windows保护模式学习笔记(三)-- 长调用/短调用/调用门 要点回顾 长调用与短调用 一.短调用 二.长调用(跨段不提权) 三.长调用(跨段并提权) 长调用执行时: 执行返回(RETF)时: 总 ...

  6. Windows保护模式学习笔记(十)—— TLB

    Windows保护模式学习笔记(十)-- TLB 地址解析 10-10-12分页 2-9-9-12分页 TLB TLB结构 TLB种类 练习1:体验TLB的存在 第一步:运行代码 第二步:设置中断门描 ...

  7. Windows保护模式学习笔记(九)—— 2-9-9-12分页

    Windows保护模式学习笔记(九)-- 2-9-9-12分页 要点回顾 10-10-12分页 原理 环境配置 2-9-9-12分页 原理 PDPTE PDE PTE XD/NX标志位 环境配置 实验 ...

  8. Windows保护模式学习笔记(七)—— PDEPTE

    Windows保护模式学习笔记(七)-- PDE&PTE Cr3 PDE(页目录表项) PTE(页表项) 物理页的属性 10-10-12分页的补充 实验1:证明PTE的特征1 第一步:选择一个 ...

  9. Windows保护模式学习笔记(十四)—— 阶段测试

    Windows保护模式学习笔记(十四)-- 阶段测试 题目一 解题步骤 题目二 解题步骤 题目一 描述:给定一个线性地址,和长度,读取内容 int ReadMemory(OUT BYTE* buffe ...

最新文章

  1. 技术以外的功夫 ----作者:李天平
  2. 双11稳定性负责人叔同讲述:九年双11的云化架构演进和升级
  3. 《c++语言导学》——3.5 建议
  4. [css] 在固定宽度的div下,怎么让字体自适应大小,不超出宽度,也不要换行
  5. ElasticSearch学习(一):Linux环境准备
  6. 电子电路设计小目录------面包板制作130例
  7. IDEA热更新插件-JRebel安装
  8. Windows 搭建 翼龙面板 ( Pterodactyl ) 前端 教程
  9. VBA实现EXCEL随机本地随机刷题
  10. Oracle for update skip locked 详解
  11. 海洋大数据应用关键技术及应用前景
  12. 【数据压缩】压缩率-图像熵-保真度
  13. chrome浏览器打开网址找不到服务器IP
  14. 《Turtle绘图》Python用Turtle库绘制多啦爱梦、小猪佩奇、皮卡丘等卡通人物
  15. Tomcat 部署多个SpringBoot 项目:ERROR org.springframework.boot.actuate.endpoint.jmx.EndpointMBeanExporter
  16. linux系统没ip,树莓派在没有显示器情况下查找未知IP教程
  17. 网络体系结构基本概念及OSI七层模型
  18. js对象新增方法object.assign()
  19. Android iOS Mac QQ邮箱 日历同步
  20. vue父子组件及非父子组件之间的传值

热门文章

  1. ML之NB、LoR:基于NB和LoR算法对Kaggle IMDB影评数据集(国外类似豆瓣电影)情感分析进行分类
  2. 成功解决VMware虚拟机中的please remove the installation medium then press enter
  3. Windows系统下使用protobuf:protobuf的简介、安装、使用方法之详细攻略
  4. MongoDB学习笔记【2】-- 试用
  5. 读书不言迟,不读终身痴[转]
  6. 五分钟搞定 Linux 文档全部知识,就看这篇文章
  7. 《JAVA程序设计》_第四周学习总结
  8. LeetCode:汇总区间【228】
  9. dockerfile centos+jdk+时区设置
  10. git错误fatal: remote origin already exists.