Stacking Melodies
metactf
Task: a public DawgCTF / UMBCCyberDawgs source release exposes a non-PIE packet parser with both a format-string bug and an integer-overflow-backed heap overflow. Solution: use the format string to leak code pointers, infer the remote win() offset, and partially overwrite the logging function pointer with %hn to jump to the flag printer.
$ ls tags/ techniques/
Stacking Melodies — metactf
Description
A server at
nc.umbccd.net 8929is hosting the same code, but theirs has a flag, retrieve it. Public source:https://github.com/UMBCCyberDawgs/dawgctf-sp26/tree/main/Stacking%20melodies
This challenge came from the public UMBCCyberDawgs / DawgCTF '26 repository, while my local workspace grouped it under metactf. We are given the source for a 64-bit Linux service that parses a small custom packet, prints a title field, computes a rating, and then calls a function pointer stored in a heap-allocated session context.
Analysis
The public source immediately reveals two memory corruption bugs.
1. Primary bug: format string
The title is attacker-controlled and reaches:
printf(title);
This gives both an information leak and an arbitrary write through %n if one of the stack arguments resolves to a writable pointer.
2. Secondary bug: integer overflow into heap overflow
The code also validates the data length incorrectly:
static inline int validate_size(uint32_t sz) { size_t aligned = (sz + 7) & ~7; return (int)aligned; }
Later it allocates with:
size_t stream_size = (size_t)(d_len + 0x40); char *stream_buf = malloc(stream_size); fread(stream_buf, 1, d_len, stdin);
Because validate_size() returns an int after alignment while the real allocation uses d_len + 0x40, a large d_len can wrap and produce a too-small heap chunk before fread() copies the full attacker-controlled size. That looks exploitable, but I did not need it for the solve.
Build assumptions
The source comment says the binary was compiled with:
gcc -no-pie -g in.c -o out
That matters a lot: a non-PIE binary keeps stable text addresses, so once a code pointer is leaked, nearby functions such as win() can be inferred reliably.
Exploitation
Step 1: confirm the format-string layout remotely
I first sent a title of the form:
%1$p|%2$p|%3$p|...|%40$p
...
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]