Step 287. ★ CTF #5: The Main-Field Depth Confirmation Match — A Competition That Measures Where Our Ceiling Is
Level 3 — The CTF Competition Cycle | Difficulty ★★★★☆ | Estimated time: 2 days (competition weekend + post-competition comparison analysis)
Prerequisites: Step 284’s team weakness analysis, Step 285’s weakness-assault competition. The main field must be agreed in the minutes.
- What you need: a weekend competition picked on CTFtime (
ctftime.org), the results CSV of competitions #1–#4, thedifficulty_stats.pybuilt below, the team board. Competition scenes are screen examples; the per-difficulty success-rate script’s run is measured (using example data). - ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime. Only the competition’s challenge servers are attack targets; the competition infrastructure and other teams are not. Read top-team write-ups published after the end only from distributed sources.
- This chapter is a competition chapter — on the stage after filling the weakness (Step 285), you test the upper bound of your strength.
At Step 285 the team opened the door to the weakness field. This time it’s the opposite side — measuring how far we’ve come in the field we’re good at. You can’t know the team’s weight class from the gut feeling "our main field is fine." Weight class is measured only by whether Easy is never missed within the same field, how much of Medium you take, and whether you’ve knocked on Hard’s door.
This competition’s operation is exactly symmetric to Step 285’s. Then it was "30% on the weakness while defending the base score"; today it’s "secure the base score, then pour half of the remaining time into main-field Hard." Solve it and your weight class rises; fail and you still get the finest debrief material — a comparison point against top-team write-ups.
1. Learning Objectives
By the end of this chapter, you will be able to:
- Quantify "current weight class" by measuring success rates per difficulty within one field
- Design and keep a balance rule between base-score securing and Hard challenges
- Assault Hard problems with 2-person pair programming (research/coding split)
- Document the reach point when time runs out
- Compare top-team write-ups against your own solve to extract "what they did where we stopped"
2. Background Knowledge — Today’s Tools and Concepts
Today’s Tools at a Glance
| Category | Details |
|---|---|
| Language/environment | CTFtime weekend competition (Jeopardy), Python 3 (success-rate tally), team board |
| Today’s command | python difficulty_stats.py results.csv Web — per-difficulty success rates for the main field |
| Concepts needed | Per-difficulty success rates, Hard challenge rule, pair programming, reach-point comparison |
| Today’s deliverable | Per-difficulty success-rate table + Hard problem reach-point document + top-team comparison notes |
2-1. Per-Difficulty Success Rates — The Ruler of "How Far We’ve Come"
One field’s skill can’t be measured in a single number. Measure three layers — Easy success rate (basic stamina), Medium success rate (real weight class), Hard attempts (ceiling). The combination of these three layers states the team’s current position.
| Pattern | Diagnosis |
|---|---|
| Easy 100% + Medium 50% + Hard unattempted | Weight-class rising zone — time to knock on Hard’s door |
| Easy 100% + Medium 100% + Hard unattempted | Stagnation risk — the zone where comfort blocks growth |
| Easy below 80% | Recheck the basics — upper-difficulty challenges are premature |
| Many Hard attempts + 0 successes | Near the ceiling — the zone where comparison debriefs are most valuable |
The name "confirmation match" for today’s competition comes from this table — the competition is an exam, and the exam result remains as an update to this table.
2-2. The Hard Challenge Rule — Balancing Ranking Defense and Growth Challenge
Hard problems carry big points but low probability. The order that protects team morale is fixed — base score first, challenge second.
Hard challenge rule (agreed before the start):
1. Early in the competition, difficulty-scan the main field's problems → designate 1 Hard-tier problem in advance
2. Secure the base score with Easy·Medium (per the team's average success rates)
3. After the base score is secured, pour half of the remaining time into Hard
4. Hard time runs not as "nonstop immersion" but as 30-minute progress checks
Item 1 is the core — Hard must be designated in advance. A Hard picked mid-competition with "what now?" is not chosen but left over, and a leftover Hard is usually a problem that doesn’t fit the team. The moment you designate it in advance, a corner of your brain runs background research on Hard even while solving Easy.
2-3. Pair Programming — Hard Is Not Solved Alone
Hard-tier problems often exceed one person’s working-memory capacity — things to research, to try, to remember pour in simultaneously. So two people attach to one screen.
| Role | What they do |
|---|---|
| Driver (coding) | Runs tools, writes scripts, attempts — the hands |
| Navigator (research) | Looks up docs, cheat sheets, similar techniques; tracks hypotheses; records progress — the eyes and the record |
Swap roles every 30 minutes. The reason for this rule is not fairness but replacing the thinking — the same problem seen from a different role shows different things. And the navigator’s progress record becomes today’s deliverable (the reach-point document) as-is.
2-4. Top-Team Comparison — Where You Stopped Becomes Material
Failing Hard is this competition’s normal outcome, and what failure leaves is exact coordinates. When top-team write-ups come up after the competition ends, the comparison summarizes into one sentence — "what did they do where we stopped."
This comparison is valuable because the difference’s kind reveals itself. A tool difference (they had a tool we didn’t), a knowledge difference (a theory we didn’t know was used), a thinking difference (they read the same clue differently). A tool difference fills in a day, a knowledge difference becomes a study route, and a thinking difference is the slowest but most valuable review target.
3. Follow Along
3-1. Before the Competition — Measure Weight Class from Past Data
From the results CSV of competitions #1–#4 (the file made in Step 284 with #4 added), pull only the main field and extract per-difficulty success rates. Save the script below as difficulty_stats.py — the code and output are measured, actually run on example data.
# difficulty_stats.py — measure per-difficulty success rates for the main field (confirmation-match scorecard)
# usage: python difficulty_stats.py results.csv Web
import csv
import sys
from collections import defaultdict
def main(path, target):
rows = list(csv.DictReader(open(path, encoding="utf-8")))
rows = [r for r in rows if r["category"] == target]
if not rows:
print(f"no data for category '{target}'.")
return
# difficulty × contest tally
cell = defaultdict(lambda: [0, 0]) # (difficulty, contest) -> [attempts, solves]
comps = sorted({r["contest"] for r in rows})
diffs = ["Easy", "Medium", "Hard"]
for r in rows:
c = cell[(r["difficulty"], r["contest"])]
c[0] += int(r["attempted"])
c[1] += int(r["solved"])
print(f"[{target} — per-difficulty success rates, trend by contest]")
header = "| difficulty | " + " | ".join(comps) + " | total |"
print(header)
print("|" + "------------|" * (len(comps) + 2))
for d in diffs:
cols, ta, ts = [], 0, 0
for comp in comps:
att, suc = cell[(d, comp)]
ta, ts = ta + att, ts + suc
cols.append(f"{suc}/{att} ({suc / att * 100:.0f}%)" if att else "-")
total = f"{ts}/{ta} ({ts / ta * 100:.0f}%)" if ta else "-"
print(f"| {d} | " + " | ".join(cols) + f" | {total} |")
print("\n[how to read]")
for d in diffs:
att = sum(cell[(d, c)][0] for c in comps)
suc = sum(cell[(d, c)][1] for c in comps)
if att == 0:
print(f"- {d}: no attempt records — the confirmation match needs a first attempt.")
else:
rate = suc / att * 100
note = "stable zone" if rate >= 80 else "growth zone" if rate >= 50 else "still a wall"
print(f"- {d}: {suc}/{att} ({rate:.0f}%) — {note}")
if __name__ == "__main__":
main(sys.argv[1], sys.argv[2])
Measured result run on an example team’s data whose main field is Web (a CSV of Web rows from competitions #1–#5) — this output includes today’s competition (CTF #5) results. You pull the table through #4 before the competition, then add #5 after it and rerun to compare.
python difficulty_stats.py results.csv Web
[Web — per-difficulty success rates, trend by contest]
| difficulty | CTF#1 | CTF#2 | CTF#3 | CTF#4 | CTF#5 | total |
|------------|--------|--------|--------|--------|--------|--------|
| Easy | 2/2 (100%) | 2/2 (100%) | 2/2 (100%) | 2/2 (100%) | 2/2 (100%) | 10/10 (100%) |
| Medium | 0/1 (0%) | 0/1 (0%) | 0/1 (0%) | 1/2 (50%) | 2/2 (100%) | 3/7 (43%) |
| Hard | - | - | - | - | 0/1 (0%) | 0/1 (0%) |
[how to read]
- Easy: 10/10 (100%) — stable zone
- Medium: 3/7 (43%) — still a wall
- Hard: 0/1 (0%) — still a wall
How to read it: this team’s story reads out — Easy perfect across five competitions, Medium on track from a #1–#3 losing streak into #4–#5, and Hard knocked on for the first time today. With this table, instead of the gut "aren’t we decent at Web?", you can state the exact current position: "Easy stable zone, entering Medium growth zone, first Hard attempt."
3-2. Early Competition — Difficulty Scan and Hard Designation
Within 30 minutes of the start, sweep all the main field’s problems and grade their difficulty. The competition’s points are the baseline, but the organizer’s difficulty and ours differ — re-measure by whether it overlaps the cheat sheet.
Screen example:
Web problem board (5 problems):
- cookie-jar (100) — session tampering, matches cheat sheet #3 → Easy
- jwt-kid (200) — kid header injection, read about it → Easy~Medium
- ssrf-cloud (300) — metadata endpoint, the type we stalled on at #4 → Medium
- race-auction (300) — race condition, debriefed before → Medium
- deser-chain (500) — deserialization chain, needs gadget assembly → Hard ★designated
Leave the grounds for the Hard designation in one line — "highest points at 500 + deserialization is a type we’ve learned the basics of + will take a long solve time." The designation grounds make the later failure-cause analysis exact.
3-3. Mid-Competition — Base Score First, Then Hard
Take Easy and Medium first. Breaking the order and grabbing Hard first is this competition’s only taboo — a Hard challenge without a base score is not a challenge but a gamble, and when it fails the team gets nothing.
Once the base score is secured, spend half of the remaining time on Hard. Attach as 2-3’s pair, and the navigator records progress every 30 minutes.
Screen example (Hard progress record):
[deser-chain progress]
+0:30 endpoint identified, serialization format confirmed (PHP serialize, estimated)
+1:00 input reflection point found — deserialization call estimated in the log viewer
+1:30 searched public gadget chains — failed to pin down the framework version
+2:00 tried building a similar environment locally — dependency version mismatch
+2:30 started manual gadget assembly — first chain candidate failed
+3:00 time. reach point: "entered the gadget-assembly stage, chain incomplete"
3-4. Right After the End — Documenting the Reach Point
Solved or not, leave the Hard problem’s reach point as a document. The format is three cells.
### Hard reach point — deser-chain (CTF#5)
- final reach: gadget-assembly stage (input → deserialization confirmed → gadget search → assembly failed)
- time split: recon 1h / environment build 1h / assembly 1h
- where it stalled: failed to pin the framework version → couldn't apply public chains → switched to manual assembly but ran out of time
This document’s value explodes in 3-5. Only with a record, not memory, is the comparison exact.
3-5. The 48 Hours After — Comparing Against Top-Team Write-ups
When write-ups come up after the end, spread your reach-point document and read. Look for one thing — what they did where we stopped.
Screen example (comparison notes):
[comparison] deser-chain — us: stalled at gadget assembly / differences from top-team solutions
- their move: skipped version pinning and read framework traces from error messages
(the 500 response's stack trace exposed vendor paths — we never looked at the errors)
- kind of difference: thinking difference — didn't see "version-pin failure" as a wall; switched information sources
- lesson: an error response is not a failure signal but an information source — add to our cheat sheet's 'traps' cell
- response by difference kind: thinking difference → reproduce this problem via their path in debrief block A
If the comparison notes’ last cell (response by kind) is missing, you only read. For a tool difference, install the tool; for a knowledge difference, set a study route; for a thinking difference, reproduce via their path.
4. Missions & Exercises
Mission — Finish the Main-Field Confirmation Match
- Before the competition, pull the main field’s per-difficulty success rates (competitions #1–#4) with
difficulty_stats.pyand write the current weight class in one sentence. - Early in the competition, difficulty-scan the main field’s problems and designate 1 Hard-tier problem with grounds.
- Secure the Easy·Medium base score first, then pour half the remaining time into Hard — as a pair (research/coding), with 30-minute progress records.
- Right after the end, write the reach-point document (final reach / time split / where it stalled).
- Add the competition results to the CSV and rerun the script to update the success-rate table.
- Compare against top-team write-ups and organize "what they did where we stopped" with responses by difference kind.
Exercises
Exercise 1. Why must a main field’s skill be measured as three per-difficulty success-rate layers (Easy/Medium/Hard) instead of "total points"?
Exercise 2. Why must a Hard problem be "designated in advance" early in the competition? What differs from picking one mid-competition?
Exercise 3. How does the rule "secure the base score before the Hard challenge" connect to team morale?
Exercise 4. Why split the difference from top teams into three kinds — "tool/knowledge/thinking"? What is each one’s response?
5. Model Answers & Completion Criteria
Mission Model Answer
Check against these verification criteria.
- Prior measurement exists: are the success-rate table pulled before the competition and the one-sentence "current weight class" present — pulling the table only after the competition makes it just a competition, not a confirmation match.
- Grounds for the Hard designation: is the designation’s reason written in at least one line — a designation without grounds is the same as having no baseline for result analysis.
- Order compliance: do the progress records’ timestamps confirm the order of base score first, Hard second?
- Reach-point concreteness: is it written in noun form "to which stage, stalled at what" rather than "sadly couldn’t solve it"?
- Comparison completeness: was the difference classified as tool/knowledge/thinking, and a matching response (install / study / reproduce) set?
Exercise Answers
Answer 1. Because total points swing with the problem set’s composition — high points at a competition heavy on Easy don’t mean skill rose. Per-difficulty success rates are pure per-layer ability with the composition’s effect strained out. Easy 100% states basic stamina, Medium’s rate the real weight class, and Hard attempts the ceiling — each separately — and training is designed per layer too.
Answer 2. Because a Hard picked mid-competition is "not chosen but left over." By then the problems fitting the team are already assigned, so the remaining Hard gets picked regardless of interest or aptitude. An advance designation, by contrast, is a choice made comparing cheat-sheet fit, points, and expected solve time. And after designation, the brain runs background research even while solving Easy — a side effect that fattens the actual time invested.
Answer 3. Because Hard is a high-failure-probability slot, so failing without a base score leaves the team empty-handed from that competition. The "secure first → challenge" order leaves points and a reach-point document even in the worst case. Growth must be repeatable, and to be repeatable the team must feel "this competition also had a harvest" — morale is results management, not emotion management.
Answer 4. Because each kind of difference costs and fills differently. A tool difference ends with installation (a day), a knowledge difference fills via a study route (weeks), a thinking difference is internalized by reproducing via their path (slowest, but most valuable). Unclassified, it all blurs into "let’s work harder"; classified, each gets a concrete action. A debrief’s deliverable is not impressions but actions.
Completion Criteria Checklist
- [ ] I pulled the main field’s per-difficulty success-rate table before the competition
- [ ] I wrote the current weight class in one sentence (e.g., "Easy stable zone, Medium growth zone, Hard unattempted")
- [ ] I designated 1 Hard-tier problem in advance with grounds
- [ ] I secured the base score, then poured half the remaining time into Hard
- [ ] I assaulted as a pair (research/coding) with 30-minute progress records
- [ ] I wrote the reach-point document (final reach / time split / where it stalled)
- [ ] I updated the success-rate table with the competition results
- [ ] I completed the top-team comparison notes (difference kinds + responses)
6. Common Pitfalls & Fixes
Wall 1. I passed a field name to the script and got "no data"
no data for category 'web'.
Cause: the CSV’s category value and your argument’s spelling differ. This script is case-sensitive — the CSV has Web but you ran web.
Fix: copy the category cell from the row below the CSV header and use it as the argument verbatim. If notation is mixed inside the CSV itself (Web and web coexisting), unify the CSV’s notation first — an aggregation tool’s accuracy comes from the data’s consistency.
Wall 2. I spent all the time on Hard and missed the base score
Symptom: settling up after the end, one Easy went unattempted. Hard failed.
Cause: Hard’s immersion swallowed the rule — a repeat of "just a bit more." Hard-tier problems have long trap stretches where progress feels like it’s happening, making them especially dangerous.
Fix: add one sentence to the 30-minute progress checks — "should we drop Hard now and go back to Easy?" This question is hard to ask yourself mid-competition. That’s why it’s nailed down as the navigator’s duty. The progress record is a tool that protects Hard’s time and simultaneously a tool that halts Hard.
Wall 3. The pair ended up with one person driving the whole time
Symptom: the driver has held the keyboard for 3 hours, and the navigator only watches.
Cause: the role-swap rule wasn’t kept. Deep in flow, neither hears the swap signal.
Fix: make swapping a timer, not a promise — when the 30-minute alarm rings, hand over the keyboard. The 5 minutes right after a swap being less efficient is normal — those 5 minutes are the cost of fresh eyes, and what those eyes discover is the substance of a Hard assault.
Wall 4. I read a top-team write-up and can’t tell what’s different
Symptom: only the impression "seems written by someone who just knows everything" remains.
Cause: you read without your team’s reach-point document. Comparison needs two points; when one point (our stopping place) is blurry, reading becomes appreciation.
Fix: rewrite the reach-point document first — even after the competition, the progress records (3-3) restore it. And reverse the reading order: don’t read the top team’s solution from the start; find and read the paragraph matching the stage where we stopped first. Comparison is not careful reading but collation.
Wall 5. The team’s mood sank because we couldn’t solve Hard
Symptom: someone says "it was beyond our level after all."
Cause: you mistook the confirmation match’s purpose. This competition didn’t go to solve Hard — it went to measure where the ceiling is.
Fix: unfold the success-rate table again — the Hard row’s "-" changing to "0/1" is this competition’s deliverable. A team with no attempts became a team that attempts, the reach point remains as a document, and the difference from top teams is classified. A ceiling starts cracking the moment it’s measured — whether the next competition’s Hard row reads "0/2" or "1/2," that is the scale mark of growth.
7. Summary
Today’s Concepts
| Concept | One-line explanation |
|---|---|
| Per-difficulty success rates | Easy (stamina) / Medium (weight class) / Hard (ceiling) — a ruler that says what totals can’t |
| Confirmation match | Operation that uses a competition as an exam — results remain as updates to the success-rate table |
| Hard challenge rule | Base score first, half the remaining time, Hard designated in advance |
| Pair programming | Driver (hands) + navigator (eyes and record), 30-minute swaps |
| Reach-point document | Final reach / time split / where it stalled — the reference point for post-competition comparison |
| 3 difference classes | Tool difference (install) / knowledge difference (study) / thinking difference (reproduce) |
Today’s Tools & Formats
| Tool/format | What it does |
|---|---|
difficulty_stats.py |
CSV → main-field per-difficulty success-rate table + diagnosis |
| Difficulty-scan memo | The procedure that re-measures the organizer’s difficulty as ours |
| Hard progress record | 30-minute position markers — a monitoring device for immersion |
| Reach-point document (3 cells) | The format that turns failure into coordinates |
| Comparison notes | The extraction frame for "what they did where we stopped" |
The Instinct Beyond Commands
A confirmation match’s deliverable is not a flag but scale marks. The first number carved in the success-rate table’s Hard row, the reach point left in sentences, the difference from top teams classified into "tool/knowledge/thinking" — these three scale marks make the team’s ceiling visible. A visible ceiling makes you want to break it, and a ceiling you want to break becomes training.
If the weakness assault (Step 285) was work that widened the map, the confirmation match is work that carves altitude into it. A team that measures both width and altitude earns the qualification for the next stage — a competition that targets rankings. That qualification is not points but the ability to state your position in numbers.
Once every box is checked, Step 287 is complete. Click the checkbox in the sidebar to save your progress.