Step 291. ★ CTF #7: Live-Fire Library Validation — An Asset’s Value Is Proven Only at a Competition

Step 291. ★ CTF #7: Live-Fire Library Validation — An Asset’s Value Is Proven Only at a Competition

Level 3 — The CTF Competition Cycle | Difficulty ★★★☆☆ | Estimated time: 2 days (competition participation + half a day of retrospective)

Prerequisites: Step 290 (exploit library v1) complete, Python 3 (for the measurement script).

  • What you need: one CTF competition for your team to enter, Step 290’s library repository, a memo for time records, Python 3. The competition scenes in this chapter are screen examples; the local time measurements and the path-failure reproduction are marked as measured (2026-09-09, Python 3.12).
  • ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime.
  • This is a validation chapter — the day you confirm the asset you built actually runs in the field.

Library v1 looks perfect inside the drawer. Comments attached, an index in place, local verification done. But an asset’s true value shows only under competition pressure — does a time-pressed hand find the template within 10 seconds, and does the skeleton hold when the competition server looks different from the local demo?

Today’s competition has a different primary goal. Not points — library validation. When a similar type appears, do you write from scratch like before, or do you start from a template in 5 minutes? This competition measures that difference. Points will follow, of course. When validation goes well, points come along.


1. Learning Objectives

By the end of this chapter, you will be able to:

  • Open the library index as the competition starts and reach a type-match verdict within 10 seconds
  • Record and compare time spent on template-used versus non-template problems
  • Classify where templates collapse in the field (dependencies, paths, input formats)
  • Apply the verdict rule "if it doesn’t fit within 5 minutes, write from scratch"
  • Close the competition retrospective with library-improvement patch commits

2. Background Knowledge — Today’s Tools and Concepts

Today’s Tools at a Glance

Category Details
Language/environment CTF competition platform, Step 290’s library, Python 3 (for measurement)
Today’s commands Running library templates, python step291_measure.py (local measurement example)
Concepts needed Type matching, the 5-minute verdict rule, the three factors of field collapse, improvement patches
Today’s deliverable Template usage record table + a library improvement commit (v2)

2-1. Type Matching — The 10-Second Verdict Procedure

When you open a problem at a competition, the question order must be fixed before you dig through the library.

Type matching, 3 questions (goal: 10 seconds):
1. What is this problem's I/O shape? (TCP prompt / web form / file download)
2. Do we have a template of the same shape? (skim only the 'conditions of use' lines in the index)
3. If yes, are the edit points a 5-minute job? (just HOST/PORT/a few values, or a different structure?)

If question 3 is "the structure differs," that template doesn’t fit this problem. Even with the same shape, the internal protocol often differs — then you take only the ingredients (payloads) and write the skeleton fresh.

2-2. The 5-Minute Verdict Rule — The Trap of Forced Matching

The source’s warning — you spend more time forcing a problem into a template. This is the most common accident at the first competition after building a library. The desire to use your asset clouds the judgment.

The rule is simple. If the first send hasn’t gone out within 5 minutes of starting to modify a template, fold it and write from scratch. Five minutes is double the time a template takes from edit to run in local verification — even with margin, a "fitting template" should already be working by then.

2-3. Where It Collapses in the Field — Three Factors

Code that passed local verification breaks at a competition at roughly three points.

Factor Symptom Prevention
Dependencies The competition PC lacks pwntools/specific packages Keep a standard-library utility alongside (Step 290’s net.py)
Paths Running from another directory can’t find files No relative paths; absolute paths anchored on __file__
Formats The competition server’s prompt/newlines differ from the demo Isolate EXPECT as an edit point; the habit of printing the first receive

We actually reproduced the path factor. What happens when you run code that opens a payload file by relative path from outside the library folder — see the measurement in 3-3.

2-4. Measurement — "It Got Faster" in Numbers

This is a validation chapter, so impressions are banned. Two numbers to record.

Template usage record table (filled in real time during the competition):
| problem  | type      | template   | match verdict | edit→first send | solved | notes |
|----------|-----------|------------|---------------|-----------------|--------|-------|
| pingpong | prompt    | tcp_prompt | 8 sec         | 4 min           | O      | edited EXPECT only |
| noteapp  | web SSTI  | (none)     | —             | —               | X      | reused payloads only |

The "edit → first send" time is the library’s report card. If the same type took 30 minutes from scratch at the previous competition, 4 minutes is 26 minutes the library earned you. The retrospective’s "total time saved" is computed as this table’s sum.


3. Follow Along

3-1. Before the Competition — The Environment Rehearsal

The day before the competition, run the entire library once on the PC you’ll use at the competition — not the PC you wrote it on. The dependency factor must all be filtered out here.

Environment rehearsal checks (on the competition PC):
[ ] Right after git clone, does the index generator run as-is?
[ ] Does each template run against the local demo server?
[ ] Does the Python version match the templates (f-strings, etc.)?
[ ] Is the index README placed where you'll view it mid-competition (second monitor/printout)?

3-2. Local Measurement — A Baseline for Template Solve Times

Don’t set the "5-minute verdict" baseline by feel — measure it locally. We ran a script (step291_measure.py) that spins up a fresh demo server each time and measures the template solve time over 5 runs.

Measured (2026-09-09, Python 3.12):

=== Template-based solve-time measurement (5 runs, local demo) ===
Run 1: 0.067s  flag captured=success
Run 2: 0.076s  flag captured=success
Run 3: 0.074s  flag captured=success
Run 4: 0.058s  flag captured=success
Run 5: 0.069s  flag captured=success
Average 0.069s / max 0.076s
* Local measurements — the competition server adds network latency

How to read it: pure execution is under 0.1 seconds — meaning nearly all of a template solve time is the human’s edit-point editing time. The localhost-vs-competition-server difference (tens to hundreds of ms) is noise inside that. Conclusion: the 5 minutes of the 5-minute verdict is calibrated not to technology but to human editing time, and for a familiar template, 1–2 minutes should be the norm.

3-3. Reproducing the Path Failure — A Preventive Shot for Mid-Competition Accidents

Let’s actually reproduce the path factor from 2-3. Run code that opens a payload by relative path from somewhere other than the library folder:

Measured (2026-09-09 — running a ctf_lib script from a tmp_test folder):

Current working directory: C:\Users\dlqht\Documents\kimi\tasks\2026-09-08\21-57-12-c850bf8c\tmp_test
FileNotFoundError occurred: [Errno 2] No such file or directory: 'payloads\\web_payloads.py'

Fix: use an absolute path anchored on __file__
Absolute path: C:\...\tmp_test\ctf_lib\payloads\web_payloads.py
Read succeeded: 908 bytes

How to read it: the same script dies depending on where you run it. Mid-competition you end up copying files all over the place, so this accident is nearly guaranteed. The prevention is a one-line rule — file-opening code is written only relative to Path(__file__).resolve().parent. Apply this rule to every template before this competition.

3-4. Running the Competition — Executing Type Matching and the 5-Minute Verdict

When the competition starts, open the index README beside you. Each time you open a problem, run 2-1’s three questions and fill 2-4’s record table.

Screen example (mid-competition operations):

14:05 Opened problem 'pingpong' — TCP prompt type. 3-second index scan → tcp_prompt_template matched
14:06 Copied template, edited HOST/PORT/EXPECT (the prompt is '$ ', not '> ')
14:09 First send succeeded, response checked → started hunting the TRIGGER
14:31 Solved. Record: match 8 sec, edit→first send 3 min, solved in 26 min

15:20 Opened problem 'notepad' — web. No template → reused only the SSTI probes from payloads/web_payloads.py
      Record: wrote the skeleton fresh; estimated 10 min saved by reusing detection payloads

16:40 Problem 'streamer' — looked prompt-type so matched the template, but it's a double-prompt structure
      First send failed after 5 min of modification → verdict rule invoked, wrote from scratch (solved afterward)
      Record: 'double prompt' → library improvement item

How to read it: the last case is this competition’s key scene. The template not fitting is not a failure but a discovery — the structural variant "double prompt" just got registered as a library blind spot. Thanks to the 5-minute verdict rule, the loss stopped at 5 minutes.

3-5. The Retrospective — Summing Saved Time and Patching Improvements

After the end, sum the record table.

=== Library validation retrospective (template) ===
Solved using templates: 2 problems (completion criterion met)
Payloads-only reuse: 1 problem
Forced match then discarded: 1 case (5-minute loss — verdict rule worked)
Estimated total time saved: about 50 min (vs. same types at previous competitions)

Improvement items (→ v2 patch):
[ ] Double-prompt handling — add a variant template chaining recvuntil twice
[ ] Missing web template — add one requests-based session template
[ ] Found 2 files without the path rule applied — patch them all

And make the patch commit on the spot.

cd ctf_lib
git add .
git commit -m "v2: double-prompt template added, path rule applied everywhere (competition #7 retrospective)"

A retrospective must end in a commit for the library to stay a living asset. An improvement item that ends with "I’ll fix it later" eats the same 5 minutes again at the next competition.


4. Missions & Exercises

Mission — Live-Fire Library Deployment and the v2 Patch

  1. The day before the competition, run the environment rehearsal checklist (3-1) on the competition PC.
  2. Verify the path rule (__file__-anchored) is applied to every template.
  3. During the competition, apply the type-matching three questions and the 5-minute verdict rule, and fill the record table (2-4) in real time.
  4. Aim for 2+ problems solved using templates.
  5. After the end, estimate the total time saved and close the improvement items as a commit (v2).

Exercises

Exercise 1. Why does the type-matching three-question procedure ask question 3 ("are the edit points a 5-minute job")? What misjudgment arises from questions 1 and 2 alone?

Exercise 2. In 3-2’s measurement, a template’s pure execution was under 0.1 seconds. Then why is the 5-minute verdict’s unit minutes, not seconds?

Exercise 3. Explain why a template that opens files by relative path breaks mid-competition, from the "execution location" standpoint, and write the one-line prevention rule.

Exercise 4. Why is a template case discarded after 5 minutes for not fitting called a "discovery" rather than a "failure"? How should that case be handled in the retrospective?


5. Model Answers & Completion Criteria

Mission Model Answer

Verify against these criteria.

  1. Traces of the rehearsal: is there a record of running right after clone on the competition PC — checking only on the writing PC is not a rehearsal.
  2. The record table’s real-timeness: are per-problem match verdicts and edit times present with timestamps — a table filled from memory after the end has inflated numbers.
  3. The 5-minute verdict in action: if there’s a forced-match discard case, did it stop near 5 minutes? If there isn’t — look back on whether everything truly fit, or whether you failed to use the verdict rule.
  4. Completion criterion: 2+ problems solved using templates.
  5. The v2 commit: are the improvement items in the repository with a commit message — if only the retrospective document exists and the code is unchanged, you did only half the validation.

Exercise Answers

Answer 1. Because even with the same shape, a different internal structure means the template doesn’t fit. Questions 1 and 2 compare only "the outer look of I/O" — even sharing the TCP-prompt shape, structural differences like double prompts or mixed binary get filtered at question 3. Skip question 3 and you fall into forced matching, clinging to a template you thought fit, where modification time exceeds problem-solving time.

Answer 2. Because most of a template solve time is not the computer’s execution time but the human’s editing time. Execution is under 0.1 seconds, but checking HOST/PORT, fitting EXPECT to the competition server’s format, and hunting the TRIGGER are keyboard work by a human. Network latency is noise-level inside that. So the verdict criterion is 5 minutes — a margin over the time a human realistically finishes edits in (1–2 minutes).

Answer 3. Because a relative path resolves against the directory the command was run from (cwd), not the script file’s location. Mid-competition you copy templates into per-problem folders, so the cwd changes every time, and the same file opens in one place and dies with FileNotFoundError: [Errno 2] in another. Prevention rule: file-opening paths are always written relative to Path(__file__).resolve().parent.

Answer 4. Because that case gave you the coordinates of a library blind spot. The information "doesn’t fit double prompts" is an asset that makes next competition’s match verdicts more accurate. Handling comes in two branches — ① note the "cases where it breaks" in the conditions-of-use comment, or ② add a new template covering the variant in v2. Either way, it must remain as a record for the 5-minute loss to be recovered as knowledge.

Completion Criteria Checklist

  • [ ] I completed the environment rehearsal (run right after clone) on the competition PC
  • [ ] I applied the __file__-anchored path rule to every template
  • [ ] I recorded type-match verdict times and edit→first-send times during the competition
  • [ ] I applied the 5-minute verdict rule (with time records for any discard cases)
  • [ ] I achieved 2+ problems solved using templates
  • [ ] I estimated the total time saved and recorded it in the retrospective
  • [ ] I made a v2 commit reflecting the improvement items

6. Common Pitfalls & Fixes

Wall 1. The templates won’t run at all on the competition PC

Symptom: they worked on the writing PC, but import errors and syntax errors appear on the competition PC.

Cause: Python version differences or missing packages — the dependency factor of 2-3. If the writing environment and competition environment differ, this is guaranteed to blow up.

Fix: the right answer is doing 3-1’s environment rehearsal the day before, on the competition PC. And structural prevention — keep utilities that run on the standard library alone, as in Step 290, and the skeleton survives even in environments without pwntools.

Wall 2. The child process’s output won’t read and my measurement script dies

Measured (2026-09-09 — actually occurred while writing the measurement script):

UnicodeDecodeError: 'cp949' codec can't decode byte 0xec in position 38: illegal multibyte sequence

Cause: on Korean Windows, subprocess.run(..., text=True) reads output in the system default encoding (cp949). If the child prints UTF-8 Korean, decoding breaks.

Fix: specify encoding="utf-8"subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8"). It’s a chronic disease of Python parent-child relationships on Korean Windows, so make it a default habit for measurement and automation scripts.

Wall 3. With a library, I feel like I’ve forgotten how to write from scratch

Symptom: when a type with no template appears, your hands stop.

Cause: library dependence — templates have started doing your thinking for you.

Fix: that’s why the 2-4 record table has a "no template" column. If the time for fresh-written cases has grown versus before, that type is the next drill topic. The library must be a delegation of repetitive work, not a muscle replacement — maintain the write-from-scratch muscle separately with Step 288-style drills.

Wall 4. I can’t keep the 5-minute verdict and keep modifying

Symptom: "just a little more and it’ll work" eats 20 minutes.

Cause: sunk cost — the 5 minutes already spent feel too precious to stop.

Fix: fix the verdict sentence in advance — ask "from this state right now, is writing from scratch faster?" The 5 minutes already spent don’t enter the answer. And don’t throw away the discarded template — park it in wip/. At the retrospective it’s evidence of "why it didn’t fit." The precious 5 minutes don’t vanish; they’re exchanged into an improvement item.

Wall 5. I spend the competition fixing the library instead of solving problems

Symptom: you start a fundamental template improvement mid-competition.

Cause: the excitement of discovery — you see a blind spot and want to fix it immediately.

Fix: fix the allowed scope of mid-competition edits — values inside the edit-points block only. All structural improvements are recorded only and sent to the retrospective. Mid-competition, the library is not for fixing but for using while taking memos.


7. Summary

Today’s Concepts

Concept One-line explanation
Type-matching 3 questions I/O shape → index scan → edit-workload verdict, within 10 seconds
5-minute verdict rule No first send within 5 minutes → discard — the cutoff line against forced matching
Three factors of field collapse Dependencies / paths / input formats — all filterable before the competition
Edit→first-send time The library’s report card — execution is 0.1s, the rest is human editing
Improvement patch commit The retrospective’s closing format — as v2 code, not a memo

Today’s Tools & Templates

Tool/template What it does
Environment rehearsal checklist Pre-validation on the competition PC — blocks dependency accidents
step291_measure.py Measuring the local baseline of template solve times
__file__ path rule Opening files regardless of execution location
Template usage record table Real-time records of match/edit/solve times
v2 patch commit Exchanging the competition’s discoveries into assets

The Core Instinct

Measure a library’s value not by storage volume but by time recovered per competition. If you saved 50 minutes at today’s competition, those 50 minutes are the interest on the time invested in the library. And the interest compounds — v2 earns bigger time at the next competition.

Conversely, remember — templates don’t substitute for judgment. The 5-minute verdict and the decision "this one doesn’t fit" remain your job. The bigger the asset grows, the more important the sense of when to put it down becomes.


Once every box is checked, Step 291 is complete. Click the checkbox in the sidebar to save your progress.