吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8175|回复: 2
收起左侧

[漏洞分析] Adobe Reader 'CoolType.dll' TTF字体溢出漏洞分析

[复制链接]
riusksk 发表于 2011-5-16 09:33
作者:Nicolas Joly
译者:riusksk(泉哥:http://riusksk.blogbus.com

本文旨在与大家分享一些关于最近Adobe Acrobat/Reader 0-Day exploit(CVE-2010-2883)的技术细节。在VUPEN组织中,我们分析了大量的漏洞和0day,并且针对各类程序和操作系统编写出相当完善的exploit代码。近几月来,我们编写了许多关于Adobe Reader漏洞的利用代码,并且均可绕过DEP保护。

那为何本0day exploit会如此有趣呢,以致我们还需著文一篇呢?因为它使用了一些令人难忘的奇淫异技,以及一些非常手段以此绕过DEPASLR保护,这在我们平时是很少见的。也许部分人已经知晓,在本漏洞中,经过恶意构造的PDF文件可利用”CoolType.dll”中的非安全函数”strcat()”导致溢出漏洞的发生。当PDF文件以特制表段来嵌入字体时,即可以此触发漏洞。
.text:0803DCF9 push ebp
.text:0803DCFA sub esp, 104h
.text:0803DD00 lea ebp, [esp-4]
.text:0803DD04 mov eax, dword_8230FB8
.text:0803DD09 xor eax, ebp
.text:0803DD0B mov [ebp+108h+var_4], eax
.text:0803DD11 push 4Ch
.text:0803DD13 mov eax, offset loc_8184A54
.text:0803DD18 call__EH_prolog3_catch                     
// setup an SE handler
.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

当字体文件中的SING表段被找到后,程序执行以下指令:
.text:0803DD74 push offset aSing ;
"SING"
.text:0803DD79 push edi ; int
.text:0803DD7A lea ecx, [ebp+108h+var_12C]
.text:0803DD7D call sub_8021B06
...
.text:0803DD9F loc_803DD9F:
.text:0803DD9F add eax, 10h
.text:0803DDA2 push eax           
                             // long string following the SING table
.text:0803DDA3 lea eax, [ebp+108h+Dest]
.text:0803DDA6 pusheax         
                              // ~256 bytes stack buffer
.text:0803DDA7 mov [ebp+108h+Dest], 0
.text:0803DDAB callstrcat                                       
//insecure!

为了利用此漏洞,通常黑客都是通过覆写返回地址或者SEhandler,但这里它可能就行不通了。因为它存在一个stackcookie,从而阻止返回地址被利用,而当进入一个设置了异常处理例程的函数后,其栈情况如下:
|      SE     |
|  NEXT SE

|
|     DEST  | <--vulnerable buffer
|      ...   

|
|  COOKIE |
|      EBP  

|
| RET ADD |

如上所示,如果你覆写了返回地址,那么cookie也会被改写,进而阻止恶意代码的运行。而如果你继续覆写下去直到触发异常,那么你就可以步过cookie,然后将控制权交由SE handler处理。显然,这种解决方法并没有什么特别之处。还有另一种方法,就是覆盖函数中的参数或者变量。这里攻击者也正好是使用这种方法,当他覆盖了栈空间后,在BIB.dll中出现首次异常,因为下一个调用函数使用了这一个覆盖的参数:
.text:0803DDB0 pop ecx
.text:0803DDB1 pop ecx
.text:0803DDB2 lea eax, [ebp+108h+Dest]
.text:0803DDB5 push eax
.text:0803DDB6 mov ecx, ebx
            // ebx actually points to arg_4, which is overwritten
.text:0803DDB8 call sub_8001243

然后:
.text:070013F7 lea eax,[ecx+1Ch]        
// ecx = [arg_4]
.text:070013FA mov [ebp+var_8], eax
.text:070013FD mov eax, [ebp+var_8]
.text:07001400 lock dec dword ptr [eax]
//first crash here

若指向了一个无效地址,那么首次异常将会在0x07001400地址触发,进而执行SE handler,最终导致AdobeAcrobat/Reader崩溃。因此必须设置一个有效指针,至少得允许程序可以在内存中任意递减一个dword字节,这也着实有效(例如CVE-2008-4812)。但即便如此,也很难编写出一个可以绕过DEPASLRexploit。不过sub_8016BDE给我们带来了希望,它将两个指针压入栈中作为参数:
.text:0803DEA9 loc_803DEA9:
.text:0803DEA9
.text:0803DEA9 lea eax, [ebp+108h+var_124]
.text:0803DEAC push eax
.text:0803DEAD push ebx
.text:0803DEAE pushedi                 
  // ebx and edi point to arg_4 and arg_0
.text:0803DEAF call sub_8016BDE

上面这段代码实际上是以arg_0为参数来调用sub_8016BDE,而sub_8016BDE将返回0或者一个指针。如果返回0,那么程序将会跳到地址0x080172CE,然后退出函数。但如果是返回一个指针,那么sub_801BB21(以arg_0作为其中的一个参数)将被调用。
.text:08016C2B push edi
.text:08016C2C mov [ebp+664h+var_668], ebx
.text:08016C2F mov [ebp+664h+var_694], ebx
.text:08016C32 mov [ebp+664h+var_678], ebx
.text:08016C35 callsub_801BB1C      
//return 0 or a pointer
.text:08016C3A cmp eax, ebx
.text:08016C3C pop ecx
.text:08016C3D mov [ebp+664h+var_67C], eax
.text:08016C40 jz loc_80172CE
.text:08016C46 push 1
.text:08016C48 push ebx
.text:08016C49 push ebx
.text:08016C4A lea eax, [ebp+664h+var_678]
.text:08016C4D push eax
.text:08016C4E lea eax, [ebp+664h+var_694]
.text:08016C51 push eax
.text:08016C52 push edi
.text:08016C53 push [ebp+664h+var_67C]
.text:08016C56 callsub_801BB21      
//this call must be reached

函数sub_801BB1C执行后:
.text:0801BA57 mov eax, dword_823A728
.text:0801BA5C test eax,eax            
// the attacker does not control this pointer
.text:0801BA5E jz short locret_801BA73
.text:0801BA60 mov ecx, [esp+arg_0]
//however ecx may point to a controlled dword
.text:0801BA64 mov ecx, [ecx+4]
.text:0801BA67
.text:0801BA67 loc_801BA67:
.text:0801BA67 cmp ecx, [eax+4]
.text:0801BA6A jz short locret_801BA73
.text:0801BA6C mov eax, [eax+8]
.text:0801BA6F test eax, eax
.text:0801BA71 jnz short loc_801BA67
.text:0801BA73
.text:0801BA73 locret_801BA73:
.text:0801BA73
.text:0801BA73 retn

这里ECX必须等于[eax+4],以便使函数能够返回除NULL以外的值,那么eax+4 必须指向哪个值呢?
0x0000006c
0x0000006b
0x00000070
0x0000006f
0x0000006d

由于strcat要被利用,因此null字节是不能使用的!此处令arg_0 + 4指向0x0000006D,这意味着此值是不可随意更改的,以便限制拷入栈中的字节数。这也正是exploit作者没有覆盖整个栈空间,而只覆盖部分空间的原因所在。最后进入sub_801BB21sub_808B116
.text:0808B2E3 mov eax, [edi+3Ch]
// edi = arg_0, but edi + 3Ch points to astack pointer,
                                                    // itself pointing to a controlled value

.text:0808B2E6 cmp eax, ebx
.text:0808B2E8 mov [esi+2F4h], eax
.text:0808B2EE mov [esi+2F8h], ebx
.text:0808B2F4 mov [ebp+var_4], ebx
.text:0808B2F7 jnz short loc_808B300
.text:0808B2F9
.text:0808B2F9 loc_808B2F9:
.text:0808B2F9 xor al, al
.text:0808B2FB jmp loc_808B594
.text:0808B300
.text:0808B300 loc_808B300:
.text:0808B300 lea ecx, [ebp+var_4]
.text:0808B303 push ecx
.text:0808B304 push ebx
.text:0808B305 push 3
.text:0808B307 push eax
.text:0808B308 call dword ptr [eax]
// EIPis redirected here

故事到此就可以结束了,但关于ROP技术还是比较少见的。取icucnv36.dll上的地址并不能实现各版本的通用性(至少在9.2.0版本以上),并且不能绕过ASLR。不过有位exploit作者对同一恶意pdf文件进行了改进,他在上面提及的dll文件上(阅读器版本>= 9.20)使用了ROP技术,借此达到攻击目的。这一DLL确实有趣,他并不是使用了函数VirtualAlloc,VirtualProctect,HeapCreate,WriteMemory,甚至连LoadLibrary也没有,这个利用起来有点复杂。他是通过查找并使用了以下函数:
4A84903CCreateFileA               
// create the file iso88591
4A849038 CreateFileMappingA   
//attrib RWE
4A849030 MapViewOfFile           
//load this file in memory with RWE flags
4A849170memcpy                  
//copy the payload

攻击者是想利用ROP模块进行堆喷射,而其后用shellcode填充。他先在磁盘上创建一个文件(iso88591),然后以RWE属性将其加载到内存中,接着将payload复制到内存,最后执行shellcode。这一exploit先将ESP指向欲喷射的地址:
.text:4A80CB38 add ebp, 794h
.text:4A80CB3E leave
.text:4A80CB3F retn

返回后来到:
.text:4A82A714 popesp            
// esp = 0x08852030
.text:4A82A715 retn

0x08852030实际指向一块由同一ROP地址所覆盖的空间,以实现栈喷射:
.text:4A801064 retn

接着返回到ROP地址,然后将所创建的文件映射到一块可执行的内存页,该地址popeax中,然后以下列指令实现调用:
.text:4A80B692 jmp dword ptr [eax]

现在你可以注意到动态参数已被写入栈中:
.text:4A80A8A6 and dword ptr [2*ebx + esp], edi

.text:4A80A8A9 jnz short loc_4A80A8AE
...
.text:4A80A8AE loc_4A80A8AE:
.text:4A80A8AE cmp al, 2Fh
.text:4A80A8B0 jz short loc_4A80A8AB
.text:4A80A8B2 cmp al, 41h
.text:4A80A8B4 jl short loc_4A80A8BA
...
.text:4A80A8C8 loc_4A80A8C8:
.text:4A80A8C8
.text:4A80A8C8 xor al, al
.text:4A80A8CA retn

最后它调用memcpy,然后跳到payload执行任意代码,即使开启了DEPASLR,亦均可无视。

至于此漏洞是通过fuzzing还是静态分析挖掘到,这就不得而知了。但很显然,攻击者对此exploit的巧妙设计,足以表明作者对Acrobat,LiveCycle,JavascriptROP技术熟知的深厚功底,并对调试器的运用也是相当娴熟。

事实上,这是一个典型的案例,对于同一DLL文件,同一个exploit文件,攻击者依然能够在在不同版本的程序、操作系统(windows XPVista7)上执行成功,即使开启了各类安全机制,依然能够凑效。
注意,存在同类安全问题的DLL文件也存在于微软的主产品中……

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

wungleon 发表于 2011-6-7 17:14
居然还有沙发   路过留名
liuxianlin7 发表于 2012-2-7 15:24
这个利用方法很牛啊。现在windows的安全机制很安全了。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-2 05:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表