2 releases
Uses new Rust 2024
| 0.1.1 | Dec 29, 2025 |
|---|---|
| 0.1.0 | Dec 29, 2025 |
#534 in Programming languages
405KB
10K
SLoC
JS-Deobfuscator
A high-performance JavaScript deobfuscator built on the OXC Rust AST library.
Features
- 3-Layer Architecture: ECMA → Runtime → Extensions
- V8 Sandbox: Safe execution for string decoding
- Convergence Loop: Iterates until no more transformations
- High Performance: Built on OXC's fast parser
Installation
Add to your Cargo.toml:
[dependencies]
js-deobfuscator = "0.1.1"
Quick Start
Simple API (Recommended)
use js_deobfuscator::{JSDeobfuscator, Extension};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let source = std::fs::read_to_string("obfuscated.js")?;
// Standard deobfuscation (ECMA + Runtime)
let output = JSDeobfuscator::new()
.deobfuscate(&source)?;
// With string rotator extension
let output = JSDeobfuscator::new()
.ecma(true)
.runtime(true)
.extensions([Extension::StringRotator])
.deobfuscate(&source)?;
std::fs::write("clean.js", output)?;
Ok(())
}
One-liner Functions
use js_deobfuscator::{deobfuscate, deobfuscate_full};
// Standard (ECMA + Runtime)
let output = deobfuscate("var a = 1 + 2;")?;
// Full (all extensions enabled)
let output = deobfuscate_full(&obfuscated_source)?;
With Result Details
use js_deobfuscator::{JSDeobfuscator, Extension};
let result = JSDeobfuscator::new()
.ecma(true)
.runtime(true)
.extensions([Extension::StringRotator])
.max_iterations(50)
.deobfuscate_with_result(&source)?;
println!("Iterations: {}", result.iterations);
println!("Modifications: {}", result.modifications);
println!("Converged: {}", result.converged);
println!("{}", result.code);
Low-Level Engine API
For advanced use cases with full control:
use js_deobfuscator::{Engine, EngineConfig};
use oxc::allocator::Allocator;
use oxc::codegen::Codegen;
use oxc::parser::Parser;
use oxc::span::SourceType;
let allocator = Allocator::default();
let mut program = Parser::new(&allocator, &source, SourceType::mjs()).parse().program;
let config = EngineConfig::full().with_max_iterations(50);
let engine = Engine::with_config(config);
let result = engine.run(&allocator, &mut program)?;
let output = Codegen::new().build(&program).code;
Configuration
Layers
| Layer | Description | Default |
|---|---|---|
ecma(true) |
Constant folding, dead code removal | ✅ Enabled |
runtime(true) |
atob, btoa, escape, unescape | ✅ Enabled |
extensions([...]) |
Obfuscator-specific patterns | ❌ Disabled |
Extensions
| Extension | Description |
|---|---|
Extension::StringRotator |
obfuscator.io style string arrays |
Extension::ControlFlow |
Control flow deflattening (WIP) |
Extension::Proxy |
Proxy function inlining (WIP) |
Architecture
┌─────────────────────────────────────────────────────────────┐
│ JS-Deobfuscator │
├─────────────────────────────────────────────────────────────┤
│ Layer 1: ECMA (ECMAScript standard) │
│ ├── Operators: +, -, *, /, %, **, &, |, ^, ~, <<, >> │
│ ├── Unary: !, +, -, ~, typeof, void │
│ ├── Comparison: ===, !==, <, >, <=, >= │
│ ├── Logical: &&, ||, ?? │
│ ├── Ternary: cond ? a : b │
│ ├── String: +, [], .length, .charAt, .slice, etc. │
│ ├── Array: .length, .join, .indexOf, etc. │
│ └── Number: parseInt, parseFloat, isNaN, isFinite │
├─────────────────────────────────────────────────────────────┤
│ Layer 2: Runtime (Browser/Node APIs) │
│ ├── Encoding: atob, btoa │
│ └── Deprecated: escape, unescape │
├─────────────────────────────────────────────────────────────┤
│ Layer 3: Extensions (Obfuscator patterns) │
│ └── String Rotator: obfuscator.io style string arrays │
└─────────────────────────────────────────────────────────────┘
Supported Transformations
Layer 1: ECMA
| Category | Transformations |
|---|---|
| Arithmetic | 1 + 2 → 3, 10 % 3 → 1, 2 ** 4 → 16 |
| Bitwise | 5 & 3 → 1, 5 | 3 → 7, ~0 → -1 |
| String | "a" + "b" → "ab", "abc"[1] → "b" |
| Logical | true && x → x, false || x → x |
| Ternary | true ? a : b → a |
| Typeof | typeof "x" → "string" |
| Comparison | 1 === 1 → true |
Layer 2: Runtime
| Function | Example |
|---|---|
atob |
atob("SGVsbG8=") → "Hello" |
btoa |
btoa("Hello") → "SGVsbG8=" |
escape |
escape("hello world") → "hello%20world" |
unescape |
unescape("hello%20world") → "hello world" |
Layer 3: Extensions
| Pattern | Description |
|---|---|
| String Rotator | Decodes obfuscator.io style string arrays with shuffler IIFE |
Examples
# Run examples
cargo run --example test_string_rotator -- input.js
cargo run --example full_pipeline
cargo run --example simple_deob
License
Apache-2.0 - see LICENSE
Dependencies
~120MB
~2.5M SLoC