文章作者:walkerfuz
0×00 写在前面
站在巨人的肩膀上,才能看的更远,开发项目亦是如此。
四年前开源的Grinder项目,和借助于它运行的nduja,着实让浏览器漏洞挖掘飞入了寻常百姓家。但随着时间的考验,Grinder也遇到了让人爱恨交加的尴尬:明明产生了Crash,可就是无法重现。有多少人和我一样,从初识Grinder的激动,到分离时的落寞,也见证了一代怀揣梦想的挖洞人的足迹。
在现有项目的基础上,对其进行改进,乃是一种进步,于是出现了Morph项目。
Morph起初的定位就是解决Grinder架构中存在的本质问题:样本无法稳定重现,所以才有了前面《 浏览器挖掘框架Morph诞生记 》中讲述的“静态随机数组”的尝试,但随之带来的并发症却是:样本难以精简。
本文正是为解决这个问题而产生的,笔者采用一种Grinder log静态化的方式,将原本Grinder中采用DLL注入截获log语句的方式改进为提前生成静态精简样本的方式,从根本上解决样本无法稳定重现和难以精简两大难题,为浏览器漏洞挖掘工作提供新的思路。
0×01 我们需要什么格式的样本?
前面《 浏览器挖掘框架Morph诞生记 》中介绍过一种“静态随机数组”方法,用来解决Grinder log记录容易出现样本无法稳定重现的问题。笔者在开发出Morph v0.2.5之后进行了大规模部署测试,也得到了一些可以稳定重现的Crash结果,但拿到样本想进一步分析时,却遇到了难题。得到的Crash样本是如下形式的HTML文档:
<script type='text/javascript'>var mor_array = [675, 142, 861, 226, 112, 157, 667, ...... 147, 368, 10, 1];//元素个数有可能上万个var mor_index = 0 ;// Pick a random number between 0 and Xfunction rand( x ){ index = (mor_index++) % (mor_array.length); return mor_array[index] % x;}function R(mod) { return rand(10000) % mod;}......function tweakattributes(elem,i){ for( var p in elem){//这里的循环要依次调用上面的mor_array数组中的元素 try { r=rand_item(interesting_vals); elem.setAttribute(p,r); } catch (exception) {} }}......function buildElementsTree(){ elementTree=[]; for (k=0;k<200;k++){//这里的循环要依次调用上面的mor_array数组中的元素 r=rand_item( elements ); elementTree[k]=document.createElement(r); elementTree[k].id="el"+k; rb=R(document.all.length); document.all[rb].appendChild(elementTree[k]); tweakattributes(elementTree[k],k); } }}function morph_fuzz(){ buildElementsTree(); ...... }</script><body onl oad="morph_fuzz()">