LAB-09Easy
Execution Trace
Trace a loop to determine its final state without stepping every iteration.
10 min5 prerequisites5 tools
Disassembly
00: mov rax, 0
01: mov rcx, 3
loop:
02: add rax, rcx
03: sub rcx, 1
04: cmp rcx, 0
05: jne loop
06: ret Hints
Hint 1
The loop body adds RCX to RAX, then decrements RCX.
Hint 2
RCX starts at 3: 3+0, then 2, then 1, then 0 exits.
Hint 3
3 + 2 + 1 = 6.
Submit Findings
Solution
Execution Trace — Solution
The loop computes 3 + 2 + 1:
| Iteration | RAX | RCX |
|---|---|---|
| start | 0 | 3 |
| 1 | 3 | 2 |
| 2 | 5 | 1 |
| 3 | 6 | 0 |
When RCX reaches 0, cmp rcx, 0 sets ZF=1 and jne loop is not taken — the loop exits.
- ADD executes 3 times
- RAX = 6
- RCX = 0 at exit
Methodology: a loop is a repeated state machine. Trace the first iteration and the exit condition, then the count is arithmetic — no need to step 3 (or 300) times.
Prerequisites
- d3-execution-flow
- a3-control-flow
- a2-arithmetic-logic
- Loop analysis patterns
- Conditional breakpoints
Methodology
Investigation Methodology
1. Identify Loop Structure
mov rax, 0 ; accumulator
mov rcx, 3 ; counter
loop:
add rax, rcx ; body
sub rcx, 1 ; decrement
cmp rcx, 0 ; condition
jne loop ; back-edge
ret
2. Trace First Iteration (Manually)
- Iteration 1: RAX=0+3=3, RCX=3-1=2, cmp 2≠0 → loop
3. Generalize Pattern
- RCX counts down: N, N-1, ..., 1, 0
- Loop runs N times (when start=N, condition=RCX≠0)
- RAX accumulates: N + (N-1) + ... + 1 = N*(N+1)/2
4. Apply Formula
- N = 3
- Iterations = 3
- Sum = 3*4/2 = 6
- Exit RCX = 0
5. Debugger Techniques for Loops
- Conditional breakpoint: Break at loop header only when RCX=1 (last iteration)
- Log breakpoint: Auto-log RAX, RCX each iteration, no stop
- Skip loop: Break at instruction after loop, observe final state
- Trace recording: Record execution (rr, WinDbg TTD, Intel PT)
6. Common Loop Patterns
| Pattern | Counter Init | Condition | Iterations |
|---|---|---|---|
| Count down | N | RCX≠0 | N |
| Count up | 0 | RCX<N | N |
| Sentinel | ptr | [ptr]≠0 | Variable |
| Infinite | — | — | Until break |
7. Loop Invariants
- Identify what doesn't change across iterations
RAX + RCX*(RCX+1)/2= constant = N*(N+1)/2
Common Pitfalls
- Stepping every iteration instead of analyzing pattern
- Off-by-one: loop runs N times when counter goes N→1 (not N→0)
- Confusing `cmp rcx, 0` / `jne` (runs while RCX≠0) with `jle` / `jg` patterns
- Missing that `cmp` doesn't modify RCX, only flags
Tools
- x64dbg / GDB (conditional breakpoints, log breakpoints)
- rr (record and replay)
- WinDbg TTD (Time Travel Debugging)
- Intel PT (Processor Trace)
- Binary Ninja Debugger
References
- Lesson D3: Execution Flow
- Lesson A3: Control Flow — Loops
- Lesson A2: Arithmetic & Logic
- GDB Conditional Breakpoints
- x64dbg Trace Logging
Extensions & Challenges
- Analyze a loop with 10000 iterations — use conditional breakpoint on last iteration
- Find a nested loop in a malware sample, trace outer * inner iterations
- Research: Loop unrolling — how does compiler transform loops?
- Practice: Use rr to record, then reverse-execute from loop exit