diff --git a/JavaScript/PwnCollegeV8Exploitation/Level1/REVISION b/JavaScript/PwnCollegeV8Exploitation/Level1/REVISION new file mode 100644 index 0000000..3975763 --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level1/REVISION @@ -0,0 +1 @@ +5a2307d0f2c5b650c6858e2b9b57b335a59946ff \ No newline at end of file diff --git a/JavaScript/PwnCollegeV8Exploitation/Level1/args.gn b/JavaScript/PwnCollegeV8Exploitation/Level1/args.gn new file mode 100644 index 0000000..31460dd --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level1/args.gn @@ -0,0 +1,10 @@ +is_component_build = false +is_debug = false +target_cpu = "x64" +v8_enable_sandbox = false +v8_enable_backtrace = true +v8_enable_disassembler = true +v8_enable_object_print = true +dcheck_always_on = false +use_goma = false +v8_code_pointer_sandboxing = false diff --git a/JavaScript/PwnCollegeV8Exploitation/Level1/patch b/JavaScript/PwnCollegeV8Exploitation/Level1/patch new file mode 100644 index 0000000..6bb7d90 --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level1/patch @@ -0,0 +1,137 @@ +diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc +index ea45a7ada6b..c840e568152 100644 +--- a/src/builtins/builtins-array.cc ++++ b/src/builtins/builtins-array.cc +@@ -24,6 +24,8 @@ + #include "src/objects/prototype.h" + #include "src/objects/smi.h" + ++extern "C" void *mmap(void *, unsigned long, int, int, int, int); ++ + namespace v8 { + namespace internal { + +@@ -407,6 +409,47 @@ BUILTIN(ArrayPush) { + return *isolate->factory()->NewNumberFromUint((new_length)); + } + ++BUILTIN(ArrayRun) { ++ HandleScope scope(isolate); ++ Factory *factory = isolate->factory(); ++ Handle receiver = args.receiver(); ++ ++ if (!IsJSArray(*receiver) || !HasOnlySimpleReceiverElements(isolate, Cast(*receiver))) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("Nope"))); ++ } ++ ++ Handle array = Cast(receiver); ++ ElementsKind kind = array->GetElementsKind(); ++ ++ if (kind != PACKED_DOUBLE_ELEMENTS) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("Need array of double numbers"))); ++ } ++ ++ uint32_t length = static_cast(Object::NumberValue(array->length())); ++ if (sizeof(double) * (uint64_t)length > 4096) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("array too long"))); ++ } ++ ++ // mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ++ double *mem = (double *)mmap(NULL, 4096, 7, 0x22, -1, 0); ++ if (mem == (double *)-1) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("mmap failed"))); ++ } ++ ++ Handle elements(Cast(array->elements()), isolate); ++ FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, i = 0, i, i < length, i++, { ++ double x = elements->get_scalar(i); ++ mem[i] = x; ++ }); ++ ++ ((void (*)())mem)(); ++ return 0; ++} ++ + namespace { + + V8_WARN_UNUSED_RESULT Tagged GenericArrayPop(Isolate* isolate, +diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h +index 78cbf8874ed..4f3d885cca7 100644 +--- a/src/builtins/builtins-definitions.h ++++ b/src/builtins/builtins-definitions.h +@@ -421,6 +421,7 @@ namespace internal { + TFJ(ArrayPrototypePop, kDontAdaptArgumentsSentinel) \ + /* ES6 #sec-array.prototype.push */ \ + CPP(ArrayPush) \ ++ CPP(ArrayRun) \ + TFJ(ArrayPrototypePush, kDontAdaptArgumentsSentinel) \ + /* ES6 #sec-array.prototype.shift */ \ + CPP(ArrayShift) \ +diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc +index 9a346d134b9..58fd42e59a4 100644 +--- a/src/compiler/typer.cc ++++ b/src/compiler/typer.cc +@@ -1937,6 +1937,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) { + return Type::Receiver(); + case Builtin::kArrayUnshift: + return t->cache_->kPositiveSafeInteger; ++ case Builtin::kArrayRun: ++ return Type::Receiver(); + + // ArrayBuffer functions. + case Builtin::kArrayBufferIsView: +diff --git a/src/d8/d8.cc b/src/d8/d8.cc +index facf0d86d79..382c015bc48 100644 +--- a/src/d8/d8.cc ++++ b/src/d8/d8.cc +@@ -3364,7 +3364,7 @@ Local Shell::CreateNodeTemplates( + + Local Shell::CreateGlobalTemplate(Isolate* isolate) { + Local global_template = ObjectTemplate::New(isolate); +- global_template->Set(Symbol::GetToStringTag(isolate), ++/* global_template->Set(Symbol::GetToStringTag(isolate), + String::NewFromUtf8Literal(isolate, "global")); + global_template->Set(isolate, "version", + FunctionTemplate::New(isolate, Version)); +@@ -3385,13 +3385,13 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + global_template->Set(isolate, "readline", + FunctionTemplate::New(isolate, ReadLine)); + global_template->Set(isolate, "load", +- FunctionTemplate::New(isolate, ExecuteFile)); ++ FunctionTemplate::New(isolate, ExecuteFile));*/ + global_template->Set(isolate, "setTimeout", + FunctionTemplate::New(isolate, SetTimeout)); + // Some Emscripten-generated code tries to call 'quit', which in turn would + // call C's exit(). This would lead to memory leaks, because there is no way + // we can terminate cleanly then, so we need a way to hide 'quit'. +- if (!options.omit_quit) { ++/* if (!options.omit_quit) { + global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit)); + } + global_template->Set(isolate, "testRunner", +@@ -3410,7 +3410,7 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + if (i::v8_flags.expose_async_hooks) { + global_template->Set(isolate, "async_hooks", + Shell::CreateAsyncHookTemplate(isolate)); +- } ++ }*/ + + return global_template; + } +diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc +index 48249695b7b..40a762c24c8 100644 +--- a/src/init/bootstrapper.cc ++++ b/src/init/bootstrapper.cc +@@ -2533,6 +2533,8 @@ void Genesis::InitializeGlobal(Handle global_object, + + SimpleInstallFunction(isolate_, proto, "at", Builtin::kArrayPrototypeAt, 1, + true); ++ SimpleInstallFunction(isolate_, proto, "run", ++ Builtin::kArrayRun, 0, false); + SimpleInstallFunction(isolate_, proto, "concat", + Builtin::kArrayPrototypeConcat, 1, false); + SimpleInstallFunction(isolate_, proto, "copyWithin", diff --git a/JavaScript/PwnCollegeV8Exploitation/Level2/REVISION b/JavaScript/PwnCollegeV8Exploitation/Level2/REVISION new file mode 100644 index 0000000..3975763 --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level2/REVISION @@ -0,0 +1 @@ +5a2307d0f2c5b650c6858e2b9b57b335a59946ff \ No newline at end of file diff --git a/JavaScript/PwnCollegeV8Exploitation/Level2/args.gn b/JavaScript/PwnCollegeV8Exploitation/Level2/args.gn new file mode 100644 index 0000000..31460dd --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level2/args.gn @@ -0,0 +1,10 @@ +is_component_build = false +is_debug = false +target_cpu = "x64" +v8_enable_sandbox = false +v8_enable_backtrace = true +v8_enable_disassembler = true +v8_enable_object_print = true +dcheck_always_on = false +use_goma = false +v8_code_pointer_sandboxing = false diff --git a/JavaScript/PwnCollegeV8Exploitation/Level2/patch b/JavaScript/PwnCollegeV8Exploitation/Level2/patch new file mode 100644 index 0000000..7ee1000 --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level2/patch @@ -0,0 +1,123 @@ +diff --git a/src/d8/d8.cc b/src/d8/d8.cc +index facf0d86d79..6b31fe2c371 100644 +--- a/src/d8/d8.cc ++++ b/src/d8/d8.cc +@@ -1283,6 +1283,64 @@ struct ModuleResolutionData { + + } // namespace + ++void Shell::GetAddressOf(const v8::FunctionCallbackInfo& info) { ++ v8::Isolate* isolate = info.GetIsolate(); ++ ++ if (info.Length() == 0) { ++ isolate->ThrowError("First argument must be provided"); ++ return; ++ } ++ ++ internal::Handle arg = Utils::OpenHandle(*info[0]); ++ if (!IsHeapObject(*arg)) { ++ isolate->ThrowError("First argument must be a HeapObject"); ++ return; ++ } ++ internal::Tagged obj = internal::Cast(*arg); ++ ++ uint32_t address = static_cast(obj->address()); ++ info.GetReturnValue().Set(v8::Integer::NewFromUnsigned(isolate, address)); ++} ++ ++void Shell::ArbRead32(const v8::FunctionCallbackInfo& info) { ++ Isolate *isolate = info.GetIsolate(); ++ if (info.Length() != 1) { ++ isolate->ThrowError("Need exactly one argument"); ++ return; ++ } ++ internal::Handle arg = Utils::OpenHandle(*info[0]); ++ if (!IsNumber(*arg)) { ++ isolate->ThrowError("Argument should be a number"); ++ return; ++ } ++ internal::PtrComprCageBase cage_base = internal::GetPtrComprCageBase(); ++ internal::Address base_addr = internal::V8HeapCompressionScheme::GetPtrComprCageBaseAddress(cage_base); ++ uint32_t addr = static_cast(internal::Object::NumberValue(*arg)); ++ uint64_t full_addr = base_addr + (uint64_t)addr; ++ uint32_t result = *(uint32_t *)full_addr; ++ info.GetReturnValue().Set(v8::Integer::NewFromUnsigned(isolate, result)); ++} ++ ++void Shell::ArbWrite32(const v8::FunctionCallbackInfo& info) { ++ Isolate *isolate = info.GetIsolate(); ++ if (info.Length() != 2) { ++ isolate->ThrowError("Need exactly 2 arguments"); ++ return; ++ } ++ internal::Handle arg1 = Utils::OpenHandle(*info[0]); ++ internal::Handle arg2 = Utils::OpenHandle(*info[1]); ++ if (!IsNumber(*arg1) || !IsNumber(*arg2)) { ++ isolate->ThrowError("Arguments should be numbers"); ++ return; ++ } ++ internal::PtrComprCageBase cage_base = internal::GetPtrComprCageBase(); ++ internal::Address base_addr = internal::V8HeapCompressionScheme::GetPtrComprCageBaseAddress(cage_base); ++ uint32_t addr = static_cast(internal::Object::NumberValue(*arg1)); ++ uint32_t value = static_cast(internal::Object::NumberValue(*arg2)); ++ uint64_t full_addr = base_addr + (uint64_t)addr; ++ *(uint32_t *)full_addr = value; ++} ++ + void Shell::ModuleResolutionSuccessCallback( + const FunctionCallbackInfo& info) { + DCHECK(i::ValidateCallbackInfo(info)); +@@ -3364,7 +3422,13 @@ Local Shell::CreateNodeTemplates( + + Local Shell::CreateGlobalTemplate(Isolate* isolate) { + Local global_template = ObjectTemplate::New(isolate); +- global_template->Set(Symbol::GetToStringTag(isolate), ++ global_template->Set(isolate, "GetAddressOf", ++ FunctionTemplate::New(isolate, GetAddressOf)); ++ global_template->Set(isolate, "ArbRead32", ++ FunctionTemplate::New(isolate, ArbRead32)); ++ global_template->Set(isolate, "ArbWrite32", ++ FunctionTemplate::New(isolate, ArbWrite32)); ++/* global_template->Set(Symbol::GetToStringTag(isolate), + String::NewFromUtf8Literal(isolate, "global")); + global_template->Set(isolate, "version", + FunctionTemplate::New(isolate, Version)); +@@ -3385,13 +3449,13 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + global_template->Set(isolate, "readline", + FunctionTemplate::New(isolate, ReadLine)); + global_template->Set(isolate, "load", +- FunctionTemplate::New(isolate, ExecuteFile)); ++ FunctionTemplate::New(isolate, ExecuteFile));*/ + global_template->Set(isolate, "setTimeout", + FunctionTemplate::New(isolate, SetTimeout)); + // Some Emscripten-generated code tries to call 'quit', which in turn would + // call C's exit(). This would lead to memory leaks, because there is no way + // we can terminate cleanly then, so we need a way to hide 'quit'. +- if (!options.omit_quit) { ++/* if (!options.omit_quit) { + global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit)); + } + global_template->Set(isolate, "testRunner", +@@ -3410,7 +3474,7 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + if (i::v8_flags.expose_async_hooks) { + global_template->Set(isolate, "async_hooks", + Shell::CreateAsyncHookTemplate(isolate)); +- } ++ }*/ + + return global_template; + } +diff --git a/src/d8/d8.h b/src/d8/d8.h +index a19d4a0eae4..476675a7150 100644 +--- a/src/d8/d8.h ++++ b/src/d8/d8.h +@@ -507,6 +507,9 @@ class Shell : public i::AllStatic { + }; + enum class CodeType { kFileName, kString, kFunction, kInvalid, kNone }; + ++ static void GetAddressOf(const v8::FunctionCallbackInfo& args); ++ static void ArbRead32(const v8::FunctionCallbackInfo& args); ++ static void ArbWrite32(const v8::FunctionCallbackInfo& args); + static bool ExecuteString(Isolate* isolate, Local source, + Local name, + ReportExceptions report_exceptions, diff --git a/JavaScript/PwnCollegeV8Exploitation/Level3/REVISION b/JavaScript/PwnCollegeV8Exploitation/Level3/REVISION new file mode 100644 index 0000000..3975763 --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level3/REVISION @@ -0,0 +1 @@ +5a2307d0f2c5b650c6858e2b9b57b335a59946ff \ No newline at end of file diff --git a/JavaScript/PwnCollegeV8Exploitation/Level3/args.gn b/JavaScript/PwnCollegeV8Exploitation/Level3/args.gn new file mode 100644 index 0000000..31460dd --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level3/args.gn @@ -0,0 +1,10 @@ +is_component_build = false +is_debug = false +target_cpu = "x64" +v8_enable_sandbox = false +v8_enable_backtrace = true +v8_enable_disassembler = true +v8_enable_object_print = true +dcheck_always_on = false +use_goma = false +v8_code_pointer_sandboxing = false diff --git a/JavaScript/PwnCollegeV8Exploitation/Level3/patch b/JavaScript/PwnCollegeV8Exploitation/Level3/patch new file mode 100644 index 0000000..e6c678c --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level3/patch @@ -0,0 +1,108 @@ +diff --git a/src/d8/d8.cc b/src/d8/d8.cc +index facf0d86d79..0299ed26802 100644 +--- a/src/d8/d8.cc ++++ b/src/d8/d8.cc +@@ -1283,6 +1283,52 @@ struct ModuleResolutionData { + + } // namespace + ++void Shell::GetAddressOf(const v8::FunctionCallbackInfo& info) { ++ v8::Isolate* isolate = info.GetIsolate(); ++ ++ if (info.Length() == 0) { ++ isolate->ThrowError("First argument must be provided"); ++ return; ++ } ++ ++ internal::Handle arg = Utils::OpenHandle(*info[0]); ++ if (!IsHeapObject(*arg)) { ++ isolate->ThrowError("First argument must be a HeapObject"); ++ return; ++ } ++ internal::Tagged obj = internal::Cast(*arg); ++ ++ uint32_t address = static_cast(obj->address()); ++ info.GetReturnValue().Set(v8::Integer::NewFromUnsigned(isolate, address)); ++} ++ ++void Shell::GetFakeObject(const v8::FunctionCallbackInfo& info) { ++ v8::Isolate *isolate = info.GetIsolate(); ++ Local context = isolate->GetCurrentContext(); ++ ++ if (info.Length() != 1) { ++ isolate->ThrowError("Need exactly one argument"); ++ return; ++ } ++ ++ Local arg; ++ if (!info[0]->ToUint32(context).ToLocal(&arg)) { ++ isolate->ThrowError("Argument must be a number"); ++ return; ++ } ++ ++ uint32_t addr = arg->Value(); ++ ++ internal::PtrComprCageBase cage_base = internal::GetPtrComprCageBase(); ++ internal::Address base_addr = internal::V8HeapCompressionScheme::GetPtrComprCageBaseAddress(cage_base); ++ uint64_t full_addr = base_addr + (uint64_t)addr; ++ ++ internal::Tagged obj = internal::HeapObject::FromAddress(full_addr); ++ internal::Isolate *i_isolate = reinterpret_cast(isolate); ++ internal::Handle obj_handle(obj, i_isolate); ++ info.GetReturnValue().Set(ToApiHandle(obj_handle)); ++} ++ + void Shell::ModuleResolutionSuccessCallback( + const FunctionCallbackInfo& info) { + DCHECK(i::ValidateCallbackInfo(info)); +@@ -3364,7 +3410,11 @@ Local Shell::CreateNodeTemplates( + + Local Shell::CreateGlobalTemplate(Isolate* isolate) { + Local global_template = ObjectTemplate::New(isolate); +- global_template->Set(Symbol::GetToStringTag(isolate), ++ global_template->Set(isolate, "GetAddressOf", ++ FunctionTemplate::New(isolate, GetAddressOf)); ++ global_template->Set(isolate, "GetFakeObject", ++ FunctionTemplate::New(isolate, GetFakeObject)); ++/* global_template->Set(Symbol::GetToStringTag(isolate), + String::NewFromUtf8Literal(isolate, "global")); + global_template->Set(isolate, "version", + FunctionTemplate::New(isolate, Version)); +@@ -3385,13 +3435,13 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + global_template->Set(isolate, "readline", + FunctionTemplate::New(isolate, ReadLine)); + global_template->Set(isolate, "load", +- FunctionTemplate::New(isolate, ExecuteFile)); ++ FunctionTemplate::New(isolate, ExecuteFile));*/ + global_template->Set(isolate, "setTimeout", + FunctionTemplate::New(isolate, SetTimeout)); + // Some Emscripten-generated code tries to call 'quit', which in turn would + // call C's exit(). This would lead to memory leaks, because there is no way + // we can terminate cleanly then, so we need a way to hide 'quit'. +- if (!options.omit_quit) { ++/* if (!options.omit_quit) { + global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit)); + } + global_template->Set(isolate, "testRunner", +@@ -3410,7 +3460,7 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + if (i::v8_flags.expose_async_hooks) { + global_template->Set(isolate, "async_hooks", + Shell::CreateAsyncHookTemplate(isolate)); +- } ++ }*/ + + return global_template; + } +diff --git a/src/d8/d8.h b/src/d8/d8.h +index a19d4a0eae4..fbb091afbaf 100644 +--- a/src/d8/d8.h ++++ b/src/d8/d8.h +@@ -507,6 +507,8 @@ class Shell : public i::AllStatic { + }; + enum class CodeType { kFileName, kString, kFunction, kInvalid, kNone }; + ++ static void GetAddressOf(const v8::FunctionCallbackInfo& args); ++ static void GetFakeObject(const v8::FunctionCallbackInfo& args); + static bool ExecuteString(Isolate* isolate, Local source, + Local name, + ReportExceptions report_exceptions, diff --git a/JavaScript/PwnCollegeV8Exploitation/Level4/REVISION b/JavaScript/PwnCollegeV8Exploitation/Level4/REVISION new file mode 100644 index 0000000..3975763 --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level4/REVISION @@ -0,0 +1 @@ +5a2307d0f2c5b650c6858e2b9b57b335a59946ff \ No newline at end of file diff --git a/JavaScript/PwnCollegeV8Exploitation/Level4/args.gn b/JavaScript/PwnCollegeV8Exploitation/Level4/args.gn new file mode 100644 index 0000000..31460dd --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level4/args.gn @@ -0,0 +1,10 @@ +is_component_build = false +is_debug = false +target_cpu = "x64" +v8_enable_sandbox = false +v8_enable_backtrace = true +v8_enable_disassembler = true +v8_enable_object_print = true +dcheck_always_on = false +use_goma = false +v8_code_pointer_sandboxing = false diff --git a/JavaScript/PwnCollegeV8Exploitation/Level4/patch b/JavaScript/PwnCollegeV8Exploitation/Level4/patch new file mode 100644 index 0000000..cc0bf62 --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level4/patch @@ -0,0 +1,83 @@ +diff --git a/BUILD.gn b/BUILD.gn +index c0192593c4a..83e264723f7 100644 +--- a/BUILD.gn ++++ b/BUILD.gn +@@ -1889,6 +1889,7 @@ if (v8_postmortem_support) { + } + + torque_files = [ ++ "src/builtins/array-setlength.tq", + "src/builtins/aggregate-error.tq", + "src/builtins/array-at.tq", + "src/builtins/array-concat.tq", +diff --git a/src/builtins/array-setlength.tq b/src/builtins/array-setlength.tq +new file mode 100644 +index 00000000000..4a2a864af44 +--- /dev/null ++++ b/src/builtins/array-setlength.tq +@@ -0,0 +1,14 @@ ++namespace array { ++transitioning javascript builtin ++ArrayPrototypeSetLength( ++ js-implicit context: NativeContext, receiver: JSAny)(length: JSAny): JSAny { ++ try { ++ const len: Smi = Cast(length) otherwise ErrorLabel; ++ const array: JSArray = Cast(receiver) otherwise ErrorLabel; ++ array.length = len; ++ } label ErrorLabel { ++ Print("Nope"); ++ } ++ return receiver; ++} ++} +diff --git a/src/d8/d8.cc b/src/d8/d8.cc +index facf0d86d79..382c015bc48 100644 +--- a/src/d8/d8.cc ++++ b/src/d8/d8.cc +@@ -3364,7 +3364,7 @@ Local Shell::CreateNodeTemplates( + + Local Shell::CreateGlobalTemplate(Isolate* isolate) { + Local global_template = ObjectTemplate::New(isolate); +- global_template->Set(Symbol::GetToStringTag(isolate), ++/* global_template->Set(Symbol::GetToStringTag(isolate), + String::NewFromUtf8Literal(isolate, "global")); + global_template->Set(isolate, "version", + FunctionTemplate::New(isolate, Version)); +@@ -3385,13 +3385,13 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + global_template->Set(isolate, "readline", + FunctionTemplate::New(isolate, ReadLine)); + global_template->Set(isolate, "load", +- FunctionTemplate::New(isolate, ExecuteFile)); ++ FunctionTemplate::New(isolate, ExecuteFile));*/ + global_template->Set(isolate, "setTimeout", + FunctionTemplate::New(isolate, SetTimeout)); + // Some Emscripten-generated code tries to call 'quit', which in turn would + // call C's exit(). This would lead to memory leaks, because there is no way + // we can terminate cleanly then, so we need a way to hide 'quit'. +- if (!options.omit_quit) { ++/* if (!options.omit_quit) { + global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit)); + } + global_template->Set(isolate, "testRunner", +@@ -3410,7 +3410,7 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + if (i::v8_flags.expose_async_hooks) { + global_template->Set(isolate, "async_hooks", + Shell::CreateAsyncHookTemplate(isolate)); +- } ++ }*/ + + return global_template; + } +diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc +index 48249695b7b..f3379ac47ec 100644 +--- a/src/init/bootstrapper.cc ++++ b/src/init/bootstrapper.cc +@@ -2531,6 +2531,8 @@ void Genesis::InitializeGlobal(Handle global_object, + JSObject::AddProperty(isolate_, proto, factory->constructor_string(), + array_function, DONT_ENUM); + ++ SimpleInstallFunction(isolate_, proto, "setLength", ++ Builtin::kArrayPrototypeSetLength, 1, true); + SimpleInstallFunction(isolate_, proto, "at", Builtin::kArrayPrototypeAt, 1, + true); + SimpleInstallFunction(isolate_, proto, "concat", diff --git a/JavaScript/PwnCollegeV8Exploitation/Level5/REVISION b/JavaScript/PwnCollegeV8Exploitation/Level5/REVISION new file mode 100644 index 0000000..3975763 --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level5/REVISION @@ -0,0 +1 @@ +5a2307d0f2c5b650c6858e2b9b57b335a59946ff \ No newline at end of file diff --git a/JavaScript/PwnCollegeV8Exploitation/Level5/args.gn b/JavaScript/PwnCollegeV8Exploitation/Level5/args.gn new file mode 100644 index 0000000..31460dd --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level5/args.gn @@ -0,0 +1,10 @@ +is_component_build = false +is_debug = false +target_cpu = "x64" +v8_enable_sandbox = false +v8_enable_backtrace = true +v8_enable_disassembler = true +v8_enable_object_print = true +dcheck_always_on = false +use_goma = false +v8_code_pointer_sandboxing = false diff --git a/JavaScript/PwnCollegeV8Exploitation/Level5/patch b/JavaScript/PwnCollegeV8Exploitation/Level5/patch new file mode 100644 index 0000000..56ee719 --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level5/patch @@ -0,0 +1,127 @@ +diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc +index ea45a7ada6b..4ed66c8113f 100644 +--- a/src/builtins/builtins-array.cc ++++ b/src/builtins/builtins-array.cc +@@ -407,6 +407,46 @@ BUILTIN(ArrayPush) { + return *isolate->factory()->NewNumberFromUint((new_length)); + } + ++BUILTIN(ArrayOffByOne) { ++ HandleScope scope(isolate); ++ Factory *factory = isolate->factory(); ++ Handle receiver = args.receiver(); ++ ++ if (!IsJSArray(*receiver) || !HasOnlySimpleReceiverElements(isolate, Cast(*receiver))) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("Nope"))); ++ } ++ ++ Handle array = Cast(receiver); ++ ++ ElementsKind kind = array->GetElementsKind(); ++ ++ if (kind != PACKED_DOUBLE_ELEMENTS) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("Need an array of double numbers"))); ++ } ++ ++ if (args.length() > 2) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("Too many arguments"))); ++ } ++ ++ Handle elements(Cast(array->elements()), isolate); ++ uint32_t len = static_cast(Object::NumberValue(array->length())); ++ if (args.length() == 1) { // read mode ++ return *(isolate->factory()->NewNumber(elements->get_scalar(len))); ++ } else { // write mode ++ Handle value = args.at(1); ++ if (!IsNumber(*value)) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("Need a number argument"))); ++ } ++ double num = static_cast(Object::NumberValue(*value)); ++ elements->set(len, num); ++ return ReadOnlyRoots(isolate).undefined_value(); ++ } ++} ++ + namespace { + + V8_WARN_UNUSED_RESULT Tagged GenericArrayPop(Isolate* isolate, +diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h +index 78cbf8874ed..8a0bd959a29 100644 +--- a/src/builtins/builtins-definitions.h ++++ b/src/builtins/builtins-definitions.h +@@ -394,6 +394,7 @@ namespace internal { + ArraySingleArgumentConstructor) \ + TFC(ArrayNArgumentsConstructor, ArrayNArgumentsConstructor) \ + CPP(ArrayConcat) \ ++ CPP(ArrayOffByOne) \ + /* ES6 #sec-array.prototype.fill */ \ + CPP(ArrayPrototypeFill) \ + /* ES7 #sec-array.prototype.includes */ \ +diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc +index 9a346d134b9..ce31f92b876 100644 +--- a/src/compiler/typer.cc ++++ b/src/compiler/typer.cc +@@ -1937,6 +1937,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) { + return Type::Receiver(); + case Builtin::kArrayUnshift: + return t->cache_->kPositiveSafeInteger; ++ case Builtin::kArrayOffByOne: ++ return Type::Receiver(); + + // ArrayBuffer functions. + case Builtin::kArrayBufferIsView: +diff --git a/src/d8/d8.cc b/src/d8/d8.cc +index facf0d86d79..382c015bc48 100644 +--- a/src/d8/d8.cc ++++ b/src/d8/d8.cc +@@ -3364,7 +3364,7 @@ Local Shell::CreateNodeTemplates( + + Local Shell::CreateGlobalTemplate(Isolate* isolate) { + Local global_template = ObjectTemplate::New(isolate); +- global_template->Set(Symbol::GetToStringTag(isolate), ++/* global_template->Set(Symbol::GetToStringTag(isolate), + String::NewFromUtf8Literal(isolate, "global")); + global_template->Set(isolate, "version", + FunctionTemplate::New(isolate, Version)); +@@ -3385,13 +3385,13 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + global_template->Set(isolate, "readline", + FunctionTemplate::New(isolate, ReadLine)); + global_template->Set(isolate, "load", +- FunctionTemplate::New(isolate, ExecuteFile)); ++ FunctionTemplate::New(isolate, ExecuteFile));*/ + global_template->Set(isolate, "setTimeout", + FunctionTemplate::New(isolate, SetTimeout)); + // Some Emscripten-generated code tries to call 'quit', which in turn would + // call C's exit(). This would lead to memory leaks, because there is no way + // we can terminate cleanly then, so we need a way to hide 'quit'. +- if (!options.omit_quit) { ++/* if (!options.omit_quit) { + global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit)); + } + global_template->Set(isolate, "testRunner", +@@ -3410,7 +3410,7 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + if (i::v8_flags.expose_async_hooks) { + global_template->Set(isolate, "async_hooks", + Shell::CreateAsyncHookTemplate(isolate)); +- } ++ }*/ + + return global_template; + } +diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc +index 48249695b7b..99dc014c13c 100644 +--- a/src/init/bootstrapper.cc ++++ b/src/init/bootstrapper.cc +@@ -2533,6 +2533,8 @@ void Genesis::InitializeGlobal(Handle global_object, + + SimpleInstallFunction(isolate_, proto, "at", Builtin::kArrayPrototypeAt, 1, + true); ++ SimpleInstallFunction(isolate_, proto, "offByOne", ++ Builtin::kArrayOffByOne, 1, false); + SimpleInstallFunction(isolate_, proto, "concat", + Builtin::kArrayPrototypeConcat, 1, false); + SimpleInstallFunction(isolate_, proto, "copyWithin", diff --git a/JavaScript/PwnCollegeV8Exploitation/Level6/REVISION b/JavaScript/PwnCollegeV8Exploitation/Level6/REVISION new file mode 100644 index 0000000..3975763 --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level6/REVISION @@ -0,0 +1 @@ +5a2307d0f2c5b650c6858e2b9b57b335a59946ff \ No newline at end of file diff --git a/JavaScript/PwnCollegeV8Exploitation/Level6/args.gn b/JavaScript/PwnCollegeV8Exploitation/Level6/args.gn new file mode 100644 index 0000000..31460dd --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level6/args.gn @@ -0,0 +1,10 @@ +is_component_build = false +is_debug = false +target_cpu = "x64" +v8_enable_sandbox = false +v8_enable_backtrace = true +v8_enable_disassembler = true +v8_enable_object_print = true +dcheck_always_on = false +use_goma = false +v8_code_pointer_sandboxing = false diff --git a/JavaScript/PwnCollegeV8Exploitation/Level6/patch b/JavaScript/PwnCollegeV8Exploitation/Level6/patch new file mode 100644 index 0000000..39bc382 --- /dev/null +++ b/JavaScript/PwnCollegeV8Exploitation/Level6/patch @@ -0,0 +1,134 @@ +diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc +index ea45a7ada6b..d450412f3e6 100644 +--- a/src/builtins/builtins-array.cc ++++ b/src/builtins/builtins-array.cc +@@ -407,6 +407,53 @@ BUILTIN(ArrayPush) { + return *isolate->factory()->NewNumberFromUint((new_length)); + } + ++BUILTIN(ArrayFunctionMap) { ++ HandleScope scope(isolate); ++ Factory *factory = isolate->factory(); ++ Handle receiver = args.receiver(); ++ ++ if (!IsJSArray(*receiver) || !HasOnlySimpleReceiverElements(isolate, Cast(*receiver))) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("Nope"))); ++ } ++ ++ Handle array = Cast(receiver); ++ ++ ElementsKind kind = array->GetElementsKind(); ++ ++ if (kind != PACKED_DOUBLE_ELEMENTS) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("Need an array of double numbers"))); ++ } ++ ++ if (args.length() != 2) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("Need exactly one argument"))); ++ } ++ ++ uint32_t len = static_cast(Object::NumberValue(array->length())); ++ ++ Handle func_obj = args.at(1); ++ if (!IsJSFunction(*func_obj)) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("The argument must be a function"))); ++ } ++ ++ for (uint32_t i = 0; i < len; i++) { ++ double elem = Cast(array->elements())->get_scalar(i); ++ Handle elem_handle = factory->NewHeapNumber(elem); ++ Handle result = Execution::Call(isolate, func_obj, array, 1, &elem_handle).ToHandleChecked(); ++ if (!IsNumber(*result)) { ++ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly, ++ factory->NewStringFromAsciiChecked("The function must return a number"))); ++ } ++ double result_value = static_cast(Object::NumberValue(*result)); ++ Cast(array->elements())->set(i, result_value); ++ } ++ ++ return ReadOnlyRoots(isolate).undefined_value(); ++} ++ + namespace { + + V8_WARN_UNUSED_RESULT Tagged GenericArrayPop(Isolate* isolate, +diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h +index 78cbf8874ed..ede2775903e 100644 +--- a/src/builtins/builtins-definitions.h ++++ b/src/builtins/builtins-definitions.h +@@ -394,6 +394,7 @@ namespace internal { + ArraySingleArgumentConstructor) \ + TFC(ArrayNArgumentsConstructor, ArrayNArgumentsConstructor) \ + CPP(ArrayConcat) \ ++ CPP(ArrayFunctionMap) \ + /* ES6 #sec-array.prototype.fill */ \ + CPP(ArrayPrototypeFill) \ + /* ES7 #sec-array.prototype.includes */ \ +diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc +index 9a346d134b9..33cf2d2edad 100644 +--- a/src/compiler/typer.cc ++++ b/src/compiler/typer.cc +@@ -1937,6 +1937,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) { + return Type::Receiver(); + case Builtin::kArrayUnshift: + return t->cache_->kPositiveSafeInteger; ++ case Builtin::kArrayFunctionMap: ++ return Type::Receiver(); + + // ArrayBuffer functions. + case Builtin::kArrayBufferIsView: +diff --git a/src/d8/d8.cc b/src/d8/d8.cc +index facf0d86d79..382c015bc48 100644 +--- a/src/d8/d8.cc ++++ b/src/d8/d8.cc +@@ -3364,7 +3364,7 @@ Local Shell::CreateNodeTemplates( + + Local Shell::CreateGlobalTemplate(Isolate* isolate) { + Local global_template = ObjectTemplate::New(isolate); +- global_template->Set(Symbol::GetToStringTag(isolate), ++/* global_template->Set(Symbol::GetToStringTag(isolate), + String::NewFromUtf8Literal(isolate, "global")); + global_template->Set(isolate, "version", + FunctionTemplate::New(isolate, Version)); +@@ -3385,13 +3385,13 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + global_template->Set(isolate, "readline", + FunctionTemplate::New(isolate, ReadLine)); + global_template->Set(isolate, "load", +- FunctionTemplate::New(isolate, ExecuteFile)); ++ FunctionTemplate::New(isolate, ExecuteFile));*/ + global_template->Set(isolate, "setTimeout", + FunctionTemplate::New(isolate, SetTimeout)); + // Some Emscripten-generated code tries to call 'quit', which in turn would + // call C's exit(). This would lead to memory leaks, because there is no way + // we can terminate cleanly then, so we need a way to hide 'quit'. +- if (!options.omit_quit) { ++/* if (!options.omit_quit) { + global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit)); + } + global_template->Set(isolate, "testRunner", +@@ -3410,7 +3410,7 @@ Local Shell::CreateGlobalTemplate(Isolate* isolate) { + if (i::v8_flags.expose_async_hooks) { + global_template->Set(isolate, "async_hooks", + Shell::CreateAsyncHookTemplate(isolate)); +- } ++ }*/ + + return global_template; + } +diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc +index 48249695b7b..5e76e66bc15 100644 +--- a/src/init/bootstrapper.cc ++++ b/src/init/bootstrapper.cc +@@ -2533,6 +2533,8 @@ void Genesis::InitializeGlobal(Handle global_object, + + SimpleInstallFunction(isolate_, proto, "at", Builtin::kArrayPrototypeAt, 1, + true); ++ SimpleInstallFunction(isolate_, proto, "functionMap", ++ Builtin::kArrayFunctionMap, 1, false); + SimpleInstallFunction(isolate_, proto, "concat", + Builtin::kArrayPrototypeConcat, 1, false); + SimpleInstallFunction(isolate_, proto, "copyWithin",