
CLI Go che deoffusca l'output di javascript-obfuscator (obfuscator.io) e deminifica JavaScript utilizzando trasformazioni AST, decodifica statica e un fallback sandbox goja.
jd è uno strumento Go che deoffusca l'output di javascript-obfuscator (obfuscator.io) e deminimizza JavaScript. È un port in Go di webcrack e synchrony.
Rileva e inverte l'output di javascript-obfuscator:
var/const/let)Oltre 20 trasformazioni di leggibilità:
| Trasformazione | Esempio |
|---|---|
| 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() → istruzioni separate |
| split-variable-declarations | var a=1, b=2 → var a=1; var b=2 |
| block-statements | racchiude corpi con singola istruzione in { } |
| 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 | rimuove void/!/typeof no-op a livello di istruzione |
| remove-double-not | !!true → true |
Il parser di goja non supporta la sintassi dei moduli ES (import/export). jd pre-estrae le istruzioni import/export, analizza lo script rimanente, esegue le trasformazioni, quindi antepone le istruzioni all'output. Le espressioni import() dinamiche vengono correttamente distinte dalle dichiarazioni import.
Per i file che goja non riesce ad analizzare completamente (ad esempio le definizioni di linguaggio dell'editor Monaco con uso intensivo di regex), jd ripiega sulla formattazione a livello di sorgente: un tokenizer divide sui punti e virgola preservando letterali regex, stringhe e commenti verbatim.
brew install ejfkdev/tap/jd
Scarica da GitHub Releases (Linux/macOS/Windows, x86_64/ARM64).
go build -o jd .
# Deoffusca un file (output su stdout)
jd obfuscated.js
# Scrivi su un file
jd obfuscated.js -o cleaned.js
# Leggi da stdin
cat obfuscated.js | jd -
# Elabora una directory — elabora ricorsivamente tutti i file .js/.mjs/.cjs,
# rispecchia l'albero delle directory nella directory di output.
jd src/ -o dist/
# Modalità directory con output predefinito: crea <input>-deobfuscated
jd src/
# Specifica le estensioni dei file
jd src/ -o dist/ --ext .js,.mjs
# Elaborazione parallela (N worker, predefinito: numero di CPU)
jd src/ -o dist/ -j 8
# Salta i file non di codice (output solo JS elaborato)
jd src/ -o dist/ --copy-noncode=false
# Solo deoffuscamento, salta unminify
jd --unminify=false obfuscated.js
# Output JSON con avvisi
jd --json obfuscated.js
| Flag | Predefinito | Descrizione |
|---|---|---|
-o, --output | stdout | file o directory di output (predefinito per dir: <input>-deobfuscated) |
--deobfuscate | true | esegue il deoffuscamento di obfuscator.io |
--unminify | true | esegue le trasformazioni di leggibilità |
--sandbox | auto | esecuzione del decoder: auto (statico poi sandbox), only (sempre sandbox), off (solo statico) |
--timeout | 10s | timeout della sandbox per file |
--ext | .js,.mjs,.cjs | estensioni dei file da elaborare in modalità directory |
-j, --workers | 0 (=CPU) | worker paralleli per la modalità directory |
--copy-noncode | true | copia i file non di codice nella directory di output |
-v, --verbose | false | stampa la diagnostica su stderr |
--json | false | emette JSON {code, warnings} |
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