$ cat writeup.md…
$ cat writeup.md…
b01lersc
Task: a PIE binary implements a min-heap priority queue of heap-allocated strings, but it also mallocs the flag at startup and loses the pointer. Solution: combine a root use-after-free, a 32-byte heap overwrite, fake-chunk creation, and glibc 2.31 tcache poisoning to overlap the hidden flag allocation and print it.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
ncat --ssl priority-queue.opus4-7.b01le.rs 8443
We are given a menu-driven priority queue of strings. At first glance it looks like a small heap challenge with insert, delete, peek, and edit operations. The important twist is in main(): the program opens flag.txt, allocates 100 bytes for it on the heap, reads the flag there, and then immediately loses the pointer.
So this is not a shell challenge. The goal is to recover an already allocated heap object that contains the flag.
The final exploit from solve.py uses three ideas:
0x20 tcache entries,flag_ptr - 0x20, then make puts() print through into the untouched flag string.Relevant files:
chall — target binarychall.c — source codesolve.py — working exploitlibc.so.6 — Debian GLIBC 2.31-13+deb11u13Dockerfile — remote packagingBinary protections:
Allocator detail that matters most: the provided libc is glibc 2.31, so tcache has no safe-linking. That makes classic tcache poisoning practical once we can overwrite a freed chunk's next pointer.
The challenge source is short enough to understand fully.
At startup:
FILE *file = fopen("flag.txt", "r"); if (file) { char *flag = malloc(100); fgets(flag, 100, file); fclose(file); }
The flag is read into a heap chunk, but flag is a local variable and is never stored anywhere global. After main() continues, that heap object still exists, but the program has no reference to it anymore.
...
$ grep --similar