-
-
[原创]看雪CTF2019Q3 第十二题:精忠报国 题目设计思路
-
发表于: 2019-9-9 21:56 3610
-
简单地说这是一个V8的利用题,patch里面先是把d8的一些函数给删掉了,不然你可以直接用read读flag。然后漏洞patch是把FillImpl
函数的用于扩大capacity的代码删除了,这样子的话,当end > capacity
的时候,可以早成OOB写。
漏洞在FillImpl
,可是我们怎么从JavaScript中调用到它并且控制end
和capacity的值呢?这个时候可以找一下cross-reference,或者直接搜索字符串。发现这里调用了FillImpl
:
然后,继续搜索这个函数的cross-reference,会发现在builtins-array.cc
的TryFastArrayFill
中使用了他,并且这个函数会被BUILTIN(ArrayPrototypeFill)
所调用。然后很明显这个函数就对应JavaScript中的Array.prototype.fill
。
总结一下,就是patch的函数是Array.prototype.fill
的底层实现之一,只要我们能够让传进去的end > capacity
,就可以OOB写。end
来自于end_index
,而这个来自于args.atOrUndefined(isolate, 3)
,即JavaScript的参数。
阅读一下这个函数,发现end_index
是从GetRelativeIndex
转换而来,而这个函数永远会保证返回的值小于等于array.length
,这个length其实一定小于等于后面的capacity。咋一看好像触发不了,但是其实是有一个小问题的,就是Object::ToInteger
可以调用JavaScript代码,然后在这个时候可以去收缩array
的长度,这样就可以在FillImpl
里面使得capacity < end
了。
具体PoC:
还有一点要注意,因为就算你收缩了arr的长度,实际上这后面能写到的地方也是未被使用的内存,所以我们需要调用一下GC,这样就可以让OOB写到有用的数据了。
接下来的利用就很常规了,首先通过堆风水,在arr后面分配另一个array,这样可以OOB写它的length,然后这个时候就能拿到一个oobArray
,把OOB写升级成OOB读写。
然后这个oobArray后面也得有一个ArrayBuffer
和一个web assembly function
的地址,这样就能leak,然后任意读写,在RWX页上写shellcode并且执行。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)