
Un ofuscador de JavaScript basado en técnicas de ofuscación por indistinguibilidad criptográfica
Este proyecto no logra ofuscación de indistinguibilidad. No debería usar este producto para proteger secretos. Existe para disuadir la ingeniería inversa, no para impedirla.
Un ofuscador de JavaScript diseñado para hacer que el código sea extremadamente difícil de leer y analizar tanto para humanos como para LLMs. Escrito en TypeScript. Implementa técnicas de investigación revisada por pares sobre ofuscación criptográfica.
npm install
npm run build
# Uso básico
node dist/index.js input.js > output.js
# Con presupuesto de tokens objetivo (por defecto: 2.000.000)
node dist/index.js --target-tokens 500000 input.js > output.js
# Ofuscación mínima (salida pequeña)
node dist/index.js --target-tokens 10000 input.js > output.js
# Máximo inflado (10M tokens)
node dist/index.js --target-tokens 10000000 input.js > output.js
# Usando variable de entorno
INPUT_FILE=input.js node dist/index.js > output.js
# Ayuda
node dist/index.js --help
| Opción | Predeterminado | Descripción |
|---|---|---|
--target-tokens <n> | 2000000 | Tamaño de salida objetivo en tokens. Las entradas pequeñas se inflan hasta este límite. Las entradas grandes producen menos inflación para mantenerse dentro del presupuesto. |
--help, -h | Muestra el mensaje de ayuda. |
npm run build # Compila TypeScript a dist/
npm run start # Ejecuta el ofuscador (lee input.js)
npm run test # Ejecuta la suite de pruebas
npm run obfuscate-package # Ejecuta pruebas de compatibilidad contra paquetes npm
const { obfuscate } = require('./dist/obfuscator');
const code = 'function add(a, b) { return a + b; }';
const obfuscated = obfuscate(code);
// Con opciones
const obfuscated = obfuscate(code, { targetTokens: 500000 });
El ofuscador aplica 20 transformaciones en 4 fases. Cada etapa se basa en la anterior.
| Orden | Transformación | Archivo | Descripción |
|---|---|---|---|
| 1 | Trampas Anti-Debug | transforms/antiDebug.ts | Inyecta sentencias eval("debugger") y 10-20 bucles setInterval con intervalos de números primos (5s-600s) que activan repetidamente puntos de interrupción del depurador. Cada instancia utiliza cadenas codificadas únicas. |
| 2 | Alarmas de Programa Perforadas | transforms/tripwires.ts | Incrusta comprobaciones ocultas que comparan hashes de parámetros con valores secretos. 5 patrones de hash (huella digital bit a bit, aritmética modular, charCodeAt, hash numérico, typeof+longitud). Desencadena corrupción silenciosa del estado, bucles ocupados o lanza excepciones en entradas secretas. [Paper 4] |
| 3 | Inyección de Ruido LPN | transforms/noiseInjection.ts | Añade y cancela ruido aleatorio a través de rutas divididas en cálculos aritméticos. 6 patrones: suma/resta, XOR, multiplicación/división, variable dual dividida, cadena de hash calculado, rotación de bits. Los valores intermedios carecen de sentido sin rastrear la cancelación completa. [Paper 7] |
| Orden | Transformación | Archivo | Descripción |
|---|---|---|---|
| 4 | Aplanamiento del Flujo de Control | transforms/controlFlowFlattening.ts | Convierte cuerpos de funciones en máquinas de estado while(true) { switch((_s * P) % M) { ... } } con despacho aritmético modular: los valores de caso se codifican mediante (stateId * multiplier) % modulus usando parámetros primos aleatorios. [Paper 3] |
| 5 | Predicados Opacos | transforms/opaquePredicates.ts | Inyecta condiciones if que siempre se evalúan como verdadero o falso pero son matemáticamente difíciles de probar (p. ej., (x*x+x)%2===0). 15 fórmulas de predicados en categorías de aritmética modular, bit a bit y comprobación de tipos. |
| 6 | Funciones Proxy | transforms/proxyFunctions.ts | Enruta todas las llamadas a funciones a través de dos despachadores: _fc(fn, ...args) para llamadas simples, _mc(obj, prop, ...args) para llamadas a métodos. Utiliza Function.prototype.apply capturado en una variable local para mayor resistencia. |
| 7 | Agotamiento de la Ventana de Contexto | transforms/contextExhaustion.ts | Envuelve expresiones en ternarios profundamente anidados con condiciones opacas, cadenas de expresiones void y relleno condicional void. Obliga a los LLMs a desperdiciar tokens de la ventana de contexto en ruido. |
| 8 | Fusión de Expresiones Coma | transforms/commaExpressions.ts | Colapsa sentencias de expresión consecutivas en expresiones coma únicas: a(); b(); return c() se convierte en return a(), b(), c(). |
| Orden | Paso | Archivo | Descripción |
|---|---|---|---|
| 9 | Paso 1: Catálogo | passes/firstPass.ts | Recorre el AST y cataloga cada identificador, construyendo un mapa de globales que asigna a cada uno un nombre Unicode aleatorio de 6 a 16 caracteres extraído de 16 rangos de escritura (CJK, Hangul, Griego, Cirílico, Devanagari, Tailandés, Árabe, Katakana, etc.). |
| 10 | Paso 2: Sustituir | passes/secondPass.ts | Reemplaza todos los nombres de identificadores con sus equivalentes Unicode ofuscados. Codifica los argumentos de require() como String.fromCharCode(...). Codifica las fuentes estáticas de import/export como literales de cadena con escape Unicode. Sustituye referencias de superClass en clases, expresiones de literales de plantilla, patrones de desestructuración. |
| 11 | Paso 3: Parámetros Ficticios | passes/thirdPass.ts | Inyecta de 0 a 15 parámetros aleatorios no utilizados en cada declaración y expresión de función. Omite funciones con parámetros rest. Elimina todos los comentarios. |