深入分析一个Pwn2Own的优质Webkit漏洞
来源:岁月联盟
时间:2020-01-29
ZDIs-Mac:webkit_ga_asan zdi$ cat lldb_cmds.txtenv DYLD_FRAMEWORK_PATH=/Users/zdi/webkit_ga_asan/WebKitBuild/Release env MALLOC_PERMIT_INSANE_REQUESTS=1r
JSC_dumpDFGDisassembly将以AT&T格式转储程序集,因此我们运行deassembly-s 0x6400042d1c22-c 70可以获得英特尔风格的程序集,结果如下:

让我们尝试匹配emitAllocateButterfly()中的一些代码。查看程序集列表,我们可以匹配以下内容:

接下来分析机器代码,此时需要设置断点。为此,我们在编译之前向jsc.cpp添加了一个dbg()函数。这将有助于在我们需要的时候进入JS代码。编译器报错显示未使用EncodedJSValue JSC_HOST_CALL functionDbg(ExecStateexec)函数中的exec,因此失败。为了解决这个问题,我们只添加了exec->argumentCount();这不会影响执行。
让我们在这里添加dbg(),因为实际的NewArrayWithSpread函数将在创建bigarr期间执行。

再次JSC_dumpDFGDisassembly=true lldb -s lldb_cmds.txt WebKitBuild/Release/jsc ~/poc3.js运行将会导出编译代码:

在bigarr创建之前中断,您可以看到NewArrayWithSpread的机器代码。让我们在函数的开始处放置一个断点并继续执行。

断点生效:

接下来,我们需要仔细分析断点信息:

那么这里到底发生了什么?还记得PoC中的下面这部分信息吗?

mk_arr函数创建一个数组,第一个参数作为大小,第二个参数作为元素。大小为(0x20000000+0x40)/8=0x4000008,这将创建一个大小为0x4000008、元素值为0x41414141410000的数组。i2f函数用于将整数转换为浮点值,以便最终在内存中得到预期值。
我们现在知道rcx指向对象a的butterfly-0x10,因为它的大小是rcx+8,这使得butterfly rcx+0x10。在这段代码的其余部分中,我们看到r8、r10、rdi、r9、rbx、r12和r13都指向对象a的一个副本-具体来说是八个副本,edx不断地添加每个副本的大小。

此时,edx的值变成了0x20000040:

那么这八个a拷贝到了哪里呢?值0x20000040代表的又是什么呢?
重新看看PoC:

这意味f变成了:

f通过扩展NUM_SPREAD_ARGS(8)第一个参数的副本和第二个参数的单个副本来创建数组。用对象a(80×04000008)和c(长度1)调用f。当NewArrayWithSpread被调用时,它为8个a和1个c腾出了空间。
最后一步到显示对象c的长度,这使得最终的edx值为0x20000041。

下一步应该是长度的分配,它发生在emitAllocateButterfly()中。

我们注意到shl r8d,0x3的溢出,其中0x20000041被封装到了0x208。当分配大小传递给emitAllocatevariableSize()时,它变为了0x210。

我们看到的越界读取访问冲突发生在mov qword ptr[rcx+8rsi],r8的以下代码片段中。这个代码片段的问题是用错误的大小0x20000041反向迭代新创建的butterfly,而溢出后的实际大小是0x210。然后,它将每个元素归零,但由于内存中的实际大小远小于0x20000041,因此在ASAN构建中发生了了越界访问冲突。
上一页 [1] [2] [3] 下一页