
Go-CLI, die die Ausgabe von javascript-obfuscator (obfuscator.io) deobfuskiert und JavaScript mithilfe von AST-Transformationen, statischer Dekodierung und einem goja-Sandbox-Fallback entminifiziert.
jd ist ein Go-Tool, das die Ausgabe von javascript-obfuscator (obfuscator.io) deobfuskiert und JavaScript entminifiziert. Es ist ein Go-Port von webcrack und synchrony.
Erkennt und kehrt die Ausgabe von javascript-obfuscator um:
var/const/let)Über 20 Lesbarkeits-Transformationen:
| Transformation | Beispiel |
|---|---|
| computed-properties | console["log"] → console.log |
| merge-strings | "a" + "b" → "ab" |
| unminify-booleans | !0 → true, !1 → false |
| number-expressions | 1 + 2 → 3 |
| void-to-undefined | void 0 → undefined |
| raw-literals | 0x1 → 1 |
| sequence | a(), b(), c() → separate Anweisungen |
| split-variable-declarations | var a=1, b=2 → var a=1; var b=2 |
| block-statements | Umschließen von Einzelanweisungs-Rümpfen mit { } |
| logical-to-if | a && b() → if (a) b() |
| ternary-to-if | a ? b() : c() → if (a) b() else c() |
| merge-else-if | else { if (...) } → else if (...) |
| for-to-while | for(;;) → while(true) |
| yoda | 5 === x → x === 5 |
| infinity | 1/0 → Infinity |
| invert-boolean-logic | !(a == b) → a != b |
| unary-expressions | No-Op void/!/typeof auf Anweisungsebene entfernen |
| remove-double-not | !!true → true |
Der Parser von goja unterstützt keine ES-Modul-Syntax (import/export). jd extrahiert import-/export-Anweisungen vorab, parst das verbleibende Skript, führt Transformationen aus und stellt die Anweisungen dann der Ausgabe voran. Dynamische import()-Ausdrücke werden korrekt von Import-Deklarationen unterschieden.
Für Dateien, die goja nicht vollständig parsen kann (z. B. Monaco-Editor-Sprachdefinitionen mit intensiver Regex-Nutzung), greift jd auf eine Formatierung auf Quellcodeebene zurück: Ein Tokenizer trennt an Semikolons und bewahrt dabei Regex-Literale, Strings und Kommentare unverändert.
brew install ejfkdev/tap/jd
Herunterladen von GitHub Releases (Linux/macOS/Windows, x86_64/ARM64).
go build -o jd .
# Deobfuscate a file (output to stdout)
jd obfuscated.js
# Write to a file
jd obfuscated.js -o cleaned.js
# Read from stdin
cat obfuscated.js | jd -
# Process a directory — recursively processes all .js/.mjs/.cjs files,
# mirrors the directory tree to the output directory.
jd src/ -o dist/
# Directory mode with default output: creates <input>-deobfuscated
jd src/
# Specify file extensions
jd src/ -o dist/ --ext .js,.mjs
# Parallel processing (N workers, default: number of CPUs)
jd src/ -o dist/ -j 8
# Skip non-code files (only output processed JS)
jd src/ -o dist/ --copy-noncode=false
# Only deobfuscate, skip unminify
jd --unminify=false obfuscated.js
# JSON output with warnings
jd --json obfuscated.js
| Flag | Standard | Beschreibung |
|---|---|---|
-o, --output | stdout | Ausgabedatei oder -verzeichnis (Standard für Verzeichnis: <input>-deobfuscated) |
--deobfuscate | true | obfuscator.io-Deobfuskierung ausführen |
--unminify | true | Lesbarkeits-Transformationen ausführen |
--sandbox | auto | Decoder-Ausführung: auto (statisch, dann Sandbox), only (immer Sandbox), off (nur statisch) |
--timeout | 10s | Sandbox-Timeout pro Datei |
--ext | .js,.mjs,.cjs | Dateiendungen, die im Verzeichnismodus verarbeitet werden |
-j, --workers | 0 (=CPU) | parallele Worker für den Verzeichnismodus |
--copy-noncode | true | Nicht-Code-Dateien in das Ausgabeverzeichnis kopieren |
-v, --verbose | false | Diagnosen nach stderr ausgeben |
--json | false | {code, warnings}-JSON ausgeben |
jd/
├── main.go # CLI entry
├── internal/
│ ├── cli/ # cobra CLI (i18n: English/Chinese)
│ ├── deobfuscator/ # top-level pipeline + ES module preprocessing
│ ├── jsast/ # AST walker (Cursor, Replace, Remove, Clone)
│ ├── codegen/ # AST → JavaScript printer (pretty/compact)
│ ├── scope/ # lexical scope & binding analysis
│ ├── sandbox/ # goja VM wrapper for decoder execution
│ ├── decoder/ # static decoding: Base64/RC4/rotation
│ ├── deobfuscate/ # string-array/rotator/decoder detection + transforms
│ ├── unminify/ # 20 readability transforms + fixpoint runner
│ └── transform/ # Transform abstraction + ApplyFixpoint
└── testdata/samples/ # test fixtures
parse → splitModuleStatements → deobfuscate → unminify → generate