star ctf chrome oob writeup
bug
1 | +BUILTIN(ArrayOob){ |
可以看到在length这里有一个off-by-one
另外,这里有一个非预期的UAF,其实在Object::ToNumber(isolate, args.at
基础知识
v8通过map来判断类型,通过off-by-one来修改map即可产生type confusion
trick
splice
通过splice控制array的内存排布紧邻。
1 | var ab = new ArrayBuffer(0x1000); |
test如下:
可以看到如图所示的内存布局:
a elements的length位置存放的就是a obj的map了,于是a.oob(xxx)就可以将a的map给覆盖掉。
1 | //0x33a1055ce0e1->0x33a1055ce0b1 |
gc
在要fake的arraybuffer的前后两次gc,使其内存分布更稳定。
debug
调试的话,直接在对应版本的v8 release上调试,然后写到html里,放到chrome里就行了,偏移什么的都没有改变。
也可以直接gdb attach到chrome里调试。
exp
利用思路非常简单
首先分配两个array,一个double array,一个object array
然后通过覆盖object array的map为double map,就可以将其中的用户空间对象leak出来。
然后在array的elments去fake一个arraybuffer。
然后通过将double array的map覆盖成object array,就可以将fake好的arraybuffer给当成object给取出来。
而这个fake的arraybuffer的内容是我们可控的,于是就可以任意地址读写了。
接下来就是找到wasm_func里rwx的地址,将shellcode写入执行即可。
我的exp写的比较dirty。
1 | <html> |
测试机器ubuntu16.04