The challenge ships a short C source (the patched version comments out the vulnerable line). The relevant functions are:
void set_msg(void)
char buf[64];
printf("Enter your message: ");
gets(buf); // <-- classic stack overflow (no bounds check)
puts("Message stored.");
void print_msg(void)
char *msg;
printf("Enter format string: ");
scanf("%s", msg); // <-- BUG: msg is uninitialized, points to stack
printf(msg); // <-- Format‑string vulnerability
msg is a local pointer that never gets initialized, so scanf("%s", msg) writes the user‑controlled string onto the stack (just above the saved RBP). The subsequent printf(msg) then treats whatever we placed there as a format string – giving us a read‑write arbitrary memory primitive.
$ checksec --file=juq016_patched
RELRO Full RELRO
Stack Canary found
NX NX enabled
PIE PIE enabled
RPATH No RPATH
What changed?
The patch did not remove the underlying stack overflow; it just made the canary harder to guess. The format‑string bug, however, gives us the exact value.
Before using an unofficial patch:
| Tool | Version (tested) | Purpose |
|------|------------------|---------|
| pwntools | 2023.0.0 | Rapid interaction, ELF parsing, ROP building |
| gdb (with pwndbg/gef) | 9.2 | Debugging, stack‑canary inspection |
| objdump / readelf | GNU binutils 2.38 | Inspect sections, symbols |
| r2 / radare2 | 5.8.0 | Quick sanity checks |
| checksec | 2.4.0 | Verify binary protections |
| Docker image (optional) | ubuntu:22.04 + above tools | Guarantees a reproducible environment |
# Example Dockerfile (optional)
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
python3 python3-pip gdb \
binutils-multiarch \
radare2 \
&& pip3 install --no-cache-dir pwntools
WORKDIR /ctf
COPY juq016 /ctf/juq016
COPY juq016_patched /ctf/juq016_patched
COPY exploit.py /ctf/
Run docker build -t juq016 . && docker run -it juq016 /bin/bash to get a clean sandbox.
