Reversing
Step 226. ★ Mid-Check: Independently Dissecting a Medium-Difficulty crackme — No Solutions, All the Way
Level 3 — Real-World CTF & Advanced Offensive Skills | Difficulty ★★★★☆ | Estimated time: 8–12 hours (spread over several days)
Prerequisites: the Reversing wrap-up run of Steps 215–225 — you’ve experienced Ghidra static analysis, x64dbg dynamic analysis, cumulative crackme solving (easy/medium), anti-debugging bypass, unpacking, keygenning, and obfuscation strategies.
- What you need: a crackmes.one account, Ghidra, x64dbg, a document for notes, a timer. Platform screens are marked as "Screen example" — check the actual listings yourself.
- ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime. crackmes.one is a public platform where crackmes are posted legally, specifically to be solved.
- Chapter type: this is a check-up chapter — no new techniques; selection criteria, procedure, stuck-point handling, and deliverable specs are everything. Since there are no local measurements, screens and outputs are marked as examples.
This is the Reversing track’s graduation exam. The rules are simple — pick one medium-difficulty crackme you haven’t solved, dissect it to the point where you can document its entire logic, without looking at anyone’s solution. The goal isn’t just finding the right answer but a "full dissection": restoring the entire verification algorithm as pseudocode and completing a working keygen. Draw the map statically (Ghidra), confirm values dynamically (x64dbg) — a full mobilization of everything you’ve learned so far.
1. Learning Objectives
By the end of this chapter, you will be able to:
- Select a crackme that makes for a fair test (difficulty, architecture, solution-count criteria)
- Run an independent dissection through the 4-stage procedure (static → dynamic → logic restoration) with time caps
- Break through long stalls with the "narrow down to one verification function" technique
- Complete the three deliverables: full logic document + answer/keygen + tools-and-techniques summary
- Decide for yourself when to stop and where to retrain when stuck
2. Background Knowledge — Today’s Tools and Concepts
Today’s Tools at a Glance
| Category | Details |
|---|---|
| Language/environment | Ghidra (static), x64dbg (dynamic), Python (keygen writing), a notes document |
| Today’s procedure | Selection → static first pass (map) → dynamic (value checks) → logic restoration → keygen → documentation |
| Concepts needed | Definition of independent dissection, full dissection vs answer-finding, the three types of stuck, time caps |
| Today’s deliverables | ① full logic document ② derived answer or keygen ③ tools/techniques summary |
2-1. The Definition of "Independent Dissection" — What’s Allowed and What’s Cheating
Allowed: official documentation, assembly manuals, earlier chapters of this book, searching for tool usage. Looking up "knowledge" is always allowed.
Cheating: reading that crackme’s write-ups, solution videos, or hints in the comments. Looking up "this problem’s answer" voids the test the moment you see it. crackmes.one has solutions posted for every problem, so the entire rule boils down to: never open the "Solutions" tab on the problem page.
Why go this far? Because in the field there are no solutions. Just as no malware sample comes with a write-up attached, today measures "the strength to face a binary nobody will solve for you." If you’ve seen the solution to a problem, it’s a shame, but drop it and pick a new one — this check’s value lies not in passing but in honest measurement.
2-2. Selection Criteria — Choosing a Fair Exam Problem
Pick from crackmes.one under these conditions (screen example):
# Screen example — the typical layout of crackmes.one search filters
Platform: Windows (or whichever platform you've practiced on)
Quality: 3.0 or higher ← sloppy problems are a variable, so exclude them
Difficulty: 2.0–3.0 ← corresponds to "medium"
The three selection rules:
- One you haven’t solved — obvious, but if scrolling the list turns up "a screen I’ve seen before," exclude it
- At least 3 posted solutions — even if you get stuck, there must be solutions to verify against after the test
- Familiar language/platform — native Windows PE or the Linux ELF you’ve practiced. You don’t learn a new language on exam day
Apply the filters and the candidate list looks like this (screen example — actual listings change constantly, so check yourself):
# Screen example — the row format of the problem list after filtering
name difficulty quality platform solutions
some-crackme-01 2.1 3.2 Windows x64 7
serial-checker-x 2.6 4.0 Windows x64 5
keygenme-lite 2.3 3.5 Linux ELF 4
In each row you look at three things — difficulty (in range?), solution count (3 or more?), platform (where my tools are?). Gather only the ones that pass all three, then commit at random — that secures fairness in selection.
2-3. The 4-Stage Procedure and Time Caps
| Stage | What you do | Cap |
|---|---|---|
| 1. Static first pass | Load in Ghidra → function list, string list, locate the verification point | 90 min |
| 2. Dynamic | BP at the verification point → observe input-vs-expected relationships, trace registers/memory | 2 hours |
| 3. Logic restoration | Write the entire verification algorithm as pseudocode | 90 min |
| 4. Completion | Derive the answer or write a keygen → verify by running → organize documentation | 2 hours |
About 6 hours total plus slack. Do it in one day or split it — either is fine. A cap is not a signal to "stop" but to "change strategy" — see 2-4. One more thing: get in the habit of writing the start time in your document at the beginning of each stage. Measuring time itself reduces impatience — "I still have an hour left on the cap" is grounds for staying calm.
2-4. The Three Types of Stuck and How to Break Through
If there’s no progress for 4+ hours, the problem is likely not technique but your unit of analysis.
- Type A — reading the ocean: you’re trying to understand the entire codebase. Breakthrough: narrow to "the one verification function." Find the comparison point via cross-references (xref) from strings ("correct", "wrong"), and read only that function. The ocean becomes land one function at a time.
- Type B — statically unreadable: it may be obfuscation (Step 224) or packing (Step 220). Breakthrough: give up reading and go dynamic — set BPs right after decryption or right before comparison and watch the values.
- Type C — you see values but no rule: you lack input-output pairs. Breakthrough: change the input one character at a time and record the changes in expected values as a table. The rule emerges from data.
All three types share one principle — "same method, longer" is not on the menu. Being stuck is always a signal to "change methods," never to "endure longer." And if you change methods and get stuck twice in a row, that problem is one level above the current you — stop, record which type it was, go back to the corresponding Step to reinforce, and retry with a new problem. This is not failure; it’s the result of measurement.
3. Follow Along — The Exam Operations Manual
Today’s "follow along" is not a technique but the procedure itself. Proceed in order, leaving each stage’s output in your document.
3-1. Selection and Oath
- Pick 3 candidates on crackmes.one using the 2-2 criteria
- Commit to one of them at random (dice, random number) — the moment you pick by preference, difficulty bias creeps in
- Write an oath on the first line of your notes document: "Until I close this document, I will not open the Solutions tab. If I get stuck, I will execute the 2-4 checklist."
- Start the timer. Record total time and per-stage time
Once the oath is written, I recommend tidying the browser — in an environment where the Solutions tab is open or appears in autocomplete, "I won’t look" willpower alone isn’t enough. Download only the problem file and close that browser tab. Making the environment help your willpower is the actual content of this stage.
3-2. Static First Pass — Drawing the Map
Load it in Ghidra and grab just three things (output example — varies per problem):
# Screen example — the shape of static-first-pass notes
functions: 23 (analysis complete)
strings: "Enter serial:", "Correct!", "Nope.", "usage: ..."
verification-point candidate: FUN_00401240 — the only function referencing "Nope."
How to read it: find "Correct!/Nope." among the strings, then xref to the function referencing them — that pins the verification point. That’s the whole map; you do not read the other functions now. If you get this far within 90 minutes, you’re on track.
3-3. Dynamic — Confirming Values
Set a breakpoint at the verification point in x64dbg, and feed a deliberately wrong input (AAAA...).
# Screen example — the shape of dynamic-observation notes
input: AAAA0000
at verification-function entry: EAX = input pointer, ECX = constant 0x1F35
just before comparison: computed value 0x1F35 vs value derived from my input 0x089A → mismatch → "Nope."
observation: changing the 4th input character changes 0x089A → the 4th character feeds the hash
How to read it: "what changes when I change the input" is the thread for reverse-engineering the algorithm. Don’t try to understand everything at once — stack input-result pairs into a table (Type C in 2-4).
Pre-listing the actions you’ll use often in the dynamic stage saves time — setting a BP at verification-function entry, running to just before the comparison instruction (cmp, test), copying register/stack values into notes, repeating with changed input. The memory breakpoints you learned in Step 216 are especially powerful when chasing "where the string gets transformed."
3-4. Logic Restoration and Completion
Using the observed data, write the verification algorithm as pseudocode. The pseudocode has one standard — could a third party write a keygen from this document alone? A summary like "transforms the input and compares" fails; you must write the transformation’s order, constants, and comparison values to pass.
Then either produce the answer through reverse computation, or write a keygen in Python that generates arbitrary serials. A keygen is "a program that solves the condition backward" — if verification is sum == 728, the keygen generates strings whose sum is 728. The final check is always the original binary — it’s complete only when you see "Correct!" with your own eyes after feeding the keygen’s serial. Even if the pseudocode is right, no original-binary pass means incomplete.
# Screen example — the completion-judgment screen
C:lab> crackme.exe
Enter serial: KIMI-7F35-Q2
Correct!
3-5. After the Test — Verification and Review
Whether you completed it or ran out of time, now open the Solutions tab and compare with other solutions. Add to your document the shortcuts you missed and the parts where you did better. This comparison is half the test — if solving alone is the input, comparing is the answer check.
Look especially at three things in the comparison. ① Other solutions’ approach to the verification point — if you went via string xref but someone came via entry-point backtracing, learn that route too. ② How others got past the points where you struggled — that difference cuts your time on the next problem. ③ Was your pseudocode correct — where it’s wrong is exactly your review address.
3-6. The Record Sheet — What Remains After the Test
The test’s output is not the memory of "I solved it" but a document. Fill in a record sheet like this (screen example):
# Screen example — independent-dissection record sheet
problem: crackmes.one / (problem name) / difficulty 2.3 / Windows x64
selection reason: passed filter conditions, randomly committed among 3 candidates
timeline: static first pass 70 min → dynamic 110 min → logic restoration 80 min → keygen+verify 60 min (total 5h 20m)
stuck log: 2 times — ① started reading entire functions (Type A, 25 min lost) → broke through by narrowing to the verification function
② XOR key back-computation mistake → re-verified with the input-output table
techniques used: string xref, software BP, input-variation observation table, Python keygen
result: full dissection success — keygen passed "Correct!" 3 times in a row
review: read 2 other solutions, noted 1 OEP shortcut I had missed
How to read it: the "stuck log" is the heart of this sheet. Recording stalls makes you faster at dodging the same traps in the next test, and the shrinking per-type time loss is the most honest indicator of improvement. Watch "time to recover from being stuck" more than total time itself.
4. Missions & Exercises
Mission — The Three Independent-Dissection Deliverables
- Full logic document: pseudocode of the verification algorithm + function map + string list. Write it to the level of "anyone who reads this knows how this crackme verifies"
- Answer or keygen: a Python keygen script + a verification record of "Correct!" in the original binary (what input you fed, what output you saw)
- Tools/techniques summary: the list of techniques you actually used this time (e.g., xref back-referencing, hardware BP, XOR key back-computation) and at which stage each was used
Exercises
Exercise 1. Explain why reading write-ups is "cheating" in this test, in terms of what this test measures.
Exercise 2. Why is "at least 3 solutions" among the three selection rules? Doesn’t it contradict the no-cheating rule?
Exercise 3. What’s the first action when there’s been no progress for 4 hours? How does it differ by type?
Exercise 4. Explain the difference between "finding the answer" and "full dissection" from the deliverables perspective. Why does this test demand the latter?
Answers & completion criteria · expand/collapse
5. Model Answers & Completion Criteria
Mission Model Answer
The deliverables differ per problem, so only the format is shown.
# Full logic document (format example)
verification flow: input → length check (8) → per-character transform (table lookup) → summation → constant comparison
verification function: 0x00401240 (alias check_serial)
key constants: transform table 0x00403000, expected sum 0x1F35
pseudocode: (5–15 lines here)
How to verify: ① can a third party write a keygen from the pseudocode alone? ② did the keygen’s output pass in the original binary (verification record)? ③ is the tools/techniques list "what was used at which stage, for what" rather than a name dump? Three yeses make a full dissection.
Exercise Answers
Answer 1. What this test measures is not "you solved the problem" but "do you have a standing routine for solving without solutions." Read a write-up and you get the result, but the routine being measured never gets used — the test becomes meaningless. The rule’s basis is that the field (unknown malware, new binaries) has no solutions.
Answer 2. It’s not a contradiction but a separation in time. You don’t look during the test (cheating); you use them afterward for comparison and verification (3-5). If you pick a problem with no solutions, you have no way to cross-verify your dissection even after finishing.
Answer 3. The first action is "narrowing the unit of analysis" — if you were reading everything (Type A), down to the one verification function; if statically stuck (Type B), to dynamic observation; if the rule is invisible (Type C), to building an input-output table. The common thread is "change the method," not "same method, longer."
Answer 4. The deliverable of answer-finding is a single serial string — even one lucky patch can produce it. The deliverables of a full dissection are pseudocode + keygen + techniques summary — evidence that you understood the algorithm. Real-world analysis (malware, vulnerabilities) demands understanding, so the test demands understanding.
Completion Criteria Checklist
- [ ] I selected an unsolved medium-difficulty crackme using the three selection rules
- [ ] I did not look at Solutions/write-ups during the test
- [ ] I completed the static first pass (function map + strings + verification point) within the 90-minute cap
- [ ] I observed and recorded input-vs-expected relationships through dynamic analysis
- [ ] I restored the entire verification algorithm as pseudocode
- [ ] I produced an answer or keygen and saw it pass in the original binary with my own eyes
- [ ] I completed the three deliverables (logic document, keygen, techniques summary)
- [ ] After the test, I compared and reviewed against other solutions
6. Common Pitfalls & Fixes
Wall 1. Peeking at "just a little" hint
Symptom: you only read the first line of a comment, just the title.
Cause: the pain of being stuck is real. But even a one-line hint voids the measurement — "progress made after a hint" is not your routine’s skill.
Fix: if you looked, mark that problem as "hint used" in your records and restart with a different problem. An honest failure record is worth far more than a fake success.
Wall 2. Spending two hours on selection
Symptom: you scroll the list hunting for "something more suitable."
Cause: exam anxiety manifesting as selection avoidance.
Fix: pull 3 candidates within 20 minutes using the 2-2 criteria, then commit at random. Picking skill is not what’s being tested.
Wall 3. Burning out trying to read everything
Symptom: you’re decompiling Ghidra’s functions in order from the top, reading them all.
Cause: Type-A stuck. Of 23 functions, usually 1–3 relate to verification.
Fix: strings → xref → verification function. Do only those three moves. The other functions get read "when needed."
Wall 4. The keygen works but the original rejects it
Symptom: it’s right by your pseudocode, but the original binary spits "Nope."
Cause: there’s a condition you missed in observation — typically a length check, case sensitivity, or a last-character checksum.
Fix: re-compare your restored pseudocode against the original’s comparison points. Look especially for "branches I skipped." This mismatch is the best learning material of all.
Wall 5. Reading the time cap as a "give-up signal"
Symptom: the moment you hit the cap, you go looking for solutions.
Cause: misreading the cap’s meaning. A cap is not "stop" — it’s "change strategy."
Fix: diagnose the type via 2-4 and go once more with a changed method. If it still fails, then stop, record which type blocked you, and set your retraining address (return to the corresponding Step).
7. Summary
Today’s Concepts
| Concept | One-line explanation |
|---|---|
| Independent dissection | Restoring the full logic without solutions — searching knowledge is allowed, searching answers is cheating |
| Full dissection | Pseudocode + keygen + verification — the three proofs of "understanding" |
| The three selection rules | Unsolved / 3+ solutions / familiar platform |
| Time cap | Not a stop signal — a strategy-switch signal |
| The three stuck types | Reading the ocean (scope) / unreadable (obfuscation → dynamic) / rule unclear (data shortage) |
| Post-test comparison | Contrasting with other solutions — half the test happens after it ends |
Today’s Procedure
| Stage | Output |
|---|---|
| Selection + oath | 3 candidates → random commitment, oath sentence |
| Static first pass | Function map, string list, verification point |
| Dynamic | Input-vs-expected observation table |
| Logic restoration | Pseudocode |
| Completion | Keygen + original-binary pass record |
| Review | Comparison notes against others’ solutions |
An Instinct More Important Than Commands
What this test measures is not memory but routine — what you do next when stuck. When "strings → xref → verification function → BP → observation table → pseudocode" comes out of your body in front of a binary whose answer you don’t know, you’ve graduated the Reversing track. And know that this routine is the very same one used on malware-analysis floors — same tools, same order, same "there is no solution."
Whatever the outcome, this test is also the starting line of the next track. The "eye that reads structure and verifies values" you built in Reversing continues into the Crypto track as "the eye that reads formulas and finds weak numbers." If you pulled off a full dissection, be confident. If you called a stop, that’s a result too — the stuck types in your record sheet are your review plan for the next two weeks.
Once every box is checked, Step 226 is complete.
ONE STEP FURTHER
Finished this lesson?
Check the completion criteria, then mark your progress.