Step 295. ★ CTF #9: The Top-30% Goal Competition — A Testing Ground for Measuring Your Weight Class
Level 3 — Real-World CTF & Advanced Offensive Skills | Difficulty ★★★★☆ | Estimated time: 2 days (a 24–48-hour competition + gap analysis)
Prerequisites: Step 289’s top-50% achieved (competition #6), Step 291’s live-fire library validation, Step 293’s team tactics fixed.
- What you need: one weekend competition (a 24–48-hour one on CTFtime), the fixed team tactics document, the exploit library (Step 290), the gap analysis script, and a 4-hour alarm. The competition scoreboard scenes in this chapter are screen examples; the gap analysis script is a tool you run hands-on with your own competition results.
- ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime. A CTF competition is a legal stage where the organizers officially open the problem environment — attacking the competition infrastructure, other teams, or systems outside the competition is both a rules violation and a crime.
- This chapter is a test — the ninth competition. We raise the goal from top 50% to top 30% and measure the team’s weight class.
Top 50% and top 30% are not a difference of the number 20. You can reach 50% as "a team that solves every easy problem without missing any." From 30% it’s different — because more than half the participating teams solve all the easy problems, rank is decided by how many Medium-tier-or-higher problems you tear off additionally. In other words, the 30% goal is a declaration that tests not "completeness of fundamentals" but "scoring power on mid-to-upper-tier problems."
That’s why today’s competition is a testing ground. Hit the goal and the weight-class rise is confirmed; miss it and the shortfall materializes into points and problem coordinates. Either way there’s something to gain — but the moment you read a miss as "my skill hasn’t grown," the gain vanishes. That’s why gap analysis is today’s core technique.
1. Learning Objectives
By the end of this chapter, you will be able to:
- Build a per-field expected-scoring table from recent competition data, grasping your strength in numbers
- Execute the time-allocation tactic of "easy problems blitzed → firepower concentrated on Medium tier"
- Manage progress against the goal with 4-hour interval midway checks
- After the end, analyze the gap by score structure instead of rank, converting the shortfall into specific problem coordinates
- Even when missing the goal, derive a single improvement goal for the next competition
2. Background Knowledge — Today’s Tools and Concepts
Today’s Tools at a Glance
| Category | Details |
|---|---|
| Language/environment | A CTFtime weekend competition, team collaboration tools (Discord, status board), Python (gap analysis) |
| Today’s command | python gap_analysis.py — rank percentile, cutoff line, shortfall-points calculation |
| Concepts needed | Percentile cutoff lines, score-structure analysis, the 4-hour midway check, the single improvement goal |
| Today’s deliverable | Competition log + per-field expected-scoring table + gap analysis result + 1 improvement goal |
2-1. Why 30% — The Meaning of Raising the Goal
At competition #6 you hit the top 50% (Step 289). Leave the goal where it is and the competition becomes repetition, not training. The rule for raising goals is "the next tick above the line you last achieved" — 50% confirmed, so the next tick is 30%.
At the same time, 30% is a structurally different zone. Most competition scoreboards split into three layers — the bottom half that solved only easy problems, the upper-middle 30–50% band that tore off a few Medium-tier problems, and the top 10–20% that reach Hard. Entering 30% is the entrance to the second layer, and that entrance’s doorstep is Medium-tier scoring power. Today’s competition’s real question is not "do we win" but "how much of a Medium-eating team are we?"
2-2. The Per-Field Expected-Scoring Table — Strength in Numbers
"Feels like we’ll do well this time" is not a strategy. Lay out the last three competitions’ (#6–#8) per-field results in a table and fill in expected scores per field for this one.
| Field | Last 3 comps’ scores | Expected | Basis |
|---|---|---|---|
| web | 2·3·2 problems | 3 problems | library validated, main field |
| pwn | 1·1·1 problems | 1–2 problems | heap drill effect unverified |
| crypto | 1·2·1 problems | 2 problems | common-factor pattern added via debrief |
| rev | 0·1·0 problems | 1 problem | second-responder experience from rotation |
| forensics | 1·0·1 problems | 1 problem | high variance — stay conservative |
This table’s uses are two — an alarm that detects mid-competition "fields scoring below expectation" early, and, after the end, a gauge measuring the accuracy of the team’s self-perception via "expected vs. actual."
2-3. The 4-Hour Midway Check — Managing Pressure with Procedure
A higher goal means bigger pressure, and pressure narrows judgment. Getting stuck on one problem for 3 hours is the signature symptom. The countermeasure is not willpower but procedure — every 4 hours an alarm rings and, no exceptions, you take your hands off and check three things.
The 4-hour check's 3 questions:
1. Current score vs. the expectation table — where are we ahead, where behind?
2. The problem being held right now — has its elapsed time passed the budget (the 2-hour swap rule)?
3. Reallocation of remaining time — has the priority of "the closest problem" changed?
Without this check, pressure accumulates and explodes in the last 2 hours. Making procedure manage emotion on your behalf — half of competition operations is this.
2-4. Gap Analysis — Translating a Miss into Coordinates
Reactions to missing a goal come in two kinds — "has my skill not grown?" (emotion) versus "which problems were short?" (analysis). The former produces no next action; the latter becomes a training plan.
Gap analysis’s structure is simple. Subtract our score from the top-30% boundary score (the cutoff line) and you get the shortfall in points; then convert that shortfall into "which combination of unsolved problems would have filled it." There’s no self-blame in numbers — only assignments with coordinates remain. Build this conversion into a script once, and you can run the same procedure every time a competition ends.
3. Follow Along
3-1. Before the Competition — The Expectation Table and Fixing the Tactics
At the kickoff meeting (30 minutes), fill 2-2’s expectation table with the team and fix the tactics. Today’s tactic has two stages.
Stage 1 (start ~ 4 hours): blitz the easy problems
- 30-minute sweep of all problems → start from each field's lowest difficulty, library at full power
- Goal: secure all base points (the sure shares in the expectation table) within 4 hours
Stage 2 (4 hours ~ end): concentrate firepower on Medium tier
- Put 70% of remaining time into 2–3 Medium-tier problems
- 2-hour budget per problem; on overrun, invoke the swap rule (Step 281)
Why: if stage 1 drags, stage 2 evaporates — and then the very chance to score Medium tier, the doorstep of 30%, disappears. The habit of solving easy problems "leisurely" is the most common cause blocking entry into the upper-middle ranks.
3-2. During the Competition — The 4-Hour Check in Practice
When the alarm rings, the team gathers in front of the status board (screen example):
[+4:00 check]
Expected: web 3 · pwn 1–2 · crypto 2 · rev 1 · forensics 1
Actual: web 3 ✓ · pwn 0 ✗ · crypto 2 ✓ · rev 0 · forensics 1 ✓
Verdict: pwn delayed. babyheap at 1h 50m elapsed — conclude within 10 minutes or swap
Reallocation: rev stays solo with its owner; 1 web owner joins pwn as consultant
How to read it: the check’s output is not "let’s work harder" but a reallocation decision. Because the expectation table exists, "pwn is behind" appears not as emotion but as a red cell in the table, and because the swap rule exists, the decision to cut off a cling is an execution of procedure, not a question of someone’s pride.
3-3. Right After the End — Reading the Cutoff Line on the Scoreboard
When the competition ends, pull three numbers from the scoreboard — total team count, our rank, and the score of the team at the top-30% boundary rank. For the boundary score, read the score of the (total teams × 0.3)-th team on the scoreboard.
Screen example (post-competition scoreboard memo):
412 teams total / us: 156th / 2350 points
Top-30% boundary = 412 × 0.3 ≈ rank 123
Rank-123 team's score = 3050 points
→ shortfall: 700 points
One caution — read the cutoff score after the competition ends. Mid-competition the scoreboard fluctuates (especially in dynamic-scoring competitions where point values keep changing), and riding the emotional waves of interim ranks contaminates the check procedure into emotional reaction. Mid-competition, the only thing to watch is not rank but our score versus the expectation table.
3-4. The Gap Analysis Script — Shortfall into Problem Coordinates
Feed 3-3’s three numbers plus "the list of unsolved problems (with point values)," and this script computes candidate combinations that would fill the shortfall. Save it as gap_analysis.py.
# gap_analysis.py — top-30% goal gap analyzer
# each time a competition ends, change only the 4 constants above and the UNSOLVED list
TOTAL_TEAMS = 412 # total team count
OUR_RANK = 156 # our final rank
OUR_SCORE = 2350 # our score
CUTOFF_RANK = int(TOTAL_TEAMS * 0.30)
CUTOFF_SCORE = 3050 # the boundary-rank team's score (looked up on the scoreboard)
UNSOLVED = [ # (name, field, points, total solving teams) — unsolved only
("babyheap", "pwn", 400, 38),
("jwt-forge", "web", 300, 61),
("rsa-fault", "crypto", 350, 44),
("packet-river", "forensics", 250, 89),
("rev-me-gently", "rev", 300, 57),
]
pct = OUR_RANK / TOTAL_TEAMS * 100
gap = CUTOFF_SCORE - OUR_SCORE
print(f"rank {OUR_RANK} of {TOTAL_TEAMS} teams → top {pct:.1f}%")
print(f"top-30% boundary: rank {CUTOFF_RANK} (score {CUTOFF_SCORE})")
print(f"points short: {gap}\n")
print("[candidates to fill the gap — unsolved problems, descending points]")
acc = 0
for name, cat, pts, solves in sorted(UNSOLVED, key=lambda x: -x[2]):
acc += pts
mark = "★ cumulative met" if acc >= gap else ""
print(f" {name:<14} {cat:<10} {pts:>4}pts (solved by {solves} teams) cumulative {acc} {mark}")
print(f"\nconclusion: {gap}pts = the size of the top 2–3 candidates. Medium-tier scoring power is the key to 30%.")
Here’s the run — the measured output with 3-3’s example data fed in:
rank 156 of 412 teams → top 37.9%
top-30% boundary: rank 123 (score 3050)
points short: 700
[candidates to fill the gap — unsolved problems, descending points]
babyheap pwn 400pts (solved by 38 teams) cumulative 400
rsa-fault crypto 350pts (solved by 44 teams) cumulative 750 ★ cumulative met
jwt-forge web 300pts (solved by 61 teams) cumulative 1050 ★ cumulative met
rev-me-gently rev 300pts (solved by 57 teams) cumulative 1350 ★ cumulative met
packet-river forensics 250pts (solved by 89 teams) cumulative 1600 ★ cumulative met
conclusion: 700pts = the size of the top 2–3 candidates. Medium-tier scoring power is the key to 30%.
How to read it: "top 37.9% — miss" is not the end of the output but its start. The 700-point shortfall means babyheap (400) + rsa-fault (350) — two problems — would have filled it, and those two problems’ "solving team counts" (38, 44 teams) show they weren’t dream problems but problems actually solved by teams around the top 10%. The miss’s cause has materialized not as "are we just not good enough" but as "heap problems and applied RSA common-factor — these two coordinates" — this is gap analysis.
3-5. The Retrospective — One Single Improvement Goal
When gap analysis ends, the team retrospective fixes exactly one single improvement goal for the next competition. Just one.
Meeting minutes example (screen example):
Gap analysis result: 700 short = heap (babyheap) + applied RSA (rsa-fault)
Improvement goal (single): "By the next competition, a 10-problem heap-type drill — starting with reproducing babyheap to the end"
Deferred: rsa-fault — the common-factor pattern already went into the playbook in block A debrief; no separate drill needed
Why only one: with 3 improvement goals, everything disperses across the 2 weeks between competitions and everything ends up half-done. One goal means 80% of training time converges on those coordinates, and at the next competition you can cleanly judge the goal’s success by "when that type appeared again, did the result change?" Gap analysis gives the coordinates; the single goal guarantees concentration — only when these two devices mesh does the competition cycle turn.
4. Missions & Exercises
Mission — Finish Competition #9 + Complete the Gap Analysis
- Pick a weekend competition on CTFtime, register, and build the per-field expected-scoring table at the kickoff meeting.
- Run the competition with the two-stage tactic (4-hour blitz → Medium-tier concentration), and perform every 4-hour check without skipping — record the reallocation decision at each check.
- After the end, confirm total team count, our rank, and the 30% boundary score on the scoreboard.
- Replace the 4 constants and the
UNSOLVEDlist ingap_analysis.pywith your competition results, run it, and fix the shortfall points and candidate problem combination. - (On success) Celebrate entering the top 30% with the team — and still run the gap analysis; it becomes the baseline for the next goal (20%?).
- (On a miss) Retrospect the gap analysis result without self-blame, and document one single improvement goal.
Exercises
Exercise 1. Explain, connecting to the scoreboard’s three-layer structure, why the difference between top 50% and top 30% is not "completeness on easy problems" but "Medium-tier scoring power."
Exercise 2. Why does the two-stage tactic put a 4-hour limit on stage 1 (blitzing easy problems)? Answer with what specifically disappears when stage 1 drags.
Exercise 3. Why must the cutoff score be read after the end, not mid-competition? What metric should be checked mid-competition?
Exercise 4. What does "solving team count" in gap analysis results mean? Explain the implications for training plans when a problem you were short on was solved by 38 teams.
5. Model Answers & Completion Criteria
Mission Model Answer
Verify against these criteria.
- The expectation table exists: was a table with per-field expected scores and bases made at kickoff — "let’s do well this time" is not an expectation table.
- Check records: are the 4-hour interval checks recorded with times, and did each check end in a reallocation decision — a check without a decision is spectating.
- Swap-rule compliance: was a swap invoked on problems exceeding 2 hours, or if extended, was the rationale recorded?
- Gap analysis completeness: does the script output contain shortfall points, candidate problem combinations, and solving team counts, and did the team agree on those coordinates?
- A single goal: is the improvement goal exactly one, with a success criterion written alongside ("solving that type at the next competition")?
- Attitude on a miss: do the minutes contain no self-blame expressions, with the shortfall described only in points and problem coordinates — the minutes’ language is the team’s culture.
Exercise Answers
Answer 1. Because the scoreboard’s bottom half is filled with easy-problem points, solving all the easy problems is a necessary condition for 50%, not a differentiator. From above 30%, most participating teams hold the base points, so what splits the ranks is additional scoring at Medium tier or higher. Thus the 30% goal becomes a test measuring not "fundamentals check" but "how many mid-to-upper problems does this team tear off," and preparation must concentrate on Medium-tier response power (drills, the library, pair assaults).
Answer 2. To protect stage 2’s time. Easy problems invite a "just a bit more polish" attachment thanks to the relief of being solvable — and if stage 1 drags by 2 hours, all that time comes out of Medium-tier assault time. The very attempt at Medium-tier scoring, the doorstep of 30%, evaporates. The 4-hour limit doesn’t mean abandoning base points — it’s a levee keeping base-point securing from devouring the whole schedule — only with the limit does "blitz" become a schedule instead of a slogan.
Answer 3. Because mid-competition scoreboards are incomplete (especially in dynamic scoring, where point values keep changing and the cutoff moves), and interim ranks shake emotions, contaminating the check procedure. Mid-competition, the comparison target is not other teams but our expectation table — only "where are we behind versus expectations" is a signal usable for reallocation; rank becomes analysis material only after the end. Separating when you watch the clock from when you watch the scoreboard is pressure-management procedure.
Answer 4. Solving team count is that problem’s market price of real difficulty. That 38 teams solved it means it was solvable for teams around the top 10% — in other words, the shortfall is not "secret techniques only the world’s best know" but "a technique teams half a step above us possess." This information places the training plan at an accurate spot — neither optimistic nor pessimistic: reachable within a few weeks of drills. Conversely, if the shortfall problem had been solved by only 3 teams, the accurate analysis would be reading it as "still a way to go" and adjusting the goal.
Completion Criteria Checklist
- [ ] I built the per-field expected-scoring table (with expectations and bases) at kickoff
- [ ] I ran the competition with the two-stage tactic (4-hour limit + Medium-tier 70%)
- [ ] I performed all 4-hour checks and recorded reallocation decisions
- [ ] I confirmed the cutoff score on the scoreboard after the end
- [ ] I ran
gap_analysis.pywith our results and fixed the shortfall points and candidate combination - [ ] I documented one single improvement goal (with success criterion) at the retrospective
- [ ] (On a miss) The minutes were written only in the language of points and coordinates — zero self-blame expressions
6. Common Pitfalls & Fixes
Wall 1. I can’t find "the boundary-rank team’s score" on the scoreboard
Symptom: our rank is on the scoreboard, but counting down to the 123rd team is hard.
Cause: every competition platform displays the scoreboard differently, and some expand only the top portion.
Fix: most platforms offer scoreboard download as CSV/JSON. Download, sort, and read row (total teams × 0.3) — that’s exact. Without such a feature, don’t count from the top of the page; copy the table, paste it into a spreadsheet, and find it by row number. As an approximation, reading the 30% point of the score-distribution graph (when the platform provides one) works too — gap analysis precision is fine at tens of points.
Wall 2. It’s the 4-hour check but everyone’s deep in focus and nobody gathers
Symptom: the alarm rings but the check gets postponed with "I’m just about to see something."
Cause: the "just about to see it" moment is often exactly where clinging begins — the proposal to postpone the check is itself a signal the check is needed.
Fix: convert the check from speech to writing — when the alarm rings, nobody has to stop working; each person fills three lines on the status board (progress / vs. expectations / requests). It takes 3 minutes and doesn’t break focus. Except: problems that have passed the swap-rule time get dropped without exception — that is the rule’s reason for existing.
Wall 3. We missed the goal and team morale sank
Symptom: the channel goes quiet right after the end, and retrospective attendance is low.
Cause: a rank number hits emotions directly — normal. The problem is skipping the retrospective over that emotion.
Fix: fix the retrospective’s first agenda item as running the gap analysis script. Emotional settling goes faster done while looking at numbers — you’re groaning at "top 37.9%" and the moment the line "700 short = two problems" appears, the conversation switches to analysis. And write this on the minutes’ first line — "a miss is data. Without the goal, we wouldn’t have known this shortfall."
Wall 4. We set 3 improvement goals — they all looked important
Symptom: heap drills, reversing basics, and speed training all became goals at once.
Cause: when gap analysis shows multiple coordinates, you want to grab them all — it arrives not as greed but in the form of responsibility.
Fix: first compute the time actually available between competitions (usually 2 weeks). At 6 hours per member per week, that’s 12 hours — barely room for one drill (10 problems). Mark the other goals as "deferred" and pull them back out at the next competition’s gap analysis. You’re not throwing goals away; you’re ordering them.
Wall 5. The expectation table misses every time — is it even useful?
Symptom: expected versus actual has disagreed three competitions in a row.
Cause: a missing expectation table is also data — it means the team is overestimating (or underestimating) its own strength.
Fix: record the misses’ direction. If the same field is overestimated every time, that field’s skill-assessment criteria (what types must you be able to solve to say "we can do it"?) need re-setting. Prediction accuracy itself is the team’s metacognition metric — the day predictions become accurate, the team has become one that knows its own weight class.
7. Summary
Today’s Concepts
| Concept | One-line explanation |
|---|---|
| The 30% doorstep | The zone split not by easy-problem completeness but by Medium-tier scoring power |
| Per-field expected-scoring table | Strength quantified — an alarm mid-competition, a metacognition metric after |
| Two-stage tactic | 4-hour blitz (secure base) → Medium-tier 70% (weight-class challenge) |
| 4-hour midway check | Managing pressure with procedure — the output is a reallocation decision |
| Gap analysis | The technique of translating a miss into "shortfall points + problem coordinates" |
| Single improvement goal | The device guaranteeing 2 weeks of concentration — with a success criterion |
Today’s Tools & Commands
| Tool/command | What it does |
|---|---|
python gap_analysis.py |
Computing percentile, cutoff line, shortfall points, candidate combinations |
| Scoreboard CSV download | Exact lookup of the boundary-rank score |
| Expected-scoring table | Kickoff’s deliverable — per-field expectations and bases |
| Written 3-line check | Progress / vs. expectations / requests — a check that doesn’t break focus |
| Minutes’ single-goal slot | 1 improvement goal + success criterion + deferred list |
The Core Instinct
What you must learn from this competition is not the result but how to read the distance between goal and result. Whether you hit 30% or missed it, the structure where the script output’s last line becomes next training’s first line — this is the device that turns a competition from "participation" into a "cycle."
Remember just one thing. The shortfall gap analysis shows is always smaller than you think — "we’re just not good enough" computes out to "two problems." A distance that was infinite when measured by emotion shrinks, measured in points, to a few weeks of drills. That is the single number sense this chapter wants to leave with you.
Once every box is checked, Step 295 is complete. Click the checkbox in the sidebar to save your progress.