利用情况

  • 未开启NX保护
  • 栈溢出空间较小,无法直接泄露libc_base

以32位为例

使用call命令,进入一个函数时,程序会进行一系列栈操作:

1
2
3
push eip+4
push ebp
mov ebp,esp

用来保护现场,避免执行完函数后堆栈不平衡以及找不到之前的入口地址

leave ret相当于

1
2
3
4
leave ==> mov esp, ebp
pop ebp

ret ==> pop eip

逆着看上面这段指令
pop eip是弹出栈顶数据并存入eip寄存器
而栈顶数据是由esp的值决定的
又由于mov esp, ebp是把ebp的值赋给esp
我们知道eip控制cpu下一条指令
所以我们可以通过覆盖ebp的值来控制ret返回地址

而两次leave ret即可控制esp为我们想要的地址
由于有pop ebp
会使esp-4,所以将ebp覆盖为想要调整的位置-4即可