
disrobe is a Rust CLI suite that statically decompiles, deobfuscates, and unpacks native binaries, bytecode, and packaged apps across 15 ecosystems, built for authorized reverse engineering and malware triage.
| Tool | 1-3-7/disrobe — Rust CLI suite for static decompilation, deobfuscation, and unpacking of native code, bytecode, scripts, firmware, and app packages |
| Category | Static reverse-engineering / software recovery toolchain |
| Primary Use | Triage unknown files, recover Python from frozen apps, Java from DEX, C# from CIL, JS from bundles, Lua from custom VMs, and extract containers for analysis with disrobe auto |
| Safe Use | Authorized penetration tests, malware triage in isolated labs, CTF work, defensive research on samples you own or are contracted to analyze |
| Telemetry Note | Purely static and local: it does not execute target code, and defenders should note that every stage, hash, and provenance record lands in chain.json and recovery.json, producing an auditable analysis trail |
disrobe positions itself as a single recovery pipeline for the messy reality of modern software distribution: a file arrives, and you do not know whether it is a PyInstaller bundle, a Nuitka onefile, a DEX-bearing APK, an Electron app wrapped around a JavaScript bundle, or a native ELF with Go runtime metadata baked in. The project, written in Rust and sitting at 113 stars on GitHub, catalogs 170 families across 15 ecosystems and detects 103 container formats in its full build. The pitch is not that it replaces Ghidra or IDA, but that it automates the tedious first hour of triage — peeling packers, lifting bytecode back toward source, and handing you a clean artifact tree before you commit to a heavyweight disassembler.
The core workflow is a three-command rhythm. disrobe identify reports the format and available signals for an input. disrobe auto then extracts and recovers the recognized layers, following recovered children into their own recovery paths — so a PyInstaller executable yields an archive, the archive yields .pyc files, and those lift back toward Python source without manual handoffs. disrobe context closes the loop with a summary of passes, confidence, and provenance. This recursion is the architectural heart of the tool: it treats a sample as a graph of nested recoverable layers rather than a single format, which is exactly how real-world malware and commercial protectors actually ship.
What stands out in the README is the honesty about boundaries. The authors distinguish between recover, partial, and detect-only outcomes, and the tool keeps "source, structure, partial output, and missing-key boundaries distinguishable in the result." That matters operationally: with --capture-stages, each intermediate pass lands under recovered/01-*/, recovered/02-*/, and recovered/final/, while chain.json records topology and hashes and recovery.json records outcomes and timings. An analyst can therefore audit exactly what was recovered, from what, and with what confidence — a provenance discipline most decompilers skip entirely.
Language coverage is unusually broad. On the Python side, disrobe handles CPython 1.0 through 3.15 bytecode and marshal to source, disassembles PyPy, MicroPython .mpy, Jython, IronPython, and Brython, extracts frozen payloads, and reads structural information out of Cython .pyd/.so binaries. The dedicated commands — py, pyinstaller, pyarmor, pyfreeze, nuitka — map directly onto the freezers and protectors analysts actually encounter during incident response, when a dropper turns out to be a wrapped script.
The protector matrix deserves close reading because it is where most tools overpromise. disrobe states plainly that PyArmor v3–v5 support is detect-only due to an RSA-wrapped key boundary, v6/v7 offer partial static recovery, and v8/v9 wrapper recovery works only where key material is available — the published 72/72 result counts complete root CodeObject decoding for default-trial wrappers, not source equivalence. That level of candor about what static recovery cannot do is rare, and it tells you the authors have actually fought these protections rather than marketing around them.
Beyond Python, the JVM/Android path covers .class, JAR, DEX, APK, and AAB with Java source, Kotlin/Scala idiom handling, and manifest and signing information. The .NET path lifts CIL to C#, F#, or VB pseudo-source, inspects ReadyToRun and Native AOT images, and extracts single-file bundles. JavaScript/TypeScript gets source deobfuscation, minification reversal, module splitting, source-map restoration, and V8 cached-data inspection — increasingly relevant as Electron-style desktop malware grows.
The native story is architecture-gated. On x86-64, disrobe native decompile emits C by default with --format rust as an option; AArch64, ARM32, and MIPS32 emit pseudo-C. The native export command rebuilds supported packed PE images for external tools — the --format ghidra flag is an explicit handoff gesture toward a full disassembler workflow. Format recognition spans PE32/PE64, EFI PE, ELF32/ELF64, kernel modules, thin/fat Mach-O, COFF, MZ, NE, LE, LX, and raw code, which covers essentially everything from DOS-era relics to UEFI implants.
Several niche lifts are worth flagging for malware analysts. The webview command extracts the frontend asset tree from Electron, Tauri, and Wails applications without starting the application — a safe-by-design choice, since running an unknown GUI app is a bad triage habit. The pickle command performs protocol disassembly, symbolic tracing, reconstruction, and classification of Python pickle payloads without calling pickle reducers, avoiding the classic arbitrary-code-execution trap of naively loading a hostile pickle. The shell/documents path covers PowerShell, Bash, VBScript, VBA p-code and stomping, XLM macros, and PDF embedded scripts — the lingua franca of phishing attachments.
Mobile runtimes get first-class treatment: Hermes v60–v96 headers parse, with pseudo-JavaScript lifting on specific versions; Flutter Dart kernel source bodies and ARM64 AOT declarations, strings, and disassembly are handled through flutter and mobile. Combined with Lua 5.1–5.4, LuaJIT, Luau, and GLua recovery, plus PHP eval-chain peeling and Phar extraction, the tool reaches into game-cheat ecosystems and custom-VM obfuscators that mainstream decompilers largely ignore.
Installation is refreshingly boring. Release archives ship for Windows, macOS, and Linux across x86-64 and ARM64, with musl support on x86-64 Linux, and each release includes SHA256SUMS and signature bundles covered by a verification guide — supply-chain hygiene that matters for a tool analysts will run against hostile inputs. From a clone, cargo build --locked --release -p disrobe-cli --bin disrobe produces the binary, and the docs discuss feature flags and slim builds for analysts who want a minimal footprint.
Everything runs statically by default, which is the correct posture for a triage tool: the sample's code is never executed, so a packed dropper cannot trigger its payload during recovery. The README's walkthrough demo — twenty CLI commands covering unpacking, source recovery, WebAssembly inspection to WAT or JSON, indicator extraction, and report preservation — reinforces that the tool is designed for documentation-grade analysis where reports and artifact hashes are preserved as evidence.
In an authorized workflow — a lab triaging malware samples, a pentester examining a client-supplied binary during a scoped engagement, or a researcher auditing a suspicious npm-adjacent desktop app — disrobe fills the gap between "I have a weird file" and "I have readable source in Ghidra." Its license is marked NOASSERTION on GitHub, so commercial users should verify terms before embedding it in a product pipeline. As a static recovery framework with honest support matrices, staged provenance, and recursive multi-layer extraction, it is one of the more thoughtfully engineered entries in the reverse-engineering tooling space this year.
1-3-7/disrobe.Educational analysis for authorized security professionals. Use only in controlled, authorized environments.
0 comentários:
Post a Comment
Note: Only a member of this blog may post a comment.