Step 310. Mock Exam Failure-Pattern Analysis & Remediation — Unsolved Machines Come in Three Kinds
Level 4 — OSCP Preparation & Sitting the Exam | Difficulty ★★★☆☆ | Estimated time: 2 days (half a day of analysis + 1.5 days of remedial study and re-attacks)
Prerequisites: the first 24-hour mock exam from Step 309 finished, with its closing report.
- What you need: the first mock exam’s lap log and time-usage analysis, the list of unsolved machines, each machine’s official walkthrough (opened only after the mock exam has fully ended), and Python 3 (the analysis tool). The analysis-data scenes in this chapter are screen examples.
- ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime. Reading walkthroughs and re-attacking are also performed only after the mock exam has completely ended, inside the same legal platforms.
- This is a concept chapter — you learn not new techniques but an analysis methodology for cutting failures into prescribable units.
When a mock exam ends, most people look only at the score. "Fifty points, twenty short" — and then they read the walkthroughs, go "ah, so that’s what it was," and move on. This is the first mock exam’s most common waste. Because unsolved machines are not all the same kind of "unsolved."
Unsolved machines divide into at least three kinds of failure, and the cures are all different. Missing technique is fixed with study; missed enumeration with the checklist; time-management failure with strategy revision. Mix them up and treat them with "try harder overall," and you’ll collapse in the same places on the next mock exam. Today is the day of the knife.
1. Learning Objectives
By the end of this chapter, you will be able to:
- Classify unsolved machines by failure type (missing technique / missed enumeration / time management / stamina collapse / insufficient report)
- Coordinate-ize the distance between "where I stopped" and "the correct path" by walkthrough comparison
- Complete per-type remedies (study + reproduction / checklist additions / allocation rule revisions) as real deliverables
- Aggregate the failure-type distribution with the analysis tool and fix the #1 remediation target
- Re-attack every unsolved machine solo, turning "spectated knowledge" into "hand knowledge"
2. Background Knowledge — Today’s Tools and Concepts
Today’s Tools at a Glance
| Category | Details |
|---|---|
| Language/environment | Python 3 (failure-type analyzer fail_analyzer.py), walkthrough documents, the when-stuck checklist file |
| Today’s commands | python fail_analyzer.py demo / python fail_analyzer.py analyze fails.csv |
| Concepts needed | The 5 failure-type classification, stopping coordinates, walkthrough comparison method, separating per-type prescriptions |
| Today’s deliverable | 1 per-type failure analysis document + a remedial study list + an updated when-stuck checklist |
2-1. The 5-Class Failure Taxonomy — Not the Same Zero
Compare each unsolved machine against its walkthrough, and every failure reduces to one of five types.
| Type | Definition | Diagnostic sentence | Prescription |
|---|---|---|---|
| ① Missing technique | You didn’t know that vulnerability/technique itself | "Even reading the correct path, the concept is new to me" | Study + lab reproduction |
| ② Missed enumeration | You knew it but didn’t check | "Just looking there would have solved it" | Add to the when-stuck checklist |
| ③ Time management | You could have solved it but had no time | "Never even started it / was tied up elsewhere" | Revise allocation rules |
| ④ Stamina collapse | Judgment broke down in a specific time zone | "Every decision I made at dawn was wrong" | Fix the sleep/meal plan |
| ⑤ Insufficient report | You solved it but have no evidence/documentation | "I thought I captured it, but it’s not there" | Habituate real-time collection |
The classification criterion is walkthrough comparison. If reading the correct path says "didn’t know," it’s ①; "knew it but didn’t look," it’s ②; "had no time to look," it’s ③. Why does this distinction matter — a person with ② mistaking it for ① and studying new techniques is like treating the disease of knowing-but-not-using by taking more medicine.
2-2. Stopping Coordinates — "Couldn’t Solve It" Is Not an Analysis
The unit of analysis is not the machine but the point. "I couldn’t solve standalone-B" is not an analysis; "I stalled for 2 hours at standalone-B’s web login, and the answer was the hidden /backup path" is an analysis.
Stopping-coordinate record format (per machine):
- Machine: standalone-B
- Where I stopped: web login form — tried brute force and SQLi, then stalled (150 min spent)
- Correct path: directory enumeration → /backup/index.php.bak → hardcoded credentials in source
- The branch point: saw .bak in the gobuster results and passed it by, thinking "a backup file, surely not"
- Type: ② missed enumeration
The key box is the branch point — not the result (unsolved) but the judgment ("surely not," passed by) is the failure’s true body. Only when the branch point is written down can the checklist reach beyond "check this" to "check this when you’re in this state of mind."
2-3. Per-Type Prescriptions — Practicing the Fact That the Cures Differ
① Missing technique is prescribed study, with one condition attached — you must reproduce it in a lab. Read only, and you’ll get stuck again next time. If you were blocked for not knowing AS-REP roasting, the end is not reading a document but actually pulling a ticket in the lab domain and cracking it. Once by hand — that is the border between "knowing" and "having spectated."
② Missed enumeration is prescribed as additions to the when-stuck checklist. The format is condition-action:
Addition examples:
- "When a web service is found" → "include backup/source extension scan (.bak .old .zip .git)"
- "When MSSQL is found" → "check whether xp_cmdshell is enabled"
- "When a Linux shell is obtained" → "check sudo -l, SUID, cron in that order within 3 minutes"
③ Time management is prescribed as rule revision. If "tied up on standalone-B, I never even started standalone-D" — then B’s cap wasn’t kept, so you state the cap as a clock time and change the switch to rely on an external device (a timer alarm).
2-4. The Distribution Is the Strategy — The Most Frequent Type Decides the Next Training
When the case-by-case analysis is done, look at the distribution. The distribution is your weakness map.
- ① most frequent → a hole in technique coverage. Next week is not takedown training but a study week.
- ② most frequent → the technique exists but the procedure leaks. Strengthen the checklist and train "the habit of returning to the checklist when stuck."
- ③ most frequent → skill is at the passing range but operations burn points. The easiest points to recover on the next mock exam.
- ④⑤ visible → operational problems easily disguised as technical ones. Fix sleep reservations and evidence habits first.
The second mock exam’s goal (Step 311) is for the most frequent type in this distribution to shrink — a score rise is the consequence.
3. Follow Along
3-1. Walkthrough Comparison — Filling the Stopping Coordinates
Now that the mock exam is completely over, you open the unsolved machines’ walkthroughs for the first time. There’s a rule — one machine at a time, and spread your own log out first before reading.
Comparison procedure (20–30 min per machine):
1. Read that machine's final state in your lap log — how far did you get
2. Read the walkthrough from the start, and stop where a branch you didn't take appears
3. Record that branch in the stopping-coordinate format (2-2)
4. Grade yourself: "Had I taken this branch, would it have solved?" — Yes → ②, No → ①
5. Fix the type and add it to the CSV
Why step 4 matters: the answer to "would I have solved it if I’d looked?" decides the type. Read a walkthrough to the end and hindsight bias makes everything feel knowable, so you must stop reading at the branch point and grade first.
3-2. Aggregating the Distribution with the Analysis Tool
Save the script below as fail_analyzer.py (Python 3, standard library only).
#!/usr/bin/env python3
# fail_analyzer.py — failure-type analyzer with the 5-type classification
# (standard library only)
#
# Usage:
# python fail_analyzer.py demo analyze the built-in example session
# python fail_analyzer.py analyze fails.csv analyze your own data
#
# fails.csv format (UTF-8, first row is the header):
# machine,type,where-stopped,correct-path,minutes-spent
# standalone-B,2,stalled 2 hours at the web login,source leak in /backup,150
#
# Type numbers: 1 missing technique / 2 missed enumeration / 3 time-management failure
# 4 stamina/condition collapse / 5 insufficient report
import csv
import sys
TYPES = {
"1": "missing technique",
"2": "missed enumeration",
"3": "time-management failure",
"4": "stamina/condition collapse",
"5": "insufficient report",
}
# Default remedy per type
REMEDY = {
"1": "study + lab reproduction — read only, and stuck again next time",
"2": "add an item to the when-stuck checklist — knew it but didn't look",
"3": "revise allocation rules — redesign the cap/switch timing",
"4": "reserve sleep/meals on the timetable — caffeine is not a plan",
"5": "real-time evidence collection + template prepared in advance",
}
DEMO_ROWS = [
# (machine, type, where stopped, correct path, minutes)
("standalone-B", "2", "stalled 2 hours at the web login",
"source leak in the hidden /backup path was the entrance", "150"),
("AD-set", "1", "got as far as domain user enumeration",
"AS-REP roasting — didn't know the concept itself", "360"),
("standalone-D", "3", "never even started",
"tied up on standalone-B, time ran out", "0"),
("standalone-C", "2", "got as far as a low-priv shell",
"never checked sudo -l — SUID was the answer", "140"),
("report", "5", "post-end tally",
"2 screenshots missing for the machine solved at dawn", "-"),
]
def analyze(rows):
counts = {k: 0 for k in TYPES}
for r in rows:
counts[r[1]] = counts.get(r[1], 0) + 1
print("=== Failure-type distribution ===")
for k in sorted(TYPES):
c = counts[k]
bar = "■" * c if c else "-"
word = "case" if c == 1 else "cases"
print(" %s %-23s %d %s %s" % (k, TYPES[k], c, word, bar))
print()
print("=== Per-machine analysis ===")
print()
for machine, t, stopped, path, mins in rows:
print("[%s] type %s — %s (%s min spent)" % (machine, t, TYPES[t], mins))
print(" stopped at : %s" % stopped)
print(" correct path: %s" % path)
print(" remedy : %s" % REMEDY[t])
print()
top = max(counts, key=counts.get)
if counts[top] > 0:
word = "case" if counts[top] == 1 else "cases"
print("Most frequent type: %s %s (%d %s) — the #1 remediation target for the next mock exam"
% (top, TYPES[top], counts[top], word))
def main():
args = sys.argv[1:]
if not args or args[0] == "demo":
analyze(DEMO_ROWS)
elif args[0] == "analyze" and len(args) >= 2:
with open(args[1], encoding="utf-8-sig", newline="") as f:
reader = csv.reader(f)
next(reader, None) # header
rows = [(r[0], r[1], r[2], r[3], r[4]) for r in reader if r]
analyze(rows)
else:
print(__doc__)
if __name__ == "__main__":
main()
Feed your data to the chapter’s analysis tool. First, learn the output with the built-in example — this is the measured result.
python fail_analyzer.py demo
=== Failure-type distribution ===
1 missing technique 1 case ■
2 missed enumeration 2 cases ■■
3 time-management failure 1 case ■
4 stamina/condition collapse 0 cases -
5 insufficient report 1 case ■
=== Per-machine analysis ===
[standalone-B] type 2 — missed enumeration (150 min spent)
stopped at : stalled 2 hours at the web login
correct path: source leak in the hidden /backup path was the entrance
remedy : add an item to the when-stuck checklist — knew it but didn't look
[AD-set] type 1 — missing technique (360 min spent)
stopped at : got as far as domain user enumeration
correct path: AS-REP roasting — didn't know the concept itself
remedy : study + lab reproduction — read only, and stuck again next time
[standalone-D] type 3 — time-management failure (0 min spent)
stopped at : never even started
correct path: tied up on standalone-B, time ran out
remedy : revise allocation rules — redesign the cap/switch timing
[standalone-C] type 2 — missed enumeration (140 min spent)
stopped at : got as far as a low-priv shell
correct path: never checked sudo -l — SUID was the answer
remedy : add an item to the when-stuck checklist — knew it but didn't look
[report] type 5 — insufficient report (- min spent)
stopped at : post-end tally
correct path: 2 screenshots missing for the machine solved at dawn
remedy : real-time evidence collection + template prepared in advance
Most frequent type: 2 missed enumeration (2 cases) — the #1 remediation target for the next mock exam
How to read it: this example session’s diagnosis is not "an engineer lacking skill." Four of five cases (②×2, ③, ⑤) are operations and procedure problems, and the real technique gap (①) is just the one AD set case. The most frequent type is missed enumeration — this candidate’s next training should be checklist habituation, not new-technique study. When analyzing your own data, make a CSV in the same format (machine,type,where-stopped,correct-path,minutes-spent) and run python fail_analyzer.py analyze fails.csv.
3-3. Building the Per-Type Remedy Deliverables
Once classified, complete the prescriptions as documents. "I’ll do better next time" in your head is not a deliverable.
| Type | Deliverable | Completion condition |
|---|---|---|
| ① Missing technique | Per-topic study + lab reproduction log | A reproduction record with commands/output remaining |
| ② Missed enumeration | New items on the when-stuck checklist | Added in condition-action format |
| ③ Time management | Revised allocation rules | Clock times stated, like "3-hour cap" → "switch at 03:00" |
| ④ Stamina collapse | Sleep/meal blocks fixed into the plan | Reflected in the next mock exam’s plan |
| ⑤ Insufficient report | Evidence-confirmation box added to the lap log format | A check item exists on each machine’s final lap |
3-4. Re-attacking — It Becomes Yours Only When You Solve It Again by Hand
The final and most important phase. Re-attack every unsolved machine, walkthrough closed, on your own strength.
Screen example (re-attack log):
[Re-attack] standalone-B — finished in 35 min
Branch point reproduced: found .bak in gobuster → checked immediately (first use of the new checklist item)
Instinct memo: the moment "surely not" rises is the check signal
[Re-attack] AD-set — 2h 10m, AS-REP roasting reproduction success
Study record: wrote docs/ad_asrep_roasting.md, reproduced ticket extraction → cracking in the lab
How to read it: solving fast on a re-attack is natural — you saw the answer. The re-attack’s purpose is not replaying the answer but confirming a new reaction at the branch point. At the point where you used to pass by with a "surely not," did you this time stop and check — that reaction change guarantees no recurrence on the next mock exam. After the re-attack, complete that machine’s report too — doubling as ⑤’s training.
4. Missions & Exercises
Mission — Failure Analysis Document and Remediation Complete
- Perform the walkthrough comparison (3-1) on every unsolved machine from the first mock exam and fill the stopping coordinates.
- Aggregate the types via CSV and run
fail_analyzer.py analyze; record the distribution and the most frequent type in the document. - Complete all per-type remedy deliverables (the table in 3-3) — reproduction log for ①, checklist items for ②, revised rules for ③.
- Re-attack every unsolved machine to completion without walkthroughs, and complete each one’s report.
- At the end of the analysis document, write one line of "verification metric for the second mock exam" — e.g., "missed enumeration 2 cases → 0–1 cases."
Exercises
Exercise 1. Why must a "knew it but didn’t check" failure (②) not be treated with new-technique study? Explain together with why ②’s correct prescription is the checklist.
Exercise 2. From the perspective of hindsight bias, explain why the walkthrough comparison "stops reading at the branch point and grades first."
Exercise 3. Why must ③ time-management failure’s prescription be a rule revision (stating clock times) rather than "I’ll manage time well next time"?
Exercise 4. A re-attack naturally solves fast because you saw the answer. Even so, under what condition does a re-attack "become knowledge rather than spectating," and what must you confirm for the re-attack to count as a success?
5. Model Answers & Completion Criteria
Mission Model Answer
Verify against these criteria.
- Stopping-coordinate specificity: does every unsolved machine have all four boxes filled — "where stopped / correct path / branch point / type"? An entry with only "didn’t know" is not an analysis.
- Grading came first: is each type grounded in self-grading at the walkthrough’s branch point ("would I have solved it if I’d looked?")? Types decided after reading to the end may be contaminated by hindsight.
- Deliverables exist: ① a reproduction log (with commands and output), ② new checklist items in condition-action format, ③ revised rules with clock times stated — does each exist as a file?
- Re-attacks completed: were all unsolved machines finished solo, with the reaction change at branch points left in memos?
- Verification metric: is it written in numbers what must shrink on the next mock exam?
Exercise Answers
Answer 1. Because ②’s disease is not the absence of knowledge but a failure of recall — the item was in your head but didn’t surface at the blocked moment. Study new techniques and that item stays silent the same way. The checklist is the prescription because it moves recall from memory to procedure — instead of waiting for "it comes to mind," "the document opened when stuck" forces the check. ② is not a study problem but an engineering problem.
Answer 2. A brain that has read the walkthrough to the end knows the answer, so it overestimates: "I’d have known if I’d looked" — that is hindsight bias. Types decided in that state get inflated toward ② (knew but didn’t look) while ① (didn’t know) hides. If you stop reading at the branch point and grade, the you of that moment doesn’t know the answer yet, so the grading is honest. Since the classification’s accuracy is the prescription’s accuracy, the grading’s timing decides the whole analysis’s quality.
Answer 3. Because a willpower-based resolution entrusts execution to the fatigued brain at hour 12 of the exam. "I’ll manage it well" is a judgment-free promise, and the fatigued brain abandons judgment. A rule revision — concretizing "3-hour cap per machine" into "switch at 03:00, alarm set" — eliminates judgment. When the time comes you move; you don’t decide then whether to move. The reason ③’s prescription is a rule is the same as the reason ②’s is a checklist — replacing memory and willpower with procedure and devices.
Answer 4. The condition is a reaction change at the branch point. A re-attack that knows the answer and replays it is spectating repeated, but when you reach the branch point you first passed by (the "surely a backup file, no" moment), do you this time stop and check — only if that reaction changed will it change on the next unknown machine too. Two things to confirm — was the re-attack finished without the walkthrough (the procedure internalized), and was the new reaction at the branch point recorded in a memo (the instinct verbalized)? Without the second, the you of the next exam is the same as the you of the first.
Completion Criteria Checklist
- [ ] I filled the stopping coordinates (point / path / branch point / type) for every unsolved machine
- [ ] I stopped reading at branch points and self-graded first
- [ ] I aggregated the type distribution with
fail_analyzer.pyand fixed the most frequent type - [ ] I remediated ① items with lab reproduction logs
- [ ] I added ② items to the when-stuck checklist in condition-action form
- [ ] I revised ③ items into rules with clock times stated
- [ ] I re-attacked every unsolved machine solo and completed the reports
- [ ] I wrote the second mock exam’s verification metric (what must shrink) as a number
6. Common Pitfalls & Fixes
Wall 1. I ran analyze and the CSV won’t load
Symptom:
FileNotFoundError: [Errno 2] No such file or directory: 'fails.csv'
Cause: the CSV isn’t in the run location (current directory), or the filename differs.
Fix: run from the folder containing the CSV, or include the path like python fail_analyzer.py analyze data/fails.csv. A CSV saved from Excel may be encoded in CP949 — this tool reads UTF-8, so choose "Save As → CSV UTF-8."
Wall 2. After reading a walkthrough, I want to move on because "I know it now"
Symptom: you catch yourself moving to the next machine’s walkthrough without re-attacking.
Cause: the exact point where learners stumble — the pleasure of understanding makes you dodge the labor of reproduction. Knowing from reading and doing by hand accumulate in different storage.
Fix: one rule — the walkthrough passes to the next volume only after the re-attack. Fixing the order as "compare → reproduce → next" physically blocks the escape route. If reproduction feels bothersome, that’s the signal that this is exactly the machine that needs it — easy machines aren’t bothersome.
Wall 3. Everything gets classified as ② — "I feel like I could have seen it all"
Symptom: even techniques you honestly didn’t know feel like "I’d have solved it if I’d known."
Cause: hindsight bias — a brain that has seen the answer can’t reconstruct its past ignorance.
Fix: change the grading question. Not "would I have solved it if I’d looked?" but "if asked to explain this technique, could the me of that moment (before reading) have explained it?" If you couldn’t have, it’s ①. If it’s still ambiguous, classify as ① — ①’s prescription (reproduction) does ② no harm, but ②’s prescription (checklist) alone can’t heal ①. When ambiguous, the heavier prescription is safer.
Wall 4. Writing the analysis document leaves only self-blame
Symptom: "why didn’t I see this" repeats, and motivation wilts.
Cause: you’re doing analysis as an interrogation. Analysis’s purpose is not punishment but map-making.
Fix: change the document’s tone to an observer’s — record in third person, like "this candidate missed the branch at minute 150," instead of "why did I," and self-blame turns into data. And remember — having every failure type exposed in the first mock exam is the cheapest tuition you’ll ever pay. Had it been exposed on the real exam, it would have cost a retake fee and months.
Wall 5. The re-attack ends in 30 minutes — is this even training?
Symptom: it solves too fast because you know the answer, and it feels hollow.
Cause: normal — the re-attack’s purpose is not time but reaction.
Fix: check 3-4’s criteria — did you stop at the branch point, did you memo the new reaction? If both, a 30-minute re-attack is complete training. That it ended quickly rather means that machine’s knowledge is already yours. Read the hollowness not as training but as the signal that recovery is finished.
7. Summary
Today’s Concepts
| Concept | One-line explanation |
|---|---|
| 5-class failure taxonomy | Missing technique / missed enumeration / time management / stamina collapse / insufficient report — different prescriptions |
| Stopping coordinates | A record not of "couldn’t solve" but "where, with what judgment, did I stop" |
| Branch point | Not the result but the judgment is the failure’s body — the point where "surely not" rose |
| Hindsight bias | A brain that saw the answer can’t reconstruct ignorance — grade first at the branch point |
| Reproduction condition | Read only, and it’s spectating — solve again by hand, and it’s knowledge |
| Verification metric | The number of what must shrink on the next mock exam — remediation’s passing bar |
Today’s Tools
| Tool | What it does |
|---|---|
| Stopping-coordinate format | Record each machine’s failure as point, path, branch point, type |
python fail_analyzer.py demo |
Practice reading the type distribution with example data |
python fail_analyzer.py analyze fails.csv |
Aggregate the distribution from your data, fix the most frequent type |
| When-stuck checklist | The document where ②’s prescriptions accumulate — condition-action format |
| Re-attack log | The document recording reaction changes at branch points |
The Core Instinct
A mock exam’s score lasts a day, but the failure distribution is an asset. "50 points" spawns no prescription, but "2 cases of missed enumeration" spawns exactly two lines of checklist. The ability to cut failures into types is reused beyond the OSCP in every future exam, project, and incident response — the secret of people who never make the same failure twice is not memory but classification.
Once every box is checked, Step 310 is complete.