
Statisches Deobfuskierungs-Toolkit für kompilierten V8-JavaScript-Bytecode, mit Schwerpunkt auf JSCeal-Payloads. Bietet musterbasierte Filter, Entflachung des Kontrollflusses, String-Rekonstruktion und optionale LLM-gestützte Funktionsumbenennung für die Analyse.
Dieses Tool dient der statischen Deobfuskierung kompilierter V8-JavaScript-Bytecodes, die mit javascript-obfuscator geschützt wurden.
Es arbeitet mit Pseudocode, der von View8 erzeugt wird, und nicht mit dem ursprünglichen JavaScript-Quellcode. Das Projekt wurde an JSCeal-Payloads entwickelt und getestet.
Die Filter sind musterorientiert und in erster Linie als Forschungswerkzeug und Referenzimplementierung gedacht. Das Tool ist kein universeller JavaScript-Deobfuskator, rekonstruiert nicht den ursprünglichen Quellcode und erzeugt kein ausführbares JavaScript. Seine Ausgabe bleibt View8-Pseudocode, der für statische Inspektion, Suche, Vergleich und den Export von Funktionsbäumen gedacht ist.
pickle. Das Laden einer bösartigen oder nicht vertrauenswürdigen .pkl-Datei kann Code ausführen. Laden Sie nur serialisierte Dateien, die Sie lokal mit View8 erzeugt haben.requirements.txt;brotli für den Linux-Stapel-Entpackungs-Workflow;Erstellen Sie eine isolierte Python-Umgebung:
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
Das OpenAI-Backend in deobf_ai.py erfordert zusätzlich das OpenAI-Python-Paket:
python3 -m pip install openai
Das Anthropic-Backend verwendet die HTTP-API über requests. Das Ollama-Backend erwartet einen erreichbaren Ollama-Server.
Der ursprüngliche JSCeal-app.jsc-Payload ist Brotli-komprimiert. Unter Linux kann er mit dem Dienstprogramm brotli dekomprimiert werden:
brotli -d app.jsc -o app.decompressed.jsc
Der Stapel-Workflow unter scripts/ führt diesen Schritt mit scripts/unpack_all.sh aus.
Unter Windows oder wenn das Befehlszeilenprogramm brotli nicht verfügbar ist, kann der enthaltene Node.js-Helfer als Fallback verwendet werden. Er dekomprimiert nur die Eingabe und führt sie nicht aus:
node Utils/decompress-jsc.js app.jsc
Er schreibt:
app.jsc.decompressed.jsc
Der V8-Code-Cache ist versionsspezifisch. Verwenden Sie einen Disassembler, der für dieselbe V8-Version wie der Payload erstellt wurde.
Die während der Entwicklung verwendeten JSCeal-Beispiele basierten auf V8 10.2.154.26. Standard-Disassembler aus einem nicht verwandten V8-Build funktionieren nicht korrekt.
Der Quellbaum enthält den Disassembler-Quellcode und die erforderlichen V8-Patches unter:
Utils/disasm/v8dasm.cpp
Utils/disasm/patches/
Ein vorgefertigtes Linux-Binary wird mit der Projektversion verteilt, während der Quellbaum den Quellcode und die Patches enthält, die für einen Neubau erforderlich sind. Eine detaillierte Beschreibung finden Sie im Projekt-Wiki. Nachdem Sie das passende v8dasm erhalten oder erstellt haben, führen Sie Folgendes aus:
/path/to/v8dasm app.decompressed.jsc > app.jsc.disasm.txt
Führen Sie die disassemblierte Datei view8.py zu und erzeugen Sie sowohl serialisierte Ausgabe für die weitere Verarbeitung als auch menschenlesbaren Pseudocode:
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
Dies erzeugt:
decompiled/app.dec.txt
decompiled/app.dec.pkl
Die Option --normalize macht generierte Funktionskennungen über wiederholte Disassemblierungs- und Dekompilierungsläufe hinweg reproduzierbar.
Es gibt separate Filter für die einzelnen Obfuskierungsebenen. Sie können zusammen auf die serialisierte View8-Ausgabe mit deobf_all.py angewendet werden:
mkdir -p deobfuscated
python3 deobf_all.py \
--inp decompiled/app.dec.pkl \
--out deobfuscated/app.deobf.txt \
--export_format decompiled serialized
Der Standard-Zeichenkettenfilter ist Variante 2, die von der Mehrheit der analysierten JSCeal-Payloads verwendet wird. Um das einfachere Zeichenkettenschema explizit auszuwählen, fügen Sie hinzu:
--str_deobf 1
Typische Ausgaben sind:
deobfuscated/app.deobf.txt
deobfuscated/app.deobf.pkl
deobfuscated/app.deobf.txt.strings.txt
decompiled/app.dec.resolved_funcs.csv
Die CSV-Datei der aufgelösten Funktionen ist ein beispielspezifischer Cache. Wenn sie fehlt, stellt der Zeichenketten-Pass die erforderliche Decoder-Konfiguration wieder her, schreibt die CSV und fährt im selben Lauf mit der Deobfuskierung der Zeichenketten fort. Spätere Läufe verwenden den Cache erneut und sind normalerweise schneller.
Verwenden Sie eine CSV-Datei aufgelöster Funktionen nicht mit einem anderen dekompilierten Payload wieder.
Nachdem alle strukturellen Deobfuskierungsfilter angewendet wurden, kann deobf_ai.py Namen vorschlagen, die das Funktionsverhalten beschreiben. Es unterstützt Anthropic-, OpenAI- und Ollama-Backends.
Übergeben Sie das Modell explizit, damit Läufe reproduzierbar bleiben.
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
Im Standardmodus erstellt der Umbenenner einen Direktaufruf-Baum, der von der Einstiegsfunktion ausgeht, und benennt nur Funktionen um, die über Aufrufe erreicht werden. Fügen Sie --greedy hinzu, um alle sichtbaren Funktionsreferenzen einzuschließen, einschließlich Callbacks und zugewiesener Handler.
Die erzeugte zweispaltige CSV dient als Cache und ermöglicht die Fortsetzung eines unterbrochenen Laufs. Wählen Sie einen vorhandenen Cache explizit mit --csv aus:
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