CVE公共漏洞和暴露分析报告2012-0774

所属分类: 网络安全 / 业界动态 阅读数: 188
收藏 0 赞 0 分享
一.漏洞描述
Adobe Reader在阅读PDF文件时使用一些公共格式载入字体说明,比如TrueTypeFont (TTF).<TTF是Apple公司和Microsoft公司共同推出的字体文件格式>
TTF中有几个片段负责格式化存储字体字形的描述,其中一个片段是字节码语言,它由TTF渲染器中的一个解释器执行。这个解释器是一个基于堆栈的虚拟机,因此它使用的大部分指令都以某种方式修改指令。MINDEX指令可以从栈中弹出一个值,并利用这个值作为一个索引进入栈区。该索引上的值被移到栈顶,栈中原有的值依次向下移动以填补移动索引值产生的空间。
MINDEX 指令的伪码:
     index = stack.pop()
     new_top = stack[index]
     for (i = 1; i<= index; i++)
     stack[i] = stack[i - 1]
     stack[0] = new_top
由于所有的栈操作都以4byte为单位,故而该索引值为了找到用于移动的位偏移值,会在Adobe Reader的解释器里进行乘以4的运算。但却没有对这个乘法运算进行整数溢出的检测。这个“索引”的原始值作为一个数字元素复制到一个循环中,如果这个“索引”足够大的(在进行乘4运算时能溢出一个小数值的)数值时,会导致缓冲区溢出。
1.补充
在解析文件时,首先查看“PDF key /FontFile2”可能会获得TTF数据。
    找到TTF数据段后,需要对其进行解析,并检查“glyf”表,每个字形条目都可以包含0个或多个TTF字节码格式的指令,需要对他们进行解码和模拟,一次来发现MINDEX指令。
    找到MINDEX指令后,需要检查位于栈顶的值(将被用做索引),如果这个值位于下列范围:0x40000001 <= index <= 0x7fffffff ,那么这个PDF文件应标记为恶意的PDF文件。
二、   调试环境与工具
环境:Windows XP3 +    AdobeReader9.4.0.195
工具:OllbDBG + IDA Pro + 010 Editer
三、   调试记录
载入POC后程序出现内存访问异常:
080079CE  MOV DWORD PTR DS:[ECX],EBX   ;ECX=0823F000,EBX=0
 
 




ALT+M查看内存窗口,发现程序尝试是向CoolType.dll的.rscr段写入数据,而.rscr段内存一般都只读的,在执行MOV DWORD PTR DS:[ECX],EBX发生了内存访问异常。
 
按MAPP的描述,发生异常的位置在MINDEX 指令处,载入IDA看看这段代码:
回头再看看图1中的EDX,EDX是一个很大的值,而字节码解释器的堆栈位于CoolType.dll的.dada内存中。MINDEX 指令处在取栈最上面的索引值后,跟据索引值计算出偏移量去取值后,堆中的元素向下移动去填补取出值的位置(堆的增长方向是向高地址与windows程序中的堆栈不同),即高地址的4个字节复制到相邻的低地址的4个字节,如果这个栈中的索引没有验证大小,MINDEX 指令在移动数据直到索引值为0才停下,如果在移动过程中覆盖到重要的数据,此漏洞可变为可利用的漏洞。
 
.text:0800798B MINDEX          proc near               ; CODE XREF: sub_800690E+49p
.text:0800798B                                         ; sub_806C605+48p
.text:0800798B                                         ; DATA XREF: .data:0821BF68o
.text:0800798B
.text:0800798B arg_0           = dwordptr  4
.text:0800798B
.text:0800798B                 moveax, StackTop
.text:08007990                 movecx, Var
.text:08007996                 push    ebx
.text:08007997                 push    esi
.text:08007998                 movesi, [ecx]      ; stack.base
.text:0800799A                 lea     edx, [eax-4]
.text:0800799D                 cmpedx, esi        ; 弹出一个值后的堆栈地址是否大于或栈基
.text:0800799F                 push    edi
.text:080079A0                 jb      short FailRet
.text:080079A0
.text:080079A2                 movedi, [ecx+154h] ; Stack.Limit?
.text:080079A8                 cmpedx, edi        ; 栈顶是否大于stack.limit
.text:080079AA                 jnb     short FailRet
.text:080079AA
.text:080079AC                 add     eax, 0FFFFFFFCh ; -4
.text:080079AF                 movedx, [eax]      ; 取索引
.text:080079B1                 movebx, edx
.text:080079B3                 shlebx, 2          ; 计算出偏移量,偏移量=索引*4
.text:080079B6                 movecx, eax
.text:080079B8                 sub     ecx, ebx         ;ebx=偏移量
.text:080079BA                 cmpecx, esi
.text:080079BC                 jb      short FailRet
.text:080079BC
.text:080079BE                 cmpecx, edi
.text:080079C0                 jnb     short FailRet
.text:080079C0
.text:080079C2                 test    edx, edx
.text:080079C4                 movedi, [ecx]      ; 保存取出的值。
.text:080079C6                 jle     short loc_80079D7
.text:080079C6
.text:080079C8
.text:080079C8 Moving:                                 ; CODE XREF: MINDEX+47j
.text:080079C8                 decedx
.text:080079C9                 lea     esi, [ecx+4]
.text:080079CC                 movebx, [esi]
.text:080079CE                 mov     [ecx], ebx
.text:080079D0                 movecx, esi
.text:080079D2                 jnz     short Moving
.text:080079D2
.text:080079D4                 sub     eax, 4
.text:080079D4
.text:080079D7
.text:080079D7 loc_80079D7:                            ; CODE XREF: MINDEX+3Bj
.text:080079D7                 mov     [eax], edi
.text:080079D9                 add     eax, 4
.text:080079DC                 movStackTop, eax
.text:080079E1                 moveax, [esp+0Ch+arg_0]
.text:080079E5                 jmp     short loc_80079F6
.text:080079E5
.text:080079E7 ; ---------------------------------------------------------------------------
.text:080079E7
.text:080079E7 FailRet:                                ; CODE XREF: MINDEX+15j
.text:080079E7                                         ; MINDEX+1Fj MINDEX+31j
.text:080079E7                                         ; MINDEX+35j
.text:080079E7                 moveax, dwEIP
.text:080079EC                 mov     dword_8232434, 1110h
.text:080079EC
.text:080079F6
.text:080079F6 loc_80079F6:                            ; CODE XREF: MINDEX+5Aj
.text:080079F6                 pop     edi
.text:080079F7                 pop     esi
.text:080079F8                 pop     ebx
.text:080079F9                 retn
.text:080079F9
.text:080079F9 MINDEX          endp
 
四、字节码相关分析
通过日志断点打印字节码信息,发现此索引是跟据glyf中的字节码数据计算出来的。
1.    打PCode长度信息:
 
2.设置打印PCode地址信息日志断点:
 
 
 
3.打印虚拟机”指令”信息:
 


4.虚拟机指令执行前的当前堆栈数据:
 
 
5.指令结束后的当前虚拟机堆栈的数据:
 
6.指令分隔符号信息,便于查看信息:
 








OllyDBG重新载入AdobeReade.exe,在MINDEX 指令的首地址下普通断点后,打开poc文件后开始打印日志,程序停下来之后查看最后的记录:
08006927  条件: PCode = 02DD6B33
08006928  条件: Instruction = 0026
08006956  条件: 执行前堆栈[vm_esp] = 40000001
0800798B  断点位于<CoolType.MINDEX>
从打印的信息来看MINDEX 指令是0x26,当前堆栈为[vm_esp] = 0x40000001.
0x40000001正好当前栈的索引值。Eax值指向当前PCode的地址。
 
从分析日志来看:
索引的值是7fff + 7fff + 3FFF0003
08006927  条件: PCode = 02DD6B2A
08006928  条件: Instruction = 0078//跳转指令
08006956  条件: 执行前堆栈[vm_esp] = 00000000
0800695E  条件: 执行后[vm_esp] = 3FFF0003
08006962  条件: **********************************************************************
08006927  条件: PCode = 02DD6B2B
08006928  条件: Instruction = 0041Push_Imm16,将7fff,7fff压入堆栈再相加
08006956  条件: 执行前堆栈[vm_esp] = 3FFF0003
0800695E  条件: 执行后[vm_esp] = 00007FFF
08006962  条件: **********************************************************************
08006927  条件: PCode = 02DD6B31
08006928  条件: Instruction = 0060  ADD [ESP-4],[ESP]
08006956  条件: 执行前堆栈[vm_esp] = 00007FFF
0800695E  条件: 执行后[vm_esp] = 0000FFFE7fff + 7fff = fffe
08006962  条件: **********************************************************************
08006927  条件: PCode = 02DD6B32
08006928  条件: Instruction = 0060ADD [ESP-4],[ESP]
08006956  条件: 执行前堆栈[vm_esp] = 0000FFFE 
0800695E  条件: 执行后[vm_esp] = 40000001 3FFF0003 + fffe = 40000001
08006962  条件: **********************************************************************
08006927  条件: PCode = 02DD6B33
08006928  条件: Instruction = 0026 MINDEX 指令
08006956  条件: 执行前堆栈[vm_esp] = 40000001
0800798B  断点位于<CoolType.MINDEX>  
 
再往上查看日志3FFF0003是从哪来的:
分析日志得知:00FFFC00 + 3EFF0403 = 3FFF0003
08006962  条件: **********************************************************************
08006927  条件: PCode = 02DED7D2
08006928  条件: Instruction = 0041
08006955  条件: 执行前VM_ESP地址= 08236230
08006956  条件: 执行前堆栈[vm_esp] = 3EFF0403
0800695E  条件: 执行后[vm_esp] = 00007FFF
0800695F  条件: 执行后VM_ESP地址= 08236238
08006962  条件: **********************************************************************
08006927  条件: PCode = 02DED7D8
08006928  条件: Instruction = 0063
08006955  条件: 执行前VM_ESP地址= 08236238
08006956  条件: 执行前堆栈[vm_esp] = 00007FFF
0800695E  条件: 执行后[vm_esp] = 00FFFC00
0800695F  条件: 执行后VM_ESP地址= 08236234
08006962  条件: **********************************************************************
08006927  条件: PCode = 02DED7D9
08006928  条件: Instruction = 0060ADD [ESP-4],[ESP]
08006955  条件: 执行前VM_ESP地址= 0823623408236234的值是7FFF而08236234-4的值是3EFF0403
08006956  条件: 执行前堆栈[vm_esp] = 00FFFC00
0800695E  条件: 执行后[vm_esp] = 3FFF0003   00FFFC00 + 3EFF0403 = 3FFF0003
0800695F  条件: 执行后VM_ESP地址= 08236230
08006962  条件: **********************************************************************
 
日志最开始的地方显示PCode的长度为0x79:
08006917  条件: Pcode长度= 00000079
 
一直通过追述到源头到发现此值是在一个循环中逐步增加计算索引的一个过程。
复制内存中的PCode在010 Editer中查看:

 
最后此漏洞分析到此完成了,还有很多东西不相关的分析没有贴上来,对于文件格式不明白,所以还有很多东西搞不清楚
更多精彩内容其他人还在看

安卓7.0解决部分勒索软件问题 安卓7.0包含正义代码

有一天打开电脑,发现电脑已经被锁住,窗口弹出说明:如果你不给钱,就把你的电脑清空,这就是遇到了勒索软件。近年来,这种勒索已经频频出现在安卓手机上,手机里的重要资料可能比电脑里还多,这时候怎么办,真的不得不给它钱?安卓7.0的发布,带来了正义的守护
收藏 0 赞 0 分享

乌云漏洞平台被连锅端?互联网安全缺失的到底是什么

还记得我们之前说过的有个白帽子提交了世纪佳缘的漏洞然后被世纪佳缘告了的事情吗?这件事情引起了国内很多白帽黑帽的关注,如今事情又发酵,中国最大的两大漏洞平台——乌云和漏洞盒子同时出现状况。我们想看到这方面的监管和立法能跟上时代,仅此而已
收藏 0 赞 0 分享

struts2安全漏洞分析

Struts2是apache项目下的一个web 框架,普遍应用于阿里巴巴、京东等互联网、政府、企业门户网站
收藏 0 赞 0 分享

Struts2 S2-016漏洞修复总结

这篇文章主要介绍了Struts2 S2-016漏洞修复总结,需要的朋友可以参考下
收藏 0 赞 0 分享

世界顶尖的[白帽子] 全球TOP7 漏洞猎人

未来的互联网最重要的不是速度,不是容量,而是安全。黑客这个词很多人已经耳熟能详,虽然他们是一群神秘的人,但不能判断他们是不是好人,越厉害的往往威胁越大。其实有一群厉害的好人,他们就是“白帽子”,中国之前被告的那个,就是白帽
收藏 0 赞 0 分享

支付宝花呗套现隐患多多 骗子已经形成产业链

支付宝花呗是支付宝提供的第三方信用平台,根据你的消费购物信用给你透支额度,给很多不想办信用卡的人带来了很多方便,但是,最近出现的利用花呗套现的人,却在不知不觉中跌入了骗子的陷阱
收藏 0 赞 0 分享

微软紧急安全公告 当心SQL攻击爆发

就在前不久微软给出了修复IE危急安全漏洞的补丁,今天,微软又发布了新的安全公告,提醒广大用户在SQL服务器数据库软件中存在一个严重的漏洞——存在于一个名为 “sp_replwritetovarbin”的储存程序中,该漏洞会影响到Mi
收藏 0 赞 0 分享

腾讯新漏洞?绕过加密QQ空间

 相信有很多网友都在使用QQ空间,可以利用QQ空间来记录自己的心情。但有的时候自己的QQ空间并不想让其他人知道,那么就需要在QQ空间上设置权限或密码,只有有权限或知道密码的网友才能查看自己的QQ空间。   但现在要小心了,有一款名字为“风很凉QQ加密空间日志查
收藏 0 赞 0 分享

互联网老兵谈中国黑客史:放弃理想而追逐短利

  5.19断网事件后,对黑客的系列报道重新引发了人们对中国黑客的思考。应网易科技之邀,且和“道上”的朋友为多年深交,撰写“中国黑客史”一文,希望还原一个真实的中国黑客世界。   “黑客”一词来源于英语动词
收藏 0 赞 0 分享

木马病毒产业链 木马制作和分销

无论通过哪种方式,从受害者账号里盗窃出来的虚拟物品最终都将在游戏里被兑换成最容易流通的虚拟物品,并转移到某个仓库账号以方便在类似淘宝、5173这样的虚拟交易平台上完成销赃,最终变成人民币。
收藏 0 赞 0 分享
查看更多