写在前面

  此系列是本人一个字一个字码出来的,包括示例和实验截图。由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我

  看此教程之前,问几个问题,


🔒 华丽的分割线 🔒


练习及参考

8003f000  00000000`00000000 00cf9b00`0000ffff
8003f010  00cf9300`0000ffff 00cffb00`0000ffff
8003f020  00cff300`0000ffff 80008b04`200020ab
8003f030  ffc093df`f0000001 0040f300`00000fff
8003f040  0000f200`0400ffff 00000000`00000000
8003f050  80008955`22000068 80008955`22680068
8003f060  00009302`2f40ffff 0000920b`80003fff
8003f070  ff0092ff`700003ff 80009a40`0000ffff
8003f080  80009240`0000ffff 00009200`00000000

1️⃣ 练习读取GDT表的位置和长度,并显示GDT表前48个段描述符。

2️⃣ 在给定的段描述符中,进行拆分练习(至少10个)。

3️⃣ 拆分如下段选择子。

002B 0023 0010 001B 003B

4️⃣ 快速辨别给定段描述符是否可用以及段基址、段长(至少10个)。

5️⃣ 从给定段描述符,请按照下面的要求进行练习(全部):

  1. 快速找出所有数据段,并分析该段属性:只读、已访问、可读可写、拓展方向
  2. 快速找出所有代码段,并分析该段属性:只执行、可读可执行、已访问、一致代码
  3. 快速找出所有系统段,并分析属性

6️⃣ 自行构造段选择子和段描述符,并用加载段描述符至段寄存器中的代码模板和要求取得成功。如果有时间同样把LSSLDSLFSLGS的实验也类比做了。

7️⃣ 如何在调试器中快速判断程序在几环权限。

8️⃣ 自学修改GDT表的相关知识,并思考如下问题。

r gdtr
dq 8003f090 00cffb00`0000ffff
r gdtr

  8003f090是GDT表中的一个段描述符的地址,更改后发现并没有更改,请思考为什么会这样。


CPL/RPL/DPL

  • CPL:CPU当前的权限级别
  • DPL:如果你想访问我,你应该具备什么样的权限(CPL)
  • RPL:用什么权限去访问一个段

RPL存在的意义:

  举个例子,我们本可以用读写的权限去打开一个文件,但为了避免出错,有些时候我们使用只读的权限去打开。

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

对于一致代码段,也称为共享段:

  • 特权级高的程序不允许访问特权级低的数据:核心态不允许访问用户态的数据
  • 特权级低的程序可以访问到特权级高的数据,但特权级不会改变:用户态还是用户态

对于非一致代码段:

  • 只允许同级访问
  • 绝对禁止不同级别的访问:核心态不是用户态,用户态也不是核心态

数据段的权限检查

  数值上,CPL<=DPLRPL<=DPL。同时满足上述条件才能通过。

代码段的权限检查

  下面的比较都是数值上的比较:

  • 如果是非一致代码段,要求:CPL==DPLRPL<=DPL
  • 如果是一致代码段,要求:CPL>=DPL

代码跨段基础

  代码跨段本质就是修改CS段寄存器。前面的教程介绍过段寄存器读写,除CS外,其他的段寄存器都可以通过MOV/LES/LSS/LDS/LFS/LGS指令进行修改。但是CS为什么不可以直接修改呢?CS的改变意味着EIP的改变,改变CS的同时必须修改EIP,故我们无法使用上面的指令来进行修改,这个也是CPU不允许的。

代码间的段间跳转

  段间跳转,有2种情况,即要跳转的段是一致代码段还是非一致代码段,它们不同做的权限检查就不同。
  同时修改CSEIP的指令如下:JMP FAR/CALL FAR/RETF/INT/IRETED

  本篇只介绍段间跳转,故只使用JMP FAR,即为长跳转。下面我举个示例来进行讲解:

CPU如何执行这行代码JMP 0x20:0x004183D7

1️⃣ 段选择子拆分
  0x20对应二进制形式:0000 0000 0010 0000

  • 解析结果:
    • RPL = 0
    • TI = 0
    • Index = 4

2️⃣ 查表得到段描述符

  TI=0 所以查GDT表,Index=4找到对应的段描述符。注意四种情况可以跳转:代码段、调用门、TSS任务段、任务门。后面的几种将会在以后的教程详细讲解。

3️⃣ 权限检查

  请参考本节的代码段的权限检查

4️⃣ 加载段描述符
  通过上面的权限检查后,CPU会将段描述符加载到CS段寄存器中。

5️⃣ 代码执行
  CPUCS.Base + Offset的值写入EIP然后跳转到将要执行的CS:EIP处的代码,段间跳转结束。

本节练习

  俗话说得好,光说不练假把式,如下是本节相关的练习。如果练习没做好,就不要看下一节教程了,越到后面,不做练习的话容易夹生了,开始还明白,后来就真的一点都不明白了。本节练习比只有很少,请保质保量的完成。

1️⃣ 记住代码段间跳转的执行流程。
2️⃣ 自己实现一致代码段的段间跳转。
3️⃣ 自己实现非一致代码段的段间跳转。

下一篇

  保护模式篇——调用门、中断门、陷阱门

09-21 18:47