-
-
Notifications
You must be signed in to change notification settings - Fork 0
catalog
This is the authoritative per-ecosystem list of every packer, obfuscator, protector, freezer, and bundler disrobe recognizes, with the support tier for each. The counts come from the in-tree catalog tables (Packer in crates/disrobe-pass-native/src/packers/mod.rs, each pass chain_detector.rs CATALOG_COUNT, crates/disrobe-pass-dotnet/src/protectors.rs, crates/disrobe-pass-jvm/src/protectors.rs and rasp.rs), so they match the binary, not a hand-kept list.
Three words describe how far recovery goes, the same vocabulary the README uses:
- Recover: real recovered output (source, bytes, or structure), measured against an independent oracle where one exists.
- Detect + carve: the layer is identified and any intact parts are extracted, without full reversal.
- Wall: no static tool can recover it without the runtime key, the live process, or the network-fetched payload. Stated honestly, never faked.
The disrobe auto chain at the bottom is what stitches these together: it fingerprints the input, runs the matching pass, re-fingerprints the output, and repeats until nothing else applies.
The Packer enum carries 27 variants and the native chain detector advertises the same 27.
The tier names below are the in-tree UnpackerStatus values, so the split is exactly what the binary advertises (10 + 6 + 3 + 6 + 2 = 27).
Tier (UnpackerStatus) |
Count | Families |
|---|---|---|
| Implemented: byte-exact decoders plus an in-house x86 stub emulator | 10 | UPX, kkrunchy, NSPack, Petite, MPRESS, MEW, FSG, ASPack, PECompact, Yoda's Crypter |
| StubEvalPending: stub emulator validated against a spec-built stub, real-sample recovery tracked | 6 | ASProtect, Morphine, nPack, NeoLite, PolyCryptor, Warzone crypter |
| GreyZoneDetectAndCarve: virtualizing tier, runtime-keyed handler stream | 3 | VMProtect, Themida, Yoda's Protector |
GreyZoneDetectOnly: gated behind --i-have-authorization
|
6 | WinLicense, Enigma Protector, Obsidium, Armadillo, PELock, PE-Protector |
| DetectOnly: CLR-layer crypter, JIT-derived key absent from the image | 2 | DotNetPatcher, NetCryptor |
The recover tier is scored byte-for-byte against real committed originals: UPX .text and .pdata are bit-identical (the whole loaded image about 96%, the residual being loader-rebuilt relocations and IAT the OS resolves at run time), kkrunchy is byte-exact, NSPack reaches about 99% of the content section, and Yoda's Crypter .rsrc is byte-identical with its .text decrypted to full plaintext. The full breakdown is in the native guide.
| Surface | Count | Families |
|---|---|---|
| Freezers / packagers | 9 | PyInstaller 2.x-6.20+, Nuitka (onefile / standalone / module / wheel), cx_Freeze, py2exe, PyOxidizer, shiv, pex, Briefcase, SourceDefender .pye
|
| Protector (PyArmor) | 7 versions | PyArmor v6-v9-pro (default / super / no-wrap); recovered 72 of 72 real-corpus samples. The v3-v5 RSA-wrapped-key tier is a runtime-key wall. |
| Source obfuscators (AST-evaluator) | 18 | Kramer/Specter, Berserker, Jawbreaker, BlankOBF, PlusOBF, Wodx, pyobfuscate.com, PyObfuscator (mauricelambert), python-obfuscator (PyPI), ObfuXtreme, Manglify, Oxyry, pyminifier, online-obfuscator family, Xindex, pyobfus, Pypacker, Patchwork |
Jawbreaker's b16/b32/b64 loader shell is decoded statically, but a payload it fetches from a remote paste at run time is absent from the file. ObfuXtreme's AES-CBC/b85/xor static body is recovered; its runtime-payload segment is not in the artifact. python-obfuscator (PyPI), pyobfus, and Pypacker are detect plus partial-peel. See the Python guide.
| Surface | Count | Families |
|---|---|---|
| JS chain catalog | 10 | 4 obfuscators (obfuscator.io full pipeline, JS-Confuser, Jscrambler, js-obfuscator (jsobfu)) plus 6 bundler markers (webpack, Vite, Rollup, esbuild, Turbopack, Bun) |
| JS esoteric encoders + protectors | separate detectors | JSFuck, aaencode, jjencode, JSFiretruck, Dean Edwards Packer (decoded); JSDefender and Arxan / Digital.ai (detect + static-transform peel); PACE (detect-only) |
| JS bundlers (unbundler) | 11 | webpack 4, webpack 5, Vite, Rollup, Rolldown, esbuild, Turbopack, Bun, Parcel, Browserify, SystemJS |
| WASM obfuscators | 5 (catalog) | Jscrambler-WASM, Wobfuscator, Tigress-via-Emscripten, Wasmixer (4 reversed); wasm-name-obfuscator is detect + classify only, because its hex renames destroy the original names |
The JS and WebAssembly guides cover each pipeline.
| Surface | Count | Families |
|---|---|---|
| JVM / Android protectors | 9 | ProGuard/R8 (mapping replay), Zelix KlassMaster, Allatori, Stringer, DashO, DexGuard (detect + structural peel, with in-class string-decrypt emulation for the keyed-constant variants); yGuard, SkidSuite2, JBCO (detect-only) |
| Android RASP vendors | 8 | Promon SHIELD, Guardsquare DexGuard RASP, Guardsquare ThreatCast, Appdome, OneSpan, Arxan / Digital.ai, Zimperium zShield, Licel DexProtector |
| .NET protectors | 20 | ConfuserEx, ConfuserEx2, Dotfuscator, Dotfuscator CE, SmartAssembly, Babel, DeepSea, Spices.Net, Goliath, Skater, .NET Reactor, Eazfuscator.NET, CryptoObfuscator, ArmDot, Agile.NET, Obfuscar, Themida (.NET wrapper), ILProtector, MaxToCode, KoiVM |
On .NET, ConfuserEx2 constant decryption is reversed on a real committed sample, the Eazfuscator VM tier is devirtualized at 57 of 57 instructions against an in-repo EazVM virtualizer of our own, and the KoiVM VM tier is devirtualized on a sample produced by the real KoiVM tool (6 of 6 bodies lifted to CIL). ILProtector, MaxToCode, and the Themida/.NET wrapper derive their per-method key in a native loader absent from the artifact, so those bodies are runtime-key walled. See the JVM and Android and .NET guides.
The Lua chain catalog is 14 entries: 12 obfuscator families plus the Luau and GLua dialect detectors.
| Surface | Count | Families |
|---|---|---|
| Obfuscators | 12 | IronBrew2 (full VM devirtualization), Prometheus, MoonSec V1, MoonSec V2, MoonSec V3, AztupBrew, DarkSec, Boronide, PSU, WeAreDevs, luaobfuscator.com, SLua |
| Dialect detectors | 2 | Luau bytecode, Garry's Mod Lua (GLua) |
IronBrew2 2.7.0 is reversed on real committed output in standard and MAX mode, validated by a real-lua execution differential. MoonSec-shape recovery runs against a synthetic bootstrap of our own design pending a real sample. The Lua guide walks the devirtualizer.
| Surface | Count | Families |
|---|---|---|
| Shell obfuscators | 19 (catalog) | PowerShell Invoke-Obfuscation (Token, AST, String, Encoding, Compress, Launcher), Invoke-Stealth, PowerHell, Chameleon, psobf, ISESteroids; Bashfuscator (Token, String, Obfuscate, Compress) and bash IFS/eval indirection; Batch %random% and set-indirection |
Full VBA p-code decompile (264-opcode table, VBA3/5/6/7) with VBA-stomping detection rounds out the shell pass. See the shell guide.
| Surface | Count | Families |
|---|---|---|
| Commercial encoders | 3 (catalog) | ionCube, SourceGuardian, Zend Guard: envelope detect and wall (the decrypt key is native-loader-resident), with a partial op_array skeleton for the legacy statically-keyed cases |
Stacked eval-chain obfuscation (FOPO, Better PHP Obfuscator, and the base64/gzinflate/rot13/XOR layer set) and Phar archives are peeled and walked in the same pass. See the PHP guide.
| Ecosystem | Coverage |
|---|---|
| Go | garble report graded None / Detected / Partial / Full; garble -literals rodata-key literals rebuilt via init-thunk emulation. Type names resolved above an 85% floor on the committed go1.26.3 fixture. |
| Ruby | MRI/YARV 2.6-3.4 and mruby recompile-equivalence decompile; Ruby2Exe and Ocra freezers detected; JRuby and TruffleRuby AOT classified. |
| BEAM |
.beam and .ez chunk parse, Core Erlang lift, Elixir Dbgi quoted-AST recovery. |
| Swift / Obj-C | Mach-O class-dump plus SwiftConfidential and SwiftShield rename-undo. |
| ActionScript 3 | SWF parse and AVM2 disasm; commercial obfuscators (secureSWF, DoSWF, Kindi, Irrfuscator, swfLock) detect-only. |
| Hermes / Flutter | Hermes bytecode v60-v96 lift; Flutter Dart kernel byte-exact body recovery and ARM64 AOT disasm. |
| Containers / archives / filesystems / firmware | 98 formats detected, all 98 with in-tree extractors that write member bytes. |
disrobe auto is the front door to the whole catalog. It fingerprints the input, picks the first pass, runs it, re-fingerprints the output, and follows the capability resolver until no further pass applies or the depth cap is hit. Detection spans 23 pass crates.
disrobe auto suspect.exe --out recovered/ # detect + chain the whole pipeline
disrobe auto suspect.exe --out recovered/ --capture-stages # keep each stage's byte-exact output
disrobe auto firmware.bin --out out/ --recursive --max-depth 6Representative chains:
PE -> UPX -> rust-demanglePyInstaller -> PyArmor -> .pyc decompileAPK -> dex -> Java + manifestElectron .asar -> unbundle -> sourceConfuserEx2 PE -> de4dot -> ILSpy -> C#
With --capture-stages, stage outputs land in out/01-*/, out/02-*/, ..., out/final/. The full mechanism, including the depth cap, cycle detection, and the chain.json topology descriptor, is in The chain runner.
This wiki is generated from docs/src in the disrobe repository by scripts/wiki_sync.py. Edit the docs there, not the wiki pages here.
Getting started
Architecture
- Overview
- The five-rung IR ladder
- Passes and the capability model
- The chain runner
- The .dr envelope
- LLM sidecar and provenance
Reverse-engineering toolkit
Language and format guides
- Python
- JavaScript / TypeScript
- WebAssembly
- JVM and Android
- .NET / CIL
- Native (PE / ELF / Mach-O)
- Go
- Lua
- PHP
- Ruby
- BEAM (Erlang / Elixir)
- Swift / Objective-C
- ActionScript 3 / Flash
- Mobile (Hermes / Flutter)
- Python pickle
- Shell / PowerShell
- Containers and archives
Reference
- CLI overview
- Global flags
- Command reference
- Project configuration
- Batch directory processing
- Run reports
- Analysis-depth commands
- Diff and guard tooling
- The daemon: HTTP, gRPC, LSP, MCP
- Use it as a library
- Python bindings
- The browser playground
- Forensics and malware-safety posture
- Threat model
Integrations
Project