LAB-06Medium
Cross-Reference Tracing
Trace cross references to determine which function references an interesting string and how it is reached.
15 min4 prerequisites5 tools
Disassembly
00: mov rcx, 0x402000
01: call sub_401100
02: mov eax, 0
03: ret
04: mov rdx, 0x402000
05: call sub_401200
06: ret Hints
Hint 1
An XREF to the string is the instruction that loads its address into a register.
Hint 2
Win64 order is RCX, RDX, R8, R9.
Hint 3
The first block (addresses 0-3) references 0x402000 too — but does it call a different function?
Submit Findings
Solution
Cross-Reference Tracing — Solution
The string at 0x402000 is referenced in two places:
- Address 0:
mov rcx, 0x402000→ passed as 1st arg tosub_401100. - Address 4:
mov rdx, 0x402000→ passed as 2nd arg tosub_401200.
- The function that takes the string as its 2nd argument is
sub_401200(address 4-5). - The pointer is in RDX.
- RDX is the 2nd argument position under Win64 (RCX=1st, RDX=2nd, R8=3rd, R9=4th).
Methodology: list all XREFs to the string, then read each call site to determine how it's used — as what argument, in what context. That tells you which function actually consumes it.
Prerequisites
- sa4-cross-references
- a4-stack-functions
- Win64 calling convention (RCX, RDX, R8, R9)
- Ghidra/Binary Ninja xref navigation
Methodology
Investigation Methodology
1. Find All Cross-References (Xrefs)
- In Ghidra: Right-click string → References → Show References to Address
- In Binary Ninja: Right-click → Cross References
- List every instruction that references the target address
2. Classify Each Xref
For each xref, determine:
- Type: Code (instruction) vs Data (pointer in table)
- Context: Which function contains the instruction?
- Role: Argument (which position?), local variable, comparison, jump target
3. Analyze Argument Position (Win64)
| Register | Position | Volatile? |
|---|---|---|
| RCX | 1st | Yes |
| RDX | 2nd | Yes |
| R8 | 3rd | Yes |
| R9 | 4th | Yes |
| Stack (RSP+0x28+) | 5th+ | Yes |
4. Trace Data Flow
- String address loaded into register
- Register passed to function call
- Function uses it (e.g., passes to API, compares, copies)
5. Distinguish Direct vs Indirect Use
- Direct: Function processes the string (prints, compares, sends)
- Indirect: Function passes it along to another function
- Setup: Function just stores pointer for later use
6. Document Findings
- String address
- All xref locations (address, function, instruction)
- Argument position at each call
- Inferred purpose per function
Common Pitfalls
- Missing xrefs because string is built dynamically (stack string, encoded)
- Confusing the caller (which loads address) with the callee (which uses it)
- Assuming RCX/first arg is always the 'important' one — context matters
- Not checking for multiple xrefs to the same string from different functions
Tools
- Ghidra (References window, Cross References)
- Binary Ninja (Cross References, Data Flow)
- IDA Pro (Xrefs, Graph view)
- radare2 (axf, axg)
- objdump / Ghidra script for automation
References
- Lesson SA4: Cross-References
- Lesson A4: Stack & Functions — Win64 calling convention
- Microsoft x64 Calling Convention docs
- Ghidra Xref Analysis Guide
Extensions & Challenges
- Find all strings in a binary, trace xrefs for each, categorize by capability
- Write a Ghidra script to auto-generate xref report for all strings
- Research: How to trace xrefs through pointer arithmetic / computed addresses
- Analyze a sample with indirect string references (pointer tables)