翻译附注:一直在分析关于PDF方面的漏洞,CVE-2009-3459是之前刚爆出来的漏洞,网上有这么一篇分析文章
自己试着翻译了一遍,并记录为以下文章,其中必然有语句不通,翻译错误的地方,还望指正。
在黑防上看到 泉哥 很多篇翻译的文章,请多多指点。
另附上:PDF格式及doc 格式文档各一份
Smashing Adobe's Heap Memory Management Systems for... Profit
原文地址为:
http://www.fortiguard.com/analysis/pdfanalysis.html
深入分析最新PDF 0day利用
2009. October.17
Research and Analysis: Haifei Li
Editors: Guillaume Lovet, Derek Manky(作者和编辑,不作翻译)
目录:
导言
概览
1. 漏洞
2. 开发
2..1神秘函数
2.2控制执行流程
2.3填充堆
2.4击溃PDF堆内存管理系统
3.记录嵌入的ShellCode的行为
结论
导言:
正如一份最近的Blog文章中的记录所指出的那样,通过比较计算机犯罪形式,安全行业对PDF漏洞的关注程度在持续不断的提升当中。
最近,一个高危险级别的新PDF 0day漏洞(CVE-2009-3459),在Adobe的Blog中被公布出来,在网络中正被积极利用。
至截稿时,此漏洞的补丁已经发布,并且我们强烈建议使用它。与此同时,修补此漏洞,安全厂商(AV(杀毒软件),IDS(入侵检测系统),IPS(入侵防御系统),等等)必须做出调整来阻止恶意PDF
文档利用此漏洞。
为此,为深入了解这个漏洞,本篇文档提供了一篇对网络上截获的恶意PDF的分析。
概述:
PDF格式文档大都有标签,参数和流组成,并且可以包含JavaScript代码。这个漏洞是Adobe Reader在处理一个特定参数触发的一个整数溢出漏洞。
当前,整数溢出是相当普遍的,但是利用它去执行任意代码却往往是非常困难并且相当有技巧性。成功利用此漏洞的人,采用了一中新颖的策略(尽管并不普遍,它只能在Adobe公司的应用程序上利用)。有5个基本步骤在这个利用中:
●一个参数被设置成一个特定的极大值在一个PDF文档中,Adobe Reader在一个操作中使用这个参数,触发整数溢出。后果:操作的结果值小于程序通过参数值所预期的大小。
●溢出值被用于在堆中分配一段缓冲区,这段缓冲区会因此小于给定的参数值。
●程序沿着正常流程,在PDF文档中,上述被溢出调整的调整的内容会按照Bit-Encoded编码在PDF文档的一个流中。一旦处理的流大于被分配的小的缓冲区,结果就回在堆内存中被覆盖(堆溢出),
●BitStream(比特流)控制的“调整”被攻击者给定(在PDF文档中),它精心特定的覆盖堆内存一段极小的部分。
由于可能的“调整”非常有限,最理想的情况是攻击者使用一个单字节来改变一个函数的指针(在堆上的一个C语言结构)。这个函数指针最终作为恶意代码(控制EIP)的一个传输点被调用。
当然确保恶意代码每次都会执行(不被Crash,等等)无疑是最难的一部分。如何确保在执行流程紧接着函数指针最终被改变后的而已代码仍然有效?
●通过填充填充NOP块,使其执行到ShellCode。这是理想的JavaScript嵌入PDF文档(典型的堆填充方法)。
这些步骤会在1,2节进行分析。
有人会说,当攻击者获得程序执行流程后会做什么仅仅是理论上的。这的确涉及到具体攻击实例,不同于一般的攻击利用:攻击部分代码将会在第三节进行分析。
1:漏洞
触发初始整数溢出(此利用样本)在恶意PDF文档的如下位置:
<<
/ParamX 1073741838 //关键参数(此处是经过替换的,原参数为Colors)
>>
/Length 299
/Filter /FlateDecode
>>
stream
[stream encoded by flate, original stream is: 00 00 20 00 00 00 10]
[流已经用flate编码,原流为00 00 20 00 00 00 10]
endstream
.text:003A7FB4 loc_3A7FB4: ; CODE XREF: sub_3A7ED0+1CDj
.text:003A7FB4 mov edx, [esp+3Ch+var_C] ; loop starts
.text:003A7FB8 mov eax, [esp+3Ch+arg_0]
.text:003A7FBC
.text:003A7FBC loc_3A7FBC: ; CODE XREF: sub_3A7ED0+E2j
.text:003A7FBC cmp eax, ecx ; if v_counter>bits_original_stream,
.text:003A7FBE jge loc_3A80A3 ; break from the loop
.text:003A7FC4 mov ebp, [esi+0Ch] ; [esi+0Ch] is 4000000Eh here
.text:003A7FC7 add eax, edi ; edi is 0
.text:003A7FC9 add eax, edx ; edx is 0
.text:003A7FCB cdq
.text:003A7FCC idiv ebp ; v_counter idiv 4000000Eh
.text:003A7FCE lea eax, [ecx+edi] ; edx became v_counter
.text:003A7FD1 mov ecx, [esi+10h]
.text:003A7FD4 cmp ecx, 3
.text:003A7FD7 lea ebx, [esi+edx*4+44h] ; lpBuff + v_counter*4 + 0x44
...
.text:003A805C loc_3A805C: ; CODE XREF: sub_3A7ED0+168j
.text:003A805C mov edx, [ebx]
.text:003A805E push edx
.text:003A805F mov edx, [esp+40h+var_20]
.text:003A8063 shl eax, cl
.text:003A8065 push edx
.text:003A8066 mov edx, [esp+44h+var_28]
.text:003A806A shl ebp, cl
.text:003A806C push ebp
.text:003A806D push eax
.text:003A806E mov eax, [esp+4Ch+arg_0]
.text:003A8072 add eax, edi
.text:003A8074 shl eax, cl
.text:003A8076 push edx
.text:003A8077 call sub_9D7850 ; will be analyzed later
.text:003A807C add esp, 14h
.text:003A807F
.text:003A807F loc_3A807F: ; CODE XREF: sub_3A7ED0+18Aj
.text:003A807F mov [ebx], eax ; overwrite the DWORD with the return value
.text:003A8081
.text:003A8081 loc_3A8081: ; CODE XREF: sub_3A7ED0+149j
.text:003A8081 ; sub_3A7ED0+163j
.text:003A8081 mov eax, [esp+3Ch+arg_0]
.text:003A8085 add [esp+3Ch+var_18], 2
.text:003A808A add [esp+3Ch+var_1C], 1
.text:003A808F mov ecx, [esp+3Ch+arg_4]
.text:003A8093 add eax, 1 ; v_counter++
.text:003A8096 cmp eax, [esi+0Ch] ; [ESI+0C]=0x4000000E, so keep looping
.text:003A8099 mov [esp+3Ch+arg_0], eax
.text:003A809D jl loc_3A7FB4 ; loop
for(;;) {
if( v_counter > bits_original_stream ) break;
tmp_counter = v_counter % ParamX;
lpCurrent = lpBuff + tmp_counter * 4 + 0x44;
iRetVal = mystery_func( *lpCurrent, variables...);
*lpCurrent = iRetVal;
v_counter++;
if( v_counter >= ParamX ) break;
.text:009D7884 mov esi, edi ; edi is v_counter
.text:009D7886 sar esi, 3 ; v_counter/8
.text:009D7889 add esi, [esp+1Ch+lp_original_stream] ; pass how many bytes
.text:009D788D mov ecx, edi
.text:009D788F movzx edx, byte ptr [esi] ; read next byte
.text:009D7892 and ecx, 7 ; pass how many bits in the next byte
.text:009D7895 mov eax, 8
.text:009D789A sub eax, ecx
.text:009D789C sub eax, ebp ; ebp is always 1
.text:009D789E mov cl, al
.text:009D78A0 shr edx, cl ; set the lowest bit as the corresponding bit
.text:009D78A2 and edx, [esp+1Ch+var_8] ; var_8 is always 1, so corresponding bit is the DWORD value
.text:009D78A6 cmp [esp+1Ch+arg_C], 0 ; arg_C is always 0
.text:009D78AC jz short loc_9D78BC ; jump
�
.text:009D78BC loc_9D78BC: ; CODE XREF: sub_9D7850+5Cj
.text:009D78BC mov ecx, [esp+1Ch+arg_10]; get the old_DWORD
.text:009D78C0 add ecx, edx ; new_DWORD = old_DWORD + corresponding-bit
.text:009D78C2 mov edx, ecx
.text:009D78C4
.text:009D78C4 loc_9D78C4: ; CODE XREF: sub_9D7850+6Aj
.text:009D78C4 and dl, [esp+1Ch+var_9]
.text:009D78C8 add edi, [esp+1Ch+arg_8]
.text:009D78CC mov [esp+1Ch+arg_10], ecx ; save the new_DWORD
�
.text:009D78E5 mov eax, [esp+18h+arg_10] ; return the new_DWORD
Breakpoint 0 hit
eax=02008b1c ebx=00000001 ecx=0012ed54 edx=0438afcb esi=0438af18 edi=0012eea0
eip=009f7868 esp=0012ed3c ebp=0438afcb iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
AcroRd32!AVAcroALM_IsFeatureEnabled+0x63e09:
009f7868 e863060000 call AcroRd32!AVAcroALM_IsFeatureEnabled+0x64471 (009f7ed0)
0:000> dd esp
0012ed3c 0012ed54 0438af18 02008b1c 00000000
0012ed4c 0210b734 01f2b424 0438afcb 00a8da8e
0:000> dd 02008b1c+80+90
02008c2c <b>0124da40</b> 00000544 0017ee98 ffffffff
02008c3c 00000000 00000000 00000000 00000000
Breakpoint 1 hit
eax=00000000 ebx=00000001 ecx=00000038 edx=00000000 esi=0438af18 edi=0012eea0
eip=009f786d esp=0012ed3c ebp=0438afcb iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
AcroRd32!AVAcroALM_IsFeatureEnabled+0x63e0e:
009f786d 83c40c add esp,0Ch
0:000> dd 02008b1c+80+90
02008c2c <b>0124da41</b> 00000544 0017ee98 ffffffff
02008c3c 00000000 00000000 00000000 00000000
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: