Install any skill in seconds. Free to start, no credit card required.
Get Started Free →This skill should be used when analyzing binaries, executables, or bytecode to understand what they do or how they work. Triggers on "binary", "executable", "ELF", "what does this do", "reverse engineer", "disassemble", "decompile", "pyc file", "python bytecode", "analyze binary", "figure out", "marshal". Routes to sub-skills for triage, static analysis, dynamic analysis, synthesis, or tool setup.
.claude/skills/aiskillstore-binary-re/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 88% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 133% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 98% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 208% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 142% | 0% |
Comprehensive guide for binary reverse engineering. This skill provides the overall methodology, philosophy, and reference material. Related skills handle specific phases:
| Skill | Purpose | Trigger Keywords | |-------|---------|------------------| | binary-re:triage | Fast fingerprinting | "what is this binary", "identify", "file type" | | binary-re:static-analysis | r2 + Ghidra analysis | "disassemble", "decompile", "functions" | | binary-re:dynamic-analysis | QEMU + GDB + Frida | "run", "execute", "debug", "trace" | | binary-re:synthesis | Report generation | "summarize", "report", "document findings" | | binary-re:tool-setup | Install tools | "install", "setup", "tool not found" |
Note: Each skill auto-detects based on keywords. You don't need to explicitly route - just ask what you need.
Before beginning any analysis, verify tooling availability:
bashrabin2 -v # Should show version r2 -v # Should show version
bash# Check r2ghidra availability r2 -qc 'pdg?' - 2>/dev/null | grep -q Usage && echo "r2ghidra OK" || echo "r2ghidra missing - install with: r2pm -ci r2ghidra"
| Host Platform | Method | Setup Required | |---------------|--------|----------------| | Linux x86_64 | Native QEMU | apt install qemu-user | | macOS (any) | Docker + binfmt | See binary-re-tool-setup skill | | Windows | WSL2 | Use Linux method inside WSL |
If dynamic tools unavailable: Proceed with static-only analysis, note reduced confidence in synthesis phase.
When radare2 or Ghidra aren't available, use standard binutils/LLVM tools:
bash# Metadata (replaces rabin2 -I) readelf -h binary # ELF header readelf -d binary # Dynamic section (dependencies) file binary # Quick identification # Imports/Exports (replaces rabin2 -i/-E) readelf -Ws binary | grep -E "FUNC|OBJECT" | awk '{print $8}' nm -D binary 2>/dev/null # Dynamic symbols # Strings (replaces rabin2 -zz) strings -a -n 8 binary | grep -Ei 'http|ftp|/etc|/var|error|pass|key|token|api' # Disassembly (replaces r2 pdf) objdump -d -M intel binary | head -500 # Or LLVM (better cross-arch support): llvm-objdump -d --no-show-raw-insn binary | head -500 # Dependencies (replaces rabin2 -l) ldd binary 2>/dev/null || readelf -d binary | grep NEEDED
Limitations of fallback approach:
The LLM drives analysis; the human provides context.
Human provides:
LLM executes:
┌─────────────────────────────────────────────────┐
│ HYPOTHESIS-DRIVEN ANALYSIS │
├─────────────────────────────────────────────────┤
│ │
│ 0. I/O SANITY → Compare known inputs/outputs │
│ 1. OBSERVE → Gather facts via tools │
│ 2. HYPOTHESIZE → Form theories from facts │
│ 3. PLAN → Design experiments to test theories │
│ 4. EXECUTE → Run tools (gate risky ops) │
│ 5. RECORD → Capture observations │
│ 6. UPDATE → Confirm/refute hypotheses │
│ 7. LOOP → Until understanding sufficient │
│ │
└─────────────────────────────────────────────────┘Before diving into code analysis, always check if known inputs/outputs exist.
This step prevents hours of wasted analysis by establishing ground truth first.
⚠️ REQUIRES HUMAN APPROVAL - Even for I/O comparison, get explicit approval before execution.
bash# SAFE: Use emulation for cross-arch binaries (after human approval) # ARM32 example: qemu-arm -L /usr/arm-linux-gnueabihf -- ./binary input.txt > actual_output.txt # x86-64 native (still requires approval): ./binary input.txt > actual_output.txt # Docker-based (macOS - safest option): docker run --rm --platform linux/arm/v7 -v ~/samples:/work:ro \ arm32v7/debian:bullseye-slim /work/binary /work/input.txt > actual_output.txt # Compare outputs: diff expected_output.txt actual_output.txt cmp -l expected_output.txt actual_output.txt | head -20 # Byte-level # Document the delta: # - Where does output first diverge? # - What pattern appears in the corruption? # - Does file size match (logic bug) or differ (truncation)?
Record as FACT:
FACT: Output differs at byte {N}, expected "{X}" got "{Y}" (source: diff/cmp)
FACT: File sizes match/differ by {N} bytes (source: ls -l)This single step often reveals the bug category before any disassembly.
Throughout analysis, maintain structured knowledge via episodic memory:
FACTS: Verified observations with tool attribution
HYPOTHESES: Theories with confidence and evidence
QUESTIONS: Open unknowns blocking progress
EXPERIMENTS: Planned tool invocations
OBSERVATIONS: Results from experiments
DECISIONS: Human-approved choices with rationaleKnowledge persists across sessions via episodic memory. Use consistent tagging:
[BINARY-RE:{phase}] {artifact_name} (sha256: {hash})
FACT: {observation} (source: {tool})
HYPOTHESIS: {theory} (confidence: {0.0-1.0})
QUESTION: {unknown}
DECISION: {choice} (rationale: {why})Starting analysis: Search episodic memory for artifact hash first After each phase: Findings are automatically captured in conversation Resuming: Search [BINARY-RE] {artifact_name} to restore context
ALWAYS ask human before:
1. Compute artifact hash: sha256sum binary
2. Search episodic memory: "[BINARY-RE] sha256:{hash}"
3. If previous analysis found:
→ "Found previous analysis from {date}. Resume or start fresh?"
4. If resuming: Load facts/hypotheses, continue from last phase
5. If fresh: Begin with triage phaseUser: "Continue analyzing that thermostat binary"
Claude:
1. Invoke episodic-memory:search-conversations
Query: "[BINARY-RE] thermostat"
2. Retrieve previous session findings
3. Summarize: "Last session identified ARM32/musl, found network
functions. We were about to run dynamic analysis."
4. Continue from that phaseUser: "Have we analyzed any ARM binaries with hardcoded passwords?"
Claude:
1. Search: "[BINARY-RE] FACT: hardcoded" or "[BINARY-RE] ARM"
2. Return matching artifacts and findingsFor typical unknown binary analysis:
1. Triage (binary-re-triage)
└─ Architecture, ABI, dependencies, capabilities
2. Static Analysis (binary-re-static-analysis)
└─ Functions, strings, xrefs, decompilation
3. Dynamic Analysis (binary-re-dynamic-analysis) - if safe
└─ Syscalls, network, file access
4. Synthesis (binary-re-synthesis)
└─ Structured report with evidencebash# Fast triage rabin2 -I binary # Metadata rabin2 -l binary # Dependencies rabin2 -zz binary # Strings # Static analysis r2 -q -c 'aa; aflj' binary # Functions r2 -q -c 'izj' binary # Strings # Dynamic (ARM example) qemu-arm -L /usr/arm-linux-gnueabihf -strace ./binary
| Indicator | Architecture | QEMU Binary | Ghidra Processor | |-----------|--------------|-------------|------------------| | e_machine=EM_386 (3) | x86 32-bit | qemu-i386 or Docker --platform linux/i386 | x86:LE:32:default | | e_machine=EM_ARM (40) | ARM 32-bit | qemu-arm or Docker --platform linux/arm/v7 | ARM:LE:32:v7 | | e_machine=EM_AARCH64 (183) | ARM 64-bit | qemu-aarch64 or Docker --platform linux/arm64 | AARCH64:LE:64:v8A | | e_machine=EM_X86_64 (62) | x86-64 | Native or Docker --platform linux/amd64 | x86:LE:64:default | | e_machine=EM_MIPS (8) | MIPS 32 LE | qemu-mipsel | MIPS:LE:32:default | | e_machine=EM_MIPS (8) BE | MIPS 32 BE | qemu-mips | MIPS:BE:32:default | | e_machine=EM_RISCV (243) | RISC-V 64 | qemu-riscv64 | RISCV:LE:64:RV64I | | e_machine=EM_RISCV (243) 32 | RISC-V 32 | qemu-riscv32 | RISCV:LE:32:RV32I |
| Interpreter | Libc | |-------------|------| | ld-linux-armhf.so.3 | glibc (ARM hard-float) | | ld-musl-arm.so.1 | musl | | ld-uClibc.so.0 | uClibc |
| Situation | Action | |-----------|--------| | Tool not found | Use binary-re-tool-setup skill | | Wrong architecture | Re-run triage, verify file output | | QEMU fails | Try Qiling, Unicorn, or on-device | | Analysis timeout | Reduce scope, use aa not aaa | | Conflicting evidence | Ask human, document both interpretations |
See companion docs:
docs/r2-commands.md - Complete r2 reference for LLMsdocs/ghidra-headless.md - Ghidra scripting guidedocs/arch-adapters.md - Per-architecture quirksdocs/python-bytecode-re.md - Python .pyc/marshal obfuscation patternsWorks with other plugins:
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 10,051 | 6,747 | -33% | 1 | 1 | 0% | 1,649 | 3,330 | +102% | 0 | 0 | — |
case-02 | fail→fail | 9,490 | 5,596 | -41% | 1 | 1 | 0% | 1,668 | 3,268 | +96% | 0 | 0 | — |
case-03 | fail→fail | 11,128 | 6,827 | -39% | 1 | 1 | 0% | 1,894 | 4,047 | +114% | 0 | 0 | — |
case-04 | fail→pass | 13,030 | 6,119 | -53% | 1 | 1 | 0% | 2,050 | 3,860 | +88% | 0 | 0 | — |
case-05 | pass→pass | 9,561 | 3,629 | -62% | 1 | 1 | 0% | 1,648 | 3,549 | +115% | 0 | 0 | — |
case-06 | pass→pass | 7,122 | 2,735 | -62% | 1 | 1 | 0% | 1,348 | 3,391 | +152% | 0 | 0 | — |
case-07 | pass→pass | 5,934 | 2,939 | -50% | 1 | 1 | 0% | 950 | 3,379 | +256% | 0 | 0 | — |
case-08 | fail→pass | 7,920 | 3,440 | -57% | 1 | 1 | 0% | 1,470 | 3,418 | +133% | 0 | 0 | — |
case-09 | pass→pass | 2,072 | 2,893 | +40% | 1 | 1 | 0% | 288 | 3,302 | +1047% | 0 | 0 | — |
case-10 | pass→pass | 2,302 | 3,066 | +33% | 1 | 1 | 0% | 381 | 3,375 | +786% | 0 | 0 | — |
case-11 | pass→pass | 5,314 | 4,292 | -19% | 1 | 1 | 0% | 1,053 | 3,621 | +244% | 0 | 0 | — |
case-12 | fail→pass | 16,785 | 3,344 | -80% | 1 | 1 | 0% | 1,758 | 3,481 | +98% | 0 | 0 | — |
case-13 | fail→pass | 7,210 | 4,122 | -43% | 1 | 1 | 0% | 1,165 | 3,585 | +208% | 0 | 0 | — |
case-14 | pass→pass | 5,217 | 3,380 | -35% | 1 | 1 | 0% | 839 | 3,459 | +312% | 0 | 0 | — |
case-15 | fail→pass | 10,195 | 7,053 | -31% | 1 | 1 | 0% | 1,667 | 4,036 | +142% | 0 | 0 | — |
case-16 | fail→pass | 7,559 | 5,403 | -29% | 1 | 1 | 0% | 1,209 | 3,766 | +211% | 0 | 0 | — |
case-21 | fail→fail | 7,200 | 9,286 | +29% | 1 | 1 | 0% | 860 | 3,751 | +336% | 0 | 0 | — |
case-17 | fail→pass | 13,153 | 3,548 | -73% | 1 | 1 | 0% | 2,050 | 3,533 | +72% | 0 | 0 | — |
case-18 | pass→pass | 9,112 | 4,586 | -50% | 1 | 1 | 0% | 1,470 | 3,725 | +153% | 0 | 0 | — |
case-19 | pass→pass | 13,251 | 6,838 | -48% | 1 | 1 | 0% | 2,051 | 3,971 | +94% | 0 | 0 | — |
case-20 | fail→fail | 6,054 | 8,194 | +35% | 1 | 1 | 0% | 466 | 3,437 | +638% | 0 | 0 | — |
case-22 | fail→fail | 10,602 | 19,314 | +82% | 1 | 1 | 0% | 1,586 | 3,248 | +105% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +32 percentage points is the difference between those two pass rates over the 19 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.