Step 280. CTF Debrief Block A: Digging Three Unsolved Problems to the Bottom — Skill Grows in the Debrief, Not the Competition
Level 3 — Real-World CTF & Advanced Offensive Skills | Difficulty ★★★☆☆ | Estimated time: 2 days (2–4 hours per problem)
Prerequisites: Step 279’s first competition finished — the competition log (
ctf_log.csv) and retrospective memo must exist.
- What you need: the competition log and retrospective memo (Step 279 deliverables), the original files of unsolved problems (downloaded during the competition), access to official/community write-ups, and the playbook (Step 272).
- ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime. Problems from CTFtime-registered competitions and write-ups published after the end are legal materials opened for learning — where publication is prohibited by competition rules, follow the rules.
- Caution: other people’s write-up screens are marked as screen examples. What we executed and verified directly in this chapter is the XOR reproduction problem and its solution script, and that output is measured.
A competition’s ranking is just a number; skill grows in the debrief. Today we establish the debrief block A routine: pick three problems you couldn’t solve and dig them to the bottom. The cycle of "2 more hours solo → confirm the answer with a write-up → reproduce by hand" — this routine is your growth engine, repeating after every competition from now on.
1. Learning Objectives
By the end of this chapter, you will be able to:
- Apply the criteria for selecting the 3 highest-debrief-value problems from a competition log
- Operate the different debrief strategies for before/after write-up publication
- Fill the debrief table (my frontier | the answer’s next step | what was needed)
- Go beyond reading a write-up to reproducing by hand and verifying
- Reflect learned techniques in the playbook as "★ use immediately at the next competition"
2. Background Knowledge — Today’s Tools and Concepts
Today’s Tools at a Glance
| Category | Details |
|---|---|
| Language/environment | Competition log CSV, original problem files, write-ups (web), per-field tools (today: Crypto reproduction in Python) |
| Today’s screens/tools | ctf_log.py report (debrief candidate check), the debrief-table template, xor_chal.py/xor_solve.py (reproduction practice) |
| Concepts needed | Debrief block A, the "almost had it" selection criterion, before/after-publication strategies, the debrief table, the reproduction principle |
| Today’s deliverable | 3 debrief tables + 1+ reproduction code + 3 new playbook items |
2-1. Why Unsolved Problems — Solved Ones Are Already Mine
After a competition, what you want to do is brag about the solved problems. But from a growth standpoint, a solved problem is doing what you already knew how to do. Unsolved problems, by contrast, contain exactly what you don’t know — which is why debrief block A’s targets are the unsolved, not the solved.
Especially valuable are the "almost had it" problems. A problem you couldn’t even get a grip on holds too much to learn for one debrief to absorb. But for a problem one or two steps short, what "that one step" was is clear — and that one step becomes points immediately at the next competition. It’s the stretch with the highest growth-per-investment.
2-2. Selection Criteria — The Log Knows the Answer
Look again at Step 279’s report output (re-quoted from measurement):
[Unsolved problems — debrief candidates]
Rev license-check stuck memo: stalled at the anti-debugging section
Web admin-panel stuck memo: all SQLi payloads blocked
Crypto xor-note stuck memo: stuck estimating the key length
There are three selection criteria.
- Depth of reach — the more concrete the stuck memo (the clearer the stopping point), the higher the priority
- Field proximity — the closer to your main track, the sooner it becomes points at the next competition
- Reproducibility — do the problem files survive, or can it be reconstructed locally?
With the log above, all three problems have concrete memos, so all are nominated. There’s no reason to choose among the three, so all 3 are today’s targets — which is also why the original curriculum fixed "3 wrong problems." Three is the right debrief volume for a week; one alone is luck, and past five each one goes shallow.
2-3. Before and After Publication — Same Problem, Different Strategy
There’s usually a gap of a few days between the competition’s end and the official write-ups’ publication. How you use that gap is half the debrief.
Before publication — 2 more hours solo. Look at the same problem again in the calm after the competition’s tension is gone. Something remarkable happens often — what was invisible mid-competition becomes visible, because tension had narrowed your vision. If it solves here, that’s the best possible debrief: the very fact "I would have solved it with just a little more time" changes your time-allocation strategy for the next competition.
After publication — answer confirmation and reproduction. If 2 hours doesn’t solve it, read the write-up. The absolute rule at this point: don’t stop at reading and going "ah, that’s it." Understanding and reproduction are different layers. Only when you solve it to the end with your own hands — without looking at the write-up (or looking only at the last hint) — does it become your technique. If there’s no environment to reproduce in, reconstruct the problem’s core mechanism locally and solve that — we actually do it in 3-3.
2-4. The Debrief Table — Three Boxes Structure the Thinking
The debrief’s record format is simple. Fill a three-box table per problem.
| Box | What to fill | Example (xor-note) |
|---|---|---|
| My frontier | The front line restored from log and memory | "Knew it was repeating XOR; stopped at not knowing the key length" |
| The answer’s next step | What the write-up showed, immediately past my frontier | "The guarantee that it starts with ‘flag{‘ = the key to a known-plaintext (crib) attack" |
| What was needed to know that | Which was missing — knowledge, tool, or habit | "The crib-dragging concept — it wasn’t in the Crypto track’s classic technique list" |
The third box is the debrief’s conclusion. "Knowledge was missing" becomes a new playbook item; "a habit was missing" (didn’t read the hint, etc.) becomes a competition operation rule; "a tool was missing" lengthens the environment checklist. Causes of different kinds can’t share one prescription.
3. Follow Along
3-1. Fixing the 3 Debrief Targets and Securing the Originals
Fix 3 from report‘s debrief candidate list (apply 2-2’s criteria). And secure the problem originals today — competition platforms often take challenge servers down about a week after the end.
[Debrief targets fixed — example]
1. Crypto - xor-note : hint text and ciphertext (hex) saved to notepad
2. Web - admin-panel : server is down → request/response captures and tried-payload list secured
3. Rev - license-check : binary downloaded (grabbed during the competition)
Server-type problems (Web, etc.) disconnect after the end, so capturing requests/responses and screens during the competition is the only original. This is why the capture habit rides on top of Step 279’s log habit.
3-2. The Pre-Publication 2 Hours — Reattaching to xor-note
Before hunting write-ups, set a 2-hour timer and look at xor-note again. The mid-competition memo was "stuck estimating the key length." Read calmly again, and the problem’s hint looks different.
[Re-reading the problem hint — screen example]
"The ciphertext is repeating-key XOR. The key length is at most 10.
The plaintext is guaranteed to start with 'flag{'."
Mid-competition, you skimmed right past that second sentence. Read slowly, and it’s odd — why would they bother telling you the plaintext’s first five characters? The organizer’s hints are not decoration; they’re keys. Knowing the first 5 bytes is the starting point of a known-plaintext (crib) attack. This is an example of what the "2 hours solo" discovers.
3-3. Local Reproduction — Rebuild It by Hand and Solve (Measured)
Even if the challenge server is down or you never got the original, it’s fine. Rebuild the core mechanism (repeating XOR + guaranteed crib) identically in your local environment and solve that. Below is the reproduction we actually wrote and ran. First, the problem generator.
# xor_chal.py — reproduce the 'xor-note' type I couldn't solve at the competition, by my own hand
import sys
FLAG = "flag{x0r_k3y_l3ngth_1s_th3_gat3}"
KEY = b"K7m" # repeating-XOR key (only the generator knows it)
HINT = (
"The ciphertext is repeating-key XOR. The key length is at most 10.n"
"The plaintext is guaranteed to start with 'flag{'.n"
)
def gen():
data = FLAG.encode()
cipher = bytes(b ^ KEY[i % len(KEY)] for i, b in enumerate(data))
with open("challenge.txt", "w", encoding="utf-8") as f:
f.write("=== xor-note (local reproduction) ===n")
f.write(HINT)
f.write("ciphertext(hex): " + cipher.hex() + "n")
print("challenge.txt created — ciphertext", len(cipher), "bytes")
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == "gen":
gen()
else:
print(__doc__)
Run result (measured):
$ python xor_chal.py gen
challenge.txt created — ciphertext 32 bytes
$ cat challenge.txt
=== xor-note (local reproduction) ===
The ciphertext is repeating-key XOR. The key length is at most 10.
The plaintext is guaranteed to start with 'flag{'.
ciphertext(hex): 2d5b0c2c4c157b4532200414145b5e25501923685c3868192304322c5619784a
Now the solution. XOR the crib flag{ with the ciphertext’s first 5 bytes and a key fragment comes out; the fragment’s minimal repeating length is the key length.
# xor_solve.py — a reproduction solve that breaks repeating XOR with a 'known plaintext (crib)'
import re
text = open("challenge.txt", encoding="utf-8").read()
cipher = bytes.fromhex(re.search(r"ciphertext(hex): ([0-9a-f]+)", text).group(1))
crib = b"flag{"
# ① XOR the crib with the first 5 bytes → key-fragment candidate
frag = bytes(c ^ k for c, k in zip(cipher[:len(crib)], crib))
key_len = None
for n in range(1, 11):
if all(frag[i] == frag[i % n] for i in range(len(frag))):
key_len = n
break
print(f"key fragment from crib '{crib.decode()}': {frag!r}")
print(f"the fragment's minimal repeat length = key length {key_len}")
# ② the fragment repeats to fix the whole key, so decrypt as-is
key = bytearray(frag[:key_len])
plain = bytes(c ^ key[i % key_len] for i, c in enumerate(cipher))
print("decryption result:", plain.decode())
Run result (measured):
$ python xor_solve.py
key fragment from crib 'flag{': b'K7mK7'
the fragment's minimal repeat length = key length 3
decryption result: flag{x0r_k3y_l3ngth_1s_th3_gat3}
How to read it: the fragment from the first 5 bytes is K7mK7 — K7m is repeating, so the key length is 3 and the whole key sits inside the fragment. The problem where you stopped at "stuck estimating the key length" mid-competition collapses into 10 lines of code the moment you know what a single crib line means. That is the debrief’s reward — and while making and fixing mistakes in the solve (in the first draft, a fragment-length miscalculation skewed the key), the technique truly attaches to your body.
3-4. Writing the Debrief Table — The xor-note Example
A problem whose reproduction is done gets its debrief table filled on the spot. A writing example.
[Debrief table 1/3] Crypto - xor-note (150 pts)
┌─────────────────────────┬───────────────────────────────────────────────┐
│ My frontier │ Identified repeating XOR. Couldn't advance │
│ │ without the key length │
│ The answer's next step │ "plaintext starts with 'flag{'" = crib. │
│ │ XOR first 5 bytes → key fragment → │
│ │ repeat period = key length │
│ What was needed │ Knowledge: the crib-dragging (known-plaintext) │
│ │ concept. Habit: also caused by skimming the │
│ │ hint sentence as "decoration" │
└─────────────────────────┴───────────────────────────────────────────────┘
Technique learned: restore key fragment from crib → find repeat period → full decrypt
Reproduced: ✅ solved to the end with a local reproduction (xor_chal.py / xor_solve.py)
By the same procedure, fill the debrief tables for admin-panel (SQLi-block bypass) and license-check (anti-debugging bypass). For a problem whose server is down, transplant the write-up’s payloads into a local test environment and verify; for one with a binary, load it straight into a debugger.
3-5. Reflecting in the Playbook — "★ Use Immediately at the Next Competition"
The debrief’s last act is adding a new item to the playbook (Step 272). One page per item is enough.
[Playbook addition — Crypto/XOR]
■ crib attack: knowing part of the plaintext restores a repeating-XOR key fragment
- procedure: crib ⊕ ciphertext → key fragment → repeat period = key length → full decrypt
- signal: when the problem "guarantees" the plaintext's starting format (flag{, CTF{, etc.)
- code: tmp/xor_solve.py (reusable)
★ use immediately at the next competition — on Crypto problems, re-read the hint sentences first
The ★ use immediately at the next competition mark fixes this item’s character — not reference knowledge but a checklist item. Reviewing the ★-marked items first during the next competition’s full sweep (Step 279’s first 30 minutes) — that is the completion of the cycle connecting debrief and competition.
4. Missions & Exercises
Mission — Complete Debrief Block A
- Select 3 "almost had it" problems from the competition log’s debrief candidates by 2-2’s criteria, and write one line of selection rationale for each.
- Put the pre-publication "2 hours solo" into each problem, and memo one line of anything newly learned (not solving is fine — the memo is the deliverable).
- Collect official/community write-ups and write 3 debrief tables in the 3-4 format.
- Reproduce at least 1 problem to the end by hand (local reconstruction counts).
- Add the 3 learned techniques to the playbook, all marked
★ use immediately at the next competition.
Exercises
Exercise 1. Explain why "almost had it" problems take priority over "couldn’t even get a grip" problems as debrief targets.
Exercise 2. Give two effects of spending 2 more hours solo "before" write-up publication.
Exercise 3. Explain how the prescription differs depending on whether the debrief table’s third box ("what was needed to know that") answers knowledge, habit, or tool.
Exercise 4. In 3-3’s reproduction solve, state the grounds for fixing the key length at 3 when the key fragment came out as b'K7mK7'.
5. Model Answers & Completion Criteria
Mission Model Answer
How to verify: ① are the selection rationales written in the vocabulary of 2-2’s criteria (depth of reach, field proximity, reproducibility)? ② does a "2 hours solo" memo exist per problem — without these memos, it’s no different from a write-up summary. ③ are all three boxes of the 3 debrief tables filled, and in particular is "the answer’s next step" concrete enough to be said in one sentence (an answer like "should have XORed harder" is unfinished)? ④ do code and output remain for the 1 reproduction — "I solved it" without output is not reproduction. ⑤ are there 3 new playbook items with ★ marks?
Exercise Answers
Answer 1. For an almost-had-it problem, the missing piece is pinpointed as "one step," so learning that one step becomes points immediately at the next competition — the highest growth-per-investment. A problem you couldn’t grip holds too much to absorb in one debrief; better to defer it to a later debrief, after the prerequisite knowledge it demands has accumulated.
Answer 2. ① Retrying with the competition’s tension gone widens your vision, and clues invisible mid-competition often appear — solving here is the best possible debrief. ② Even if unsolved, "my frontier" becomes precise, so when you later read the write-up, the difference between the answer and your reach sharpens into one step — the learning efficiency differs from just reading a write-up cold.
Answer 3. If it was "missing knowledge," the prescription is adding the technique to the playbook; if it was a "missing habit" (didn’t read the hint, didn’t capture), the prescription is adding a competition operation rule; if it was a "missing tool," the prescription is expanding the environment checklist. Only by classifying the cause’s kind correctly does the debrief connect to next actions.
Answer 4. In repeating XOR, ciphertext ⊕ plaintext = the key repeating, so the fragment obtained from a five-character crib is the key’s first five characters (or their repetition). In the fragment K7mK7, characters 1–3 (K7m) match the front of characters 4–5 (K7) — that is, repetition with a period of 3 holds. Shorter lengths (1, 2) can’t explain the fragment, so the minimal length at which repetition holds — 3 — is the key length.
Completion Criteria Checklist
- [ ] I can explain the 3 debrief targets’ selection rationales in the criteria’s vocabulary
- [ ] I executed the pre-publication "2 hours solo" per problem and left memos
- [ ] I wrote 3 debrief tables (frontier / next step / what was needed)
- [ ] I reproduced at least 1 problem to the end by hand
- [ ] I can explain why you must not stop at "read it, ah that’s it"
- [ ] 3 learned techniques were added to the playbook with ★ marks
6. Common Pitfalls & Fixes
Wall 1. Reading the write-up I understand everything, but solo I can’t solve it
Cause: understanding and reproduction are different layers. Knowing from reading is recognition; what a competition needs is recall.
Fix: after reading the write-up, always close it and reproduce from start to finish by hand. Where you stall is exactly where you don’t know. If reproduction is too hard, regulate difficulty by looking only at the last step’s hint and filling the rest solo.
Wall 2. The challenge server is down and reproduction is impossible
Cause: server-type problems often disappear with the competition’s end.
Fix: Two routes. ① Reconstruct just the core mechanism locally — as done in 3-3, rebuilding the vulnerability’s essence (repeating XOR, a weak upload filter, etc.) in your own environment is itself deep learning. ② From the next competition on, secure originals with the habit of capturing requests/responses during the competition.
Wall 3. I kept postponing the debrief and a month passed
Cause: debriefing is work done after the competition’s thrill has cooled, so no motivation arises.
Fix: Block memory’s half-life with a rule — make finishing block A within 1 week of the competition’s end a personal regulation. After a week, even the stuck memos’ meaning blurs. If you’re busy, finish even 1 of the 3 — one deep debrief beats three shallow ones.
Wall 4. The solve script won’t run due to a syntax error
Symptom (measured — actually occurred in the draft of 3-3’s solve code):
File ".../xor_solve_draft.py", line 4
print("cipher length:" + f"{len(cipher)}":>8)
^
SyntaxError: invalid syntax
Cause: a typo that put the f-string format specifier (:>8) outside the f-string. Common when writing reproduction code in a hurry.
Fix: put format specifiers inside the f-string braces — f"{value:>8}". Write reproduction code in small pieces, printing output at each step, and you’ll see immediately which line went off.
Wall 5. Every write-up solves it differently and I don’t know which to follow
Cause: CTF problems often have more than one correct answer, and experts’ write-ups skip a lot.
Fix: at the beginner stage, pick the longest write-up, the one that records even the failure paths — a same-eye-level solution that says "I also wandered on this" serves reproduction better than an expert’s success-only write-up. And the criterion is one: can I reproduce it?
7. Summary
Today’s Concepts
| Concept | One-line explanation |
|---|---|
| Debrief block A | The debrief that digs unsolved problems to the bottom — the body of growth |
| "Almost had it" problem | Top-priority debrief target whose frontier is clear, needing just one step |
| 2 hours solo | The pre-publication retry — vision restored after tension + frontier fixed |
| crib (known plaintext) | Knowing part of the plaintext — the key to restoring a repeating-XOR key fragment |
| Debrief table | Frontier | the answer’s next step | what was needed — structuring the thinking |
| The reproduction principle | Not knowing-by-reading (recognition) but solving again by hand (recall) |
| ★ use immediately at the next competition | The playbook mark that connects debriefs to next-competition action |
Today’s Commands & Tools
| Command/tool | What it does |
|---|---|
python ctf_log.py report |
Check the debrief candidate list in the competition log |
python xor_chal.py gen |
Reconstruct an unsolved problem’s core mechanism locally |
python xor_solve.py |
Decrypt repeating XOR with a crib attack (reproduction solve) |
| Debrief-table template | Per problem: 3 boxes + technique learned + reproduced or not |
| Playbook ★ items | The checklist to review first at the next competition’s full sweep |
The Core Instinct
If one competition day is 10, two debrief days are 90 — no exaggeration, because a competition only shows the total of what you know; it teaches you nothing new. What teaches is the wall, and the time spent dismantling the wall is the debrief. Once this routine — competition → log → 3 debriefs → playbook ★ — starts turning, the competition stops being an exam and becomes a device that builds your curriculum for you.
Once every box is checked, Step 280 is complete.