avatar

Catalog
长调用与短调用

在上一篇章中提过,实现跨段的跳转,可以使用JMP FAR指令,但是想要实现跨段的调用,就需要学习一个新的指令CALL FAR;CALL FAR指令要更为复杂一些,原因是JMP指令是不影响堆栈的,而CALL指令会影响堆栈

短调用

首先来回顾下短调用,短调用其实就是普通的CALL调用,是相对于CALL FAR而言,所以叫做短调用。短调用会影响EIP寄存器和ESP寄存器,因此在返回时需要额外去平衡一下堆栈;短调用属于三环知识,这里不再赘述,具体的调用和返回时的堆栈变化如下图所示:

长调用(跨段不提权)

长调用分为提权和不提权两种,这里先讲不提权的情况。

这图看不明白没关系,一个个分析。首先,EIP为什么是废弃的?因为,这个长调用指令,压根不会跳转到你给的EIP的位置,而是会跳转到调用门里提供的地址。那什么是调用门呢?下一篇会具体提到, 这里简单概括调用门就是一种位于GDT表里特殊的描述符。

回到长调用这里,当CALL执行后,与一般的调用指令不同,长调用使得堆栈提升了8个字节,除了返回地址外,还压入了调用者的CS,以便在调用返回至原来程序时,CS也能得到恢复。其中返回地址依然是位于[esp]处,调用者的CS位于[esp+4]处。

长调用返回也与普通调用不同,普通调用使用ret指令即可返回到原来程序的位置,而长调用返回时需要使用长返回指令RETF,长返回指令除了会将返回地址送入EIP寄存器,还会将CS恢复至执行前的状态,同时平衡堆栈。

长调用(跨段并提权)

不提权的长调用还稍微好理解一点,提权的长调用,就稍微有些复杂了,由于发生了提权,CS的CPL发生了改变,根据Intel的规定,CS和SS的CPL一定要保持一致,所以此时SS的值也会发生改变,除此之外,因为发生了提权,堆栈从3环的堆栈变为了0环的堆栈,因此ESP也会发生改变。所以提权的长调用会4个寄存器的值发生改变,分别是EIP,CS,ESP,SS,来看一下执行前后的变化

提权后,分别将返回地址,调用者CS,ESP,SS压入了0环的堆栈中,这样在返回3环时,可以确保这些寄存器恢复到原本的状态。

同样,提权后返回用的也是RETF,长返回指令,分别将返回地址,调用者的CS,ESP,SS压入相应的寄存器中,大致如下:

总结

长调用相较长跳转更为复杂,这篇只是做个简单的介绍,在后面的篇章中,将通过分析调用门的实现过程来详细讲解长调用,这里对本篇提到的几个特点做些总结。

  1. 跨段调用时,一旦有权限切换,就会切换堆栈
  2. CS的权限一旦改变,SS的权限也要随着改变,CS与SS的等级必须一样
  3. JMP FAR只能跳转到同级非一致代码段或者共享段,但CALL FAR可以通过调用门提权,提升CPL的权限

参考课程 : https://www.bilibili.com/video/av68700135?p=16

Author: cataLoc
Link: http://cataloc.gitee.io/blog/2020/03/14/%E9%95%BF%E8%B0%83%E7%94%A8%E4%B8%8E%E7%9F%AD%E8%B0%83%E7%94%A8/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶