
Obfuscates PowerShell and JavaScript scripts using tree-sitter-based parsing with multiple configurable impostor profiles for stealth, size, and reversing difficulty.
Ditto is a Powershell and JavaScript obfuscator base on tree-sitter-powershell and tree-sitter-javascript.
ditto-cli [options]
| Short Option | Long Option | Description |
|---|---|---|
| -h | --help | Display help information and exit. |
| -v | --version | Display version information and exit. |
| -p | --path | Path to the script file to process. |
| -i | --impostor | Impostor profile to use for obfuscation (case-insensitive). |
| -L | --list | List all available impostor profiles. |
| -t | --time | Show computation time taken for the obfuscation process. |
| -d | --debug-level | Debug level. Options: off, error, warn, info, debug, trace (Default: info). |
| -q | --quiet | Only output the final obfuscated script, suppressing all other logs. |
Each language comes equipped with distinctive, Pokemon-themed Impostors. An impostor is a named recipe that chains several obfuscation passes together. Each one favours a different mix of techniques, so the same script obfuscated by two impostors looks nothing alike. Pick the one whose trade-off (stealth, size, readability, reversing difficulty) fits your needs.
| Impostor | What it does |
|---|---|
| Pikachu | The all-rounder mascot. Converts literals to static strings, rewrites cmdlets and type members as strings, Base64-encodes strings, splits integers with inline modulo/hexlify, and renames variables randomly. A balanced default. |
| Bulbasaur | Entry-level starter. String/cmdlet/member rewriting, Base64 encoding, random variable names, and integers rebuilt via a reversed-modulo trick. Light and readable-ish. |
| Ivysaur | Bulbasaur's evolution. Same base recipe but variables are named after PowerShell verbs (${Set-...}, ${Add-...}, ${Remove-...}) to blend in with legitimate code, plus inline hexlify and modulo-reverse integers. |
| Charizard | The heavy hitter. Static strings, Base64, randomized inline modulo/hexlify, member-as-string, modulo-reverse integers, and randomized variable names and types stacked together for aggressive obfuscation. |
| Alakazam | The math brain. Pre-computes every boolean and integer into arithmetic expressions, breaks invocation expressions apart, and turns cmdlets, members and types into strings. Produces dense, expression-heavy output. |
| Onix | The array specialist. Stores tokens in constant arrays, shuffles them, hexlifies via foreach, and rebuilds every integer through XOR/add arithmetic evaluated at runtime. |
| Eevee | The renamer. Randomly renames all functions, parameters and variables, rewrites cmdlets/members as strings, and assigns UUID-style and verb-style names with wildcard masking. Focused on identifier obfuscation. |
| Ditto | The mimic — a meta-impostor. Instead of transforming the whole file, it scans the source for # ditto(<engine>) comments and applies the named engine only to the statement that immediately follows the comment. This lets you mix impostors within a single script. See Selective obfuscation with Ditto. |
| Impostor | What it does |
|---|---|
| Tinkatuff | The well-rounded default. Rewrites member accesses as subscripts, occasionally converts expressions to switch/if-else, turns numbers into math expressions, and encodes/splits/escapes strings and identifiers. Good balance of coverage and size. |
| Unown | The symbol cipher. Encodes numbers, strings, booleans, specials and default objects with JSFuck-style tricks and renames identifiers using only $ and _. Output is nearly unreadable. |
| Metagross | "Wait, it's all numbers?" Turns strings into fromCharCode, rewrites every number as an expression, and renames all identifiers to number-like names. The output is almost entirely digits. |
| Wailord | The whale. Produces a massive output (average expansion ratio ~4643x). Only use it on small scripts — it stacks bubble-named identifiers, string splitting, JSFuck numbers and array transforms. |
| Clefable | The gambler. Randomly picks among all available passes so you get a comparatively "small" output that still carries every kind of protection. A reverser has to handle every possible pass. Because passes are chosen at random and can interfere, you may need to run it a few times. |
| Cofagrigus | The tomb. Renames identifiers with Egyptian-hieroglyph names, encodes strings, rewrites numbers as expressions, and applies string/number "curse" transforms. Eerie, dense, and hard to read. |
List all available impostors directly from your shell:
ditto-cli --list
Don't hesitate to add yours ! And then you can invoke the one you want.
Original PowerShell Script:
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed', 'NonPublic,Static').SetValue($null, $true)
Obfuscation Command:
ditto-cli --path test.ps1 --impostor ivysaur
Obfuscated Output: