保护模式-第4讲-段-段跨越段权限
保护模式-第4讲-段-段跨越段权限
一丶段描述符 段选择子 等段特权级讲解
1.1 CPU层面的模式
这一点主要是了解下. 我们很多时候都听别人说 ring3 ring0 其实就是 CPU的等级划分.
不同的级别可以执行不同的 特权指令. 比如 IN OUT 等指令.在16位 实模式下就可以直接执行.
而保护模式下就不让你执行了. 原因就是 CPU分了等级了. 一共四个等级. ring3 - ring 0 而操作系统只使用了 ring3 与 ring0 所以 ring3就是应用程序. ring0 就是内核程序. 应用程序不可以执行特权指令
内核程序可以执行特权指令. 请注意. CPU是有4个等级的. ring3 ring 2 ring 1 ring0 操作系统使用了两个. 也就是微软使用了两个. 所以不要搞混. 我们要知道 特权级别是CPU提供. 微软只是使用而已.
1.2 CPL RPL DPL 讲解
1.2.1 CPL RPL DPL 介绍
根据inter手册图表示
-
CPL
CPL 是在CS 与 SS 段寄存器中的 bit 0位与 bit1位 记住是CS段寄存器. 它来表示我们的程序的当前特权级别. 也就是说 表示你是 运行在ring3的权限. 还是 ring0的权限.
-
RPL bit 0 bit1
RPL是段选择子的特权级别. 举个例子.看如下代码
mov ds,ax
ax里面是一个值.我们知道这个值是一个 段选择子 拆分开来可以是索引. 根据这个索引去GDT表中寻找对应的段描述符 然后段描述符 赋值给ds. 但是我们有没有想过. CPU执行这条指令的时候.为什么要去查.难道不该限制吗.不管是ring3 还是 ring0都可以查表吗. 不是这样的. RPL就是一个限制. 表示你想请求的特权级别. 当你请求的特权级别不满足.那么CPU肯定不会执行这条指令的.
那么不满足什么那. 就是我们下面所说的DPL
-
DPL 高13 14位
DPL是描述段描述符的. 是指明了我们这个段描述符 你想访问我你需要什么权限. 也就是说我们的RPL想访问段描述符. 会跟 DPL做对比. <= DPL才可以访问. 进而操作这个段描述符.
还是以代码为例子
mov ds,ax
这条指令是执行在ring3的. 所以不用说 CS 的低两位 = 11 也就是3
但是我们知道 ax是一个段选择子.回去找GDT表中的段描述符. 而ax指向的这个段描述符的DPL正好是0 就是特权很高. 0是最高特权. 那么这条指令不会成功. 原因就是 CPL > DPL CPL必须<= DPL才能成功. 就是是一次段特权级别的 比较.
核心就是DPL 任何CPL RPL 都是为访问DPL(段描述符)来进行准备的. 如果不与DPL相等或者小于 那么 就可以访问. 如果大于 那么久拒绝你访问
-
三种特权级别的表示方法
CPL bit0 bit1 == 1 表示 ring3应用 也就是CPL = 3 代表你是处于ring3的程序
CPL bit0 bit1 == 0 表示 ring0 程序. 运行在ring0中.
CS/SS CPL在同一时间特权都是一样的.X86规定的.也就是说 CS = 3 那么SS 也是3 CS = 0 SS 也是0
RPL 选择子 RPL特选级别 要么是0 要么是3 也就是 RPL 要么两位都是0 要么都是1
DPL DPL == 0 级别权限很高.
DPL = 3 级别权限低. 只要 CPL RPL <= 3都可以访问.
1.2.2 CPL RPL DPL的检查
CPL RPL DPL我么知道是啥了.那么我么可以进行模拟.
-
DPL针对数据段的权限检查
CPL <= DPL 且 RPL <= DPL 才可以执行指令成功
举个例子
CS = 8 代表当前特权级别是ring0 mov ax,0xF 段选择子为 1111 二进制 RPL是 3 mov dx,ax 执行指令操作
执行指令操作有. 优先与CPL比.然后在于RPL比.
根据指令我们知道 我们是在内核层执行的特权指令. mov dx,ax
首先检查CPL CPL = 0 DPL = 0 CPL<DPL 成立. 所以代表当前指令可以执行
继续比较
RPL = 3 DPL = 0 RPL<=DPL 不成立. 拒绝指令. 所以这三行指令表达了
指令可以执行.但是 你访问这个段描述符的权限不足. 所以不让你访问.
二丶代码跨段
3.1 代码跨段原理以及本质
3.1.1 原理及其本质
代码跨段的原理是修改CS 寄存器. 但是CS寄存器比较特殊. 因为CS寄存器跟EIP是配套的. 如果CS改了. EIP没改. 那么就是非一致代码段. 然后EIP跳转的时候就会出错.
要想同时修改CS 与 EIP的话 有以下几条指令
JMP FAR / CALL FAR /RETF /INT /IRETED
长跳转 长Call 长返回 int指令 iRetEd指令
但是只修改EIP的话就很简单了. 指令如下
JMP /CALL /JCC /RET
这些都可以进行修改EIP. 包括x64下也是一样的.
-
一致代码段与非一致代码段的介绍
一致代码段: 可以理解为是共享段.数据是共享的.可以允许低权限去访问
非一直代码段: 如果不想让低权限访问.想对这一块加限制.那么可以用非一致代码段修饰
修饰的本质还是 校验特权位
非一致: 要求CPL == DPL 且 RPL<= DPL 才可以访问
一致: CPL>=DPL 则可以. cpl > 则代表权限是低的.
3.1.2 JMP Far CPU执行流程
JMP far指令执行流程
截图如下
汇编指令如下
jmp far 0x0020:A50000
当CPU执行这条指令的时候会经过五个步骤
-
1.段选择子拆分查表
cpu 首先会将段选择进程拆分. 如我们的汇编的段选择子 0x0020
拆分为:
二进制: 0000 0000 0010 0000
RPL = 00
TI = 0
index = 4
-
2.查表获取段描述符
CPU则会根据 TI 判断查询是否是GDT表. 如果是查询GDT表. 然后根据index 去GDT表中查找对应的段描述符. 但是请注意,当我们查询的是 代码段 调用门 TSS任务段 任务门 的时候才能继续跳转
-
进行权限检查
查表之后当然首先第一步要进行权限检查.看是否你能访问我. 是否能访问段描述符 . 此时段描述符里面有DPL记录. 记录着段描述符的权限.
一致代码段的情况下: 当CPL== DPL 且 RPL <= DPL 的时候.才能访问 数据段. 我们知道 权限要么是0 要么是3
二进制分别对应的是 00 11 CPL 与RPL DPL都是两位表示. 而数字越低权限越高. 所以我们说的非一致代码段的情况下. 当前运行的特权级别(CPL) 权限必须与 段描述符权限相等(DPL) 否则不让你访问. 第一步通过之后. 然后判断
段选择子 (RPL) 是否 与DPL权限相当. 如果不是也不让你访问.
-
4.加载段描述符
当前三不执行过后. 此时CPU 才会真正的将 段描述符加载到CS段寄存器中
-
5.代码执行
我们说过 jmp far 执行要跨段必须修改 CS与EIP才可以. 我们CS已经通过第四步获取到了. 那么EIP的填写便是
将 cs.base + offset 填写到EIP中. 最后执行 cs:eip的指令. 这样我们流程才会结束
比如我们的 指令为
jmp far 0x0020:A50000
CS.base 已经通过段描述符获取了(第四步) 那么偏移就是 A50000 cs.base + A50000 然后进行代码执行
3.1.3 总结
当我们使用 JMP FAR指令的时候 CPU总会执行五步
1.拆分段选择子
2.通过拆分的段选择子 查找对应的表. 得出对应的段描述符
3.进行权限检查. CPL RPL DPL等检查.
4.加载段描述符
5.填写EIP 执行代码.
3.2 双机调试 代码跨段实验
原理就是根据五步步骤来操作.
其实本质还是 构造段选择子. 段选择子指向一个你自己定义的段描述符.
段描述符里面可以设置权限等.
- 1.从GDT表中寻找代码段
这个简单.根据段描述符.来找 我们上一篇已经说过了. s = 1 代表是代码段或者是数据段. 然后再根据s解析type来
具体的判断是代码段还是数据段.
其实简单的方法就是看 段描述符的 16进制表示的低五位来判断寻找即可. 或者根据讲解段描述符的时候写的代码来寻找.
查看段描述符
我们可以看到.s跟type是紧密相连的. 所以s和type可以看作是一个整体的二进制位. 并且这4位可以组成一个整体.
也就是一个16进制位 正好就是 高32位的第5个字节表示 表示了s与type. 而s = 1的时候代表是系统段或者数据段.
所以可以肯定如为1 那么组成的这个16进制位必然是大于8的.
举个例子. Windbg查看段描述符
r gdtr
dq gdtrbase
.formats gdtrbase[1]
我们直接查看的是第二项.看下它的高4个字节的第五位 00CF9 9就是一个16进制位. 包含了s与type 我们说过
s = 1那么必然会导致 s与type的组合肯定 > 8 根据我们解析的二进制数据我们看一下 看一下第五位
解析出来是 1001 1代表s = 1 后面的001代表的type解析 分别是 C RA 也就是code代码段 可以看一下上篇的
type解析与s解析.
那么确定了这个段是代码段. 那么我们就可以将这个代码段 拷贝到GDT表数组中要给新的地方. 最后构造段选择子
让其访问即可.
- 从GDT表中拷贝一个代码段到GDT中没有使用的位置
观察上图.我们看GDT的时候. 第一项是没有使用的. 我们将一个段描述符(代码段)拷贝到GDT表中第16项中.
代码段怎么找也是同上. 看s = 1还是0 确定是是代码或者数据段. 然后紧接着看s后面跟着的type值. 由type值确定是代码段还是数据段. 这里我们直接用GDT表中的第四项来进行操作
00cffb00~0000ffff
windbg如下
r gdtr
dq GDTbase
eq 地址 拷贝的内容
dq GDTBASE
图中遮挡的不要看.因为这是我实验之后没有修改回去而产生的错误项. 只需要看黑框一栏即可.
通过以上指令我们可以看到 将GDT表中的第四项,拷贝到了 第16项中.
下面就是构造段选择子 然后进行跨段实验
- 3.段选择子构造 以及跨段实验
我们所添加的新项在 GDT表中的第16项. 我们知道段选择子的构成 所以按照段选择子进行构造
但是GDT表的我们说过本质是一个数组. 这个数组里面是8个字节大小.存储着段描述符.
所以我们下标要从0开始. 所有构造段选择子的时候就要按照下表的方式来.
16项 = 下表15
15 = 二进制 1111
RPL以及TI 构造位 011 RPL = 3
结合起来 =
1111 011
按照从右向左 4个字节分组. 构成16进制的段选择子
111 1011 = 7B
所以我们段选择子是0x7B
跨段实验
我们直接用上面搜说的 jmp far指令来进行跳转 模拟段操作.当这条指令执行的时候就会执行我们的五步步骤
显然这条指令是可以执行成功了. 如果执行失败就会跑飞. 跳转到异常处理位置.
-
4.段权限检查
上面我们伪造的代码段描述符 = 00cffb00~0000ffff
其结果如下 我们直接洗DPL所在的高32位即可. 如下
kd> .formats 0x00cffb00 Evaluate expression: Hex: 00cffb00 Decimal: 13630208 Octal: 00063775400 Binary: 00000000 11001111 11 11(DPL) 1011 00000000 Chars: .... Time: Mon Jun 08 02:10:08 1970 Float: low 1.91e-038 high 0 Double: 6.73422e-317
通过解析.我们的DPL = 二进制的11 十六进制的3 我们构造的段选择子的权限也是11 所以执行我们指令的时候
权限通过. 可以进行执行.
但是我们可以尝试以下.将段选择子的RPL修改为0特权看一下.
代码段选择子改为 0x78 经过尝试也可以进行访问的. 原因就是 权限检查的时候 RPL <= DPL 既然DPL = 3那么就代表 权限小于或者等于我就可以访问了. RPL = 0 代表高权限 DPL = 3 代表地权限 搞特权是肯定能访问低特权描述符的.
- 5.修改描述符段DPL 重新尝试
尝试将DPL的11修改为00 然后重新执行代码跨段流程 从右边向左.从0开始都 读取到第13 14 DPL位 修改为00
0000 0000 1100 1111 11 11(DPL) 1011 0000 0000 0 0 C F 1001(9) B 0 0 0x00CF9B00~xxx
经过尝试是不可以进行访问了.且会跳到异常处理 就算段选择子的RPL = 0 也不可以. 因为我们的CPL特权级别不够. 而要修改CPL只能通过门来修改.
至此我们可以进行总结以及代码添加段描述符了. 并且进行测试
三丶总结
首先当访问段描述符的时候.操作系统会经过五个步骤
1.拆分段选择子
2.查表
3.DPL权限对比
4.通过之后加载段描述符
5.段描述符中的base+当前的偏移修改到EIP中进行执行
也经过windbg调试进行校验.发现确实可以伪造并且跳转. 注意一点的是
构造段选择子的index 是下标. 还要构建RPL TI等
坚持两字,简单,轻便,但是真正的执行起来确实需要很长很长时间.当你把坚持两字当做你要走的路,那么你总会成功. 想学习,有问题请加群.群号:725864912(收费)群名称: 逆向学习小分队 群里有大量学习资源. 以及定期直播答疑.有一个良好的学习氛围. 涉及到外挂反外挂病毒 司法取证加解密 驱动过保护 VT 等技术,期待你的进入。
详情请点击链接查看置顶博客 https://www.cnblogs.com/iBinary/p/7572603.html
本文来自博客园,作者:iBinary,未经允许禁止转载 转载前可联系本人.对于爬虫人员来说如果发现保留起诉权力.https://www.cnblogs.com/iBinary/p/13246172.html
欢迎大家关注我的微信公众号.不定期的更新文章.更新技术. 关注公众号后请大家养成 不白嫖的习惯.欢迎大家赞赏. 也希望在看完公众号文章之后 不忘 点击 收藏 转发 以及点击在看功能. QQ群: