
Go CLI, который деобфусцирует вывод javascript-obfuscator (obfuscator.io) и разминифицирует JavaScript с помощью AST-преобразований, статического декодирования и резервного варианта с песочницей goja.
jd — это инструмент на Go, который деобфусцирует вывод javascript-obfuscator (obfuscator.io) и выполняет обратную минификацию JavaScript. Это порт на Go для webcrack и synchrony.
Обнаруживает и обращает вывод javascript-obfuscator:
var/const/let)Более 20 преобразований для читаемости:
| Преобразование | Пример |
|---|---|
| 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() → отдельные инструкции |
| split-variable-declarations | var a=1, b=2 → var a=1; var b=2 |
| block-statements | обернуть тела из одной инструкции в { } |
| 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 на уровне инструкции |
| remove-double-not | !!true → true |
Парсер goja не поддерживает синтаксис ES-модулей (import/export). jd предварительно извлекает инструкции import/export, парсит оставшийся скрипт, выполняет преобразования, а затем добавляет эти инструкции в начало вывода. Динамические выражения import() корректно отличаются от объявлений import.
Для файлов, которые goja не может полностью разобрать (например, определения языков редактора Monaco с интенсивным использованием регулярных выражений), jd переключается на форматирование на уровне исходного кода: токенизатор разбивает по точкам с запятой, сохраняя регулярные литералы, строки и комментарии без изменений.
brew install ejfkdev/tap/jd
Скачайте со страницы GitHub Releases (Linux/macOS/Windows, x86_64/ARM64).
go build -o jd .
# Деобфусцировать файл (вывод в stdout)
jd obfuscated.js
# Записать в файл
jd obfuscated.js -o cleaned.js
# Чтение из stdin
cat obfuscated.js | jd -
# Обработать каталог — рекурсивно обрабатывает все файлы .js/.mjs/.cjs,
# повторяет структуру каталогов в выходном каталоге.
jd src/ -o dist/
# Режим каталога с выводом по умолчанию: создаёт <input>-deobfuscated
jd src/
# Указать расширения файлов
jd src/ -o dist/ --ext .js,.mjs
# Параллельная обработка (N воркеров, по умолчанию: число CPU)
jd src/ -o dist/ -j 8
# Пропустить файлы, не являющиеся кодом (выводить только обработанный JS)
jd src/ -o dist/ --copy-noncode=false
# Только деобфускация, пропустить обратную минификацию
jd --unminify=false obfuscated.js
# Вывод в JSON с предупреждениями
jd --json obfuscated.js
| Флаг | По умолчанию | Описание |
|---|---|---|
-o, --output | stdout | выходной файл или каталог (по умолчанию для каталога: <input>-deobfuscated) |
--deobfuscate | true | запустить деобфускацию obfuscator.io |
--unminify | true | запустить преобразования для читаемости |
--sandbox | auto | выполнение декодера: auto (сначала статически, затем песочница), only (всегда песочница), off (только статически) |
--timeout | 10s | таймаут песочницы на файл |
--ext | .js,.mjs,.cjs | расширения файлов для обработки в режиме каталога |
-j, --workers | 0 (=CPU) | параллельные воркеры для режима каталога |
--copy-noncode | true | копировать файлы, не являющиеся кодом, в выходной каталог |
-v, --verbose | false | выводить диагностику в stderr |
--json | false | выводить 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