Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
rust-deobf — Recover what obfuscation hides in Rust binaries (strings, crates, library functions, flattened control flow) via static analysis + Unicorn emulation, without running them. For malware triage, protected-app audits. ELF/PE/Mach-O, x86-64/ARM64/32-bit. | Kitploit
Tools/GitHubGitHub/vahpem/rust-deobf
Indicator of Compromise (IOC) ManagementStatic AnalysisDynamic Analysis (Sandboxing)Reverse EngineeringInformation GatheringMalware AnalysisBinary AnalysisThreat IntelligenceAI-Assisted Reversing
GitHubvahpem/rust-deobf

rust-deobf

42619h 36m agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Recover what obfuscation hides in Rust binaries (strings, crates, library functions, flattened control flow) via static analysis + Unicorn emulation, without running them. For malware triage, protected-app audits. ELF/PE/Mach-O, x86-64/ARM64/32-bit.

View Repository
rust-deobf: strings finds 0 indicators in an obfuscated Rust binary; recover.py recovers all 8 (IP, path, user agent, flag, registry key, mutex, URL, identifier)

strings sees nothing. FLOSS sees nothing. rust-deobf sees the C2.

rust-deobf recovers what obfuscated Rust binaries hide — C2 addresses, file paths, mutexes, registry keys, config — without ever running the sample.

CI core license formats arch python

Demo · Use it from an AI agent · Quick start · Results · Real malware · Limitations


⚡ 30-second demo

A stripped Rust program built the way malware ships (opt-level="z", fat LTO, panic=abort), with its eight indicators encrypted by obfstr — the strings sit in a struct, match arms, comparisons, and a branch that never runs. None is ever printed.

Terminal: strings | grep finds 0 matches; python3 scripts/recover.py sample recovers 8 decoded strings tagged ip, path, registry, mutex and url

Rendered from the captured output of a real run (Linux x86-64, rustc 1.97): the text is verbatim, the colours and typing animation are added, the ~8 s emulation wait is sped up, and the output is trimmed to the decoded strings. The plain-text output below is the same run.

Plain-text output (copyable)

What the file shows you:

$ B=build/scatter_obfstr__elf__size-lto__strip
$ strings $B | grep -ciE 'northwind|10\.66|NW-5c1e9a|skip-update'
0

What rust-deobf recovers (static + Unicorn emulation; the binary is never executed):

$ python3 scripts/recover.py $B
binary: scatter_obfstr__elf__size-lto__strip   format=ELF   arch=x86_64
  static x86-64 (recover_callsite): 0 strings  decoders=9  seconds=0.2
  emulation (recover_emulate): 8 strings  functions=416/416  timed_out=False  workers=1  seconds=6.8

== decoded strings ==
  10.66.12.7:8443   [ip]
      function 0xf20c  (emulation)
  C:\ProgramData\NorthwindSvc\state.db   [path]
      function 0xf20c  (emulation)
  Mozilla/5.0 (Windows NT 10.0; Win64; x64) NorthwindAgent/2.1
      function 0xf20c  (emulation)
  --skip-update-check
      function 0xf443  (emulation)
  Software\Northwind\Agent\Settings   [registry]
      function 0xf51b  (emulation)
  Global\NW-5c1e9a   [mutex]
      function 0xf5a8  (emulation)
  https://telemetry.northwind.example/api/v3/beacon   [url]
      function 0xfd58  (emulation)
  nw-agent::stage=collect
      function 0xfd58  (emulation)

8/8 in under 10 seconds, each string tagged and traced to the function that builds it. Reproduce it with ONLY=scatter_obfstr PROFILES=size-lto FORMATS=elf bash scripts/build_all.sh (output trimmed to the decoded strings). (The input is a benign benchmark program; every planted string is listed in bench_src/manifest.json.)


🔥 Why this exists

Rust malware is rising, and its deobfuscation tooling is effectively absent. FLOSS — the standard open-source string deobfuscator — recovers nothing from the common Rust obfuscation crates:

obfuscatorstringsFLOSSrust-deobf
litcrypt / litcrypt20/50/55/5
obfstr (inlined XOR+ADD)0/50/55/5
cryptify (default key)0/50/55/5
muddy (ChaCha20-Poly1305 AEAD)0/50/55/5
tight stack strings0/50/55/5
hand-rolled XOR / ADD / SUB0/50/55/5

Canary benchmark, release builds, ELF and PE x86-64 and AArch64, stripped and not. Full table, including the one case that needs dynamic recovery (cryptify with a custom key), under Results.

On real samples: EDDIESTEALER (PE) — 32 obfuscated strings including its hidden C2 domain and URL path, where static tools and FLOSS recover 0. AmnesiaStealer (macOS Mach-O) — C2 exfil URL, crypto-clipper config, staging paths. More below.


✨ What's inside

  • String deobfuscation — static call-site recovery (seconds) + a Unicorn emulation engine with a real loader, a C runtime, path exploration and global-constructor replay. Recovers strings built only in one match arm or on a branch that never runs.

  • One-screen SOC triage — soc_triage.py: format/arch, Rust toolchain, crate capability fingerprint (networking / crypto / recon / persistence / staging), indicators grouped by type, and a calibrated LOW / MEDIUM / HIGH signal with its evidence. --json for a SIEM, --fail-on HIGH for scripted gating. --fast (metadata + literal indicators, no decoding) scales with binary size: under a second on a small sample, ~20 s on a 20 MB binary.

  • Multi-arch, multi-format — x86-64, ARM64 and 32-bit x86 across ELF, PE and Mach-O.

  • Fits your workflow — FLOSS-compatible export (--floss-json), headless Ghidra annotation (plate comments, bookmarks, renames), library-function identification by byte signature (lib_<name> in stripped binaries), batch mode over a directory (--jsonl).

  • Beyond strings — config/C2 extraction, hash-obfuscated API-import resolution, unpacked stage-2 carving, control-flow-flattening detection and reconstruction (x86-64 and AArch64, validated on goldberg, OLLVM -fla and a real LLVM-18 flattening pass), MBA / opaque-predicate simplification with Z3, Rust trait-object vtable recovery (recover_types.py), and optimization-reversal (jump-table un-switching, unrolled-loop detection — premium/opt_reverse.py).

  • Code virtualization — detect_vm.py flags VMProtect/Themida/Tigress-style bytecode VMs; the premium devirtualizer lifts them back. From a VM with randomized opcodes and encrypted operands, it reconstructs:

    return (((a0 > 1000) & (((((a0 * 31) + a1) ^ (a0 >> 3)) % 97) == 0)) ? (a1 + a0) : 0xffffffff);
    

    — the function's exact source.

  • Safe by design — static + emulation by default: emulation runs functions of the binary under Unicorn, never the binary itself. Dynamic (Frida) recovery is opt-in and for isolated VMs only.

  • Rust metadata that survives strip — rustc version, third-party crates with exact versions, and panic sites, rebuilt from the source paths the compiler leaves in every Rust binary (no cargo-auditable needed).


🤖 Use it from an AI agent

A decompiler's string view, strings, FLOSS — anything that reads strings from the file — can only show bytes that are in the file. An obfuscation crate makes sure the plaintext never is, so an AI agent reading a decompiler sees the same nothing you do. rust-deobf gives it the facts instead.

It is a CLI with JSON output, so any agent that can run shell commands (Claude Code, Codex, Cursor, …) can call it next to whatever decompiler tooling it already drives:

Download Tool