一种由于栈溢出空间不够难以直接在溢出处构造的一种迂回方法。
先决条件
栈迁移的先决条件首先得是栈溢出,溢出空间不足的栈溢出。视溢出的字段长度不同依赖不同的先决条件。如果能覆盖上一个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
自此,栈被更改为了我们想要的任何地方。
应用速查
作用目标
栈溢出空间不足,需要扩展利用面。
需求
leave retgadget- 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]