A lightly obfuscated CrackMe where static analysis alone cannot determine the key. Apply static analysis first, document what it reveals and what it cannot, then apply dynamic analysis to resolve the gap.
Overview
Some binaries cannot be fully understood by static analysis alone. This lab uses a CrackMe that applies a simple runtime transformation to its check string, making the key invisible in the static disassembly. You work through the static analysis process honestly -- documenting what you can and cannot determine -- then apply gdb, strace, and ltrace to resolve what static analysis left open.
Tools: file, strings, readelf, objdump, Ghidra, gdb, strace, ltrace
Time: ~90 minutes.
The binary: lab7_target -- a stripped x86-64 ELF provided by the instructor. The binary accepts one command-line argument (the key) and prints "Access granted" or "Access denied". Self-paced fallback: see labs/_artifacts/README.md ("Self-paced fallback: Lab 7") for a C source + compile command that produces an equivalent binary with ROT13 obfuscation.
Safety: This binary is a course-provided CrackMe. It does not make network connections and does not write to disk outside its own process space. Run it in your normal lab environment.
Part A: Static analysis phase
Do your full static analysis workflow before running the binary.
file lab7_target
readelf -h lab7_target
readelf -S lab7_target
nm -D lab7_target
strings -n 8 lab7_target
Guided questions for Part A:
-
What library functions does the binary import (from
nm -D)? Are there any string comparison functions (strcmp,strncmp,memcmp)? Are there any unusual imports? -
From
strings -n 8, do you see any obvious key string? Note: you should NOT see a plaintext key -- the binary is designed to make this search unproductive. What strings do you see that might be relevant? -
Import the binary into Ghidra. Run the auto-analyser. Find
mainvia the entry point. Trace the control flow to the key check function. What does the check function do? (Write a description in pseudo-C terms.) -
Where does the key comparison happen? Is it a direct string comparison against a static string, or is there some transformation of the input or the expected value before comparison?
-
What specifically makes static analysis insufficient here? What information would you need to determine the key that the static analysis cannot give you?
Write your static analysis findings (100-150 words) before proceeding to Part B.
Part B: Dynamic analysis phase
Now apply dynamic analysis tools, working from the hypothesis you formed in Part A.
Step 1: ltrace
ltrace ./lab7_target test_input 2>&1
What library calls do you see? If the key comparison is a library call (strcmp, memcmp), ltrace may show you both arguments directly.
Record the ltrace output. Did it reveal the key?
Step 2: strace
strace ./lab7_target test_input 2>&1 | grep -v "mmap\|mprotect\|brk\|pread"
What system calls does the binary make? Does it open files? Read environment variables? Make network calls? This tells you about the binary's behavior beyond its key check.
Step 3: gdb -- breakpoint at the comparison
From your static analysis (Part A), you identified where the comparison happens. Set a breakpoint there:
gdb ./lab7_target
(gdb) break *0x<address_of_comparison>
(gdb) run test_input
When the breakpoint fires:
(gdb) info registers
(gdb) x/s $rdi # inspect first argument as string
(gdb) x/s $rsi # inspect second argument as string
(gdb) x/16xb $rdi # inspect as raw bytes if not a string
What do you see in the registers at the comparison point? What is the expected key?
Part C: Structured comparison
Write a structured comparison of the two analysis phases:
| Aspect | Static analysis | Dynamic analysis |
|---|---|---|
| What it revealed | ... | ... |
| What it could not reveal | ... | N/A |
| Primary tool used | ... | ... |
| Time spent | ... | ... |
Then write a paragraph (100-150 words) answering: Why is the static-first posture still the right approach, even in a case where dynamic analysis is necessary? What did the static analysis phase contribute to the effectiveness of the dynamic phase? (Think about: how did you know where to set the gdb breakpoint? How did you know what to look at with ltrace?)
Part D: Solution and technique summary
Document:
- The key (the correct input that produces "Access granted").
- The obfuscation technique the binary uses (how is the expected key stored or computed in a way that makes the static string search unproductive?).
- Which dynamic tool gave you the key, and at what specific step.
Lab Report
Submit one document with Parts A through D:
- Part A: pre-dynamic static findings, your hypothesis, what static analysis could not determine
- Part B: output from ltrace, strace, and gdb (quote the relevant lines), and what each revealed
- Part C: comparison table and analytical paragraph
- Part D: solution and technique summary
Grading
| Criterion | Points |
|---|---|
| Part A: Static analysis is genuine (not skipped to go straight to running) | 25 |
| Part A: Hypothesis and limitation are accurately stated | 15 |
| Part B: All three dynamic tools applied; output quoted | 25 |
| Part C: Comparison is analytical, not just a list | 20 |
| Part D: Key correct; technique accurately described | 15 |
| Total | 100 |
A report that goes straight to ltrace ./lab7_target test and reports the answer earns credit for Part D and zero for Part A. The static analysis phase is required and graded.
Lab 7 of 9. Due: end of Week 9. This lab is the most direct application of the "read first, run second" posture -- executed in sequence, not just mentioned.