(3) [保护模式]代码跨段跳转 (jmp far)


文中如有错误,还请大佬指正

前言

已知的段寄存器有:ES, CS, SS, DS, FS, GS, LDTR, GDTR, IDTR, TR

每个寄存器都可以通过一些指令来修改他们的值。如ES, SS, DS, FS, GS可以通过mov, LES, LSS, LDS, LFS, 'LGS’来修改,LDTR, GDTR, IDTR, TR可以通过 LLDT, LGDT, LIDT, LTR来修改
唯独CS的修改比较特殊。首先CS寄存器会直接影响到当前执行代码的位置 (当前执行代码的线性地址 = CS.base + EIP),所以只修改CS寄存器可能会使得程序跑偏了。所以没有提供只修改CS寄存器的指令,要修改CS寄存器,只能连同EIP一起修改,这样才能保证程序的正确性。


jmp far指令

与之前所看到的jmp有所不同,以前我们写的jmp是这样的: jmp EIP,这个称为段间跳转,或者叫短跳;而现在jmp指令改写成这样jmp CS:EIP,这个称为跨段跳转,或者叫长跳(jmp far)。


jmp far的执行顺序

首先有一条jmp far指令:jmp 0x1B:0x12345678

  1. 第一个地址是段选择子,所以要把0x1B按照段选择子的拆分方法进行分解,index = 3, TI = 0, RPL = 3

  2. TI == 0,所以查GDT表index为3的位置(index要从0开始算起),而且段描述符所描述的段必须是代码段,否则就会进入异常处理
    描述符要代表代码段:P == 1, S == 1, Type的最高位(第11位) == 1
    (忘了可以看看前写的段描述符)
    在这里插入图片描述

  3. 如果Type的E位(第10位) == 1代表非一致代码段,这时候要求 CPL == DPL && RPL <= CPL
    如果Type的E位(第10位) == 0代表一致代码段,这时候要求 CPL >= DPL

  4. 上面的检查全通过了之后才能将段选择子和段描述符加载到段寄存器

  5. 最后使用CS.base + EIP


小实验

首先通过windbg查询gdt表的位置,将一个空白的位置用index = 3 的描述符进行填充如图所示
在这里插入图片描述

eq 8003f048 00cffb00`0000ffff

(GDTR = 0x8003f000)
然后计算index的值,构造段选择子,index = (0x8003f048 - 0x8003f000) / 8== = 9
所以段选择子为 1001 0 11 = 0x4B
打开OD,修改指令为jmp 0x4B:1003E30,并观察当前的CS寄存器的值
在这里插入图片描述
然后执行这条指令
在这里插入图片描述

观察CS的值,变成了 0x4B


我们尝试将DPL改成0试试,意思是需要0环权限才能访问此段
图中红线部分变成了9
eq 8003f048 00cf9b00 0000ffff
在这里插入图片描述

在这里插入图片描述

依旧是修改成这条指令,执行试试
在这里插入图片描述
进入了ntdll模块,不是我们想要的位置,这是个异常函数,不是我们想去的位置
证明3环不能直接跳到0环去执行


修改一些描述符,将其改成0环代码的一致代码段
eq 8003f048 00cf9f00`0000ffff
图中b改成 f
在这里插入图片描述
在这里插入图片描述

可以看到跳转成功了,验证了一直代码段的作用
并且看到CS的权限依旧是3环的,所以一致代码段并不能提升权限


总结

jmp far 只能跳转到 相同权限的地方 和 不同权限的一致代码段

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值