Day-of playbook
Read once the week before, skim again the morning of. Registration, offline pre-staging, CTF mechanics, triage order, and what to bring.
The week before
- Register on the CTF platform,
ctf.quantumvillage.org. This platform is open between cons, not just during DEF CON week — get an account early and spend ten minutes learning the scoreboard UI (category board layout, how a solve is confirmed, where hints live) before it matters under time pressure. - Join the Quantum Village Discord and follow @quantum_village — challenge drops, hints, and any last-minute logistics changes go out there first.
- Confirm the DC34 CTF times once Quantum Village posts them. As of this writing only the con window itself (DEF CON 34, Aug 7–9 2026, Las Vegas) is confirmed — the CTF's specific start/end times within that window are not yet posted. Recheck Discord and @quantum_village in the last few days before travel.
Do not assume a specific start time or room. Check the platform and Discord directly.
Pre-staging the environment
The DEF CON network is hostile and unreliable by design and by reputation — assume
there is no working internet on-site, and treat any internet that does work as
adversarial. Everything needed has to be installed, configured, and tested
offline before travel. Nothing gets pip installed on the con floor.
These pages work offline: git clone the repo and open
site/index.html directly from disk, no server needed.
Pre-flight checklist — run through this at home, on the actual network you'll use con-side if possible (e.g. phone hotspot with WiFi/data off, to simulate no connectivity):
| Check | Command / action |
|---|---|
| venv builds on Python 3.12 | python3.12 -m venv .venv && source .venv/bin/activate && pip install -r env/requirements.txt |
| Qiskit + Aer import and run | python -c "import qiskit; from qiskit_aer import AerSimulator; print('ok')" |
| liboqs (PQC) installed | brew install liboqs && pip install liboqs-python, then python toolkit/pqc.py |
| Every toolkit module self-test green | ./run_selftests.sh |
| Toolkit importable from a scratch notebook | open Jupyter offline, from toolkit import bb84, chsh, qasm_tools, algorithms, pqc |
| This repo cloned locally, not just on GitHub | git clone to the laptop; confirm site/index.html opens from file:// |
| Offline docs cached | local copies or downloaded PDFs of the Qiskit API reference, OpenQASM spec, Q# kata docs |
| Repo itself has no uncommitted state you need | git status clean, everything pushed somewhere retrievable |
CTF mechanics, for a first-timer
This is background a CTF veteran wouldn't think to explain. It matters here because the first hour of the first-ever CTF is the worst time to be figuring out the UI instead of the challenges.
- A flag is the string you submit to prove a challenge is solved.
Format is usually stated somewhere — on the challenge description or a platform-wide rule
— commonly something like
flag{...}. Note the exact format from the first challenge that states it; later challenges may assume it. - Jeopardy-style is the format: a board of categories (BB84, CHSH, circuit golf, Q#, PQC, algorithms, misc — see Categories), each containing several independent challenges, usually ordered by point value within the category. Unlike an attack/defense CTF there's no live opposing team — it's you against a fixed set of puzzles.
- Points and dynamic scoring. Many modern jeopardy platforms use dynamic scoring: a challenge is worth more points while few teams have solved it, and its value decays as more teams solve it. Practically this means point value is a live difficulty/rarity signal, not a fixed rating — check it, don't just trust a number you saw earlier.
- Submitting a flag is normally a text box on the challenge card; submission is checked immediately and either accepts (challenge marked solved, points awarded) or rejects (try again, no penalty for wrong guesses in most CTF platforms — though check whether this one differs).
- "First blood" means being the first team/person to solve a given challenge. Some platforms give a small bonus for it. Not worth chasing — solving the challenge at all is the goal, not the race.
- Hints often cost points — taking one deducts from that challenge's value. Worth it if genuinely stuck past the timebox (see day-of workflow); not worth it as a first move.
- Read the challenge text literally. The wording is usually a deliberate pointer to the technique — "referee," "bases," "in N lines or fewer," "distinguish," "factor" are not flavor text, they name the attack. See the pattern table below.
- Attachments and netcat/remote services. Some challenges ship a
downloadable file (QASM source, a transcript, an image); others give a
host:portto connect to — a live remote process you interact with, often programmatically (socket open, send bytes, read response, repeat). Expect to write a short Python script usingsocketorpwntools-style interaction for these rather than a one-shot manual exchange.
Day-of workflow
- Sweep every category's intro challenge first. Each category on the board opens with an easy, usually low-point intro challenge that unlocks the rest of that category (later challenges may be locked, or just conceptually build on it). Before going deep on anything, touch every category at least once. This also surfaces which categories are actually live/working early, when a report to the organizers still helps.
- Then sort by points ascending within the strongest categories (BB84/QKD and OpenQASM are historically the highest-yield). Low point value after the dynamic-scoring adjustment is a reasonable proxy for "most teams have already solved this" — i.e., probably approachable.
- Keep a Jupyter scratchpad open for the whole event, toolkit
imported once:
from toolkit import bb84, chsh, qasm_tools, algorithms, pqc, crypto_utils, qsim. Reuse the same kernel across challenges rather than re-launching. - Note-taking discipline: one file per challenge under
writeups/<challenge-name>/. Paste the challenge text in verbatim first — before doing anything else — then log what was tried, in order, including dead ends. This is what makes a later writeup possible without having to reconstruct the session from memory. - Timebox each challenge. Pick a hard limit (e.g. 30–40 min) before starting. When it's hit with no thread to pull, stop and rotate to something else on the board rather than tunnelling. Coming back later with fresh eyes routinely unsticks things that felt impossible mid-session.
- Deciding when to keep going vs. move on: a partial result — a sifted key with a high QBER, a circuit that's close to the line budget, a factor that divides evenly but isn't prime — usually means the approach is right and it's an off-by-one or parameter issue, not a wrong technique. That's worth pushing through the timebox for. No traction at all after the timebox (no idea which toolkit module even applies) is the signal to bank the time and come back later, possibly after a hint.
Pattern-recognition table
Fast lookup from challenge-text keywords to category and toolkit entry point. This is the table to scan first when a challenge description doesn't immediately say what it is.
| Keywords in challenge text | Category | Toolkit entry point |
|---|---|---|
| "bases," "sifting," "Alice and Bob," "eavesdropper" | BB84 / QKD | bb84.sift, bb84.reconstruct_key, bb84.qber |
| "referee," "win rate," "75%," "Bell" | CHSH | chsh.quantum_winrate, chsh.classical_winrate |
| "in N lines or fewer," ".qasm" | Circuit golf | qasm_tools.golf_report, qasm_tools.load_qasm |
| "distinguish," "one query," "oracle" | Q# kata / phase kickback | Q# kata harness — see categories page |
| "factor," "modulus," "RSA" | Shor | algorithms.shor_factor |
| "find the input such that" | Grover | algorithms.grover_search, algorithms.phase_oracle |
| "Kyber," "ML-KEM," "Dilithium," "signature" | Post-quantum crypto | pqc.kyber_encaps/kyber_decaps, pqc.dilithium_sign/verify |
| unfamiliar file, no obvious quantum content | Misc / stego | file, strings, exiftool, LSB extraction |
What to bring
- Laptop with the full environment pre-installed and tested per the offline checklist above — venv built, all self-tests green, no step deferred to "I'll finish this on-site."
- Charger. Obvious, still the single most common reason for lost con-floor hours.
- Offline docs — the cached Qiskit/OpenQASM/Q# references, and this site itself cloned locally (see above).
- Phone hotspot as a network fallback — not for pulling new dependencies (nothing should need that by the time the con starts), but as a way to reach the CTF platform or Discord if the venue WiFi is saturated or actively hostile. Standard DEF CON network advice applies generally: assume anything on the con WiFi/wired network is visible to someone else, don't reuse sensitive credentials on it, and prefer the hotspot or a VPN for anything that isn't the CTF itself.
- Water, food, sleep. This runs across a 3-day con, not a single sitting — treat rest as a performance factor, not a luxury. A tired brain misses the "factor," "distinguish," "referee" keyword-match on a challenge it would otherwise solve in two minutes.
After: writeups
Keep the per-challenge notes in writeups/ (see day-of
workflow) good enough that they could be published afterward with light editing —
challenge text, approach, what worked, what didn't. This prep leaned directly on other
people's published writeups (the CharonV DEF CON 32 walkthrough, the CUJO AI DEF CON 2021
CHSH/BB84/AES writeup — both linked from the start page);
publishing a writeup afterward is how that same body of knowledge keeps growing for the
next person doing this same prep.