flash漏洞調試技巧

本週中心抓到一個在野的flash 0day(相關信息見此連接),因而又撿起了一年多的flash 漏洞的相關知識,遂總結一下。函數

普通的trace

調試flasher樣本通常建議使用調試版的flash player,在調試版本下能夠輸出swf文件運行時的相關日誌,便於進行相關的分析,安裝以後會在家目錄(C:\User\<your name>mm.cfg)生成該文件(早期的flash調試版本不會生成該文件,須要手動生成)。spa

 

文件中包含如下配置選項,手動生成的話紅色框中的選項爲必選項,用於告訴flash生成錯誤日誌及trace日誌(對應的日誌文件保存在C:\Users\<your name>\AppData\Roaming\Macromedia\Flash Player\Logs目錄下)。.net

 

經過FFdec,能夠直接往flash中打trace補丁,用於輸出對應的參數,變量。3d

findpropstrict Qname(PackageNamespace(""),"trace")調試

pushstring "Hello World!"日誌

callpropvoid Qname(PackageNamespace(""),"trace") 1code

  

Jit函數監控

可是大多數漏洞調試中,trace不夠強大,這就須要經過調試器了,由於flash裏的腳本在執行的時候會轉爲jit,所以調試很是不便,這也是早期flash很難搞的一個問題,可是能夠經過如下斷點解決。對象

29.r0.140  flash.ocxblog

.dvalloc /b 0x79990000 30;eb 0x79990000 5e;ew 0x79990001 c3ip

bp Flash32_29_0_0_140 + 0x8D03D2 ".printf \"the method_name is: %ma\\n\",poi(eax+8);.if(poi(esi+20)=0xFFFFFFFF){bp poi(esi+4}.else{gc}"

bp Flash32_29_0_0_140 + 0x8BA425 ".printf \"the method_index is:%p the method_info_pointer is:%p the jit code is:%p the method_body is:%p\\n\",poi(esi+20),esi,poi(esi+4),poi(esi+24);r ecx = esi;r $t0 = poi(esp);ed esp eip+1;r esp = esp - 4;ed esp @$t0;r esp = esp -4;ed esp 0x79990000;r eip = Flash32_29_0_0_140 + 0x8D03AF;g"

原理

fun_verifyMethod,該函數是flash引擎中用於對jit函數校驗的地方,該函數返回的esi實際上是一個jit method的對象,裏面包含了具體生成的jit函數的index,method ,jit code等屬性,其中index是引擎內部用於識別jit函數的標記(就一數字),jit code標記了生成的對應地址,可是對應正常人而言index這種數字明顯沒有意義,咱們須要具體的函數名,這就引出以後的fun_getMethodName函數。

fun_getMethodName,其ecx接受一個method的對象(即fun_verifyMethod返回的對象),結果會返回一個具體函數的函數名,可是該函數默認在flash運行時不會調用,所以須要在fun_verifyMethod調用後手動調用一下fun_getMethodName,既能夠得到對應的函數名,此時結合fun_verifyMethod返回的地址,就能實現正常的調試。

 

使用

腳本中一共三條命令,第一條用於生成一段內存,主要用於在fun_verifyMethod後,改變程序流程去執行fun_getMethodName(你能夠理解爲hook),以後分別是這兩個函數的斷點。

.dvalloc /b 0x79990000 30;eb 0x79990000 5e;ew 0x79990001 c3

bp Flash32_29_0_0_140 + 0x8D03D2 ".printf \"the method_name is: %ma\\n\",poi(eax+8);.if(poi(esi+20)=0xFFFFFFFF){bp poi(esi+4}.else{gc}"

bp Flash32_29_0_0_140 + 0x8BA425 ".printf \"the method_index is:%p the method_info_pointer is:%p the jit code is:%p the method_body is:%p\\n\",poi(esi+20),esi,poi(esi+4),poi(esi+24);r ecx = esi;r $t0 = poi(esp);ed esp eip+1;r esp = esp - 4;ed esp @$t0;r esp = esp -4;ed esp 0x79990000;r eip = Flash32_29_0_0_140 + 0x8D03AF;g"

 

調試的時候,下這兩個斷點,運行以後生成整個jit函數的信息,記下來,每一個函數index很重要。

運行第二遍就能夠正常調試了,此時只要將紅字換成對應的函數index便可(對同一個swf,index是固定的),此時運行,便可在指定jit函數生成的時候斷下。

bp Flash32_29_0_0_140 + 0x8D03D2 ".printf \"the method_name is: %ma\\n\",poi(eax+8);.if(poi(esi+20)=0xFFFFFFFF){bp poi(esi+4}.else{gc}"

此時針對replace的jit code地址下斷點,及能夠斷下。

 

通用性

替換,該腳本是針對29.r0.140  flash.ocx,以後須要使用其餘版本的時候須要改對應的地址,這就涉及到如何快速獲取對應的fun_getMethodName和fun_verifyMethod函數。

fun_getMethodName,ida裏找cinit字符,對應引用的函數。

 

引用函數以下。 

再向上一層就是了。 

fun_verifyMethod函數,搜JIT failed字符。

 

對應的引用。

 

對該函數的引用,第一個就是,不是就找找反正很少。

 

須要修改如下三個值(藍色部分根據你要跟的函數index本身替換),

第一個紅色地址爲fun_getMethodName返回的ret地址。

第二個紅色地址爲fun_verifyMethod返回前的pop esi的地址。

第三個紅色地址爲fun_getMethodName的起始地址減一(爲啥減一是爲了windbg中斷點hook的須要)。

.dvalloc /b 0x79990000 30;eb 0x79990000 5e;ew 0x79990001 c3

bp Flash32_29_0_0_140 + 0x8D03D2 ".printf \"the method_name is: %ma\\n\",poi(eax+8);.if(poi(esi+20)=0xFFFFFFFF){bp poi(esi+4}.else{gc}"

bp Flash32_29_0_0_140 + 0x8BA425 ".printf \"the method_index is:%p the method_info_pointer is:%p the jit code is:%p the method_body is:%p\\n\",poi(esi+20),esi,poi(esi+4),poi(esi+24);r ecx = esi;r $t0 = poi(esp);ed esp eip+1;r esp = esp - 4;ed esp @$t0;r esp = esp -4;ed esp 0x79990000;r eip = Flash32_29_0_0_140 + 0x8D03AF;g"

 

 轉載請註明出處

相關文章
相關標籤/搜索