Comparison

How disrobe sits next to the established tool for each ecosystem. The aim is not to win every cell. For several targets a mature dedicated tool already exists and is the better choice for that one format; disrobe's value is doing all of them from one binary, behind a deterministic pipeline that records what it recovered and what it could not.

Recovery is always measured against an independent reference, never the tool's own output, and lossy results are reported as measured. The limits are listed at the bottom of this page and in Limits.

Source recovery (bytecode to source)

EcosystemEstablished toolsWhere disrobe differs
Pythonpycdc, pylingual, uncompyle6, decompyle3One engine spans 3.6-3.15; each construct is recompiled and diffed opcode-for-opcode, reaching 92.76% per-code-object equivalence on the CPython 3.14 stdlib (5831 of 6286). uncompyle6 stops near 3.8 and decompyle3 near 3.9; the ML decompilers are non-deterministic and carry benchmark-contamination risk.
JVM / Kotlin / ScalaCFR, Vineflower, Procyon, FernflowerIn-house Rust decompiler is the default; on the EdgeCases corpus at least 93.1% of decompiled methods recompile error-free under real javac (asserted floor 122 of 131, 128 measured on JDK 25). CFR, Vineflower, Procyon, and jadx remain available as --backend. Adds ProGuard/R8 mapping replay and obfuscator peel in the same pass.
Android (DEX)jadx, dex2jar + a Java decompilerDirect DEX-to-Java without the dex2jar hop; APK signature v1-v3 verification and RASP detection in one binary. Recovered bodies are graded by the real JVM verifier (-Xverify:all) on the committed dex corpus, where 99% of verifiable classes pass (102 of 103). On the gitignored real FOSS apks the lifter self-reports a body for 89% to 92.5% of methods (transmissionic 92.5%, enrecipes 90.7%, rustdesk 89.0%), not verifier-attested; a live-range-splitting pass recovers bodies whose registers carry conflicting JVM types across control-flow joins (307 re-hosted bodies verify clean), leaving only the one class whose Kotlin supertype is unbundled in the corpus.
.NET / CILILSpy, dnSpy, de4dotIn-house CIL to C#/F#/VB plus an actively maintained obfuscator reverser; de4dot has been unmaintained since 2020. ILSpy, dnSpy, and de4dot stay available as --backend.
Luaunluac, luadecCovers 5.1-5.4, LuaJIT, full Luau (all 82 opcodes, child-proto linking), and GLua in one decoder, plus 11 obfuscator reversers. For real IronBrew2 2.7.0 register-VM output, disrobe reconstructs the opcode permutation and xor key from the bootstrap, decodes the constant pool, and lifts the VM bytecode back to runnable Lua in standard and MAX mode, validated by a real-Lua execution differential against the original on a committed sample corpus (the execution differentials CI job). MoonSec-shape recovery runs against a synthetic bootstrap of our own design pending a real sample. Runtime-key and anti-tamper variants return unrecovered. unluac is the maturity benchmark for stock luac.
Rubynone (no FOSS YARV/mruby decompiler)Decompiles MRI/YARV 2.6-3.4 and mruby, with a recompile-equivalence oracle reaching 100% opcode-equivalence on a greeter fixture and 85% on a mixed-construct megafile (about 90% recoverable, the rest an oracle comment-stripping artifact). No comparable open-source Ruby decompiler exists.
BEAM (Erlang / Elixir)beam_disasm (disassembly only)Lifts BEAM chunks to Core Erlang and recovers Elixir from the Dbgi chunk. The standard tooling disassembles but does not reconstruct source.
PHPnone for modern bytecode (ionCube/SourceGuardian are commercial)Detects ionCube/SourceGuardian/Zend Guard and walls them (the decrypt key is native-loader-resident, so no static opcode recovery), with a partial op_array skeleton for the legacy statically-keyed cases; full Phar archive extraction. No maintained FOSS PHP-bytecode decompiler exists.
WebAssemblywasm-decompile, wasm2c, wasm-toolsLifts to typed Rust, TypeScript, WAT, or C with DWARF recovery and four obfuscator reversers (Jscrambler-WASM, Wobfuscator, Tigress-via-Emscripten, Wasmixer), rather than emitting a single fixed target. A fifth family, wasm-name-obfuscator, is detected and classified but its hex renames are not reversible.
JavaScript / TypeScriptwebcrack, synchrony, REstringer; for V8 .jsc, View8, ghidra_nodejs, jscdecompiler.comobfuscator.io (full pipeline), JS-Confuser, Jscrambler, esoteric encoders, V8/Bytenode, and 11 bundlers with scope-aware renaming and source-map reconstruction. For .jsc, the self-contained static option: View8 needs a patched V8 binary, ghidra_nodejs needs Ghidra, jscdecompiler.com is an online service; disrobe recovers the user-string layer plus structure offline with Node 18-24 detection. Internalized identifiers (console, log) live in V8's read-only snapshot heap, absent from the .jsc, an information-theoretic boundary the binary-dependent tools cross and disrobe does not.
ActionScript 3 / FlashJPEXS Free Flash Decompiler (FFDec)FFDec is the mature, full-graph SWF and AS3 decompiler and remains the better tool for deep Flash work. disrobe parses SWF and disassembles ABC bytecode as part of the unified chain; this path is local-corpus only and not CI-validated.

Unpacking and extraction (byte-exact where possible)

EcosystemEstablished toolsWhere disrobe differs
Python freezerspyinstxtractor (PyInstaller only), per-freezer scriptsPyInstaller, cx_Freeze, py2exe, PyOxidizer, shiv, pex, Briefcase, and Nuitka unpacked by one tool, then handed to the decompiler. Nuitka onefile/standalone is byte-exact; its native bodies are lossy.
Python protectorsPyarmor-Static-Unpack-1shot, GDATA Pyarmor-Tooling (PyArmor v8-9.x)PyArmor v6-v9-pro runtime-key extraction and AES decrypt (72 of 72 real-corpus samples) paired with an in-tree decompiler for end-to-end source, plus SourceDefender .pye decryption; the v3-v5 RSA-wrapped-key tier is an information-theoretic wall.
Native packersunipacker; UPX (unpacks UPX only); per-packer one-off scriptsGeneral-purpose unpacker for the tier in one static Rust binary (no Python or unicorn): UPX, kkrunchy, NSPack, Petite, MPRESS, MEW, ASPack, and PECompact are decompressed via our own decoders and an in-house x86 stub emulator, scored against real committed originals. NSPack reaches ~99% of the content section. ASPack and PECompact rebuild the decompressed section image at its load RVA on committed samples: the packed .text of near-random entropy and zero resolvable calls drops to ~6.2-6.5 with dozens to hundreds of disassembler-resolvable intra-code calls (no disk-aligned byte-identity reference for the overlay). MEW rebuilds a flat image of the committed Sysinternals samples, read as the entropy drop to ~4.2-4.9 and tens of thousands of decoded instructions. FSG decodes via the same aPLib-clone path but ships no committed fixture, so no number reproduces from a checkout. Yoda's Crypter recovers .rsrc byte-identical and decrypts .text to full plaintext through the stub emulator; Yoda's Protector and the virtualized tier (VMProtect, Themida, Enigma) are detect + carve (runtime-only keys).
React Native Hermeshermes-dec, hbctoolBytecode v60-v96. A structured lifter, not a full decompiler: variadic call args are marked <arg?> where the Hermes frame-register layout is not modeled, and no-op opcodes count as fallback. On a 66 MiB production bundle, disrobe parsed the 122,633-function table with no parse failure (header scale, not body lifts, measured locally, not a CI-gated correctness percentage; the committed hello fixture is the CI-gated case).
Containers and archivesunsquashfs, 7-Zip, binwalk, asar, format-specific CLIsDetects 98 container/archive/filesystem/firmware formats and writes member bytes in-tree for all 98 (ZIP, tar, 7z, .deb, .rpm, MSI, NSIS, Docker/OCI; bare gz/bz2/zst/lzma/lzip/lz4-frame/zlib/.Z streams; legacy ar/arj/arc/lzh/lzop/uzip/xalz/par2/ELF-overlay; embedded-linux squashfs/cramfs/ext4/romfs/minixfs/jffs2/ubifs/yaffs/erofs/ntfs/android-sparse/btrfs-send; GPT/MBR/VHD/VHDX/WIM disk images walked through FAT; vendor firmware via D-Link AES, EnGenius XOR, Autel table, QNAP PC1 and CRC-verified Netgear/Xiaomi/Tesla carves) with a recursive carve-everything engine and universal zip-slip and decompression-bomb guards; WIM XPRESS/LZX/LZMS chunk payloads decompress in-tree, InnoSetup writes the decoded setup-data block stream and InstallShield its stored and zlib members. Member-byte decoding is byte-exact for the documented codecs; ARJ method 4, ARC methods 5-7, EROFS microlzma and the compact index, StuffIt compressed forks, and OTP-AES airoha firmware are carved or reported rather than decoded. binwalk surveys firmware but does not decrypt the vendor schemes or walk these filesystems to byte-exact files.

Native and AOT-compiled (symbols and demangling, not source)

These targets compile to machine code, so function bodies are not recoverable as source. The deliverable is unpacking, symbol and metadata recovery, and demangling that gives a disassembler cleaner input.

EcosystemEstablished toolsWhere disrobe differs
Native (PE/ELF/Mach-O)Ghidra, IDA, Binary NinjaNot a competitor on raw decompilation. The unpack, symbol-recovery, and chain-detect layer that feeds those tools cleaner input. DWARF/PDB/STABS across x86, ARM, RISC-V, MIPS, PowerPC, SPARC, and eBPF.
GoGoReSym, redressSymbol recovery plus garble undo and embedded-FS walking; pclntab eras go1.2 through go1.26, with type-name resolution gated above 85%.
Swift / Objective-Cclass-dump, swift-demangleMach-O class-dump with SwiftConfidential and SwiftShield rename-undo in one pass. Bodies stay native; the output is the interface and restored names.
Flutter (Dart)blutter, doldrumsTwo paths: a Dart kernel (.dill) yields byte-exact source bodies from the kernel source table, while an ARM64 AOT libapp.so erases bodies and recovers class and method names and library URIs plus disassembly. Both are CI-gated on a committed sample.
Nim / Zig / Crystalbinary disassemblers, language demanglersDetect, demangle, and recover symbols and metadata from each binary's own symtab and type table. Source is not recoverable.

Where disrobe is not the right tool

  • Deep, interactive Flash reversing: use FFDec.
  • Full native decompilation to C: use Ghidra, IDA, or Binary Ninja. disrobe prepares input for them; it does not replace them.
  • Devirtualizing a commercial protector against a running licensed sample (VMProtect, Themida, Enigma): disrobe detects the protector and carves intact sections. Its generic devirtualizer (disrobe native devirt) recovers the interpreter, fingerprints each handler behaviorally, and lifts the handler bytecode to a re-executable IR plus pseudo-code, validated end-to-end on a self-authored Tigress-shape VM; the commercial front-ends are extended from published RE write-ups, not a running commercial sample, and a handler stream assembled at run time from a per-machine key is the wall.
  • Any AOT-compiled language (Nim, Zig, Crystal, Flutter Dart, Swift bodies): source bodies are gone at compile time; demangling and symbol recovery are the ceiling, the same ceiling every tool faces.