suleram / View8

View8 - Decompiles serialized V8 objects back into high-level readable code.
157 stars 18 forks source link

About Reproducibility and Disassembler Binaries in Repository #1

Open wowshy opened 4 months ago

wowshy commented 4 months ago

How is the executable generated?

j4k0xb commented 4 months ago

Also consider using a python C extension module for the version detector instead of a pre-compiled binary so it's compatible with all operating systems. Or hashing the existing ~232 v8 versions directly in python (here's how I did it: https://github.com/j4k0xb/v8-version-analyzer/blob/2d36fc52d488f3913c0d9bba6db47126bba8ad7c/assets/analyzer.js)

suleram commented 4 months ago

Hi @wowshy, I will upload the patches for the V8 project in the coming days to replicate it for more versions. In the meantime, you might find it helpful to familiarize yourself with the process of compiling the V8 project. Here are some useful links for Windows:

https://gist.github.com/jhalon/5cbaab99dccadbf8e783921358020159 https://medium.com/angular-in-depth/how-to-build-v8-on-windows-and-not-go-mad-6347c69aacd4

Also, note that very similar versions can be used with the same disassembler by using the --path argument to the similar version.

The reason the disassembler binaries are not kept in the BIN folder alongside VersionDetector.exe is to avoid the need to download unnecessary files with each clone (potentially adding more and more disassembler versions).

suleram commented 4 months ago

@j4k0xb Thank you for the advice. I'll consider changing it according to your suggestion.

zzzwwolf commented 4 months ago

Hi @wowshy, I will upload the patches for the V8 project in the coming days to replicate it for more versions. In the meantime, you might find it helpful to familiarize yourself with the process of compiling the V8 project. Here are some useful links for Windows:

Hi wowshy, can you please upload the patch that you use?

wowshy commented 4 months ago

No I do not have the patch. I came from this article https://research.checkpoint.com/2024/exploring-compiled-v8-javascript-usage-in-malware/

j4k0xb commented 3 months ago

I will upload the patches for the V8 project in the coming days to replicate it for more versions

Hey, any news on this? I tried replicating it with https://github.com/v8/v8/tree/11.3.244.8 and https://github.com/noelex/v8dasm but it fails to deserialize the .jsc file (kMagicNumber mismatch despite being the same version). Even when compiling v8 straight from https://github.com/nodejs/node/tree/v20.10.0/deps/v8

v8 patch to enable disassembling:

diff --git a/src/diagnostics/objects-printer.cc b/src/diagnostics/objects-printer.cc
index 30d8095f62a..da51919111c 100644
--- a/src/diagnostics/objects-printer.cc
+++ b/src/diagnostics/objects-printer.cc
@@ -1843,6 +1843,13 @@ void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) {
   } else {
     os << "<none>";
   }
+
+  os << "\n; #region SharedFunctionInfoDisassembly\n";
+  if (this->HasBytecodeArray()) {
+      this->GetBytecodeArray(isolate).Disassemble(os);
+      os << std::flush;
+  }
+  os << "; #endregion";
   os << "\n";
 }

diff --git a/src/objects/objects.cc b/src/objects/objects.cc
index 43ea4a73502..8452d5ef404 100644
--- a/src/objects/objects.cc
+++ b/src/objects/objects.cc
@@ -1828,6 +1828,8 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) {
     os << accumulator.ToCString().get();
     return;
   }
+
+  size_t len;
   switch (map(cage_base).instance_type()) {
     case MAP_TYPE: {
       os << "<Map";
@@ -1913,11 +1915,27 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) {
          << "]>";
       break;
     case FIXED_ARRAY_TYPE:
-      os << "<FixedArray[" << FixedArray::cast(*this).length() << "]>";
+      len = FixedArray::cast(*this).length();
+      os << "<FixedArray[" << len << "]>";
+
+      if (len) {
+          os << "\nStart FixedArray\n";
+          FixedArray::cast(*this).FixedArrayPrint(os);
+          os << "End FixedArray";
+      }
+
       break;
     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
-      os << "<ObjectBoilerplateDescription[" << FixedArray::cast(*this).length()
-         << "]>";
+      len = FixedArray::cast(*this).length();
+      os << "<ObjectBoilerplateDescription[" << len << "]>";
+
+      if (len) {
+          os << "\nStart ObjectBoilerplateDescription\n";
+          ObjectBoilerplateDescription::cast(*this).
+          ObjectBoilerplateDescriptionPrint(os);
+          os << "End ObjectBoilerplateDescription";
+      }
+
       break;
     case FIXED_DOUBLE_ARRAY_TYPE:
       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(*this).length()
diff --git a/src/snapshot/code-serializer.cc b/src/snapshot/code-serializer.cc
index c83e8e4581a..2b36d1e5504 100644
--- a/src/snapshot/code-serializer.cc
+++ b/src/snapshot/code-serializer.cc
@@ -447,6 +447,11 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
     return MaybeHandle<SharedFunctionInfo>();
   }

+  std::cout << "Start SharedFunctionInfo\n";
+  result->GetBytecodeArray(isolate).Disassemble(std::cout);
+  std::cout << "End SharedFunctionInfo\n";
+  std::cout << std::flush;
+
   // Check whether the newly deserialized data should be merged into an
   // existing Script from the Isolate compilation cache. If so, perform
   // the merge in a single-threaded manner since this deserialization was

disassembler:

#include <fstream>
#include <iostream>
#include <string>

#include "include/libplatform/libplatform.h"
#include "include/v8.h"

#pragma comment(lib, "v8_libbase.lib")
#pragma comment(lib, "v8_libplatform.lib")
#pragma comment(lib, "wee8.lib")

#pragma comment(lib, "secur32.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "dmoguids.lib")
#pragma comment(lib, "wmcodecdspuuid.lib")
#pragma comment(lib, "msdmo.lib")
#pragma comment(lib, "Strmiids.lib")
#pragma comment(lib, "DbgHelp.lib")

static v8::Isolate* isolate = nullptr;

static v8::ScriptCompiler::CachedData* compileCode(const char* data) {
  auto str = v8::String::NewFromUtf8(isolate, data).ToLocalChecked();
  auto script =
      v8::Script::Compile(isolate->GetCurrentContext(), str).ToLocalChecked();
  auto unboundScript = script->GetUnboundScript();

  return v8::ScriptCompiler::CreateCodeCache(unboundScript);
}

static void fixBytecode(uint8_t* bytecodeBuffer, const char* code) {
  auto* dummyBytecode = compileCode(code);

  // Copy version hash, source hash and flag hash from dummy bytecode to source
  // bytecode. Offsets of these value may differ in different version of V8.
  // Refer V8 src/snapshot/code-serializer.h for details.
  for (int i = 4; i < 16; i++) {
    bytecodeBuffer[i] = dummyBytecode->data[i];
  }
  delete dummyBytecode;
}

static void runBytecode(uint8_t* bytecodeBuffer, int len) {
  // Compile some dummy code to get version hash, source hash and flag hash.
  const char* code = "\"ಠ_ಠ\"";
  fixBytecode(bytecodeBuffer, code);

  // Load code into code cache.
  auto* cached_data = new v8::ScriptCompiler::CachedData(bytecodeBuffer, len);

  // Create dummy source.
  v8::ScriptOrigin origin(isolate,
                          v8::String::NewFromUtf8Literal(isolate, "code.jsc"));
  v8::ScriptCompiler::Source source(
      v8::String::NewFromUtf8(isolate, code).ToLocalChecked(), origin,
      cached_data);

  // Compile code from code cache to print disassembly.
  v8::MaybeLocal<v8::UnboundScript> v8_script =
      v8::ScriptCompiler::CompileUnboundScript(
          isolate, &source, v8::ScriptCompiler::kConsumeCodeCache);
}

static void readAllBytes(const std::string& file, std::vector<char>& buffer) {
  std::ifstream infile(file, std::ios::binary);

  infile.seekg(0, infile.end);
  size_t length = infile.tellg();
  infile.seekg(0, infile.beg);

  if (length > 0) {
    buffer.resize(length);
    infile.read(&buffer[0], length);
  }
}

int main(int argc, char* argv[]) {
  // Set flags here, flags that affects code generation and serialization
  // should be same as the target program. You can add other flags freely
  // because flag hash will be overriden in fixBytecode().
  v8::V8::SetFlagsFromString("--no-lazy --no-flush-bytecode --log-all --profile_deserialization");

  v8::V8::InitializeICU();
  auto platform = v8::platform::NewDefaultPlatform();
  v8::V8::InitializePlatform(platform.get());
  v8::V8::Initialize();

  v8::Isolate::CreateParams create_params;
  create_params.array_buffer_allocator =
      v8::ArrayBuffer::Allocator::NewDefaultAllocator();

  isolate = v8::Isolate::New(create_params);
  {
    v8::Isolate::Scope isolate_scope(isolate);
    v8::HandleScope scope(isolate);
    auto ctx = v8::Context::New(isolate);
    v8::Context::Scope context_scope(ctx);

    std::vector<char> data;
    readAllBytes(argv[1], data);
    runBytecode((uint8_t*)data.data(), data.size());
  }
}

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
silverwolfceh commented 3 months ago

@j4k0xb maybe the result of your disassembler different with the pre-built disassembler. Did you test it? (just do disassembler)

kiwina commented 3 months ago

@j4k0xb the patch will not work on the version you mentioned 11.3.244.8 as the code has changed

j4k0xb commented 3 months ago

the patch will not work on the version you mentioned 11.3.244.8 as the code has changed

I already adapted it to that version. Got it working now by using the flags that node uses when building (pointer compression had to be disabled):

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

Updated patch:

diff --git a/src/objects/code.cc b/src/objects/code.cc
index 1ca28beb309..823ea11f311 100644
--- a/src/objects/code.cc
+++ b/src/objects/code.cc
@@ -779,6 +779,8 @@ void BytecodeArray::Disassemble(Handle<BytecodeArray> handle,
     iterator.Advance();
   }

+  os << AsHex::Address(handle->address()) << ": [SharedFunctionInfo] in idk\n";
+
   os << "Constant pool (size = " << handle->constant_pool().length() << ")\n";
 #ifdef OBJECT_PRINT
   if (handle->constant_pool().length() > 0) {
diff --git a/src/objects/objects.cc b/src/objects/objects.cc
index 43ea4a73502..2850dbbfef3 100644
--- a/src/objects/objects.cc
+++ b/src/objects/objects.cc
@@ -1828,6 +1828,8 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) {
     os << accumulator.ToCString().get();
     return;
   }
+
+  size_t len;
   switch (map(cage_base).instance_type()) {
     case MAP_TYPE: {
       os << "<Map";
@@ -1913,11 +1915,27 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) {
          << "]>";
       break;
     case FIXED_ARRAY_TYPE:
-      os << "<FixedArray[" << FixedArray::cast(*this).length() << "]>";
+      len = FixedArray::cast(*this).length();
+      os << "<FixedArray[" << len << "]>";
+
+      if (len) {
+          os << "\nStart FixedArray\n";
+          FixedArray::cast(*this).FixedArrayPrint(os);
+          os << "End FixedArray";
+      }
+
       break;
     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
-      os << "<ObjectBoilerplateDescription[" << FixedArray::cast(*this).length()
-         << "]>";
+      len = FixedArray::cast(*this).length();
+      os << "<ObjectBoilerplateDescription[" << len << "]>";
+
+      if (len) {
+          os << "\nStart ObjectBoilerplateDescription\n";
+          ObjectBoilerplateDescription::cast(*this).
+          ObjectBoilerplateDescriptionPrint(os);
+          os << "End ObjectBoilerplateDescription";
+      }
+
       break;
     case FIXED_DOUBLE_ARRAY_TYPE:
       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(*this).length()
@@ -2000,6 +2018,12 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) {
       } else {
         os << "<SharedFunctionInfo>";
       }
+      Isolate* isolate;
+      if (GetIsolateFromHeapObject(shared, &isolate)) {
+        os << "\nStart SharedFunctionInfo\n";
+        shared.GetBytecodeArray(isolate).Disassemble(os);
+        os << "End SharedFunctionInfo\n";
+      }
       break;
     }
     case JS_MESSAGE_OBJECT_TYPE:
diff --git a/src/snapshot/code-serializer.cc b/src/snapshot/code-serializer.cc
index c83e8e4581a..2b36d1e5504 100644
--- a/src/snapshot/code-serializer.cc
+++ b/src/snapshot/code-serializer.cc
@@ -447,6 +447,11 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
     return MaybeHandle<SharedFunctionInfo>();
   }

+  std::cout << "Start SharedFunctionInfo\n";
+  result->GetBytecodeArray(isolate).Disassemble(std::cout);
+  std::cout << "End SharedFunctionInfo\n";
+  std::cout << std::flush;
+
   // Check whether the newly deserialized data should be merged into an
   // existing Script from the Isolate compilation cache. If so, perform
   // the merge in a single-threaded manner since this deserialization was
g++ -g -I. -Iinclude v8dasm.cpp -o v8dasm -fno-rtti -lv8_monolith -lv8_libbase -lv8_libplatform -ldl -Lout.gn/x64.release/obj/ -pthread -std=c++17
./v8dasm index.jsc
Start SharedFunctionInfo
Parameter count 1
Register count 1
Frame size 8
Bytecode age: 0
    0 S> 0xf3b449e4dbe @    0 : 80 00 00 00       CreateClosure [0], [0], #0
         0xf3b449e4dc2 @    4 : c4                Star0
  272 S> 0xf3b449e4dc3 @    5 : a9                Return
0x0f3b449e4d88: [SharedFunctionInfo] in idk
Constant pool (size = 1)
0xf3b449e4dc9: [FixedArray] in OldSpace
 - map: 0x12d91b5c0211 <Map(FIXED_ARRAY_TYPE)>
 - length: 1
           0: 0x0f3b449e4de1 <SharedFunctionInfo>
Start SharedFunctionInfo
Parameter count 6
Register count 7
Frame size 56
Bytecode age: 0
   10 E> 0xf3b449e4e4e @    0 : 83 00 01          CreateFunctionContext [0], [1]
         0xf3b449e4e51 @    3 : 1a f8             PushContext r2
         0xf3b449e4e53 @    5 : 10                LdaTheHole
         0xf3b449e4e54 @    6 : 25 02             StaCurrentContextSlot [2]
   78 S> 0xf3b449e4e56 @    8 : 13 01             LdaConstant [1]
         0xf3b449e4e58 @   10 : c0                Star4
   78 E> 0xf3b449e4e59 @   11 : 62 04 f6 00       CallUndefinedReceiver1 a1, r4, [0]
         0xf3b449e4e5d @   15 : c4                Star0
  109 S> 0xf3b449e4e5e @   16 : 61 fa 02          CallUndefinedReceiver0 r0, [2]
         0xf3b449e4e61 @   19 : c3                Star1
  132 S> 0xf3b449e4e62 @   20 : 00 0d b8 0b       LdaSmi.Wide [3000]
  132 E> 0xf3b449e4e66 @   24 : 25 02             StaCurrentContextSlot [2]
  142 S> 0xf3b449e4e68 @   26 : 2d f9 02 04       GetNamedProperty r1, [2], [4]
         0xf3b449e4e6c @   30 : c1                Star3
         0xf3b449e4e6d @   31 : 13 03             LdaConstant [3]
         0xf3b449e4e6f @   33 : bf                Star5
         0xf3b449e4e70 @   34 : 80 04 00 02       CreateClosure [4], [0], #2
         0xf3b449e4e74 @   38 : be                Star6
  142 E> 0xf3b449e4e75 @   39 : 5f f7 f9 f5 f4 06 CallProperty2 r3, r1, r5, r6, [6]
  195 S> 0xf3b449e4e7b @   45 : 2d f9 05 08       GetNamedProperty r1, [5], [8]
         0xf3b449e4e7f @   49 : c1                Star3
         0xf3b449e4e80 @   50 : 17 02             LdaImmutableCurrentContextSlot [2]
         0xf3b449e4e82 @   52 : bf                Star5
  202 E> 0xf3b449e4e83 @   53 : 80 06 01 02       CreateClosure [6], [1], #2
         0xf3b449e4e87 @   57 : be                Star6
  195 E> 0xf3b449e4e88 @   58 : 5f f7 f9 f5 f4 0a CallProperty2 r3, r1, r5, r6, [10]
         0xf3b449e4e8e @   64 : 0e                LdaUndefined
  269 S> 0xf3b449e4e8f @   65 : a9                Return
0x0f3b449e4e18: [SharedFunctionInfo] in idk
Constant pool (size = 7)
0xf3b449e4e91: [FixedArray] in OldSpace
 - map: 0x12d91b5c0211 <Map(FIXED_ARRAY_TYPE)>
 - length: 7
           0: 0x0f3b449e4ed9 <ScopeInfo FUNCTION_SCOPE>
           1: 0x0f3b449e4f49 <String[7]: #express>
           2: 0x12d91b5c63d1 <String[3]: #get>
           3: 0x12d91b5c31e9 <String[1]: #/>
           4: 0x0f3b449e4f61 <SharedFunctionInfo>
Start SharedFunctionInfo
Parameter count 3
Register count 3
Frame size 24
Bytecode age: 0
  169 S> 0xf3b449e4fce @    0 : 2d 04 00 00       GetNamedProperty a1, [0], [0]
         0xf3b449e4fd2 @    4 : c4                Star0
         0xf3b449e4fd3 @    5 : 13 01             LdaConstant [1]
         0xf3b449e4fd5 @    7 : c2                Star2
  169 E> 0xf3b449e4fd6 @    8 : 5e fa 04 f8 02    CallProperty1 r0, a1, r2, [2]
  189 S> 0xf3b449e4fdb @   13 : a9                Return
0x0f3b449e4f98: [SharedFunctionInfo] in idk
Constant pool (size = 2)
0xf3b449e4fe1: [FixedArray] in OldSpace
 - map: 0x12d91b5c0211 <Map(FIXED_ARRAY_TYPE)>
 - length: 2
           0: 0x0f3b449e5001 <String[4]: #send>
           1: 0x0f3b449e5019 <String[12]: #Hello World!>
Handler Table (size = 0)
Source Position Table (size = 9)
0x0f3b449e5039 <ByteArray[9]>
End SharedFunctionInfo

           5: 0x0f3b449e5349 <String[6]: #listen>
           6: 0x0f3b449e51b1 <SharedFunctionInfo>
Start SharedFunctionInfo
Parameter count 1
Register count 3
Frame size 24
Bytecode age: 0
  222 S> 0xf3b449e521e @    0 : 21 00 00          LdaGlobal [0], [0]
         0xf3b449e5221 @    3 : c3                Star1
  222 E> 0xf3b449e5222 @    4 : 2d f9 01 02       GetNamedProperty r1, [1], [2]
         0xf3b449e5226 @    8 : c4                Star0
         0xf3b449e5227 @    9 : 13 02             LdaConstant [2]
         0xf3b449e5229 @   11 : c2                Star2
         0xf3b449e522a @   12 : 17 02             LdaImmutableCurrentContextSlot [2]
  259 E> 0xf3b449e522c @   14 : aa 03             ThrowReferenceErrorIfHole [3]
         0xf3b449e522e @   16 : 77                ToString
         0xf3b449e522f @   17 : 38 f8 04          Add r2, [4]
         0xf3b449e5232 @   20 : c2                Star2
         0xf3b449e5233 @   21 : 13 04             LdaConstant [4]
         0xf3b449e5235 @   23 : 38 f8 04          Add r2, [4]
         0xf3b449e5238 @   26 : c2                Star2
  222 E> 0xf3b449e5239 @   27 : 5e fa f9 f8 05    CallProperty1 r0, r1, r2, [5]
  267 S> 0xf3b449e523e @   32 : a9                Return
0x0f3b449e51e8: [SharedFunctionInfo] in idk
Constant pool (size = 5)
0xf3b449e5241: [FixedArray] in OldSpace
 - map: 0x12d91b5c0211 <Map(FIXED_ARRAY_TYPE)>
 - length: 5
           0: 0x12d91b5c5ce9 <String[7]: #console>
           1: 0x20a936c419b1 <String[3]: #log>
           2: 0x0f3b449e5291 <String[30]: #Example app listening on port >
           3: 0x0f3b449e4f31 <String[4]: #port>
           4: 0x12d91b5c3099 <String[1]: #!>
Handler Table (size = 0)
Source Position Table (size = 16)
0x0f3b449e52c1 <ByteArray[16]>
End SharedFunctionInfo

Handler Table (size = 0)
Source Position Table (size = 29)
0x0f3b449e5361 <ByteArray[29]>
End SharedFunctionInfo

Handler Table (size = 0)
Source Position Table (size = 7)
0x0f3b449e53a9 <ByteArray[7]>
End SharedFunctionInfo

After copying v8dasm to Bin/11.3.244.8 it can be used for decompiling:

python view8.py index.jsc out
function func_start_0x0c0502224d88()
{
    r0 = func_unknown_0x0c0502224e18
    return func_unknown_0x0c0502224e18
}
function func_unknown_0x0c0502224e18(a0, a1, a2, a3, a4)
{
    r2 = Scope[0]
    Scope[1][2] = null
    r0 = a1("express")
    r1 = r0()
    Scope[1][2] = 3000
    ACCU = r1["get"]("/", func_unknown_0x0c0502224f98)
    ACCU = r1["listen"](Scope[1][2], func_unknown_0x0c05022251e8)
    return undefined
}
function func_unknown_0x0c05022251e8()
{
    r2 = ("Example app listening on port" + String(Scope[1][2]))
    r2 = (r2 + "!")
    return "console"["log"](r2)
}
function func_unknown_0x0c0502224f98(a0, a1)
{
    return a1["send"]("Hello World!")
}
kiwina commented 3 months ago

@j4k0xb have a look at the d8 code as that prints out everything. What version are you trying??

suleram commented 3 months ago

@j4k0xb Added 2 more patches: 1) Disabling the Sanit check 2) Support for FixedDoubleArray

diff --git a/orig/code-serializer.cc b/patch/code-serializer.cc
index c83e8e4..bf7555b 100644
--- a/orig/code-serializer.cc
+++ b/patch/code-serializer.cc
@@ -427,14 +427,14 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
   const SerializedCodeData scd = SerializedCodeData::FromCachedData(
       cached_data, SerializedCodeData::SourceHash(source, origin_options),
       &sanity_check_result);
-  if (sanity_check_result != SerializedCodeSanityCheckResult::kSuccess) {
+  /*if (sanity_check_result != SerializedCodeSanityCheckResult::kSuccess) {
     if (v8_flags.profile_deserialization)
       PrintF("[Cached code failed check]\n");
     DCHECK(cached_data->rejected());
     isolate->counters()->code_cache_reject_reason()->AddSample(
         static_cast<int>(sanity_check_result));
     return MaybeHandle<SharedFunctionInfo>();
-  }
+  }*/

   // Deserialize.
   MaybeHandle<SharedFunctionInfo> maybe_result =
@@ -446,6 +446,12 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
     if (v8_flags.profile_deserialization) PrintF("[Deserializing failed]\n");
     return MaybeHandle<SharedFunctionInfo>();
   }
+  // add patch
+  std::cout << "\nStart SharedFunctionInfo\n";
+  result->GetBytecodeArray(isolate).Disassemble(std::cout);
+  std::cout << "\nEnd SharedFunctionInfo\n";
+  std::cout << std::flush;
+  // end patch

   // Check whether the newly deserialized data should be merged into an
   // existing Script from the Isolate compilation cache. If so, perform
@@ -735,10 +741,10 @@ SerializedCodeData SerializedCodeData::FromCachedData(
   DisallowGarbageCollection no_gc;
   SerializedCodeData scd(cached_data);
   *rejection_result = scd.SanityCheck(expected_source_hash);
-  if (*rejection_result != SerializedCodeSanityCheckResult::kSuccess) {
+  /*if (*rejection_result != SerializedCodeSanityCheckResult::kSuccess) {
     cached_data->Reject();
     return SerializedCodeData(nullptr, 0);
-  }
+  }*/
   return scd;
 }

diff --git a/orig/objects-printer.cc b/patch/objects-printer.cc
index 30d8095..28f5742 100644
--- a/orig/objects-printer.cc
+++ b/patch/objects-printer.cc
@@ -1821,7 +1821,7 @@ void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) {
   } else {
     os << "<unavailable>";
   }
-  PrintSourceCode(os);
+  //PrintSourceCode(os);
   // Script files are often large, thus only print their {Brief} representation.
   os << "\n - script: " << Brief(script());
   os << "\n - function token position: " << function_token_position();
@@ -1844,6 +1844,13 @@ void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) {
     os << "<none>";
   }
   os << "\n";
+  // add patch
+  os << "\nStart BytecodeArray\n";
+  this->GetBytecodeArray(isolate).Disassemble(os);
+  os << "\nEnd BytecodeArray\n";
+  os << std::flush;
+  // end patch
 }

 void JSGlobalProxy::JSGlobalProxyPrint(std::ostream& os) {
diff --git a/orig/objects.cc b/patch/objects.cc
index 43ea4a7..89e8453 100644
--- a/orig/objects.cc
+++ b/patch/objects.cc
@@ -1914,15 +1914,33 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) {
       break;
     case FIXED_ARRAY_TYPE:
       os << "<FixedArray[" << FixedArray::cast(*this).length() << "]>";
-      break;
+   // add patch
+   os << "\nStart FixedArray\n";
+   FixedArray::cast(*this).FixedArrayPrint(os);
+   os << "\nEnd FixedArray\n";
+   os << std::flush;
+   // end patch
+   break;
     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
       os << "<ObjectBoilerplateDescription[" << FixedArray::cast(*this).length()
          << "]>";
-      break;
+   // add patch
+   os << "\nStart ObjectBoilerplateDescription\n";
+   ObjectBoilerplateDescription::cast(*this).ObjectBoilerplateDescriptionPrint(os);
+   os << "\nEnd ObjectBoilerplateDescription\n";
+   os << std::flush;
+   // end patch
+      break;
     case FIXED_DOUBLE_ARRAY_TYPE:
       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(*this).length()
          << "]>";
-      break;
+   // add patch
+   os << "\nStart FixedDoubleArray\n";
+   FixedDoubleArray::cast(*this).FixedDoubleArrayPrint(os);
+   os << "\nEnd FixedDoubleArray\n";
+   os << std::flush;
+   // end patch
+   break;
     case BYTE_ARRAY_TYPE:
       os << "<ByteArray[" << ByteArray::cast(*this).length() << "]>";
       break;
@@ -2000,6 +2018,12 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) {
       } else {
         os << "<SharedFunctionInfo>";
       }
+   // add patch
+   os << "\nStart SharedFunctionInfo\n";
+   shared.SharedFunctionInfoPrint(os);
+   os << "\nEnd SharedFunctionInfo\n";
+   os << std::flush;
+   // end patch
    break;
     }
     case JS_MESSAGE_OBJECT_TYPE:
suleram commented 3 months ago

but it fails to deserialize the .jsc file (kMagicNumber mismatch despite being the same version).

This issue may be due to an x86-x64 mismatch (SharedFunctionInfo size). In my experience, manually changing the magic can resolve the problem.

silverwolfceh commented 3 months ago

I found the version of my program is: 10.6.194.27-electron.0, but I can't find corresponding v8 tag, please help.

j4k0xb commented 3 months ago

I found the version of my program is: 10.6.194.27-electron.0, but I can't find corresponding v8 tag

Electron patches the v8 source and edited the version, 10.6.194.26 should work Maybe one of the disassemblers in https://github.com/suleram/View8/releases/tag/v1.0 work as well

silverwolfceh commented 3 months ago

I tried all but may be the version hash check was too strictly, so it failed on the version hash check. Any way, thank for your recommendation. I will build the 10.6.194.26 and try again.

VityaSchel commented 1 month ago

@suleram Which patches are required in order to use v8 binary with this tool? Can you write a short instruction on how to apply these patches, at which stage? Should we apply them before compiling v8?

VityaSchel commented 1 month ago

Can you also post a guide on how to use custom v8 version with this tool? I think I got it, you have to patch and build v8 for windows and then use the resulting exe file with your python tool, but it would be nice to get confirmation from you that I got that right

datrix88 commented 1 month ago

Hi @suleram Can you build a patched binary for 9.1.269.40 version? I already tried with the existents bin, but not works. Thanks in advance.