│ Category: Binary Exploitation
│ Difficulty: Easy
│ Points: 50
│ Author: Imattas aka Zemi
────────────────────────────────────────────────────────────────────────────────
--[ Challenge Description ]--
│ Solve the quiz. Download the source code to answer questions.
────────────────────────────────────────────────────────────────────────────────
--[ Recon / Initial Analysis ]--
This is an introductory binary exploitation challenge worth 50 points with 2473
solves, making it one of the most solved challenges in the competition. The
challenge provides a binary (and its source code) that presents a quiz about
binary exploitation concepts. The twist is that the answers to the quiz
questions must be derived by reading the source code.
Examining the source code reveals:
1. The program asks a series of questions about C/binary exploitation concepts.
2. The answers can be found by carefully reading the provided source file.
3. After answering all questions correctly, the program prints the flag.
Typical questions in this style of challenge involve:
- Buffer sizes (e.g., "What is the size of the buffer?")
- Function names or addresses found in the source
- Specific variable values or constants defined in the code
- Vulnerability types present (e.g., "buffer overflow", "format string")
- Offsets or padding amounts
────────────────────────────────────────────────────────────────────────────────
--[ Vulnerability / Observation ]--
The key insight is that this is not really an "exploitation" challenge in the
traditional sense -- you just need to read the source code carefully and provide
the correct answers to each quiz question. The binary then rewards you with the
flag.
:: Typical Source Code Pattern
-- c --
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 64
#define SECRET_VALUE 0xdeadbeef
void win() {
// reads and prints the flag
FILE *f = fopen("flag.txt", "r");
char buf[64];
fgets(buf, sizeof(buf), f);
printf("%s\n", buf);
}
void quiz() {
char answer[128];
printf("Question 1: What is the size of the buffer? ");
scanf("%s", answer);
if (atoi(answer) != BUFFER_SIZE) { printf("Wrong!\n"); exit(1); }
printf("Question 2: What is the secret value (in hex)? ");
scanf("%s", answer);
if (strcmp(answer, "0xdeadbeef") != 0) { printf("Wrong!\n"); exit(1); }
printf("Question 3: What is the name of the win function? ");
scanf("%s", answer);
if (strcmp(answer, "win") != 0) { printf("Wrong!\n"); exit(1); }
win();
}
The actual source will differ, but the pattern is the same: read the source,
find the answers, get the flag.
────────────────────────────────────────────────────────────────────────────────
--[ Exploitation / Solution ]--
1. Download the binary and source code from the challenge page.
2. Read the source code carefully. Look for:
- Defined constants (buffer sizes, magic numbers)
- Function names (especially any win or print_flag functions)
- Variable declarations and their sizes
- Any comments that hint at answers
3. Run the binary and answer each question based on what you found in the
source:
- Questions typically ask about specific values visible in the C source
- Pay attention to #define macros, array sizes, and function signatures
- Some questions may ask about exploitation concepts (e.g., "What type of
vulnerability is present?")
4. After all correct answers, the program outputs the flag.
────────────────────────────────────────────────────────────────────────────────
--[ Full Exploit Script ]--
-- python --
#!/usr/bin/env python3
"""
Quizploit - picoCTF 2026
Category: Binary Exploitation | Points: 50
Solve the quiz by reading the source code and providing correct answers.
Usage:
python3 solve.py # Run against local binary
python3 solve.py REMOTE_HOST PORT # Run against remote server
Before running:
1. Download the binary and source code from the challenge page
2. Read the source code to determine the correct quiz answers
3. Update the ANSWERS list below with the correct responses
4. chmod +x quizploit (if running locally)
"""
import sys
from pwn import *
# ============================================================
# CONFIGURATION - UPDATE THESE BASED ON THE SOURCE CODE
# ============================================================
BINARY = "./quizploit"
# Read the source code and fill in answers here.
# These are EXAMPLE answers -- replace them with the real ones
# found in the downloaded source file.
ANSWERS = [
b"64", # Example: Q1 - buffer size
b"0xdeadbeef", # Example: Q2 - secret value in hex
b"win", # Example: Q3 - name of the win function
# Add more answers as needed based on the actual quiz questions
]
# ============================================================
# EXPLOIT
# ============================================================
def solve():
# Connect to remote or run locally
if len(sys.argv) >= 3:
host = sys.argv[1]
port = int(sys.argv[2])
log.info(f"Connecting to {host}:{port}")
p = remote(host, port)
else:
log.info(f"Running local binary: {BINARY}")
p = process(BINARY)
# Send each answer when prompted
for i, answer in enumerate(ANSWERS):
log.info(f"Question {i+1}: sending answer '{answer.decode()}'")
# Wait for the question prompt (adjust the expected text as needed)
p.recvuntil(b"? ")
p.sendline(answer)
# Receive the flag
response = p.recvall(timeout=3).decode(errors="ignore")
print("\n" + "=" * 50)
print("Server response:")
print(response)
print("=" * 50)
# Try to extract the flag
import re
flag_match = re.search(r'picoCTF\{[^}]+\}', response)
if flag_match:
print(f"\nFLAG: {flag_match.group(0)}")
else:
print("\nFlag not found in output. Check the response above.")
print("You may need to update the ANSWERS list based on the source code.")
p.close()
def read_source():
"""Helper: read and display the source code if available."""
import os
source_files = [f for f in os.listdir('.') if f.endswith(('.c', '.h'))]
if source_files:
print("Found source files:", source_files)
for sf in source_files:
print(f"\n{'=' * 50}")
print(f"Contents of {sf}:")
print('=' * 50)
with open(sf, 'r') as f:
print(f.read())
print("\nUpdate the ANSWERS list in this script based on the source above.")
else:
print("No source files found in current directory.")
print("Download them from the challenge page first.")
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == "--read-source":
read_source()
else:
solve()
────────────────────────────────────────────────────────────────────────────────
--[ Key Takeaways ]--
- Not every "Binary Exploitation" challenge requires memory corruption -- this
one is a source-reading exercise that hands you the flag for correct answers.
- The answers live in the C source: #define macros, array sizes, function names
(win/print_flag), and constants.
- pwntools (process/remote + recvuntil/sendline) makes automating the
prompt-response loop trivial once the answers are known.
- A --read-source helper that dumps local .c/.h files speeds up finding the
answers.