View8
is a static analysis tool designed to decompile serialized V8 bytecode objects (JSC files) into high-level readable code. To parse and disassemble these serialized objects, View8 utilizes a patched compiled V8 binary. As a result, View8 produces a textual output similar to JavaScript.
9.4.146.24
(Used in Node V16.x)10.2.154.26
(Used in Node V18.x)11.3.244.8
(Used in Node V20.x)For compiled versions, visit the releases page.
input_file
: The input file name.output_file
: The output file name.--path
, -p
: Path to disassembler binary (optional).--disassembled
, -d
: Indicate if the input file is already disassembled (optional).--export_format
, -e
: Specify the export format(s). Options are v8_opcode
, translated
, and decompiled
. Multiple options can be combined (optional, default: decompiled
).To decompile a V8 bytecode file and export the decompiled code:
python view8.py input_file output_file
By default, view8
detects the V8 bytecode version of the input file (using VersionDetector.exe
) and automatically searches for a compatible disassembler binary in the Bin
folder. This can be changed by specifing a different disassembler binary, use the --path
(or -p
) option:
python view8.py input_file output_file --path /path/to/disassembler
To skip the disassembling process and provide an already disassembled file as the input, use the --disassembled
(or -d
) flag:
python view8.py input_file output_file --disassembled
Specify the export format(s) using the --export_format
(or -e
) option. You can combine multiple formats:
v8_opcode
translated
decompiled
For example, to export both V8 opcodes and decompiled code side by side:
python view8.py input_file output_file -e v8_opcode decompiled
By default, the format used is decompiled
.
The V8 bytecode version is stored as a hash at the beginning of the file. Below are the options available for VersionDetector.exe
:
-h
: Retrieves a version and returns its hash.-d
: Retrieves a hash (little-endian) and returns its corresponding version using brute force.-f
: Retrieves a file and returns its version.Guide/disassembler/patch based on v8dasm and https://github.com/v8/v8/tree/10.6.194.26.
The disassembler can be built to be compatible with either Node or Electron (depending on how the .jsc
file was generated).
The v8 version of a .jsc
file can be found using https://j4k0xb.github.io/v8-version-analyzer, but sometimes Node or Electron create their own custom versions. In that case just choose the closest one.
Check out your v8 version: https://v8.dev/docs/source-code
Apply the patch:
git apply -3 v8.patch
And resolve any conflicts that may occur in different versions.
Create a build configuration:
./tools/dev/v8gen.py x64.release
Edit the build flags in out.gn/x64.release/args.gn
:
dcheck_always_on = false
is_component_build = false
is_debug = false
target_cpu = "x64"
use_custom_libcxx = false
v8_monolithic = true
v8_use_external_startup_data = false
v8_static_library = true
v8_enable_disassembler = true
v8_enable_object_print = true
v8_enable_pointer_compression = false
Build the static library:
ninja -C out.gn/x64.release v8_monolith
Compile the disassembler:
For Node:
clang++ v8dasm.cpp -g -std=c++17 -Iinclude -Lout.gn/x64.release/obj -lv8_libbase -lv8_libplatform -lv8_monolith -o v8dasm
For Electron:
clang++ v8dasm.cpp -g -std=c++17 -Iinclude -Lout.gn/x64.release/obj -lv8_libbase -lv8_libplatform -lv8_monolith -o v8dasm -DV8_COMPRESS_POINTERS