堆栈平衡和栈转移

1.栈平衡

1.为什么需要堆栈平衡?

  • 保持栈的大小,是ESP始终指向栈顶

2.概念

  • 函数如果要返回父程序,则在堆栈中进行操作时,一定要在RET指令之前,将ESP指向函数压入栈中时的地址
  • 如果通过堆栈传递参数了,那么在函数执行完毕后,要平衡参数导致的堆栈变化

3.总结

  • 当函数在栈中操作时,需要先把ESP交给EBP,然后继续操作,当操作完成后,在ret之前,要先将ESP恢复成进入栈之前的状态,最后再将EBP移除栈

2.栈转移

1.为什么需要栈转移?

  • 在栈空间不够存放payload的情况下,需要一个新的地址空间存放payload
  • 开启PIE保护,栈地址未知,我们可以将栈劫持到已知的区域

2.概念

  • 劫持栈的rsp(ESP),使其指向其他位置,形成一个伪造的栈,在此栈中做ROP

3.必要的gadget

  • pop ebp;ret 释放EBP,并连接伪造的栈
  • leave;ret 更改ESP,指向后续的payload

4.原理

  • 通过 pop ebp;ret + 伪造的栈让程序直接跳转到伪造的栈里面,然后为了保持栈平衡,从而执行 leave ;ret,最后继续执行伪造栈内的payload

5.过程

  • 使用输入函数(如read),将后续的payload加载到bss段内,也就是伪造的栈
  • 通过 pop ebp;ret | pop ebx;ret 来调整EBP寄存器
  • 通过 leave ret; 来更改 ESP,使其指向伪造的栈
  • 然后在伪造的栈中执行下一段ROP