保护模式篇——段权限检查与代码跨段跳转
写在前面
此系列是本人一个字一个字码出来的,包括示例和实验截图。由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我。
你如果是从中间插过来看的,请仔细阅读 羽夏看Win系统内核——简述 ,方便学习本教程。
看此教程之前,问几个问题,基础知识储备好了吗?上一节教程学会了吗?上一节课的练习做了吗?没有的话就不要继续了。
🔒 华丽的分割线 🔒
练习及参考
如下是从虚拟机读取的GDT表的前18个段描述符,下面的实验均按照此进行练习。
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个段描述符。
🔒 点击查看答案 🔒r gdtr //读取GDT表地址 r gdtl //读取GDT表的大小 dq 8003f000 l30 //0x8003f000为GDT表的地址
2️⃣ 在给定的段描述符中,进行拆分练习(至少10个)。
🔒 点击查看答案 🔒本答案仅提供一个样例,其余自行校验: 对于段描述符 0040f300`00000fff : P:1 S:1 G:0 Type:3 DB:1 Base:0 Limit:FFF DPL:3
3️⃣ 拆分如下段选择子。
002B 0023 0010 001B 003B🔒 点击查看答案 🔒
002B: RPL:3 TI:0 Index:5 0023: RPL:3 TI:0 Index:4 0010: RPL:0 TI:0 Index:2 001B: RPL:3 TI:0 Index:3 003B: RPL:3 TI:0 Index:7
4️⃣ 快速辨别给定段描述符是否可用以及段基址、段长(至少10个)。
5️⃣ 从给定段描述符,请按照下面的要求进行练习(全部):
- 快速找出所有数据段,并分析该段属性:只读、已访问、可读可写、拓展方向
- 快速找出所有代码段,并分析该段属性:只执行、可读可执行、已访问、一致代码
- 快速找出所有系统段,并分析属性
我拿出一个段描述符为例进行介绍,学会后可以自行找别的段描述符练习,如下图所示:
表示不同含义的位或十六进制数我都加以区分。由于直接标注在段描述符上非黑色数字通过结构示意图直接能对应上,故不再详细讲解。我们先看
c,它的二进制就是
1100,这个位置大于
8就说明G位有效。同理看
9,这个位置大于
8就说明段描述符有效;为奇数说明为代码段或者数据段,反之为系统段。其他的位不太常用于快速判断,规律可自行总结。 🔒 点击查看答案 🔒
1. 所有的数据段,分析属性自行查表: 00cf9300`0000ffff 00cff300`0000ffff ffc093df`f0000001 0040f300`00000fff 0000f200`0400ffff 00009302`2f40ffff 0000920b`80003fff ff0092ff`700003ff 80009240`0000ffff 2. 所有的代码段,分析属性自行查表: 00cf9b00`0000ffff 00cffb00`0000ffff 80009a40`0000ffff 2. 所有的系统段,分析属性自行查表: 80008b04`200020ab 80008955`22000068 80008955`22680068
6️⃣ 自行构造段选择子和段描述符,并用
加载段描述符至段寄存器中的代码模板和要求取得成功。如果有时间同样把
LSS、
LDS、
LFS、
LGS的实验也类比做了。
🔒 点击查看答案 🔒本题答案不唯一,合理并能够正常运行即可,注意小端存储。此题目有一个坑,自行踩坑。
#include "stdafx.h" int main(int argc, char* argv[]) { //索引为3的短描述符为:00cffb00`0000ffff char buffer[6]={0xff,0xff,0xff,0xff,0x18,0x00}; _asm { les ecx,fword ptr ds:[buffer] //高2个字节给es,低四个字节给ecx } return 0; }
7️⃣ 如何在调试器中快速判断程序在几环权限。
🔒 点击查看答案 🔒根据CS或者SS,因为它存储的是段选择子,可以通过低两位直接判断。
8️⃣ 自学修改GDT表的相关知识,并思考如下问题。
r gdtr dq 8003f090 00cffb00`0000ffff r gdtr
8003f090是GDT表中的一个段描述符的地址,更改后发现并没有更改,请思考为什么会这样。 🔒 点击查看答案 🔒
你看我之前写读取GDT表为什么用地址了吗?你再用地址
dq以下看看。
CPL/RPL/DPL
- CPL:CPU当前的权限级别
- DPL:如果你想访问我,你应该具备什么样的权限(CPL)
- RPL:用什么权限去访问一个段
RPL存在的意义:
举个例子,我们本可以用
读写的权限去打开一个文件,但为了避免出错,有些时候我们使用
只读的权限去打开。
一致代码段与非一致代码段
对于一致代码段,也称为共享段:
- 特权级高的程序不允许访问特权级低的数据:核心态不允许访问用户态的数据
- 特权级低的程序可以访问到特权级高的数据,但特权级不会改变:用户态还是用户态
对于非一致代码段:
- 只允许同级访问
- 绝对禁止不同级别的访问:核心态不是用户态,用户态也不是核心态
数据段的权限检查
数值上,
CPL<=
DPL且
RPL<=
DPL。同时满足上述条件才能通过。
代码段的权限检查
下面的比较都是数值上的比较:
- 如果是非一致代码段,要求:
CPL
==DPL
且RPL
<=DPL
- 如果是一致代码段,要求:
CPL
>=DPL
代码跨段基础
代码跨段本质就是修改CS段寄存器。前面的教程介绍过段寄存器读写,除CS外,其他的段寄存器都可以通过
MOV/
LES/
LSS/
LDS/
LFS/
LGS指令进行修改。但是
CS为什么不可以直接修改呢?
CS的改变意味着
EIP的改变,改变
CS的同时必须修改
EIP,故我们无法使用上面的指令来进行修改,这个也是CPU不允许的。
代码间的段间跳转
段间跳转,有2种情况,即要跳转的段是一致代码段还是非一致代码段,它们不同做的权限检查就不同。 同时修改
CS与
EIP的指令如下:
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️⃣ 代码执行
CPU将
CS.Base + Offset的值写入
EIP然后跳转到将要执行的
CS:EIP处的代码,段间跳转结束。
直接对代码段进行
JMP或者CALL的操作,无论目标是一致代码段还是非一致代码段,CPL都不会发生改变。如果要提升CPL的权限,只能通过调用门。
本节练习
本节的答案将会在下一节进行讲解,务必把本节练习做完后看下一个讲解内容。不要偷懒,实验是学习本教程的捷径。
俗话说得好,光说不练假把式,如下是本节相关的练习。如果练习没做好,就不要看下一节教程了,越到后面,不做练习的话容易夹生了,开始还明白,后来就真的一点都不明白了。本节练习很少,请保质保量的完成。
1️⃣ 记住代码段间跳转的执行流程。 2️⃣ 自己实现一致代码段的段间跳转。 3️⃣ 自己实现非一致代码段的段间跳转。
下一篇
- 实模式跳转保护模式,代码全注释
- 保护模式4-段权限检查
- 实模式跳转保护模式,代码全注释
- 用vbs检查注册表项的访问权限的代码
- ASP.NET 2.0 HttpHandler实现对某种文件类型权限保护(示例代码下载)
- 保护模式下,什么是一致性代码和非一致性代码段
- (实模式+保护模式)模式切换的过程步骤(代码+文字解析)
- 2013-02-23 -一个简单的实模式跳转到保护模式程序(无loader功能)
- 鬼影3样本Mbr之后保护模式代码详细注释(最精华的地方啦)
- 80386保护模式--分页机制,附pmtest8代码详解
- 实模式跳转到保护模式时用到的概念
- 从实模式到保护模式跳转的详解
- 实模式跳转到保护模式
- 在Offline模式下使用Emma进行代码覆盖率检查(命令行方式)
- ASP.NET 2.0 HttpHandler实现对某种文件类型权限保护(示例代码下载)
- java 反射机制 之 getDeclaredField 获取私有保护字段, 再setAccessible(true)取消对权限的检查 实现对私有的访问和赋值
- [系列]OS学习-自己写操作系统(3)- 实模式到保护模式的跳转
- IOS问题汇总:2014-12-11 iOS应用检查更新的最优方法附代码(转)+在 iOS 应用中直接跳转到 AppStore 的方法
- x386保护模式下的特权级互相跳转小结
- 【Android 权限检查】写业务代码写久了,权限问题都不记得了,还好意思么。。