Skip to the content.

ToC

  • [Overview of Tools]
    • [Binary Ninja]
    • [IDA Pro]
    • [Ghidra]
    • [Radare2]
  • Detailed Breakdown

Overview of Tools

Rust Binary Analysis Challenges

Rust binaries present unique challenges for reverse engineers:

  • Heavy use of generics and monomorphization creates code bloat
  • Name mangling makes symbols difficult to read
  • LLVM optimizations produce complex control flow
  • Panic handling adds boilerplate code throughout
  • Zero-cost abstractions compile to efficient but harder-to-read assembly
  • Trait implementations and vtables can be confusing

Binary Ninja

Binary Ninja has been making steady improvements for Rust analysis:

Strengths:

  • Rust symbol demangling built-in (both legacy and v0 mangling schemes)
  • Clean decompilation with the HLIL (High-Level IL) often producing readable pseudo-code
  • Type recovery works reasonably well for Rust structures
  • Plugin ecosystem includes Rust-specific analysis tools
  • Fast analysis compared to competitors
  • Good handling of panic infrastructure - can identify and simplify panic-related code

Workflow tips:

  • Use the symbol list to find meaningful functions (filter by demangled names)
  • Look for main or ::main to find the actual entry point
  • The type system can be manually improved with struct definitions
  • HLIL is generally more useful than decompilation for Rust

IDA Pro

IDA remains the industry standard with strong Rust support:

Strengths:

  • Excellent decompiler (Hex-Rays) handles Rust fairly well
  • Robust symbol demangling for Rust (supports both formats)
  • FLIRT signatures can identify standard library functions
  • Mature plugin ecosystem with Rust-specific tools available
  • Superior debugging integration for dynamic analysis
  • Strong pattern recognition for identifying Rust idioms

Limitations:

  • Expensive licensing
  • Can struggle with heavily optimized LLVM output
  • Type recovery requires manual work for complex Rust types

Plugins worth noting:

  • rust-rtti plugins for recovering type information
  • Various scripts for identifying common Rust patterns

Ghidra

Ghidra (NSA’s free tool) has decent Rust support:

Strengths:

  • Free and open-source
  • Rust demangling built-in
  • P-Code intermediate representation useful for understanding optimized code
  • Collaborative features for team analysis
  • Scriptable in Python/Java for custom Rust analysis

Weaknesses:

  • Decompiler output can be messier than IDA’s for Rust
  • Slower analysis on large Rust binaries
  • Type recovery less sophisticated than commercial tools
  • Can struggle with panic handling code

Tips:

  • Use the “Demangler” analyzer (should run automatically)
  • Look for rust_panic and rust_begin_unwind to understand error paths
  • The Function Call Trees are useful for navigating monomorphized functions

Radare2/Rizin

Radare2 and its fork Rizin offer command-line focused analysis:

Strengths:

  • Free and open-source
  • Scriptable with r2pipe
  • Rust demangling supported
  • Cutter GUI (for Rizin) provides visual interface
  • Good for automation and scripting analysis workflows

Weaknesses:

  • Steeper learning curve (command-line focused)
  • Decompiler (Ghidra integration or r2dec) less polished than competitors
  • Type system less sophisticated for Rust-specific constructs
  • Documentation can be fragmented

Useful commands:

  • aaa - analyze all
  • afl - list functions
  • pdf @ sym.function - disassemble function
  • afn newname @ addr - rename function

General Rust Reverse Engineering Tips

Regardless of tool:

  1. Find the real main: Look for <crate_name>::main not the entry point wrapper
  2. Identify the standard library: Functions like std::io::*, std::collections::* are building blocks
  3. Look for string references: Rust programs often have many error strings that reveal functionality
  4. Understand Result/Option: Many functions return these enums, affecting control flow
  5. Use dynamic analysis: Running under a debugger can clarify what static analysis obscures
  6. Demangle everything: All tools support this, make sure it’s enabled
  7. Focus on high-level flow first: Don’t get lost in monomorphized helper functions

General Recommendation

  • For professional/commercial work: IDA Pro (best overall decompilation and tooling)
  • For best Rust experience: Binary Ninja (modern architecture, good Rust support, reasonable price)
  • For free/open-source: Ghidra (most mature free option)
  • For scripting/automation: Radare2/Rizin (best for custom workflows)

Detailed Breakdown

Let me give you a detailed breakdown of Radare2’s Rust support:

Rust Demangling in Radare2

Built-in Support:

  • Radare2 has native Rust demangling built into the core
  • Supports both legacy mangling and v0 mangling schemes
  • Automatic demangling when loading Rust binaries

Commands:

# Automatic demangling (usually enabled by default)
e bin.demangle=true
e bin.demangler=rust

# Manual demangling of a symbol
iD <mangled_symbol>

# List all symbols (demangled)
is

# List functions (demangled)
afl

# Show demangled name in disassembly
pdf @ sym._ZN...

Rust Binary Analysis Capabilities

1. Symbol Analysis

# List all Rust symbols
is ~rust

# Find main function
afl ~main

# Search for specific Rust stdlib functions
afl ~std::

# Find panic handlers
afl ~panic

2. String Analysis

Rust strings are particularly important for analysis:

# List all strings
iz

# Search strings with context
izz ~error
izz ~"unwrap"

# Find string cross-references
axt @ str.some_string

3. Function Analysis

# Analyze all functions
aaa

# Show function info
afi @ <function>

# Show function arguments (limited for Rust)
afv

# Generate call graph
agc

# Function call tree
aftl

4. Disassembly & Decompilation

r2dec (Radare2’s decompiler):

# Install r2dec
r2pm -ci r2dec

# Decompile function
pdc @ sym.function_name

r2ghidra (Ghidra decompiler integration):

# Install r2ghidra
r2pm -ci r2ghidra

# Decompile with Ghidra engine
pdg @ sym.function_name

5. Type Information (DWARF)

If the binary has debug symbols:

# Load DWARF info
id

# Show type information
it

# Show structure definitions
its

6. Cross-References

# Show xrefs to address
axt @ <address>

# Show xrefs from address
axf @ <address>

# Show all xrefs
ax

Practical Rust Analysis Workflow

Here’s a typical workflow:

# 1. Open binary
r2 rust_binary

# 2. Analyze
aaa

# 3. Find main
afl ~main
# Look for something like: sym.myapp::main

# 4. Seek to main and disassemble
s sym.myapp::main
pdf

# 5. Look at strings to understand functionality
izz ~!std  # Filter out std library strings

# 6. Find interesting functions
afl | grep -v "std::" | grep -v "core::"

# 7. Decompile interesting functions
pdg @ sym.interesting_function

# 8. Trace calls
aftl @ sym.interesting_function

# 9. Analyze panic paths
afl ~panic
afl ~unwrap

Limitations for Rust

What Radare2 struggles with:

  1. Type Recovery: Limited ability to reconstruct Rust structs, enums, traits
  2. Trait Objects: No automatic vtable reconstruction
  3. Panic Metadata: Manual analysis required
  4. Monomorphization: Hard to track which generic instantiations exist
  5. Decompilation Quality: Less readable than IDA/Binary Ninja for complex Rust
  6. Async State Machines: No special handling

Strengths for Rust

  1. Scriptability: Great for automating Rust analysis
  2. Fast: Quick analysis on large binaries
  3. Pattern Matching: Can script detection of Rust patterns
  4. DWARF Support: Good if debug symbols present
  5. Free: No licensing costs
  6. Hex Editing: Can patch Rust binaries easily

Useful r2 Scripts for Rust

Finding main:

r2 -q -c 'aaa; afl ~main; q' binary

Extract all non-std functions:

r2 -q -c 'aaa; afl | grep -v "std::" | grep -v "core::"; q' binary

Find panic strings:

r2 -q -c 'izz ~panic ~unwrap; q' binary

Cutter (GUI for Radare2/Rizin)

If you prefer a GUI, Cutter provides:

  • Visual function graphs
  • Integrated decompiler view
  • Better navigation for Rust binaries
  • Side-by-side assembly/decompilation
  • Built on Rizin (r2 fork)
# Install Cutter
# Download from: https://cutter.re
# Or use package manager

Rizin vs Radare2

Rizin (r2 fork) has some improvements for Rust:

  • Better maintained demangler
  • Cleaner API
  • Cutter integration
  • More consistent behavior

Both have similar Rust support, but Rizin may have newer fixes.

Comparison with Other Tools

When to use Radare2 for Rust:

  • ✅ Automated analysis/scripting
  • ✅ Quick triage of binaries
  • ✅ Command-line workflows
  • ✅ Budget constraints
  • ✅ Integration with other tools

When to use alternatives:

  • ❌ Need best decompilation quality → IDA Pro
  • ❌ Need interactive Rust-specific features → Binary Ninja
  • ❌ Want free + GUI + better decompiler → Ghidra
  • ❌ Deep type recovery needed → Binary Ninja/IDA

For serious Rust analysis with Radare2:

# Install r2
git clone https://github.com/radareorg/radare2
cd radare2
sys/install.sh

# Install plugins
r2pm -ci r2ghidra  # Better decompiler
r2pm -ci r2dec     # Alternative decompiler
r2pm -ci r2frida   # For dynamic analysis

# Configure
echo 'e bin.demangle=true' >> ~/.radare2rc
echo 'e asm.demangle=true' >> ~/.radare2rc
echo 'e bin.demangler=rust' >> ~/.radare2rc

Based on my research, I need to provide you with a more nuanced picture of Radare2’s Rust demangling support. Here are the resources and evidence:

Evidence for Rust Demangling Support

1. Built-in Support in Code

Radare2’s source code includes Rust demangling definitions in its demangle.h header file, which defines DMGL_RUST and rust_demangling as part of the demangling styles enumeration.

2. Historical Implementation

Radare2 version 0.10.0 (released January 2016) officially added “demangling for Rust binaries” as a new feature.

In December 2016, there was a GitHub issue suggesting integration of a Rust demangler from the Linux kernel’s perf tool (demangle-rust.c).

3. libiberty Integration

Radare2 uses libiberty (from GCC/binutils), which includes rust-demangle.c - a demangler written by David Tolnay and rewritten by Eduard-Mihai Burtescu for v0 support. The rust-demangle.c code explicitly mentions it handles “Rust mangling version, with legacy mangling being -1” for the legacy scheme and modern v0 mangling.

Important Clarifications

However, I need to correct my earlier statement about “automatic demangling when loading Rust binaries”:

  1. Not Always Automatic: Historical issues show that demangling wasn’t enabled by default and required configuration via e bin.demangle=true and e asm.demangle=true in the radare2rc file.

  2. Version-Dependent: The quality and automation of Rust demangling has evolved over Radare2 versions, and older versions required manual configuration.

Accurate Summary

What is proven:

  • ✅ Radare2 has native Rust demangling built into the core (via libiberty)
  • ✅ Supports both legacy and v0 mangling schemes (in the code)
  • ⚠️ May require manual configuration - not always automatic

Corrected statement: Radare2 has native Rust demangling support built into the core through libiberty integration, which supports both legacy and v0 mangling schemes. However, users may need to enable it manually using:

e bin.demangle=true
e asm.demangle=true
e bin.demangler=rust

The “automatic demangling when loading Rust binaries” depends on the Radare2 version and user configuration - it’s not guaranteed to work out-of-the-box on all installations.

Comparison Table

Enhanced Rust Binary Analysis Tool Comparison

Existing Rows (from original table)

Rust Features Binary Ninja Ghidra IDA Pro Radare 2
Version v5.1.8104 Personal v11.4.2 v9.2 v6.0.0
Native Rust Demangler Yes (LLVM demangler built-in) Yes (v11.0+, v0 mangling) Yes (configurable) Yes (libiberty-based, requires config)
String Analysis Rust String Slicer plugin Yes (RustStringAnalyzer) Yes (plugin) Basic (iz/izz commands)
Library Recognition Signature Kit + custom plugins FunctionID/FIDB databases RIFT (FLIRT + binary diffing) Zignatures + FLIRT
Trait Object Analysis Better vtable support Limited Limited Limited
Type Recovery Quality Good HLIL foundation Basic-Fair (general: 36.1-38.6% precise on stripped binaries per research) Better with RIFT Basic
Panic Metadata Analysis Plugin extractable metadata Basic Manual analysis possible Manual
DWARF Support Good Good Good Good
Custom Calling Conventions Standard Standard only Custom __usercall syntax Limited
Decompilation Quality Clean HLIL output Readable but loses semantics Excellent (gold standard) Basic (r2dec/r2ghidra)
Plugin/API Languages Python, C++, Rust (unique) Java, Python, JavaScript Python (IDAython), IDC Python (r2pipe), C, JavaScript

NEW ROWS - Enhanced Analysis Features

Cross-References Quality

How well each tool handles Rust’s heavy cross-referencing

Binary Ninja Ghidra IDA Pro Radare 2
Excellent - Fast xref computation, pinned UI panel with tabs, handles monomorphized functions well, works great with Rust’s heavy xref patterns Good - Built-in xref support, handles cross-references adequately but can be slower on very large Rust binaries Excellent - Industry standard for xrefs, reliable even on complex Rust binaries, mature implementation Fair - Basic xref support (axt/axf commands), can struggle with large monomorphized codebases, may miss some references

Notes:

  • Rust binaries generate heavy cross-reference graphs due to monomorphization and trait implementations
  • Binary Ninja and IDA Pro handle this best, with fast navigation between related monomorphized functions
  • Radare2 xrefs work but may require manual analysis for complex cases

Async/Await Analysis

Support for analyzing Rust’s async state machines

Binary Ninja Ghidra IDA Pro Radare 2
Manual with MLIL/HLIL aid - No automatic async recognition, but MLIL/HLIL makes state machine analysis tractable. Can manually identify Future trait implementations and poll methods Manual - No specialized async support. Decompiler output helps but requires manual interpretation of state machine enums and match statements Manual - No automatic async detection. Hex-Rays decompilation aids understanding but async patterns must be identified manually Minimal - No async-specific support. Requires extensive manual work to identify and trace state machines

Notes:

  • Async/await in Rust compiles to state machine enums implementing the Future trait
  • None of the tools automatically identify or annotate async state machines
  • Analysis requires understanding of Rust’s async lowering (see Tyler Mandry’s blog series)
  • Look for: enum with variants for suspension points, poll() methods, switchInt patterns in MIR/assembly

Macro Expansion Visibility

Whether you can see what macros generated

Binary Ninja Ghidra IDA Pro Radare 2
None - Macros are expanded at compile time. No visibility into original macro source. DWARF info may help if available None - Cannot see macro expansions. Only compiled result is visible. DWARF debug info can provide hints about source locations None - Macros expanded before compilation. No direct visibility. DWARF info can help correlate to source None - No macro expansion visibility. Only final compiled code is analyzable

Notes:

  • Rust macros are expanded during compilation, before any binary is generated
  • No reverse engineering tool can recover macro expansions from compiled binaries
  • With debug symbols (DWARF), you may see source line numbers that reference macro definitions
  • Best approach: Keep source code alongside if macro understanding is critical
  • Common Rust macro patterns (println!, vec!, etc.) can be recognized by their expanded patterns

Result/Option Enum Recognition

Automatic identification of common Rust patterns

Binary Ninja Ghidra IDA Pro Radare 2
Limited - No automatic pattern detection. Can use rust_type_layout_helper_bn plugin to import type layout info. Manual type application helps Limited - No automatic Result/Option recognition. Decompiler may show generic enum patterns. Manual type annotation required Limited - No built-in pattern recognition. Manual identification of Ok/Err and Some/None branches needed. RTTI plugins may help with debug builds Minimal - No automatic detection. Requires manual pattern recognition and annotation

Notes:

  • Result<T, E> and Option compile to discriminated unions (tagged enums)
  • Common patterns: match statements become switch/if chains on discriminant values
  • Look for discriminant checks (typically at offset 0 or in specific byte)
  • Without debug info, distinguishing Result from Option or other enums is challenging
  • Helper: Use -Zprint-type-sizes when compiling to understand memory layouts

Ownership/Lifetime Hints

Any reconstruction of Rust’s memory safety features

Binary Ninja Ghidra IDA Pro Radare 2
None - Ownership/lifetimes are compile-time only. No runtime representation. Cannot be reconstructed from binary None - Lifetimes are compile-time concepts only. Not present in compiled code None - Ownership model enforced at compile-time. No trace in binary analysis None - Cannot recover Rust’s ownership/borrowing information from binaries

Notes:

  • Ownership and lifetimes are zero-cost abstractions - they exist only at compile time
  • The borrow checker validates code before compilation; no runtime overhead
  • By the time code is compiled, ownership information is erased
  • What you CAN see: Drop implementations (destructors), reference counting (Arc/Rc), and explicit checks
  • LLVM IR and MIR (mid-level compiler representations) contain lifetime info, but not final binaries

Cargo/Crate Identification

Can it identify which crates were used?

Binary Ninja Ghidra IDA Pro Radare 2
Manual via symbols - No automatic crate detection. Demangled symbols reveal crate names (e.g., tokio::runtime::...). String analysis finds crate names in panic messages Manual via symbols - Parse demangled symbols for crate names. Strings may contain crate references. No automatic crate catalog Manual via symbols - Demangled symbols show crate namespace. Can script symbol extraction. No built-in crate identification Manual via symbols - Symbol listing (is/afl) shows demangled crate names. No automatic identification

Notes:

  • Crate names appear in demangled symbol paths: std::, tokio::, serde::, etc.
  • Panic strings often include crate names and file paths
  • Debug builds retain more crate information than release builds
  • Common crates to look for:
    • tokio:: - Async runtime
    • serde:: - Serialization framework
    • clap:: - CLI argument parsing
    • reqwest::, hyper:: - HTTP clients/servers
    • diesel::, sqlx:: - Database ORMs
  • Strategy: Search for :: in demangled symbols to find crate boundaries

Performance on Large Binaries

Rust binaries can be huge due to monomorphization

Binary Ninja Ghidra IDA Pro Radare 2
Good - Fast analysis engine, handles large Rust binaries (10-50MB+) well. HLIL/MLIL generation is efficient. Multi-threading helps Fair to Good - Can handle large files but initial analysis may be slow (10-30 mins for 50MB+). Memory intensive. Java-based, so GC impacts performance Good - Mature analysis handles large binaries well. Initial analysis can be lengthy but generally faster than Ghidra. Stable on huge files Fair - Can struggle with very large Rust binaries. Analysis may be slow or incomplete. Works better with smaller targets (<20MB)

Notes:

  • Rust release builds with full optimization can be 50-200MB+ due to:
    • Generic monomorphization (separate copy of code for each type)
    • Aggressive inlining
    • LLVM optimizations
    • Standard library statically linked by default
  • Size reduction tips:
    • strip binary to remove symbols
    • Use --release with LTO (Link-Time Optimization)
    • Consider wasm or embedded targets for smaller footprints
    • cargo-bloat tool to analyze binary size
  • Performance comparison for 50MB Rust binary (rough estimates):
    • Binary Ninja: 5-15 minutes initial analysis
    • Ghidra: 15-30 minutes initial analysis
    • IDA Pro: 10-20 minutes initial analysis
    • Radare2: Varies greatly, may timeout or require manual guidance

Additional Recommendations

Best Practices for Rust Binary Analysis

  1. Enable Debug Symbols if possible (cargo build with --debug or DWARF info)
  2. Keep source code when analyzing your own Rust binaries
  3. Use multiple tools - combine Binary Ninja/IDA’s UI with Ghidra’s decompiler
  4. Learn Rust patterns - understanding monomorphization, vtables, and panic handling is crucial
  5. Script symbol extraction - automate crate/module identification via demangled symbols
  6. Focus on HLIL/decompiled output rather than raw assembly for Rust
  7. Use compiler explorer (godbolt.org) to understand how Rust patterns compile

Tool Selection Guide for Rust

  • Professional work + Budget: IDA Pro (best overall, mature)
  • Modern + Clean UX + Good Rust support: Binary Ninja (fast, excellent API)
  • Free + Powerful: Ghidra (best free option, good decompiler)
  • Automation + Scripting: Radare2 or Binary Ninja (both have good APIs)
  • Async-heavy analysis: Binary Ninja or IDA (better HLIL/decompiler for state machines)
  • Very large binaries (100MB+): IDA Pro or Binary Ninja (better performance)

Community Resources


Summary Score (Additional Features)

Scoring: 1.0 (Full support), 0.5 (Partial), 0.0 (None/Manual)

Feature Binary Ninja Ghidra IDA Pro Radare 2
Cross-References Quality 1.0 0.75 1.0 0.5
Async/Await Analysis 0.3 0.25 0.3 0.1
Macro Expansion 0.0 0.0 0.0 0.0
Result/Option Recognition 0.25 0.25 0.25 0.1
Ownership/Lifetime Hints 0.0 0.0 0.0 0.0
Crate Identification 0.4 0.4 0.4 0.3
Large Binary Performance 0.9 0.7 0.9 0.6
TOTAL 3.85/7 3.35/7 3.85/7 2.6/7

Last Updated: November 2025 Tools evolve rapidly - verify current capabilities before making decisions

Important Clarifications & Corrections

Binary Ninja Rust Demangler

Correction: Binary Ninja has built-in Rust demangling via LLVM demangler (supports msvc/itanium/rust/dlang). The FAQ states: “We currently demangle both GNU3 and MSVC symbols including C++11 using our own cross-platform library” and the API docs show demangle_llvm() function that handles Rust symbols natively. While there are community Rust demangler plugins available, native support exists in the core.

Ghidra Type Recovery Precision

Clarification: The 36.1-38.6% precision figure comes from a research paper titled “A Framework for Assessing Decompiler Inference Accuracy” (2023). This metric is for general stripped binaries (not Rust-specific) and represents “precisely infers” vs “partially infers” (which achieves 97.2-99.3%). With debug symbols, precision jumps to 99.7%. These are general benchmarks, not Rust-specific measurements.

Radare2 Rust Demangler Configuration

Important Note: Radare2’s Rust demangling via libiberty requires manual configuration and may not work automatically on all installations. Users need to:

e bin.demangle=true
e asm.demangle=true  
e bin.demangler=rust

This is version-dependent and not guaranteed out-of-the-box.

Additional Verification Notes

  • All version numbers should be verified as tools update frequently
  • Plugin availability changes over time - check current repositories
  • Performance metrics are rough estimates based on community reports
  • Rust-specific features remain limited across all tools as of November 2025