
Recupera lo que la ofuscación oculta en binarios de Rust (cadenas, crates, funciones de biblioteca, flujo de control aplanado) mediante análisis estático + emulación con Unicorn, sin ejecutarlos. Para el triaje de malware y auditorías de aplicaciones protegidas. ELF/PE/Mach-O, x86-64/ARM64/32 bits.
strings no ve nada. FLOSS no ve nada. rust-deobf ve el C2.
rust-deobf recupera lo que los binarios Rust ofuscados ocultan — direcciones C2, rutas de archivo, mutex, claves de registro, configuración — sin ejecutar nunca la muestra.
Demo · Úsalo desde un agente de IA · Inicio rápido · Resultados · Malware real · Limitaciones
Un programa Rust sin símbolos compilado tal como se distribuye el malware (opt-level="z", LTO completo, panic=abort),
con sus ocho indicadores cifrados por obfstr — las cadenas
residen en una struct, en ramas de match, en comparaciones y en una rama que nunca se ejecuta. Ninguna se imprime jamás.
Generado a partir de la salida capturada de una ejecución real (Linux x86-64, rustc 1.97): el texto es literal, los colores y la animación de escritura son añadidos, la espera de emulación de ~8 s está acelerada y la salida está recortada a las cadenas decodificadas. La salida en texto plano de abajo corresponde a la misma ejecución.
Lo que el archivo te muestra:
$ B=build/scatter_obfstr__elf__size-lto__strip
$ strings $B | grep -ciE 'northwind|10\.66|NW-5c1e9a|skip-update'
0
Qué recupera rust-deobf (análisis estático + emulación con Unicorn; el binario nunca se ejecuta):
$ 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 en menos de 10 segundos, cada cadena etiquetada y rastreada hasta la función que la construye.
Reprodúcelo con ONLY=scatter_obfstr PROFILES=size-lto FORMATS=elf bash scripts/build_all.sh
(salida recortada a las cadenas decodificadas). (La entrada es un programa de referencia
benigno; cada cadena implantada está listada en bench_src/manifest.json.)
El malware en Rust está en aumento, y su herramienta de desofuscación está efectivamente ausente. FLOSS — el desofuscador de cadenas estándar de código abierto — no recupera nada de los crates de ofuscación comunes de Rust:
| ofuscador | strings | FLOSS | rust-deobf |
|---|---|---|---|
| litcrypt / litcrypt2 | 0/5 | 0/5 | 5/5 |
| obfstr (XOR+ADD inlineado) | 0/5 | 0/5 | 5/5 |
| cryptify (clave por defecto) | 0/5 | 0/5 | 5/5 |
| muddy (ChaCha20-Poly1305 AEAD) | 0/5 | 0/5 | 5/5 |
| cadenas apretadas en la pila | 0/5 | 0/5 | 5/5 |
| XOR / ADD / SUB hechos a mano | 0/5 | 0/5 | 5/5 |
Benchmark canario, compilaciones release, ELF y PE x86-64 y AArch64, con y sin strip. Tabla completa, incluyendo el único caso que requiere recuperación dinámica (cryptify con una clave personalizada), en Resultados.
En muestras reales: EDDIESTEALER (PE) — 32 cadenas ofuscadas incluyendo su dominio C2 oculto y la ruta URL, donde las herramientas estáticas y FLOSS recuperan 0. AmnesiaStealer (macOS Mach-O) — URL de exfiltración C2, configuración del crypto-clipper, rutas de staging. Más abajo.
Desofuscación de cadenas — recuperación estática en el sitio de llamada (segundos) + un motor de emulación Unicorn con
un cargador real, un runtime de C, exploración de rutas y repetición de constructores globales. Recupera cadenas construidas
solo en una rama match o en una rama que nunca se ejecuta.
Triaje SOC en una pantalla — soc_triage.py: formato/arquitectura, toolchain de Rust, huella de capacidades
del crate (networking / crypto / recon / persistence / staging), indicadores agrupados por tipo, y
una señal calibrada LOW / MEDIUM / HIGH con su evidencia. --json para un SIEM, --fail-on HIGH
para gating por script. --fast (metadatos + indicadores literales, sin decodificación) escala con el tamaño
del binario: menos de un segundo en una muestra pequeña, ~20 s en un binario de 20 MB.
Multi-arquitectura, multi-formato — x86-64, ARM64 y x86 de 32 bits en ELF, PE y Mach-O.
Se adapta a tu flujo de trabajo — exportación compatible con FLOSS (--floss-json), anotación headless en Ghidra
(comentarios de placa, marcadores, renombrados), identificación de funciones de biblioteca por firma de bytes
(lib_<name> en binarios con strip), modo por lotes sobre un directorio (--jsonl).
Más allá de las cadenas — extracción de configuración/C2, resolución de importaciones de API ofuscadas por hash, carving
de stage-2 desempaquetado, detección y reconstrucción de aplanamiento de flujo de control (x86-64 y AArch64,
validado en goldberg, OLLVM -fla y una pasada de aplanamiento real de LLVM-18), simplificación
MBA / de predicados opacos con Z3, recuperación de vtables de trait-object de Rust (recover_types.py), y
reversión de optimizaciones (des-switching de tablas de salto, detección de bucles desenrollados — premium/opt_reverse.py).
Virtualización de código — detect_vm.py señala VMs de bytecode estilo VMProtect/Themida/Tigress; el
devirtualizador premium las eleva de vuelta. Desde una VM con opcodes aleatorizados y operandos
cifrados, reconstruye:
return (((a0 > 1000) & (((((a0 * 31) + a1) ^ (a0 >> 3)) % 97) == 0)) ? (a1 + a0) : 0xffffffff);