吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5032|回复: 7
收起左侧

[系统底层] 保护模式笔记六 代码跨段跳转

  [复制链接]
lyl610abc 发表于 2021-4-21 15:16

前言

所有保护模式索引链接:保护模式笔记一 保护模式介绍

在先前的保护模式笔记三 段描述符和段选择子中提到了可以使用MOV、LES、LSS、LDS、LFS、LGS指令修改段寄存器

但CS段寄存器不能通过上面的指令修改;CS段寄存器为代码段寄存器,改变CS的同时必然要修改EIP

EIP寄存器,用来存储CPU要读取指令的地址,CPU通过EIP寄存器读取即将要执行的指令。每次CPU执行完相应的汇编指令之后,EIP寄存器的值就会增加

代码跨段跳转

同时修改CS和EIP的指令

指令 含义
JMP FAR 远跳转
CALL FAR 远调用
RETF(return far) 远返回
INT(interrupt) 中断
IRET(interrupt return) 执行到中断程序或过程的远返回

只改变EIP的指令

指令 含义
JMP 跳转
CALL 调用
JCC(jump condition code) 跳转指令状态码/条件跳转
RET 返回

JMP FAR 指令

指令格式

JMP Selector:Offset

形如:JMP 0x20:0x00452610

  • Selector为段选择子
  • Offset为要跳转的偏移

CPU执行指令流程

以上面的 JMP 0x20:0x00452610为例,探究CPU的执行流程

执行流程为:

  1. 拆分段选择子
  2. 根据段选择子查表得到段描述符
  3. 权限检查
  4. 加载段描述符
  5. 代码执行

拆分段选择子

段选择子为:0x001B

将其转换成二进制得到:0000 0000 0001 1011

然后根据段选择子的结构得到:(有关段选择子的结构可回顾保护模式笔记三 段描述符和段选择子

Index TI RPL
二进制值 0000 0000 0001 1 0 11
十进制值 3 0 3
含义 索引为3 查询GDT表 请求特权等级为3

根据段选择子查表得到段描述符

根据前面得到的段选择子的TI 可以确定要查询的表为GDT表

对应的段描述符地址 = GDT表首地址 + 索引× 段描述符长度 = GDT表首地址 + 索引 × 8

所以:对应的段描述符地址 = 0x8003f000 + 3×8= 0x8003f000 + 24 = 0x8003f000 + 0x18 = 0x8003f018

使用windbg查看对应的段描述符地址

image-20210411225609994


得到对应的段描述符为:00cffb00`0000ffff

将其转换为二进制得到:0000 0000 1100 1111 1111 1011 0000 0000 ` 0000 0000 0000 0000 1111 1111 1111 1111

根据段描述符的结构得到:(有关段描述符的结构可回顾保护模式笔记四 段描述符结构

数据位 31-24 23 22 21 20 19-16 15 14-13 12 11-8 7-0
含义 Base G D/B 0 AVL Seg.Limit P DPL S Type Base
解释 基地址 粒度 默认操作大小 固定为0 用于系统软件使用 段大小限制 有效位 特权等级 描述符类型 段类型 基地址
数值 00000000 1 1 0 0 1111 1 11 1 1011 0000000

数据位 31-16 15-0
含义 Base Adress Segment Limit
解释 基地址 段大小限制
数值 0000000000000000 1111111111111111

这里要关注S位和Type域

S位

此时的S位为1,表明该段描述符为代码段描述符或者数据段描述符

Type域

此时的Type域为1011,表明该段描述符为代码段描述符,且可执行可读,可访问


根据索引得到的段描述符只有4种情况可以实现跳转:代码段、调用门、TSS任务段、任务门

此时的段描述符为代码段描述符,因此可以看下一步


权限检查

有关权限检查的内容在保护模式笔记五 段权限检查中已详细介绍,这里不过多赘述

判断 DPL是否满足:EPL=max(RPL,CPL)<=DPL是否成立

此时EPL=3,DPL=3;满足EPL<=DPL,权限检查通过

PS:权限检查还需要关注Type域的属性,如果Type域的属性允许从较低特权级别调用(表明该段为一致代码段(共享段)),则CPL>=DPL即可;该例中的Type域表明此段为非一致代码段,于是需要进行权限检查

  • 如果是非一致代码段,要求:EPL=max(RPL,CPL)<=DPL
  • 如果是一致代码段,要求:CPL>=DPL

加载段描述符

通过以上的检查后,CPU会将段描述符加载到CS段寄存器中

代码执行

CPU将CS.Base+Offset的值写入EIP 然后执行CS:EIP处的代码,段间跳转结束

根据前面的段描述符结构,可以得到CS.Base为0,于是EIP会被修改为Offset:0x00452610


测试JMP FAR指令

前面了解了JMP FAR指令的执行流程,接下来验证JMP FAR指令执行的结果

因为CS段寄存器原本的段选择子就是0x001B,所以如果使用前面的例子会导致效果不明显

因此要自己构造一个段描述符,并使用对应的段选择子进行测试

确定段选择子

使用Windbg找到一处未被使用的段描述符

image-20210421142619680

确定了要被构造的段描述符的地址为:0x8003f048

根据 段描述符地址 = GDT表首地址 + 索引× 段描述符长度 = GDT表首地址 + 索引 × 8可以逆推出

索引 =( 段描述符地址 - GDT表首地址)÷ 8

即 索引 = (0x8003f048-0x8003f000) ÷ 8 = 0x48 ÷ 8 = 72 ÷ 8 = 9

Index TI RPL
二进制值 0000 0000 0100 1 0 11
十进制值 9 0 3
含义 索引为9 查询GDT表 请求特权等级为3

将二进制拼接起来得到:0000 0000 0100 1000,对应十六进制为0x4B

即段选择子为0x4B


构造段描述符

确定了段选择子以后,就可以构造段描述符了

数据位 31-24 23 22 21 20 19-16 15 14-13 12 11-8 7-0
含义 Base G D/B 0 AVL Seg.Limit P DPL S Type Base
解释 基地址 粒度 默认操作大小 固定为0 用于系统软件使用 段大小限制 有效位 特权等级 描述符类型 段类型 基地址
数值 00000000 1 1 0 0 1111 1 00 1 1111 0000000

数据位 31-16 15-0
含义 Base Adress Segment Limit
解释 基地址 段大小限制
数值 0000000000000000 1111111111111111

主要修改了DPL为0;段类型设置为可执行可读,可从较低特权级别调用,可访问的 代码段描述符

将上面的二进制拼接得到:00cf9f00`0000ffff


写入段描述符

将构造好的段描述符写入

在windbg中使用指令

 eq  8003f048 00cf9f00`0000ffff

eq :edit qword,以qword的数据宽度编辑修改指定地址的数据

指令格式为:eq address data


修改后再用windbg查看

image-20210421144222620

确认写入成功后继续下一步


OD测试指令

使用OD随便打开一个软件,这里用的demo为EverEdit.exe

修改要执行的指令为:

jmp far 0x4b:0056AF36

image-20210421145806413


image-20210421145936444


修改后,按F8单步步过,观察CS和EIP的变化

image-20210421150125416

可以看到EIP被修改为了Offset(偏移),CS被修改为了Selector(段选择子);EIP和CS被同时修改了


尝试修改CPL

原本的CPL为3,CPL为当前特权级别,等于CS和SS的RPL(请求特权级别)

前面的其它操作不变,将段选择子的请求特权级别修改为0

即将段选择子修改为

Index TI RPL
二进制值 0000 0000 0100 1 0 00
十进制值 9 0 0
含义 索引为9 查询GDT表 请求特权等级为0

得到新的段选择子为0x0048

使用OD执行新的指令

jmp far 0x48:0056AF36

image-20210421150945583

可以看到,CS仍然是0x4B,CPL仍然没有发生改变,当前特权等级依旧为3

也就是说CPL无法通过这种方式改变


总结

对于一致代码段(共享段)

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

对于普通代码段(非一致代码段)

  • 只允许同级访问
  • 绝对禁止不同级别的访问

直接对代码段进行JMP 或者 CALL的操作,无论目标是一致代码段还是非一致代码段,CPL都不会发生改变

如果要提升CPL的权限,只能通过调用门(这也就是所谓的提权操作)


为了对数据进行保护,普通代码段是禁止不同级别进行访问的。用户态的代码不能访问内核的数据,同样,内核态的代码也不能访问用户

态的数据。这种数据隔离的性质更好地保障了系统的安全性和稳定性


免费评分

参与人数 6吾爱币 +6 热心值 +4 收起 理由
MasterW + 1 用心讨论,共获提升!
bailemenmlbj + 1 + 1 谢谢@Thanks!
timego + 1 + 1 用心讨论,共获提升!
debug_cat + 1 + 1 6666666666666666666666666
gongmingtao0601 + 1 + 1 用心讨论,共获提升!
xzl9552547 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

gongmingtao0601 发表于 2021-4-21 16:33
学习了!最近在了解些底层的东西
debug_cat 发表于 2021-4-21 17:30
有、 发表于 2021-4-22 17:47
zjf919 发表于 2021-4-23 13:27
谢谢大神分享!好好学习好好学习!
jsncy 发表于 2021-6-2 09:36
用心讨论,共获提升!
lxt520 发表于 2023-8-21 14:48
请教一下给位大佬,我按照步骤做,od却报错说没有权限
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-22 00:46

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表