一种由于栈溢出空间不够难以直接在溢出处构造的一种迂回方法。

先决条件

栈迁移的先决条件首先得是栈溢出,溢出空间不足的栈溢出。视溢出的字段长度不同依赖不同的先决条件。如果能覆盖上一个rbp地址,就具备了栈迁移的基本条件,在此之上,如果能够控制返回地址,就具备了在一处完成完整的栈迁移的可能性。

基本原理

前置:

在新的函数开始时,旧的栈底压栈,栈顶成为新的栈底。在函数结束时,要还原栈帧,弹出旧栈底,并把栈顶还原。即

leave
ret

也就是

mov  rsp, rbp ; pop  rbp
pop  rip

此时,如果我们至少拥有修改栈上的rbp的值的能力,就可以用2次leave ; ret来把栈迁移到任何地方。

栈是内存上由2个寄存器的值框定的区域。分别为rsp框定栈顶,rbp框定栈底。 在控制旧rbp的值之后,全过程如下:

在调用 leave ; ret 时,函数一切正常。 rsp = 0x7f????????????80 rbp = 0x7f????????????a0

第一次 leave ; ret 时,由于pop rbp,rbp被修改。 rsp = 0x7f????????????80 rbp = 0x114514

第二次 leave ; ret ,首先mov rsp, rbp rsp = 0x114514 rbp = 0x114514 然后pop rbp rsp = 0x114514 rbp = 0x1919810

自此,栈被更改为了我们想要的任何地方。

应用速查

作用目标

栈溢出空间不足,需要扩展利用面。

需求

  1. leave ret gadget
  2. bss段有足够空间或泄露了栈地址

利用方式

64位栈布局

第一次ret:

rbp   [fake_rsp]
rbp+8 [seg_w̄c_can_call_lr_again]

第二次ret:

rbp   [fake_rbp]
rbp+8 [print_or_sth_ꝥ_can_overflowing]