在這篇文章中,我們將會(huì)跟大家討論目前惡意軟件在隱藏其Windows API訪問(wèn)痕跡時(shí)所采用的常用技術(shù)。在本文所給出的分析樣例中,為了確定惡意軟件的功能,分析人員必須計(jì)算要計(jì)算出API的起始地址并對(duì)運(yùn)行時(shí)進(jìn)程進(jìn)行符號(hào)解析。
在介紹完這些技術(shù)之后,我們會(huì)給大家演示一款我們自行開(kāi)發(fā)的開(kāi)源工具,在IDA腳本的幫助下,它可以對(duì)虛擬機(jī)中正在運(yùn)行的進(jìn)程進(jìn)行符號(hào)解析操作。這樣一來(lái),它便給我們提供了一種能夠快速提升反匯編代碼可讀性的有效方法。
技術(shù)分析
在執(zhí)行一次分析時(shí),我們通?梢钥吹綈阂廛浖䲡(huì)嘗試掩蓋(通過(guò)模糊處理等技術(shù))它所要使用的API。作為一名惡意軟件分析人員,如果想要確定待分析的惡意軟件會(huì)使用哪一個(gè)API,首先我們要做的就是對(duì)其進(jìn)行符號(hào)解析,這樣才能確定惡意代碼真正的功能。
在這篇文章中我們所要討論的兩種常見(jiàn)的混淆技術(shù)為Encoded Function Pointer Tables和Detours Style Hook Stubs。在這兩種場(chǎng)景中,API的入口點(diǎn)是無(wú)法直接從源代碼中找出來(lái)的。
比如說(shuō),請(qǐng)大家先看下面這張圖片中的代碼,這部分代碼來(lái)自于xdata加密勒索軟件樣本C6A2FB56239614924E2AB3341B1FBBA5的內(nèi)存數(shù)據(jù)中提取出來(lái)的:

在上面這張圖片中,我們可以看到一個(gè)數(shù)字值被加載進(jìn)了eax,然后再與另一個(gè)數(shù)字值進(jìn)行異或運(yùn)算,最后作為一個(gè)函數(shù)指針被加載調(diào)用。需要注意的是,這些數(shù)字值只有在一個(gè)正在運(yùn)行的進(jìn)程中才有意義。我們可以根據(jù)內(nèi)存導(dǎo)出數(shù)據(jù)中的這些數(shù)字值來(lái)計(jì)算出最終的數(shù)字結(jié)果,但我們還需要想辦法弄清楚這個(gè)特定進(jìn)程中所解析的API地址。除此之外我們還要考慮到,首選基地址沖突或開(kāi)啟了ASLR的系統(tǒng)都將有可能引起DLL重定位。
下面這張圖片中顯示的是數(shù)字值的初始化設(shè)置地址:

在我們此次的分析場(chǎng)景中,初始值是通過(guò)一次API哈希查詢(xún)來(lái)完成加載的,這樣一來(lái),我們現(xiàn)在就有很多種方法可以來(lái)解決目前所面臨的問(wèn)題了。我既可以搜索一個(gè)公開(kāi)的哈希列表,然后提取出其中的哈希值來(lái)構(gòu)建一個(gè)我們自己的數(shù)據(jù)庫(kù),或者也可以想辦法對(duì)已解碼的API地址進(jìn)行動(dòng)態(tài)解析。
在我們真正開(kāi)始之前,讓我們先來(lái)看一看另外一個(gè)例子。下圖所顯示的代碼來(lái)自于Andromeda樣本(3C8B018C238AF045F70B38FC27D0D640):

上圖所示的是惡意軟件注入在內(nèi)存中的代碼,我們可以看到其中的第一個(gè)指令是從實(shí)際的Windows API中竊取來(lái)的,并存儲(chǔ)在一個(gè)stub之中。在這種情況下,惡意軟件可以通過(guò)這些stub訪問(wèn)所有的API。我們也可以從反匯編代碼中看到,竊取來(lái)的指令是可變長(zhǎng)度的指令。
為了對(duì)這些功能函數(shù)進(jìn)行深入解析,我們需要完成以下幾個(gè)步驟:
1.枚舉出所有的stub;
2.計(jì)算第一條指令占有多少個(gè)字節(jié);
3.提取出jmp地址;
4.減去竊取來(lái)的指令所占字節(jié),得到API的入口點(diǎn)(entrypoint);
5.對(duì)計(jì)算出來(lái)的地址進(jìn)行解析,找出指定的進(jìn)程實(shí)例;
6.將stub重命名為有意義的值;
在這個(gè)例子中,我們嘗試搜索了相關(guān)值的交叉引用,但并沒(méi)有得到什么有意義的結(jié)果。現(xiàn)在我們面臨的主要是兩個(gè)問(wèn)題:首先,我們?nèi)绾尾拍芨玫貙?duì)計(jì)算出的API地址進(jìn)行解析?;其次,如何才能將解析數(shù)據(jù)與我們的IDA數(shù)據(jù)庫(kù)聯(lián)系起來(lái)或添加進(jìn)數(shù)據(jù)庫(kù)中?
我們所嘗試的第一種技術(shù)首先要計(jì)算出所有的最終地址,將它們寫(xiě)入到代碼文件中,然后將數(shù)據(jù)注入到進(jìn)程中,最后在下圖所示的調(diào)試程序中檢查數(shù)據(jù)表。由于調(diào)試程序中已經(jīng)有一個(gè)API地址查詢(xún)表了,所以我們可以更加方便快速地得到我們所需要的信息。

這樣一來(lái),我們就可以提取出相關(guān)的符號(hào)解析然后通過(guò)一個(gè)腳本來(lái)將其整合進(jìn)我們的IDB中。
我們的工具
我們真正要做的是為每一個(gè)進(jìn)程構(gòu)建一個(gè)我們自己的符號(hào)查詢(xún)表,并通過(guò)我們的腳本來(lái)將這類(lèi)表的訪問(wèn)操作流程化。那么現(xiàn)在首先需要解決的問(wèn)題是:我們?nèi)绾尾拍軜?gòu)建出API地址的查詢(xún)表?為了解決這個(gè)問(wèn)題,我們可以按照以下步驟進(jìn)行操作:
1.枚舉出一個(gè)進(jìn)程所加載的所有DLL;
2.對(duì)于每一個(gè)DLL,遍歷輸出表并提取出函數(shù)名和RVA;
3.根據(jù)DLL基地址計(jì)算出API的入口地址,然后提取出RVA;
4.根據(jù)上述所有信息構(gòu)建出一個(gè)查詢(xún)表;
雖然上述步驟聽(tīng)起來(lái)好像很麻煩的樣子,但我們已經(jīng)給大家提供了能夠自動(dòng)完成上述操作的代碼庫(kù)了。下面這張圖片展示的是我們針對(duì)這種特殊場(chǎng)景所開(kāi)發(fā)出來(lái)的一款遠(yuǎn)程查詢(xún)工具。

為了充分釋放這種類(lèi)型的工具所能帶來(lái)的便捷性,這種工具必須具備高效性。那么我們?cè)鯓硬拍芨玫卦L問(wèn)這些數(shù)據(jù)呢?以下幾個(gè)因素是我們需要考慮的,例如數(shù)據(jù)如何提交、工具可接受的是哪種輸入格式、以及工具如何更好地整合到我們的分析過(guò)程之中。
我們首先得考慮如何與該工具進(jìn)行交互。為了最大程度地實(shí)現(xiàn)靈活性和可擴(kuò)展性,我們可以選擇下面這三種方法:
1.查詢(xún)請(qǐng)求通過(guò)textbox單獨(dú)提交;
2.查詢(xún)請(qǐng)求通過(guò)批量文件提交;
3.查詢(xún)請(qǐng)求通過(guò)網(wǎng)絡(luò)和遠(yuǎn)程客戶端提交;
對(duì)于輸入格式,我們可以選擇以下幾種:
1.十六進(jìn)制內(nèi)存地址
2. 不區(qū)分大小寫(xiě)的API名稱(chēng)
3.dll_name@ordinal4.dll_name.export_name
工具的輸出是一個(gè)CSV列表,其中包含有地址、名稱(chēng)、序數(shù)和DLL。雖然該工具的基本功能已經(jīng)足夠強(qiáng)大,但是在我們的分析過(guò)程中,我們?nèi)匀恍枰环N更加高效的方法來(lái)使用這款工具。該工具雖然可以很好地處理單獨(dú)的查詢(xún)請(qǐng)求和測(cè)試,但對(duì)于批量查詢(xún)還不能夠很好地支持。批量文件查詢(xún)有時(shí)是非常方便的 ,但它需要將數(shù)據(jù)輸出/導(dǎo)入與IDA數(shù)據(jù)庫(kù)進(jìn)行整合。
實(shí)際上,我們真正需要的是在IDA中運(yùn)行我們的腳本,計(jì)算API地址,然后在IDA腳本的運(yùn)行過(guò)程中解析這些地址,它將允許我們?cè)谶M(jìn)程的運(yùn)行過(guò)程中對(duì)函數(shù)和指針進(jìn)行重命名。為了實(shí)現(xiàn)這個(gè)目標(biāo),我們可以在IDA Jscript中整合一個(gè)網(wǎng)絡(luò)客戶端。IDA Jscript是一款開(kāi)源的IDA腳本工具,它具備語(yǔ)法高亮、智能感知、函數(shù)原型提示工具和調(diào)試器等組件。

在這個(gè)例子中我們可以看到,腳本解碼了xdata指針表,通過(guò)網(wǎng)絡(luò)對(duì)API地址進(jìn)行了解析,然后生成了一個(gè)IDC腳本并在IDA中對(duì)指針進(jìn)行了重命名。運(yùn)行該腳本之后,反編譯輸出結(jié)果的可讀性大大增加了。

接下來(lái),讓我們回到剛才Andromeda的那個(gè)例子。我們可以通過(guò)下圖所示的idajs腳本恢復(fù)出惡意軟件所使用的API相關(guān)信息。

注:對(duì)于IDAPython用戶,推薦使用一款python遠(yuǎn)程查詢(xún)客戶端。
總結(jié)
本文對(duì)惡意軟件常用的Windows API模糊技術(shù)進(jìn)行了分析,由于這些技術(shù)的存在,使得惡意軟件分析人員必須提取出程序的運(yùn)行時(shí)數(shù)據(jù),計(jì)算出入口地址,然后將特定運(yùn)行進(jìn)程中提取出的數(shù)據(jù)解析成可讀性較高的數(shù)據(jù)。除此之外,本文還介紹了一款簡(jiǎn)單的開(kāi)源工具,這款工具可以整合多種IDA腳本語(yǔ)言,并允許分析人員繞過(guò)惡意軟件所使用的模糊技術(shù)。
【工具下載】
|