CVE-2010-2883
漏洞描述
Adobe Reader的CoolType.dll库在解析字体文件SING表格中的uniqueName项时存在栈溢出漏洞,用户打开了特制的PDF文件可能导致执行任意代码。
漏洞分析
用IDA反汇编CoolType.dll库,查看字符串可发现“SING”字体,直接定位进去即可查看到该库对sing表格的解析方式,主要是strcat造成的溢出漏洞:
漏洞利用
利用PdfStreamDumper导入利用漏洞的PDF文件,在Object中找到Sing的Object,右键选择Save Decompressed Streams保存到本地。在保存的文件中能看到TableEntry数据结构
官方文档对TableEntry结构的定义
typedef sturct_SING
{
char tag[4];//"SING"
ULONG checkSum;//校验和
ULONG offset;//相对文件偏移
ULONG length;//数据长度
} TableEntry;
根据TableEntry结构可知从SING入口偏移0x11c为SING真实数据,在参考SING表的数据结构文档(参考官方文档或《漏洞战争》)知道SING从真实数据偏移0x10为uniqueName域,从代码上可以看出strcat是将uniqueName复制到栈空间,直至遇到NULL字符串终止符。
在调试中也能看出
如果uniqueName域超过正常大小,那么将破环这个函数的堆栈造成溢出,精心构造的数据可以控制程序的EIP执行任意代码。但在strcat后面还有其它代码执行,可能会用到栈中的数据,所以在构造EXP的时候要注意那些地方要用到破坏后的数据,要调整这些地址上的数据以满足代码执行逻辑,以防未控制EIP前程序先异常。当然也可以利用SEH异常处理模块,通过覆盖SEH指针控制EIP。
当执行完strcat函数后,查看0012E4E4这片数据调用的地方,对这片区域下内存访问断点然后执行,在这中间会在BIB这个模块中断很多次,这里面对0012E4E4数据的处理并不会引发异常,所以跳过。然后会断在CoolType.dll中0800124B这个位置,在OD中可以看到代码获取了0012E614这个位置的数据
从代码可以看出esi的值为ecx所赋,也可以知道ecx为this指针,而exc的值0012E614中的数据也在被覆盖范围内,所以在构造exp的时候要注意this指针的值,以免引发异常。在这个exp中的使用的数据为4A8A08C6。而这个地址是icucnv36中的一个地址,在《漏洞战争》中提到这个地址必须为可读写的,但我在调试的时候该地址为读属性,但也并未异常。
继续执行下去,程序会断在0808B1C0这个地址,而这个地址的获取也是从buffer中获取,可以看出这句代码直接call了buffer中的数据4A80CB38,也相当于我们控制了程序的EIP。
4A80CB38位于icucnv36模块中,其对应的指令为
继续执行retn返回到4A82A714
程序继续执行返回到08852030中数据指向的地址,08852030中的数据如下,可以看出该数据为Heap Spary。而4A801064的代码为retn,所以程序一直弹栈。
一直执行到ESP值改变,变成4A8063A5,EIP将跳转到4A8063A5执行
后面的代码就是利用ROP绕过DEP保护,将shellcode拷贝到一段可读可写可执行的地址执行。理论上也可以通过ROP调用VirtualProtect修改shellcode所在位置的属性为可读可写可执行进而执行shellcode。
在构造ROP指令时均使用icucnv36模块中的地址,因为icucnv36.dll不受ASLR保护,因此也可以用于绕过ASLR保护。
嵌入到PDF中的javascript代码实现Heap Spary,进而执行ROP,最后跳入shellcode执行。