
Rekonstruiere, was Obfuskation in Rust-Binärdateien verbirgt (Strings, Crates, Bibliotheksfunktionen, abgeflachte Kontrollflüsse) mittels statischer Analyse + Unicorn-Emulation, ohne sie auszuführen. Für Malware-Triage, Audits geschützter Anwendungen. ELF/PE/Mach-O, x86-64/ARM64/32-Bit.
strings sieht nichts. FLOSS sieht nichts. rust-deobf sieht das C2.
rust-deobf stellt wieder her, was obfuskierte Rust-Binärdateien verbergen — C2-Adressen, Dateipfade, Mutexe, Registrierungsschlüssel, Konfiguration — ohne die Probe jemals auszuführen.
Demo · Aus einem KI-Agenten verwenden · Schnellstart · Ergebnisse · Echte Malware · Einschränkungen
Ein gestripptes Rust-Programm, gebaut wie Malware ausgeliefert wird (opt-level="z", fat LTO, panic=abort),
mit seinen acht Indikatoren verschlüsselt durch obfstr — die Strings
liegen in einer Struktur, match-Zweigen, Vergleichen und einem Zweig, der nie ausgeführt wird. Keiner wird jemals ausgegeben.
Gerendert aus der aufgezeichneten Ausgabe eines echten Laufs (Linux x86-64, rustc 1.97): Der Text ist wörtlich, die Farben und die Tippanimation wurden hinzugefügt, die ~8 s Emulationswartezeit ist beschleunigt und die Ausgabe ist auf die dekodierten Strings gekürzt. Die Klartextausgabe unten stammt aus demselben Lauf.
Was die Datei dir zeigt:
$ B=build/scatter_obfstr__elf__size-lto__strip
$ strings $B | grep -ciE 'northwind|10\.66|NW-5c1e9a|skip-update'
0
Was rust-deobf wiederherstellt (statisch + Unicorn-Emulation; die Binärdatei wird nie ausgeführt):
$ 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 unter 10 Sekunden, jeder String getaggt und bis zur Funktion zurückverfolgt, die ihn erzeugt.
Reproduzieren mit ONLY=scatter_obfstr PROFILES=size-lto FORMATS=elf bash scripts/build_all.sh
(Ausgabe auf die dekodierten Strings gekürzt). (Die Eingabe ist ein harmloses Benchmark-
Programm; jeder eingepflanzte String ist in bench_src/manifest.json aufgeführt.)
Rust-Malware nimmt zu, und ihre Deobfuskierungs-Tooling ist praktisch nicht vorhanden. FLOSS — der Standard-Open-Source-String-Deobfuskator — gewinnt nichts aus den gängigen Rust-Obfuskierungs- Crates zurück:
| Obfuskator | strings | FLOSS | rust-deobf |
|---|---|---|---|
| litcrypt / litcrypt2 | 0/5 | 0/5 | 5/5 |
| obfstr (inlined XOR+ADD) | 0/5 | 0/5 | 5/5 |
| cryptify (Standard-Schlüssel) | 0/5 | 0/5 | 5/5 |
| muddy (ChaCha20-Poly1305 AEAD) | 0/5 | 0/5 | 5/5 |
| enge Stack-Strings | 0/5 | 0/5 | 5/5 |
| handgeschriebenes XOR / ADD / SUB | 0/5 | 0/5 | 5/5 |
Canary-Benchmark, Release-Builds, ELF und PE x86-64 und AArch64, gestrippt und nicht gestrippt. Vollständige Tabelle, einschließlich des einen Falls, der dynamische Wiederherstellung erfordert (cryptify mit einem benutzerdefinierten Schlüssel), unter Ergebnisse.
Bei echten Samples: EDDIESTEALER (PE) — 32 obfuskierte Strings, einschließlich seiner versteckten C2-Domain und URL-Pfad, bei denen statische Tools und FLOSS 0 wiederherstellen. AmnesiaStealer (macOS Mach-O) — C2-Exfil-URL, Crypto-Clipper-Konfiguration, Staging-Pfade. Mehr unten.
String-Deobfuskierung — statische Call-Site-Wiederherstellung (Sekunden) + eine Unicorn-Emulations-Engine mit
einem echten Loader, einer C-Runtime, Pfadexploration und Global-Constructor-Replay. Stellt Strings wieder her, die
nur in einem match-Arm oder auf einem Zweig erzeugt werden, der nie ausgeführt wird.
SOC-Triage auf einem Bildschirm — soc_triage.py: Format/Arch, Rust-Toolchain, Crate-Fähigkeits-
Fingerprint (Networking / Crypto / Recon / Persistence / Staging), nach Typ gruppierte Indikatoren und
ein kalibriertes LOW / MEDIUM / HIGH-Signal mit seinen Belegen. --json für ein SIEM, --fail-on HIGH
für skriptgesteuerte Gating. --fast (Metadaten + literale Indikatoren, keine Dekodierung) skaliert mit der Binär-
größe: unter einer Sekunde bei einem kleinen Sample, ~20 s bei einer 20 MB großen Binärdatei.
Multi-Arch, Multi-Format — x86-64, ARM64 und 32-Bit-x86 über ELF, PE und Mach-O.
Passt in deinen Workflow — FLOSS-kompatibler Export (--floss-json), Headless-Ghidra-Annotation
(Plate-Kommentare, Lesezeichen, Umbenennungen), Identifikation von Bibliotheksfunktionen per Byte-Signatur
(lib_<name> in gestrippten Binärdateien), Batch-Modus über ein Verzeichnis (--jsonl).
Über Strings hinaus — Config/C2-Extraktion, Auflösung hash-obfuskierter API-Imports, Carving ungepackter
Stage-2-Payloads, Erkennung und Rekonstruktion von Control-Flow-Flattening (x86-64 und AArch64,
validiert an goldberg, OLLVM -fla und einem echten LLVM-18-Flattening-Pass), MBA- / Opaque-Predicate-
Vereinfachung mit Z3, Wiederherstellung von Rust-Trait-Object-Vtables (recover_types.py) und
Optimierungsumkehr (Jump-Table-Un-Switching, Erkennung entrollter Schleifen — premium/opt_reverse.py).
Code-Virtualisierung — detect_vm.py erkennt Bytecode-VMs im Stil von VMProtect/Themida/Tigress; der
Premium-Devirtualizer hebt sie zurück. Aus einer VM mit randomisierten Opcodes und verschlüsselten
Operanden rekonstruiert er:
return (((a0 > 1000) & (((((a0 * 31) + a1) ^ (a0 >> 3)) % 97) == 0)) ? (a1 + a0) : 0xffffffff);