[保护模式]段间跳转和跨段跳转

段间跳转

代码跨段,本质就是修改CS段寄存器

段寄存器

段寄存器有下面几个:ES CS SS DS FS GS LDTR TR。除了CS以外,其他的段寄存器都可以通过MOV LES LSS LDS LFS LGS指令进行修改。

那么CS为什么不能直接修改呢?因为cs.base+eip=真正执行的地址。CS的改变意味着EIP的改变,改变CS的同时必须修改EIP,所以我们无法使用上面的指令来进行修改

段间跳转

段间跳转有两种情况,即要跳转的段是一致代码段还是非一致代码段。那么如果想要修改CS,可以使用下面的指令同时修改EIP和CS段寄存器

jmp far
call far
retf
int
ireted

段间跳转的执行流程

jmp far的指令格式为

jmp 0x20 0x12345678    

CPU在遇到这行代码时,执行流程如下:

1.段选择子拆分

0x20对应的二进制数为0000 0000 0010 0000

RPL=00 代表请求特权等级为0环权限

TI=0 代表查GDT表

Index=4代表查GDT表第5项(下标为4)

2.查表得到段描述符

通过段选择子的Index找到对应的段描述符后,满足四种情况则继续执行:代码段 调用门 TSS任务段 任务门

3.权限检查

如果GDT表项是非一致代码段,要求:CPL==DPL并且RPL<=DPL

如果GDT表项是一致代码段,要求CPL>=DPL

原因在于一致代码段允许权限低的代码段访问权限高的代码段,而非一致代码段只能被同等级权限或更高权限的代码访问。

4.加载段描述符

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

5.代码执行

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

总结

对于一致代码段:也就是共享的段

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

对于非一致代码段:

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

直接对代码段进行JMP或者CALL的操作,无论目标是一致代码段还是非一致代码段,CPL都不会发生改变。如果要提升CPL的权限,只能通过调用门。

跨段跳转

一致代码段允许特权级低的代码访问特权级高的代码,那么如果遇到非一致代码段怎么办呢?那么就需要提权了。也就是所谓的跨段跳转。

我们通过JMP FAR可以实现段间跳转,如果要实现跨段跳转就必须用CALL FAR。CALL FAR比JMP FAR要复杂,JMP并不影响堆栈,但CALL指令会影响

短调用

普通的调用指令格式为:call 立即数/寄存器/内存。短调用执行时会先将返回地址压入到堆栈,然后修改EIP。堆栈图如下:

在这里插入图片描述

而ret指令则相当于是pop eip+jmp eip。call和ret指令影响的寄存器有ESP和EIP。

长调用

跨段不提权

指令格式:CALL CS:EIP(EIP是废弃的),其堆栈图如图所示:

在这里插入图片描述

长调用执行时会将当前的CS段寄存器和返回地址压入到堆栈,RETF指令执行时则会将当前的CS和返回地址弹出堆栈。CALL指令执行完成之后当前的EIP会指向哪由CS指向的段描述符决定。发生改变的寄存器有:ESP EIP CS

跨段提权

指令格式:CALL CS:EIP(EIP是废弃的),其堆栈图如图所示:

在这里插入图片描述

跨段提权时当前CS的寄存器的CPL会发生改变,CS发生改变必然伴随着SS的改变。所以跨段提权的长调用执行后会将SS ESP CS和放回地址都压入到堆栈中。

发生改变的寄存器:ESP EIP CS SS。

总结

  1. 跨段调用时,一旦有权限切换,就会切换堆栈
  2. CS权限一旦改变,SS的权限也会随着改变,CS与SS的特权等级必须一样
  3. JMP FAR只能跳转到同级非一致代码段,但CALL FAR可以通过调用门提权
发布了93 篇原创文章 · 获赞 83 · 访问量 7万+
展开阅读全文
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览