Analyzing Rust Binaries logo

Analyzing Rust Binaries

Community
trilwu
analyzing-rust-binaries

Reverse engineer Rust binaries — demangling legacy and v0 symbol schemes, recognizing monomorphized generics, Result and Option control flow, trait object vtable dispatch, and panic-site strings that leak source paths and crate names. Use when a binary contains rustc version strings, core::panicking, or _ZN/_R mangled symbols, when a stripped binary is unexpectedly large, or when analyzing Rust malware or a Rust service.

Overview

Publishertrilwu
Repositorysecskills
Skill nameanalyzing-rust-binaries
Stars
144
Forks
15
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by trilwu on GitHub. Read the source before you install it.

Installation

Install the Analyzing Rust Binaries AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/trilwu/secskills.git /tmp/secskills
mkdir -p .claude/skills
cp -r /tmp/secskills/secskills-core/skills/analyzing-rust-binaries .claude/skills/analyzing-rust-binaries
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Analyzing Rust Binaries in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Analyzing Rust Binaries on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Analyzing Rust Binaries is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Analyzing Rust Binaries

Rust binaries are large, statically linked, and full of inlined generic code — but they leak more than most people expect. Panic sites embed the source file path and line, symbols carry crate and module structure, and the standard library's formatting machinery is instantly recognizable. The job is knowing which parts are yours and which are the 90% that is core, alloc, and vendored crates.

When to Use

  • strings shows rustc version, core::panicking, /rustc/<hash>/library/
  • Symbols begin with _ZN...17h<hex>E (legacy) or _R (v0 mangling)
  • A stripped binary is 3–30 MB with minimal dynamic imports
  • Analyzing Rust malware, a Rust CLI, or a compiled Rust service

When NOT to Use

  • Go binaries — use analyzing-go-binaries; symbol recovery differs entirely
  • .NET or Unity — use the matching skill
  • Suspected malware, before containment — use analyzing-malware first
  • Source is available — use auditing-code-for-vulnerabilities, which has the Rust unsafe checklist

Confirm and Fingerprint

bash
strings -n 8 target | rg -m8 'rustc version|/rustc/[0-9a-f]{40}|core::panicking|cargo/registry'

Two artifacts do most of the work before you disassemble anything:

Panic strings leak the source tree. Rust embeds the file path and line number of every panic!, unwrap(), and bounds check. That gives you the crate layout, the developer's directory structure, and often the project name.

bash
strings -n 10 target | rg 'src/[a-z_/]+\.rs' | sort -u | head -40
# → src/main.rs, src/crypto/aes.rs, /home/dev/projects/implant/src/c2.rs

Registry paths name the dependencies. Vendored crates compiled in leave their ~/.cargo/registry/src/.../<crate>-<version>/ paths in panic sites, which is effectively a dependency list.

bash
strings target | rg -o 'cargo/registry/src/[^/]+/([a-z0-9_-]+-[0-9.]+)' -r '$1' | sort -u

That combination — module layout plus dependency list — usually tells you what the binary does before a single instruction is read.

Demangle

Rust has two mangling schemes, and tools must handle both.

bash
# Legacy: _ZN4core3fmt5Write9write_fmt17h<16 hex>E
nm -C target | head -30
rustfilt < symbols.txt

# v0 (RFC 2603): starts with _R, encodes generics and paths properly
rustfilt      # handles both
# Ghidra 11+ and IDA 8+ have v0 demanglers; enable Rust demangling in the
# analyzer options rather than reading raw symbols
bash
# Filter to your target's code. Everything under core::, alloc::, std::, and
# a registry crate name is stock.
nm -C target 2>/dev/null | rg -v '^.* (core|alloc|std|hashbrown|serde|tokio)::' | head -40

When symbols are fully stripped, fall back to the panic strings: each one is adjacent to the function that contains it, so cross-referencing a panic message with a known source path names the surrounding function.

Reading Rust in a Disassembler

Five patterns account for most of the confusion:

Monomorphization. A generic function is compiled once per concrete type, so Vec<u8>::push and Vec<String>::push are separate functions with similar bodies. Expect duplicates, and do not assume two near-identical functions are copy-paste.

Result and Option returns. These are enums returned by value, often in two registers — a discriminant and a payload. A function returning Result<T, E> looks like it returns a struct; the branch immediately after the call testing the first register is the error check. Recognizing this makes error paths readable, and error paths are where the bugs are.

Bounds checks everywhere. Every slice index emits a comparison and a conditional branch to a panic site. These clutter the listing; learn to skip them. Their absence is informative — it means unsafe or get_unchecked.

Trait object dispatch. dyn Trait calls go through a vtable: a pointer pair (data, vtable), then an indirect call at a fixed vtable offset. Recover the vtable to recover the concrete type, the same way you would for C++.

String handling. Rust String and &str are pointer+length with no terminator, exactly like Go. Adjacent literals run together in strings output; find the length constant next to the pointer load.

Finding the Interesting Code

bash
# Panic paths point at your code; use them as anchors
strings -t x target | rg 'src/' | head -30      # offsets included
# Cross-reference an offset in the disassembler to land in the owning function

# Crypto and network crates are recognizable by their panic paths
strings target | rg -i 'ring-|rustls|openssl|aes-gcm|chacha20|reqwest|hyper|tokio'

For a service or implant, the fastest route is: identify the async runtime (tokio is near-universal), find the request handler or the C2 loop by its panic paths, then read outward.

Rust-Specific Security Review

If you are hunting bugs rather than behaviour:

  • unsafe blocks are where memory-safety bugs live. In a binary, look for the absence of bounds checks around indexing, and for from_raw_parts / transmute call sites if symbols survive.
  • Integer overflow is checked in debug builds and wraps silently in release. A release binary's arithmetic has no overflow traps.
  • unwrap() / expect() on attacker-controlled input is a remote panic — a denial of service, and a real finding for a network service.
  • FFI boundaries. extern "C" functions taking pointers are where Rust's guarantees stop.
  • Deserialization with serde into types whose invariants the constructor enforces but Deserialize does not.

With source, use auditing-code-for-vulnerabilities and cargo geiger.

Rust Malware Notes

Rust is increasingly used for ransomware and loaders, largely for cross-compilation and analyst friction. What still helps you:

  • Panic paths leak the developer's build environment — usernames, project names, and directory structures, which are attribution-relevant.
  • The dependency list from registry paths identifies the networking and crypto crates, which narrows the C2 protocol and the encryption scheme before you read the code.
  • rustc version in the binary dates the build.
  • Samples that strip aggressively still emit bounds-check panic sites unless compiled with panic=abort and heavy strip; when even those are gone, note it as a deliberate anti-analysis measure.

Hand containment and IOC work to analyzing-malware.

Rationalizations to Reject

  • "It's stripped, nothing to recover." Panic strings survive stripping and name the source files.
  • "Thousands of functions." Most are core/alloc/vendored crates. Filter by demangled path.
  • "These two functions are identical, it's copy-paste." It is monomorphization of one generic.
  • "The decompiler shows a struct return I don't understand." It is Result/Option. The discriminant test after the call is the error branch.
  • "Rust is memory-safe, so there are no memory bugs." unsafe and FFI exist, and logic bugs are unaffected by the borrow checker.
  • "The strings are corrupted." Rust strings are pointer+length, not null-terminated.

References

  • analyzing-binaries — general triage, dynamic analysis, anti-analysis
  • analyzing-go-binaries — the other statically-linked-and-large case
  • analyzing-malware — containment and IOCs for Rust samples
  • auditing-code-for-vulnerabilities — the Rust unsafe checklist with source
  • rustfilt, Ghidra/IDA Rust demanglers, cargo-geiger, Binary Ninja

Frequently asked questions

What does the Analyzing Rust Binaries AI skill do?

Reverse engineer Rust binaries — demangling legacy and v0 symbol schemes, recognizing monomorphized generics, Result and Option control flow, trait object vtable dispatch, and panic-site strings that leak source paths and crate names. Use when a binary contains rustc version strings, core::panicking, or _ZN/_R mangled symbols, when a stripped binary is unexpectedly large, or when analyzing Rust malware or a Rust service.

Why use Analyzing Rust Binaries on TypingMind?

Because you install it once and use it with any model. Analyzing Rust Binaries is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Analyzing Rust Binaries in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/trilwu/secskills/tree/main/secskills-core/skills/analyzing-rust-binaries. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Analyzing Rust Binaries?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Analyzing Rust Binaries?

As many as you like. As long as a model supports skills, you can use Analyzing Rust Binaries with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Analyzing Rust Binaries AI skill free?

Yes. It is published on GitHub by trilwu under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇