
Декомпилирует сериализованный байт-код V8 (файлы JSC) в высокоуровневый читаемый код, похожий на JavaScript, с поддержкой нескольких версий V8, древовидного вывода и детерминированных имён функций для анализа вредоносного ПО.
View8 — это инструмент статического анализа, предназначенный для декомпиляции сериализованных объектов байт-кода V8 (файлов JSC) в высокоуровневый читаемый код. Для разбора и дизассемблирования этих сериализованных объектов View8 использует пропатченный скомпилированный бинарный файл V8. В результате View8 создаёт текстовый вывод, похожий на JavaScript.
9.4.146.24 (используется в Node V16.x)10.2.154.26 (используется в Node V18.x)11.3.244.8 (используется в Node V20.x)Скомпилированные версии доступны на странице релизов.
--inp, : Имя входного файла.-i--out, -o: Путь к выходному файлу. В зависимости от выбранных опций вывод может представлять собой один файл или дерево каталогов.--input_format, -f: Укажите формат входных данных. Варианты:
raw: входные данные — это необработанный файл JSC.disassembled: входной файл уже дизассемблирован.serialized: входные данные уже декомпилированы и сохранены в сериализованном формате. Текущий сериализованный формат — Python pickle; используйте только доверенные входные данные.--export_format, -e: Укажите формат(ы) экспорта. Варианты: v8_opcode, translated, decompiled и serialized. Можно комбинировать несколько вариантов. По умолчанию: decompiled.--path, -p: Путь к бинарному файлу дизассемблера. Требуется, если входные данные имеют необработанный формат и View8 не может автоматически найти подходящий дизассемблер.--scope: Распространять аргументы области видимости. По умолчанию: 1.--normalize: Заменить идентификаторы функций, производные от адресов, детерминированными именами на основе порядка разбора.--normalize-map [CSV]: При использовании --normalize записать CSV-файл с сопоставлением каждого исходного имени функции с её нормализованным именем. Если путь опущен, View8 формирует <output>.name_map.csv из --out или из --inp, если путь вывода не задан.--tree, -t: Разделить вывод на структуру дерева вместо хранения всех функций в одном файле. Укажите функцию, которая будет использоваться как корень дерева. Чтобы начать с основной функции по умолчанию, используйте start.--split_mode: Режим разделения дерева. Варианты: declarers, calls и references. По умолчанию: declarers.--inline_depth, -d: В режимах calls и references включает функции, достижимые из выбранного корня дерева, на глубину до N в главный файл дерева. Глубина 0 означает только выбранный корень; глубина 1 включает прямые вызовы/ссылки; глубина 2 включает их дочерние элементы. Не используется с declarers.--inline_branch_limit, -l: В режиме дерева включает полные дочерние ветви, содержащие не более N функций, в главный файл дерева, когда дочерние ветви включены параметром --inline_depth. Более крупные ветви сохраняются отдельно.--split_depth: В режимах calls и references ограничивает глубину обхода экспортируемых ветвей использования. По умолчанию: 4.--include, -n: Файл, содержащий функции для включения в вывод.--exclude, -x: Файл, содержащий функции для исключения из вывода.--func: Отобразить выбранную функцию.--show_all: В режиме отображения функции также показывать строки, помеченные как скрытые.--verbosity, -v: Уровень подробности вывода. Допустимый диапазон: от 0 до 3.Чтобы декомпилировать файл байт-кода V8 и экспортировать декомпилированный код:
python view8.py -i input_file -o output_fileПо умолчанию View8 определяет версию байт-кода V8 входного файла с помощью VersionDetector.exe и автоматически ищет совместимый бинарный файл дизассемблера в папке Bin. Это можно изменить, указав другой бинарный файл дизассемблера с помощью опции --path или -p:
python view8.py -i input_file -o output_file --path /path/to/disassemblerЧтобы пропустить процесс дизассемблирования и передать уже дизассемблированный файл в качестве входных данных, используйте опцию --input_format disassembled или -f disassembled:
python view8.py -i input_file -o output_file -f disassembledИспользуйте --normalize, чтобы заменить имена функций, производные от адресов, детерминированными идентификаторами. Чтобы сохранить связь между исходными и нормализованными именами, добавьте --normalize-map:
python view8.py \
--input_format disassembled \
--inp sample.jsc.disasm.txt \
--normalize \
--normalize-map \
--out decompiled/sample.dec.txt \
--export_format decompiled serializedЭто создаст файл decompiled/sample.dec.name_map.csv со следующими столбцами:
original_name,normalized_name
func_start_0x268514e9dcd9,func_start_0x100000000
func_rne_0x268514eb0779,func_rne_0x100000001Также можно указать явный путь к CSV-файлу:
python view8.py \
--input_format disassembled \
--inp sample.jsc.disasm.txt \
--normalize \
--normalize-map mappings/sample.names.csv \
--out decompiled/sample.dec.txtИногда полезно декомпилировать файл в сериализованный формат, который сохраняет разобранные объекты и структуры. Такой тип вывода может быть проще для постобработки, чем текстовый формат, например, при дальнейшей деобфускации. Чтобы создать сериализованный вывод, используйте формат экспорта serialized:
python view8.py -i input_file -o output_file -e serializedПредупреждение о безопасности: текущий сериализованный формат — это файл Python pickle (.pkl). Распаковка данных из ненадёжных источников может выполнить произвольный код. Загружайте только те сериализованные файлы, которые вы создали сами.
Чтобы загрузить сериализованный вывод обратно и экспортировать его в другом формате, используйте --input_format serialized или -f serialized:
python view8.py -i input_file -o output_file -f serializedУкажите формат(ы) экспорта с помощью опции --export_format или -e. Можно комбинировать несколько форматов:
v8_opcodetranslateddecompiledserializedНапример, чтобы экспортировать и V8-опкоды, и декомпилированный код рядом:
python view8.py -i input_file -o output_file -e v8_opcode decompiledПо умолчанию используется формат decompiled.
Для больших объединённых полезных нагрузок запись всех декомпилированных функций в один файл может затруднить анализ. Древовидный вывод разделяет выбранный корень и связанные функции на структуру каталогов.
Используйте --tree, чтобы выбрать корень дерева:
python view8.py \
--inp input.pkl \
--input_format serialized \
--out ./tree_out/ \
--tree startСпециальное значение start означает основную функцию по умолчанию, восстановленную View8.
Дерево можно разделить одним из трёх режимов:
declarers: отслеживает лексические отношения объявления, то есть какие функции объявлены внутри или под другой функцией. Это полезно для понимания объединённой или модульной структуры, но не отражает поток выполнения.calls: отслеживает прямые вызовы функций, например func_x(...). Это полезно для восстановления скелета выполнения из выбранного корня.references: отслеживает все видимые ссылки на функции, а не только прямые вызовы. Это включает колбэки, экспортированные обработчики, обработчики маршрутов, свойства объектов и другие назначенные функции. Этот режим полезен для обнаружения поверхностей возможностей, но может создавать гораздо более крупные деревья, чем calls.Пример:
python view8.py \
--inp input.pkl \
--input_format serialized \
--out ./tree_calls/ \
--tree start \
--split_mode callsГлавный файл дерева всегда содержит выбранную корневую функцию.
В режимах calls и references параметр --inline_depth управляет тем, сколько уровней графа включается в главный файл:
--inline_depth 0 -> только корень
--inline_depth 1 -> корень + прямые вызовы/ссылки
--inline_depth 2 -> корень + прямые вызовы/ссылки + их дочерние элементыНапример, следующая команда создаёт компактный обзор выполнения, содержащий корень и его прямые вызовы:
python view8.py \
--inp input.pkl \
--input_format serialized \
--out ./tree_calls/ \
--tree start \
--split_mode calls \
--inline_depth 1Чтобы включить один дополнительный уровень вызовов:
python view8.py \
--inp input.pkl \
--input_format serialized \
--out ./tree_calls/ \
--tree start \
--split_mode calls \
--inline_depth 2--inline_depth поддерживается только в режимах calls и references. Он не используется с declarers.
Крупные дочерние ветви сохраняются в отдельные файлы. В режимах calls и references параметр --split_depth управляет глубиной обхода экспортируемых ветвей использования:
python view8.py \
--inp input.pkl \
--input_format serialized \
--out ./tree_calls/ \
--tree start \
--split_mode calls \
--inline_depth 1 \
--split_depth 5Опция --inline_branch_limit управляет тем, включаются ли небольшие полные дочерние ветви также в главный файл:
--inline_branch_limit 3Это означает, что полные дочерние ветви, содержащие не более 3 функций, могут быть встроены в главный файл. Более крупные ветви сохраняются отдельно.
В режимах calls и references дочерние ветви встраиваются только тогда, когда выбранный --inline_depth уже включает дочерние функции. Например, --inline_depth 0 означает только корень, поэтому дочерние ветви не встраиваются, даже если они небольшие.
Для компактного обзора выполнения:
python view8.py \
--inp input.pkl \
--input_format serialized \
--out ./tree_calls/ \
--tree start \
--split_mode calls \
--inline_depth 1 \
--split_depth 5Для более широкого архитектурного обзора:
python view8.py \
--inp input.pkl \
--input_format serialized \
--out ./tree_calls/ \
--tree start \
--split_mode calls \
--inline_depth 2 \
--split_depth 5Для экспортированных колбэков, обработчиков, маршрутов и поверхностей возможностей:
python view8.py \
--inp input.pkl \
--input_format serialized \
--out ./tree_refs/ \
--tree start \
--split_mode references \
--inline_depth 1 \
--split_depth 3Для лексической или модульной структуры:
python view8.py \
--inp input.pkl \
--input_format serialized \
--out ./tree_declarers/ \
--tree start \
--split_mode declarers \
--split_depth 3Чтобы отобразить выбранную функцию, используйте --func:
python view8.py \
--inp input.pkl \
--input_format serialized \
--func func_nameЧтобы также показать строки, помеченные как скрытые:
python view8.py \
--inp input.pkl \
--input_format serialized \
--func func_name \
--show_allВерсия байт-кода V8 хранится в виде хеша в начале файла. Ниже приведены доступные опции для VersionDetector.exe:
-h: Получает версию и возвращает её хеш.-d: Получает хеш в формате little-endian и возвращает соответствующую версию методом перебора.-f: Получает файл и возвращает его версию.