CTF Harness Engineering

Module S04 · Course 2A

60 min · Domain Routing · Speed / Parallelism / HITL · Flag Extraction & Scoring

Prerequisite: S00, S01, S02, S03

The speed inversion

A CTF is not a smaller pentest. It optimizes for speed to flag, not coverage.

S02 and S03 optimize for thoroughness. CTF inverts several of those constraints. The engineering discipline is knowing which inversions are safe and which are catastrophic.

pentest: thorough   CTF: fast

S04.1 — CTF Domain Architecture

DomainReasoningToolsContext burn
Webrequest manipulation, payload craftingBurp headless, sqlmap, ffuf, XSS payloadslow-med
Pwnmemory layout, gadget chainspwntools, GDB+pwndbg, checksec, ROPgadgethigh
Cryptoweakness detection, mathCyberChef, SageMath, frequency analyzersmed
Forensicsartifact carving, parsingbinwalk, strings, exiftool, tsharklow
Reversingdisassembly, decompile triageGhidra headless, radare2, ltrace/stracevery high
Miscstego, scripting, encodingzsteg, stegsolve, custom Pythonvariable

Why a single harness fails

Context pollution
Web challenge does not need ROPgadget in the manifest. Every tool description dilutes selection signal and burns context.
Reasoning drift
Pwn mode (low-level, careful) is the opposite of Web mode (broad fuzzing, rapid iteration). A model told to do both excels at neither.
Token waste
Each tool's schema is paid every turn, every challenge. Six domains of tools = six domains of overhead, every turn.
Cure
Meta-agent routes to a specialized agent. Narrow prompt, narrow tools, domain-specific reasoning loop.

The domain router

Challenge in (description + artifacts)
Meta-agent / classifier — emits domain label
Web
Burp, sqlmap, ffuf
Pwn
pwntools, GDB, checksec
Crypto
CyberChef, SageMath
Forensics
binwalk, tshark
Reversing
Ghidra, radare2
Misc
zsteg, custom py

Uncertain? TriageAgent runs cheap probes (file, checksec, strings freq, HTTP code) and re-routes. Router is allowed to be uncertain; agents are not.

S04.2 — Speed, Parallelism, HITL

Four properties produce benchmark-level speed:

1. No approval gates — every tool call executes immediately
2. Pre-loaded tool context — schemas, examples, heuristics in system prompt
3. Narrow domain scope — router has already restricted tools + reasoning
4. Deterministic tool routing — checklists, not rediscovery (checksec first, always)

The first — no approval gates — is the most consequential and the most dangerous.

When is HITL removal safe?

Safe when all three hold: (a) target owned or sandboxed, (b) isolated from production at network layer, (c) worst-case action is bounded (restart target, waste time).

ContextHITLWhy
Owned Docker with CTF binaryremoveOwned, isolated, restartable
Competition sandboxed VMremoveSandboxed by organizer, isolated
Remote CTF servicepartialService fair game; credential-reuse gate stays
Live bug bounty (NOT CTF)keepS02 rules apply; not owned
Production adjacent to sandboxkeepIsolation unverified; blast radius unbounded

The speed comparison

HITL ENABLED

checksec: wait 25s + exec 2s
ROPgadget: wait 30s + exec 5s
payload: wait 28s + exec 1s

~91s wall-clock

AUTONOMOUS

checksec: exec 2s
ROPgadget: exec 5s
payload: exec 1s

~8s wall-clock

Exception that stays: credential-reuse gate. Discovered creds are never auto-reused against other services. Unbounded risk.

Parallel solve attempts

Intra-challenge: multiple exploit hypotheses against one challenge, concurrently. First flag wins; loser killed.

Inter-challenge: 3–5 challenges concurrently, isolated sessions, isolated memory.

Session A: Challenge 1 → WebAgent → FlagExtractor
Session B: Challenge 2 → PwnAgent → FlagExtractor
Session C: Challenge 3 → PwnAgent (stack overflow hypothesis)
Session D: Challenge 3 → PwnAgent (format string hypothesis) → first flag wins, other killed

Shared memory is forbidden. Reintroduces the context pollution domain routing was designed to eliminate.

S04.3 — Flag Extraction & Scoring

Flag detection is middleware on every tool output, not a step the agent remembers to call.

Tool output (any agent)
Regex sweep — flag{...}, CTF{...}, competition prefix
Candidates → Verifier (plausibly the answer to THIS challenge?)
Verifier → drop decoys / submit plausibles

Why verify? Challenge descriptions, examples, and decoy output all contain flag-shaped strings. Submitting decoys burns attempts and trips rate limits.

CTFd submission

POST /api/v1/challenges/attempt
Authorization: Token {token}
{ "challenge_id": id, "submission": "flag{...}" }

Response:
  "correct"        → mark solved, kill parallel, free slot
  "incorrect"      → log, agent continues
  "already_solved" → treat as correct, do NOT re-submit

Rate-limit the client. 2–3s between submissions; per-challenge lockout after N wrong. Most scoreboards throttle teams that submit too fast.

The scorecard

With 5 challenges running concurrently, the scorecard is the only sane view.

FieldTracks
challenges[]state: unattempted / in_progress / solved / abandoned; sessions; attempts; first_blood_at
flags_captured[]flag strings, source challenge, source session, timestamp
flags_submitted[]submission text, CTFd response, attempt count

Metrics: challenges/hour · mean time to flag per domain · router accuracy · flag-extraction precision (true vs decoy).

Anti-patterns

Single undifferentiated agent
All six domains of tools loaded. Context pollution, drift, wrong-tool errors.
HITL off vs unowned target
Treating "CTF" as blanket license. Blast radius unbounded.
Skip checksec / file
ROP against a binary with stack canaries. Wasted engagement.
Auto-submit every regex match
Decoy flags burn attempts and trip rate limits.

What you take into S05

The CTF harness is operational: domain router, specialized agents, autonomous mode, flag pipeline.

S05 builds the meta-harness — the layer that orchestrates bug bounty (S02), pentest (S03), and CTF (S04) harnesses into a single system that selects the right harness for the engagement type.