
Kit de desofuscación estática para bytecode de JavaScript V8 compilado, centrado en cargas útiles de JSCeal. Proporciona filtros basados en patrones, aplanamiento inverso del flujo de control, reconstrucción de cadenas y renombrado opcional de funciones asistido por LLM para el análisis.
Esta herramienta está dedicada a desofuscar estáticamente el bytecode de JavaScript V8 compilado que fue protegido con javascript-obfuscator.
Opera sobre el pseudocódigo producido por View8, en lugar de sobre el código fuente JavaScript original. El proyecto fue desarrollado y probado con payloads de JSCeal.
Los filtros están basados en patrones y están pensados principalmente como un kit de herramientas de investigación y una implementación de referencia. La herramienta no es un desofuscador de JavaScript de propósito general, no reconstruye el código fuente original y no produce JavaScript ejecutable. Su salida sigue siendo pseudocódigo de View8 destinado a inspección estática, búsqueda, comparación y exportación de árboles de funciones.
pickle de Python. Cargar un archivo .pkl malicioso o no confiable puede ejecutar código. Solo carga archivos serializados que hayas generado localmente con View8.requirements.txt;brotli para el flujo de trabajo de desempaquetado por lotes en Linux;Crea un entorno de Python aislado:
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
El backend de OpenAI en deobf_ai.py requiere adicionalmente el paquete de Python de OpenAI:
python3 -m pip install openai
El backend de Anthropic usa la API HTTP a través de requests. El backend de Ollama espera un servidor de Ollama accesible.
El payload original app.jsc de JSCeal está comprimido con Brotli. En Linux, se puede descomprimir con la utilidad brotli:
brotli -d app.jsc -o app.decompressed.jsc
El flujo de trabajo por lotes bajo scripts/ realiza este paso con scripts/unpack_all.sh.
En Windows, o cuando la utilidad de línea de comandos brotli no esté disponible, se puede usar el helper de Node.js incluido como respaldo. Solo descomprime la entrada y no la ejecuta:
node Utils/decompress-jsc.js app.jsc
Escribe:
app.jsc.decompressed.jsc
La caché de código V8 es específica de la versión. Usa un desensamblador construido para la misma versión de V8 que el payload.
Las muestras de JSCeal utilizadas durante el desarrollo estaban basadas en V8 10.2.154.26. Los desensambladores predeterminados de una compilación de V8 no relacionada no funcionarán correctamente.
El árbol de fuentes contiene el código fuente del desensamblador y los parches de V8 requeridos bajo:
Utils/disasm/v8dasm.cpp
Utils/disasm/patches/
Un binario de Linux precompilado se distribuye con el lanzamiento del proyecto, mientras que el árbol de fuentes contiene el código fuente y los parches necesarios para recompilarlo. Hay una descripción detallada disponible en el Wiki del proyecto. Después de obtener o construir el v8dasm coincidente, ejecuta:
/path/to/v8dasm app.decompressed.jsc > app.jsc.disasm.txt
Alimenta el archivo desensamblado a view8.py y produce tanto la salida serializada para procesamiento posterior como el pseudocódigo legible por humanos:
mkdir -p decompiled
python3 View8/view8.py \
--input_format disassembled \
--inp app.jsc.disasm.txt \
--normalize \
--out decompiled/app.dec.txt \
--export_format decompiled serialized
Esto produce:
decompiled/app.dec.txt
decompiled/app.dec.pkl
La opción --normalize hace que los identificadores de funciones generados sean reproducibles entre ejecuciones repetidas de desensamblado y descompilación.
Hay filtros separados para las capas individuales de ofuscación. Se pueden aplicar juntos a la salida serializada de View8 con deobf_all.py:
mkdir -p deobfuscated
python3 deobf_all.py \
--inp decompiled/app.dec.pkl \
--out deobfuscated/app.deobf.txt \
--export_format decompiled serialized
El filtro de cadenas predeterminado es la variante 2, utilizada por la mayoría de los payloads de JSCeal analizados. Para seleccionar explícitamente el esquema de cadenas más simple, agrega:
--str_deobf 1
Las salidas típicas son:
deobfuscated/app.deobf.txt
deobfuscated/app.deobf.pkl
deobfuscated/app.deobf.txt.strings.txt
decompiled/app.dec.resolved_funcs.csv
El CSV de funciones resueltas es una caché específica de la muestra. Cuando está ausente, la pasada de cadenas recupera la configuración del decodificador requerida, escribe el CSV y continúa desofuscando cadenas en la misma ejecución. Las ejecuciones posteriores reutilizan la caché y normalmente son más rápidas.
No reutilices un CSV de funciones resueltas con un payload descompilado diferente.
Después de que se hayan aplicado todos los filtros de desofuscación estructural, deobf_ai.py puede proponer nombres que describan el comportamiento de las funciones. Soporta backends de Anthropic, OpenAI y Ollama.
Pasa el modelo explícitamente para que las ejecuciones sean reproducibles.
export ANTHROPIC_API_KEY='...'
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--llm_backend anthropic \
--model '<model-id>' \
--export_format decompiled serialized
export OPENAI_API_KEY='...'
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--llm_backend openai \
--model '<model-id>' \
--export_format decompiled serialized
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--llm_backend ollama \
--model '<local-model>' \
--ollama_url http://localhost:11434 \
--export_format decompiled serialized
En el modo predeterminado, el renombrador construye un árbol de llamadas directas comenzando desde la función de entrada y renombra solo las funciones alcanzadas a través de llamadas. Agrega --greedy para incluir todas las referencias de funciones visibles, incluyendo callbacks y handlers asignados.
El CSV de dos columnas generado actúa como una caché y permite que una ejecución interrumpida continúe. Selecciona una caché existente explícitamente con --csv:
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--csv deobfuscated/app.deobf.renamed_funcs.greedy.example-model.csv \
--llm_backend anthropic \
--model '<model-id>' \
--greedy \
--export_format decompiled serialized