Project 4: OllyDbg Control-Flow Recon on a Toy Game
Map the damage routine by tracing control flow and building a call graph in OllyDbg or x64dbg.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Level 3 |
| Time Estimate | 1-2 weeks |
| Main Programming Language | Tool-driven (OllyDbg/x64dbg) |
| Alternative Programming Languages | N/A |
| Coolness Level | Level 4 |
| Business Potential | Level 1 |
| Prerequisites | P02 scanning, P03 pointers |
| Key Topics | Control flow, breakpoints |
1. Learning Objectives
By completing this project, you will:
- Identify the instruction that modifies HP.
- Build a call stack narrative explaining how execution arrived there.
- Document a control-flow graph around the damage routine.
2. All Theory Needed (Per-Concept Breakdown)
Control-Flow Recon with Breakpoints
-
Fundamentals Control-flow recon is about turning disassembly into a story: which functions call which, where decisions are made, and how data flows through registers and memory. Breakpoints and watchpoints are your tools to stop execution at important moments so you can observe context.
-
Deep Dive into the concept At the binary level, control flow is a sequence of instructions, jumps, and calls. If you want to understand why HP changed, you need to find the exact instruction that wrote to the HP address and then build the path that led there. A write breakpoint is the most direct way to start: it triggers on a memory write to HP, stopping execution at the precise instruction. Once stopped, you inspect registers to see which object pointer is in use, and you examine the call stack to see the higher-level function chain.
Control-flow graphs (CFGs) are the mental model for complex logic. Each basic block is a straight-line sequence of instructions that ends in a branch. Branches represent decisions such as “if HP <= 0 then transition to Dead state.” By mapping these branches, you can label which paths correspond to damage application, death checks, or invulnerability windows. This is what transforms a raw disassembly listing into an understandable behavior map.
Another subtle part is recognizing function boundaries without symbols. In stripped binaries, you must infer function starts and ends by patterns (prologue/epilogue, call/ret). This is critical to making sense of the call stack. Tools like OllyDbg highlight these boundaries, but you must still verify them. If you misidentify a function boundary, your call graph will be wrong and your conclusions will be misleading.
Control-flow recon is iterative. You stop at the HP write, annotate, step backward or upward in the call stack, and build a chain of responsibility. Each time you trigger the event (e.g., a hit), you confirm that the same path is taken. This produces a stable explanation of game logic. The result is a map that you can use later in Linux tools, even if the tooling changes.
-
How this fit on projects This concept is essential for Projects 4 and 5, and it informs Project 7’s watchpoint analysis.
- Definitions & key terms
- Basic block: Linear instruction sequence with one entry/exit.
- CFG: Control-flow graph of blocks and branches.
- Breakpoint: Stop execution at a point of interest.
- Call stack: Chain of active function calls.
- Mental model diagram ``` Control Flow
[Hit Event] -> [Apply Damage] -> [Update HP] -> [Check Dead] -> [Set State] -> [Return]
- **How it works (step-by-step)**
1. Set a write breakpoint on HP.
2. Trigger a hit to stop execution.
3. Inspect registers and stack.
4. Walk up the call stack and label frames.
5. Sketch the CFG around the branch logic.
- **Minimal concrete example**
Breakpoint hit at: update_health Caller: apply_damage Caller: game_loop
- **Common misconceptions**
- “The top of the stack is the only relevant frame.” (Callers matter.)
- “Breakpoints alone reveal logic.” (You must annotate branches.)
- **Check-your-understanding questions**
1. Why is the call stack important for recon?
2. How do you detect a branch that changes state?
3. What happens if you misidentify a function boundary?
- **Check-your-understanding answers**
1. It reveals the chain of logic that led to the write.
2. Look for conditional jumps around state updates.
3. Your CFG and reasoning become incorrect.
- **Real-world applications**
- Malware analysis and root cause tracing.
- Debugging crashes without source code.
- **Where you’ll apply it**
- This project’s §5.4 and §6.2.
- Also used in: P05-ollydbg-debug-patch.md, P07-linux-gdb-watchpoints.md.
- **References**
- "Practical Reverse Engineering" - Ch. 1, 4.
- OllyDbg/x64dbg documentation.
- **Key insights**
Control-flow recon turns raw instructions into understandable behavior.
- **Summary**
Breakpoints plus CFG thinking give you a reproducible explanation for state changes.
- **Homework/Exercises to practice the concept**
1. Draw a CFG for a simple if-else branch in pseudocode.
2. Identify a call chain in a sample disassembly listing.
- **Solutions to the homework/exercises**
1. The CFG should show two branches and a join point.
2. The call chain should list three frames and the order of calls.
---
## 3. Project Specification
### 3.1 What You Will Build
A control-flow map and call stack narrative for the damage routine in your sandbox binary. You will document which instruction modifies HP, and which function chain leads to it.
### 3.2 Functional Requirements
1. Locate HP address (from Project 2/3).
2. Set a write breakpoint on HP.
3. Capture the call stack when HP changes.
4. Draw a CFG around the decision logic.
### 3.3 Non-Functional Requirements
- **Performance**: Breakpoint triggers within one hit event.
- **Reliability**: Same call stack appears across runs.
- **Usability**: Notes are clear and reproducible.
### 3.4 Example Usage / Output
Call Stack: update_health <- apply_damage <- game_loop
### 3.5 Data Formats / Schemas / Protocols
- **Recon notes**: call stack + CFG diagram + instruction addresses.
### 3.6 Edge Cases
- Multiple writes to HP per tick.
- Inlined functions that obscure boundaries.
### 3.7 Real World Outcome
#### 3.7.1 How to Run (Copy/Paste)
1. Launch sandbox in OllyDbg/x64dbg.
2. Set a write breakpoint on HP.
3. Trigger hit event.
#### 3.7.2 Golden Path Demo (Deterministic)
Breakpoint stops at the same instruction each run and the call stack matches.
#### 3.7.3 Failure Demo
Breakpoint set on UI copy: triggers without gameplay change.
---
## 4. Solution Architecture
### 4.1 High-Level Design
[HP Address] -> [Write Breakpoint] -> [Call Stack] -> [CFG Diagram]
### 4.2 Key Components
| Component | Responsibility | Key Decisions |
|-----------|----------------|---------------|
| Breakpoint | Stop on HP write | Hardware vs software |
| CFG | Map branches | Scope around HP update |
### 4.3 Data Structures (No Full Code)
- **CFG diagram** with labeled branches and blocks.
### 4.4 Algorithm Overview
**Key Algorithm: Recon Loop**
1. Trigger hit.
2. Record instruction and stack.
3. Map branches.
**Complexity Analysis**
- Time: O(number of blocks)
- Space: O(number of annotated nodes)
---
## 5. Implementation Guide
### 5.1 Development Environment Setup
- Use Windows VM with OllyDbg/x64dbg.
### 5.2 Project Structure
project/ ├── recon-notes.md └── diagrams/
### 5.3 The Core Question You're Answering
> "Which instruction changes HP, and what path leads there?"
### 5.4 Concepts You Must Understand First
- Breakpoints and watchpoints
- Call stack interpretation
### 5.5 Questions to Guide Your Design
1. Which breakpoints will give the cleanest signal?
2. How far up the call stack should you analyze?
### 5.6 Thinking Exercise
Annotate a call stack with labels for each frame’s role.
### 5.7 The Interview Questions They'll Ask
1. "How do you build a CFG?"
2. "Why is a call stack useful in reverse engineering?"
3. "How do you detect function boundaries?"
### 5.8 Hints in Layers
**Hint 1:** Start with a write breakpoint.
**Hint 2:** Trigger a single hit event.
**Hint 3:** Label each frame.
**Hint 4:** Sketch a CFG.
### 5.9 Books That Will Help
| Topic | Book | Chapter |
|-------|------|---------|
| Control flow | Practical Reverse Engineering | Ch. 1 |
| Debuggers | Practical Reverse Engineering | Ch. 4 |
### 5.10 Implementation Phases
#### Phase 1: Breakpoint Setup (2 hours)
- Attach debugger and set write breakpoint.
**Checkpoint:** Breakpoint triggers reliably.
#### Phase 2: Stack Trace (4 hours)
- Capture and annotate call stack.
**Checkpoint:** Frame roles identified.
#### Phase 3: CFG Mapping (4 hours)
- Draw CFG around HP update.
**Checkpoint:** Branches documented.
### 5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale |
|----------|---------|----------------|-----------|
| Breakpoint type | software vs hardware | hardware write | precise signal |
---
## 6. Testing Strategy
### 6.1 Test Categories
| Category | Purpose | Examples |
|----------|---------|----------|
| Reproducibility | Same stack | Re-run hit |
| Accuracy | Correct path | Compare logs |
### 6.2 Critical Test Cases
1. Trigger hit three times: same instruction.
2. Run twice: same call stack.
### 6.3 Test Data
Expected: update_health <- apply_damage <- game_loop ```
7. Common Pitfalls & Debugging
7.1 Frequent Mistakes
| Pitfall | Symptom | Solution |
|---|---|---|
| Wrong address | Breakpoint never hits | Verify HP address |
| UI copy | Breakpoint hits but no change | Validate value |
7.2 Debugging Strategies
- Verify HP address via freeze test.
- Narrow breakpoint scope.
8. Extensions & Challenges
8.1 Beginner Extensions
- Map a second value (ammo).
8.2 Intermediate Extensions
- Expand CFG to include death state transitions.
8.3 Advanced Extensions
- Annotate register usage with inferred variable names.
9. Real-World Connections
9.1 Industry Applications
- Reverse engineering proprietary software.
9.2 Related Open Source Projects
- Use the sandbox from P01.
9.3 Interview Relevance
- Control-flow and debugger usage are common interview topics.
10. Resources
10.1 Essential Reading
- Practical Reverse Engineering - Ch. 1, 4
10.2 Video Resources
- Reverse engineering workflow talks.
10.3 Tools & Documentation
- OllyDbg official site, x64dbg docs.
10.4 Related Projects in This Series
- P02-cheat-engine-value-scanning.md
- P05-ollydbg-debug-patch.md
11. Self-Assessment Checklist
11.1 Understanding
- I can explain why the call stack matters.
- I can identify a branch that changes state.
11.2 Implementation
- Call stack documented.
- CFG diagram completed.
11.3 Growth
- I can repeat the recon steps without notes.
12. Submission / Completion Criteria
Minimum Viable Completion:
- Breakpoint and call stack captured.
Full Completion:
- CFG diagram created and annotated.
Excellence (Going Above & Beyond):
- Full call graph for HP and ammo changes.