Brick Workshop
umasscybersec
Task: an amd64 menu service stores calibration integers in stack locals inside `workshop_turn()` and later reuses them after a state change. Solution: trigger diagnostics once to seed stale stack values, choose pigment `0xBEEF`, then invoke diagnostics again so the uninitialized reuse satisfies the win check.
$ ls tags/ techniques/
Brick Workshop — UMass Cybersecurity CTF
Description
Provided challenge materials:
bad_eraser,bad_eraser.c,Dockerfile,Makefile, and the remote servicenc bad-eraser-brick-workshop.pwn.ctf.umasscybersec.org 45002.
English summary: this was a small amd64 menu binary themed as a brick workshop. The goal was to review the control flow, find how the hidden win() condition could be reached, and retrieve the flag from the remote service.
Service:
nc bad-eraser-brick-workshop.pwn.ctf.umasscybersec.org 45002
Challenge Summary
This was not a classic memory-corruption pwn with a buffer overflow or ROP chain. The binary was an amd64 ELF, dynamically linked, non-PIE, NX enabled, no canary, partial RELRO, and not stripped, but the real issue was a logic bug caused by uninitialized stack variables.
The exploit path was just:
- Choose menu option
3 - Enter
0 48879 - Choose menu option
3again
That second diagnostics call reused stale stack values from the previous call and immediately hit win().
Recon / Code Review
The important code lives in workshop_turn():
static void workshop_turn(void) { int choice; unsigned int mold_id; unsigned int pigment_code; banner(); if (scanf("%d", &choice) != 1) { exit(0); } ... if (!service_initialized) { puts("First-time calibration required."); puts("Enter mold id and pigment code."); if (scanf("%u %u", &mold_id, &pigment_code) != 2) { exit(0); } puts("Calibration saved. Re-enter diagnostics for clutch validation."); service_initialized = 1; return; } diagnostics_bay(mold_id, pigment_code); }
The hidden success path is in diagnostics_bay():
static unsigned int clutch_score(unsigned int mold_id, unsigned int pigment_code) { return (((mold_id >> 2) & 0x43u) | pigment_code) + (pigment_code << 1); } static void diagnostics_bay(unsigned int mold_id, unsigned int pigment_code) { puts("Running clutch-power diagnostics..."); if (clutch_score(mold_id, pigment_code) == 0x23ccdu) { win(); } puts("Result: unstable clutch fit. Send batch back to sorting."); exit(0); }
Vulnerability Explanation
The bug is use of uninitialized stack variables.
...
Permission denied (requires auth)
Sign in to read this free writeup
This writeup is free — just sign in with GitHub to read it.
$ssh [email protected]