欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

从零开始学Fuzzing系列:带领nduja突破Grinder的壁垒

来源:本站整理 作者:walkerfuz 时间:2016-05-30 TAG: 我要投稿

四年前开源的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文档:
html>
head>
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 X
function 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;k200;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>
head>
body onload="morph_fuzz()">body>
html>
要想在上述样本中定位到是哪个js语句最终导致crash,必须依次读取静态数组,一步步调试执行buildElementsTree和tweakattributes函数中的for循环,拆解得到相关js语句。而且该语句有可能与之前循环的某个语句还有联系,必须将两者或更多的语句都定位出来才能得到完整的POC样本。
显而易见,如此分析起来,是极其繁琐的。用一句话形容这些样本:食之无味,弃之可惜。
那我们到底需要什么格式的样本呢?搞过浏览器漏洞分析的人员都知道,平常分析的POC都是这样的:
html>
head>
script>
function exploit()
{
 var e0 = null;
 var e1 = null;
 var e2 = null;
 try {
  e0 = document.getElementById("a");
  e1 = document.createElement("div");
  e2 = document.createElement("q");
  e1.applyElement(e2);
  e1.appendChild(document.createElement('button'));
  e1.applyElement(e0);
  e2.innerHTML = "";
  e2.appendChild(document.createElement('body'));
 }catch(e){ }
 CollectGarbage();
}
script>
head>
body onload="exploit()">
form id="a">form>
body>
html>
稍微跟踪调试即可确定crash产生的原因。另外,用Grinder成功重现出Crash样本的童鞋也知道,得到的POC样本通常都是这种格式:
html>
body>body>
script>var createdObjects={}
var c = document.createElement("CANVAS")
c.width = 1000
c.height = 1000
document.body.appendChild(c)
var img = new Image()
img.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAANlBMVEX///+6v8a2u8PKztPAxcu7wMf4+fm0ucH =="
try{ ctx = c.getContext("2d")} catch(e){}
try{ HTML0= document.createElement("MENU")} catch(e){}
try{ createdObjects["HTML0"]=HTML0} catch(e){}
try{ document.body.appendChild(HTML0)} catch(e){}
try{ P0= new Path2D()} catch(e){}
try{ createdObjects["P0"]=P0} catch(e){}
try{ ctx.height="36191.05884594913180334528604"} catch(e){}
try{ delete createdObjects['HTML0']} catch(e){}
try{ ctx.translate(-0.9872812044341117,0)} catch(e){}
try{ ctx.getLineDash()} catch(e){}
try{ CollectGarbage()} catch(e){}

[1] [2] [3] [4]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载