Angler Exploit在最近變得非常火熱,主要是最近的幾次flash 0day都出現在該Exploit Kit中,該Exploit Kit最大的特點就是混淆的十分厲害,相比
國內比較流行DoSWF,這個的混淆方式簡直滅絕人性==!,下面就是該Exploit Kit使用的一個CVE-2014-0569樣本:
一個個不知道有多長的點點槓槓會看的人整個精神分裂、四肢無力、頭昏目眩、口吐白沫…
最近的Angler Exploit Kit中用到了兩種不同的混淆方式。在CVE-2014-0569、CVE-2014-8439、CVE-2015-0311、CVE-2015-0313中都有出現。
第一種混淆
這種混淆方式比較簡單,該混淆主要將觸發漏洞的swf文件以string或者ByteArray的方式保存在變量中,然後通過Loader類的loadBytes方法來加載惡意的swf文件:
因此只需要在調用LoadBytes函數之前攔截到參數peramennaya4即爲觸發漏洞的swf文件,怎麼攔截這個參數呢?
一個方法是直接修改as文件並重新編譯,修改後編譯的as文件如下:
這裏調用了flash一個用來輸出調試信息的函數trace,爲了捕獲trace輸出,需要用debug版本的flash插件,下載地址如下:
http://helpx.adobe.com/flash-player/kb/archived-flash-player-versions.html
有了debug版本的插件,還需要一個用來查看調試的工具Vizzy,前面的文章有用到這個工具,這樣就可以攔截到swf文件:
swf文件會保存在vizzy的log文件中,默認路徑爲:C:\Users\用戶名\Application Data\Macromedia\Flash Player\Logs\flashlog.txt
但是這樣存在一個編碼問題,swf文件中的編碼會在讀取ByteArray時出現錯誤,導致swf文件錯誤,那麼我們可以使用base64編碼的方式將ByteArry進行編碼再寫入
到log文件:
這裏使用了com.dynamicflash.util.Base64庫,使用前需要import。
這樣就可以完整的得到base64的編碼的swf文件。
用以下的python代碼進行解碼即可:
>import base64 >f1=open("base64.txt",'rb') >f2=open("decode.swf",'wb') >base64.decode(f1,f2) >f2.close() >f1.close()
第二種混淆
第二種混淆相比第一種要複雜很多,反混淆也非常麻煩,這裏主要用到一個叫FFDec的工具,其自帶一個反混淆的方法,在對Angler混淆時候比較有用:
儘管經過了反混淆的處理後,代碼仍然十分難讀,這裏主要學習下該混淆(實際應該叫加密了)的方法。
1.內嵌二進制數據
as3通過extends ByteArrayAsset來嵌入二進制數據,具體參考以下方法:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/core/ByteArrayAsset.html
被嵌入的二進制數據可以根據被嵌入時的名稱通過類似類的方式直接引用,如下:
2.關鍵字符串加密
一些可能會被當作檢測特徵的字符串,如exec、sandboxType等等都經過了一連串的加密處理,這些加密的字符串保存在一個內嵌二進制加密字符串列表中:
第一個4字節代表加密的字符串個數,接下來的結構爲:加密字符串長度+加密字符串內容
在解密字符串時,首先獲取字符串在字符串加密表中的索引,獲取索引的時候會指定第一個用到的access_key ,該key會通過傳入的參數異或來得到
在字符串加密表中的索引值。access_key大小爲4個字節,通過嵌入的形式保存在swf文件中:
加密方式爲簡單的一個異或:
public static funtion get_encrypt_index(param1:int) { return (param1^access_key) }
知道了索引後就知道了加密字符串的位置,接下來就是解密字符串了,解密的方式爲RC4,RC4使用的key同樣以內嵌二進制數據的形式保存:
第一個字節紅色代表key的組數,綠色和藍色是兩組key,每組key的長度爲16個字節。
根據被加密字符串的長度來選取不同的RC4 key,選取規則如下:
RC4key_array[加密字符串索引位置%RC4 key組數]
當加密的字符串爲8BDFD9B7,其索引位置在加密字符串表中爲13,則使用的RC4 key爲第二組key,解密後的字符串內容爲exec:
最後附上python RC4加解密的代碼:
def rc4(data, key): ''' data: data that to be encrypted or decrypted. key: key to encrypt or decrypt. ''' #some parameters check here ... #if the data is a string, convert to hex format. if(type(data) is type("string")): tmpData=data data=[] for tmp in tmpData: data.append(ord(tmp)) #if the key is a string, convert to hex format. if(type(key) is type("string")): tmpKey=key key=[] for tmp in tmpKey: key.append(ord(tmp)) #the Key-Scheduling Algorithm x = 0 box= list(range(256)) for i in range(256): x = (x + box[i] + key[i % len(key)]) % 256 box[i], box[x] = box[x], box[i] #the Pseudo-Random Generation Algorithm x = 0 y = 0 out = [] for c in data: x = (x + 1) % 256 y = (y + box[x]) % 256 box[x], box[y] = box[y], box[x] out.append(c ^ box[(box[x] + box[y]) % 256]) result="" printable=True for tmp in out: if(tmp<0x21 or tmp>0x7e): # there is non-printable character printable=False break result += chr(tmp) if(printable==False): result="" #convert to hex string for tmp in out: result += "{0:02X}".format(tmp) return result out=rc4([0x8B,0xDF,0xD9,0xB7], [0x6D,0x0C,0x6B,0x0D,0x54,0x6F,0x38,0x7F,0x45,0x3A,0x36,0x0A,0x5C,0x41,0x60,0x77]) out=rc4([0x8B,0xDF,0xD9,0xB7], [0x1A,0x4D,0x57,0x75,0x7C,0x29,0x11,0x56,0x30,0x20,0x6A,0x5B,0x63,0x72,0x56,0x77]) print(out)
參考鏈接:
https://www.fireeye.com/blog/threat-research/2015/01/a_different_exploit.html
http://blog.csdn.net/white_eyes/article/details/6560355