神操作:教你用Python識(shí)別惡意軟件
在本文中,我們將介紹惡意軟件靜態(tài)分析的基礎(chǔ)知識(shí)。靜態(tài)分析是對(duì)程序文件的反匯編代碼、圖形圖像、可打印字符串和其他磁盤(pán)資源進(jìn)行分析,是一種不需要實(shí)際運(yùn)行程序的逆向工程。雖然靜態(tài)分析技術(shù)有欠缺之處,但是它可以幫助我們理解各種各樣的惡意軟件。
通過(guò)細(xì)致的逆向工程,你將能夠更好地理解惡意軟件二進(jìn)制文件在攻擊目標(biāo)后為攻擊者提供的好處,以及攻擊者可以隱藏并繼續(xù)攻擊受感染計(jì)算機(jī)的方式。正如你將看到的,本文結(jié)合了描述和實(shí)例,每個(gè)部分都介紹了靜態(tài)分析技術(shù),然后說(shuō)明其在實(shí)際分析中的應(yīng)用。
本文的代碼和數(shù)據(jù),可以在公眾號(hào)后臺(tái)回復(fù)惡意軟件獲取下載方式。你將在數(shù)據(jù)目錄/ch1中找到本文示例中使用的惡意軟件示例。為了演示本文討論的技術(shù),我們?cè)谘菔局惺褂胕rcbot.exe,這是一個(gè)互聯(lián)網(wǎng)中繼聊天(Internet Relay Chat,IRC)機(jī)器人,也在日常廣泛監(jiān)測(cè)中最常見(jiàn)的惡意軟件的示例之一。
嚴(yán)格來(lái)說(shuō),當(dāng)連接到IRC服務(wù)器時(shí),這個(gè)程序被設(shè)計(jì)常駐在目標(biāo)計(jì)算機(jī)上。在ircbot.exe控制目標(biāo)后,攻擊者可以通過(guò)IRC控制目標(biāo)計(jì)算機(jī),執(zhí)行控制指令,例如打開(kāi)網(wǎng)絡(luò)攝像頭偷偷捕獲視頻、提取目標(biāo)的地理位置和桌面的截圖,以及從目標(biāo)機(jī)器中提取相關(guān)文件等。
01 微軟Windows可移植可執(zhí)行文件格式
要進(jìn)行惡意軟件靜態(tài)分析,你需要了解Windows PE文件格式,該格式描述了如.exe、.dll和.sys等當(dāng)今Windows程序文件的結(jié)構(gòu),并定義了它們存儲(chǔ)數(shù)據(jù)的方式。PE文件包含x86指令、圖像和文本等數(shù)據(jù),以及程序運(yùn)行所需的元數(shù)據(jù)。
PE格式最初的設(shè)計(jì)是用來(lái)進(jìn)行下面的操作。
1)告訴Windows如何將程序加載到內(nèi)存中
PE格式描述了文件的哪些塊應(yīng)該加載到內(nèi)存中,以及在哪里加載。它還告訴你,Windows應(yīng)該在程序代碼里的哪個(gè)位置開(kāi)始執(zhí)行程序,以及哪些動(dòng)態(tài)鏈接代碼庫(kù)應(yīng)該加載到內(nèi)存中。
2)為運(yùn)行程序提供在執(zhí)行過(guò)程中可能使用的媒體(或資源)
這些資源可以包括字符串,如GUI對(duì)話框或控制臺(tái)輸出的字符串,以及圖像或視頻。
3)提供安全數(shù)據(jù),例如數(shù)字代碼簽名
Windows使用這些安全數(shù)據(jù)來(lái)確保代碼出自受信任的來(lái)源。
PE格式通過(guò)利用圖1-1中所示的一系列結(jié)構(gòu)來(lái)完成以上工作。

▲圖1-1 PE文件格式
如圖1-1所示,PE文件格式包括一系列頭(header),用來(lái)告訴操作系統(tǒng)如何將程序加載到內(nèi)存中。它還包括一系列節(jié)(section)用來(lái)包含實(shí)際的程序數(shù)據(jù)。Windows將這些節(jié)加載到內(nèi)存中,使其在內(nèi)存中的偏移量與它們?cè)诖疟P(pán)上的顯示位置相對(duì)應(yīng)。
讓我們從PE頭開(kāi)始,來(lái)更詳細(xì)地探討這個(gè)文件結(jié)構(gòu)。我們將略過(guò)對(duì)DOS頭的討論,這是20世紀(jì)80年代微軟DOS操作系統(tǒng)的遺留產(chǎn)物,僅僅出于兼容性原因而存在。
1. PE頭
如圖1-1底部所示,在DOS頭❶的上面是PE頭❷,它定義了程序的一般屬性,如二進(jìn)制代碼、圖像、壓縮數(shù)據(jù)和其他程序?qū)傩?。它還告訴我們程序是否是針對(duì)32位或64位系統(tǒng)而設(shè)計(jì)的。
PE頭為惡意軟件分析師提供了基本但有用的情景信息。例如,頭里包括了時(shí)間戳字段,這個(gè)字段可以給出惡意軟件作者編譯文件的時(shí)間。通常惡意軟件作者會(huì)使用偽造的值替換這個(gè)字段,但是有時(shí)惡意軟件作者會(huì)忘記替換,就會(huì)發(fā)生這種情況。
2. 可選頭
可選頭❸實(shí)際上在今天的PE可執(zhí)行程序中無(wú)處不在,恰恰與其名稱的含義相反。它定義了PE文件中程序入口點(diǎn)的位置,該位置指的是程序加載后運(yùn)行的第一個(gè)指令。
它還定義了Windows在加載PE文件、Windows子系統(tǒng)、目標(biāo)程序(例如Windows GUI或Windows命令行)時(shí)加載到內(nèi)存中的數(shù)據(jù)大小,以及有關(guān)該程序其他的高級(jí)詳細(xì)信息。由于程序的入口點(diǎn)告訴了逆向工程師該從哪里開(kāi)始進(jìn)行逆向工程,這個(gè)頭信息對(duì)逆向工程師來(lái)說(shuō)是非常寶貴的。
3. 節(jié)頭
節(jié)(section)頭❹描述了PE文件中包含的數(shù)據(jù)節(jié)。PE文件中的一個(gè)節(jié)是一塊數(shù)據(jù),它們?cè)诓僮飨到y(tǒng)加載程序時(shí)將被映射到內(nèi)存中,或者包含有關(guān)如何將程序加載到內(nèi)存中的指令。
換句話說(shuō),一個(gè)節(jié)是磁盤(pán)上的字節(jié)序列,它要么成為內(nèi)存中一串連續(xù)字節(jié)的字符串,要么告知操作系統(tǒng)關(guān)于加載過(guò)程的某些方面。
節(jié)頭還告訴Windows應(yīng)該授予節(jié)哪些權(quán)限,比如程序在執(zhí)行時(shí),是否應(yīng)該可讀、可寫(xiě)或可執(zhí)行。例如,包含x86代碼的.text節(jié)通常被標(biāo)記為可讀和可執(zhí)行的,但是不可寫(xiě)的,以防止程序代碼在執(zhí)行過(guò)程中意外修改自身。
圖1-1描述了許多節(jié),如.text和.rsrc。執(zhí)行PE文件時(shí),它們會(huì)被映射到內(nèi)存中。其他如.reloc節(jié)的特殊節(jié)不會(huì)被映射到內(nèi)存中,我們也將討論這些節(jié)。下面我們來(lái)瀏覽圖1-1中顯示的節(jié)。
1).text節(jié)
每個(gè)PE程序在其節(jié)頭中包含了至少一個(gè)標(biāo)記為可執(zhí)行的x86代碼節(jié);這些節(jié)幾乎總是命名為.text❺。
2).idata節(jié)
.idata節(jié)❻,也被稱為導(dǎo)入節(jié),包含導(dǎo)入地址表(IAT),它列出了動(dòng)態(tài)鏈接庫(kù)和它們的函數(shù)。IAT是最重要的PE結(jié)構(gòu)之一,在對(duì)PE二進(jìn)制文件進(jìn)行最初的分析時(shí)需要查看它,因?yàn)樗赋隽顺绦蛩{(diào)用的庫(kù),然而這些調(diào)用反過(guò)來(lái)又可能會(huì)泄露惡意軟件的高級(jí)功能。
3)數(shù)據(jù)節(jié)
在PE文件結(jié)構(gòu)中的數(shù)據(jù)節(jié)可以包括.rsrc、.data和.rdata等節(jié),它們存儲(chǔ)程序使用的鼠標(biāo)光標(biāo)圖像、按鈕圖標(biāo)、音頻和其他媒體等。例如,圖1-1中的.rsrc節(jié)❼包含了程序用于將文本呈現(xiàn)為字符串的可打印字符串。
.rsrc(資源)節(jié)中的信息對(duì)惡意軟件分析師是非常重要的,因?yàn)橥ㄟ^(guò)檢查PE文件中的可打印字符串、圖形圖像和其他資產(chǎn),他們可以獲得關(guān)于文件功能的重要線索。
在03節(jié)中,你將了解如何使用icoutils工具包(包括icotool和wrestool)從惡意軟件二進(jìn)制文件的資源節(jié)中提取圖形圖像。然后,在04節(jié)中,你將學(xué)習(xí)如何從惡意軟件資源節(jié)中提取可打印的字符串。
4).reloc節(jié)
PE二進(jìn)制文件的代碼并非是與位置獨(dú)立的,這意味著如果將它從預(yù)期的內(nèi)存位置移動(dòng)到新的內(nèi)存位置,它將無(wú)法正確執(zhí)行。.reloc❽在不破壞代碼的情況下通過(guò)允許移動(dòng)代碼來(lái)解決這個(gè)問(wèn)題。
如果一個(gè)PE文件的代碼已被移動(dòng),它就告訴Windows操作系統(tǒng)將該文件的代碼中進(jìn)行內(nèi)存地址轉(zhuǎn)換,這樣代碼仍可以正確運(yùn)行。這些轉(zhuǎn)換通常涉及在內(nèi)存地址中添加或減去偏移量。
02 使用pefile解析PE文件格式
由Ero Carerra編寫(xiě)和維護(hù)的Python模塊pefile已經(jīng)成為解析PE文件的一個(gè)行業(yè)標(biāo)準(zhǔn)的惡意軟件分析庫(kù)。在本節(jié)中,我將向你展示如何使用pefile來(lái)解析ircbot.exe。代碼清單1-1假設(shè)ircbot.exe已位于你當(dāng)前的工作目錄中。
輸入以下命令安裝pefile庫(kù),以便我們可以在Python中導(dǎo)入它:
- $ pip install pefile
現(xiàn)在,使用代碼清單1-1中的命令啟動(dòng)Python,導(dǎo)入pefile模塊,然后使用pefile打開(kāi)并解析PE文件ircbot.exe。
- 代碼清單1-1 加載pefile模塊并解析PE文件(ircbot.exe)
- $ python
- >>> import pefile
- >>> pe = pefile.PE("ircbot.exe")
我們實(shí)例化pefile.PE,它是PE模塊實(shí)現(xiàn)的核心類。它解析PE文件,以便我們可以查看它們的屬性。通過(guò)調(diào)用PE構(gòu)造函數(shù),我們加載并解析指定的PE文件,在本例中為ircbot.exe?,F(xiàn)在我們已經(jīng)加載并解析了這個(gè)文件,運(yùn)行代碼清單1-2中的代碼從ircbot.exe的pe字段中提取信息。
- 代碼清單1-2 遍歷PE文件的各個(gè)節(jié)并打印有關(guān)它們的信息
- #基于 Ero Carrera的示例代碼(pefile庫(kù)的作者)
- for section in pe.sections:
- print(section.Name, hex(section.VirtualAddress),
- hex(section.Misc_VirtualSize), section.SizeOfRawData)
- 代碼清單1-3顯示了打印輸出的內(nèi)容。
代碼清單1-3 使用Python的pefile模塊從ircbot.exe中提取節(jié)數(shù)據(jù)

如代碼清單1-3所示,我們從PE文件五個(gè)不同的節(jié)中提取了數(shù)據(jù):.text、.rdata、.data、.idata和.reloc。輸出是以五元組的形式給出,每提取一個(gè)PE節(jié)對(duì)應(yīng)一個(gè)元素。每一行的第一個(gè)條目標(biāo)識(shí)PE節(jié)。(你可以忽略一系列的\\x00空字節(jié),它們只是C語(yǔ)言樣式的空字符串終止符。)其余字段告訴我們,一旦將每個(gè)節(jié)被加載到內(nèi)存中,它的內(nèi)存利用率將是多少,以及一旦被加載,它將在內(nèi)存中的何處被找到。
例如,0x1000❶是加載這些節(jié)的虛擬內(nèi)存地址基址,也可以將其視為節(jié)的內(nèi)存地址基址。在虛擬大小(virtual size)字段中的0x32830❷指定了節(jié)被加載后所需的內(nèi)存大小。第三個(gè)字段中的207360❸表示該節(jié)將在該內(nèi)存塊中所占用的數(shù)據(jù)量。
除了使用pefile解析程序的節(jié)之外,我們還可以使用它列出二進(jìn)制文件將加載的DLL文件,以及它將在這些DLL文件中所請(qǐng)求的函數(shù)調(diào)用。我們可以通過(guò)鏡像(dump)PE文件的IAT來(lái)實(shí)現(xiàn)這一點(diǎn)。代碼清單1-4顯示了如何使用pefile鏡像ircbot.exe的IAT。
- 代碼清單1-4 從ircbot.exe中提取導(dǎo)入信息
- $ python
- pe = pefile.PE("ircbot.exe")
- for entry in pe.DIRECTORY_ENTRY_IMPORT:
- print entry.dll
- for function in entry.imports:
- print '\t', function.name
代碼清單1-4會(huì)生成如代碼清單1-5所示的輸出(為了簡(jiǎn)潔起見(jiàn),輸出進(jìn)行了截?cái)?。
- 代碼清單1-5 ircbot.exe的IAT表內(nèi)容,其顯示了這個(gè)惡意軟件使用的庫(kù)函數(shù)

如代碼清單1-5所示,這個(gè)輸出對(duì)于惡意軟件分析很有價(jià)值,因?yàn)樗谐隽藧阂廛浖暶骱蛯⒁玫呢S富的函數(shù)數(shù)組。
例如,輸出的前幾行告訴我們,惡意軟件將使用WriteFile❶寫(xiě)入文件,使用CreateFileA❷打開(kāi)文件,并使用CreateProcessA❸創(chuàng)建新的進(jìn)程。雖然這些只是關(guān)于惡意軟件的基本信息,但它們是了解惡意軟件更為詳細(xì)行為的開(kāi)始。
03 檢查惡意軟件的圖片
要了解惡意軟件是如何設(shè)計(jì)來(lái)捉弄攻擊目標(biāo)的,讓我們看看在它的.rsrc節(jié)中所包含的圖標(biāo)。例如,惡意軟件二進(jìn)制文件常常被設(shè)計(jì)成偽裝的Word文檔、游戲安裝程序、PDF文件等常用軟件的圖標(biāo)來(lái)欺騙用戶點(diǎn)擊它們。
你還可以在惡意軟件中找到攻擊者自己感興趣程序中的圖像,例如攻擊者為遠(yuǎn)程控制受感染機(jī)器而運(yùn)行的網(wǎng)絡(luò)攻擊工具和程序。
回到我們的樣本圖像分析,你可以在本文的數(shù)據(jù)目錄中找到名為fakepdfmalware.exe的這個(gè)惡意軟件樣本。這個(gè)樣本使用Adobe Acrobat圖標(biāo)誘騙用戶認(rèn)為它是一個(gè)Adobe Acrobat文檔,而實(shí)際上它是一個(gè)惡意的PE可執(zhí)行文件。
在我們使用Linux命令行工具wrestool從二進(jìn)制文件fakepdfmalware.exe中提取圖像之前,我們首先需要?jiǎng)?chuàng)建一個(gè)目錄來(lái)保存我們將提取的圖像。代碼清單1-6顯示了如何完成所有這些操作。
- 代碼清單1-6 從惡意軟件樣本中提取圖像的Shell命令
- $ mkdir images
- $ wrestool -x fakepdfmalware.exe -output=images
- $ icotool -x -o images images/*.ico
我們首先使用mkdir images創(chuàng)建一個(gè)目錄來(lái)保存提取的圖像。接下來(lái),我們使用wrestool從fakepdfmalware.exe中提取圖像資源(-x)到/images目錄,然后使用icotool提取(-x)并將Adobe中.ico圖標(biāo)格式中的所有資源轉(zhuǎn)換(-o)為.png圖形,以便我們可以使用標(biāo)準(zhǔn)的圖像瀏覽工具查看們。
如果你的系統(tǒng)上沒(méi)有安裝wrestool,你可以從這里下載:
http://www.nongnu.org/icoutils/
一旦你使用wrestool將目標(biāo)可執(zhí)行文件中的圖像轉(zhuǎn)換為PNG格式,你就可以在你喜歡的圖像瀏覽工具中打開(kāi)它們,并以各種分辨率查看Adobe Acrobat圖標(biāo)。
正如我在這里給出的例子所示,從PE文件中提取圖像和圖標(biāo)相對(duì)簡(jiǎn)單,可以快速顯示與惡意軟件二進(jìn)制文件相關(guān)的有趣且又有用的信息。同樣地,我們可以輕松地從惡意軟件中提取可打印字符串來(lái)獲取更多信息,我們接下來(lái)會(huì)做這項(xiàng)工作。
04 檢查惡意軟件的字符串
字符串是程序二進(jìn)制文件中可打印字符的序列。惡意軟件分析師通常依賴惡意樣本中的字符串來(lái)快速了解其中可能發(fā)生的情況。這些字符串通常包含下載網(wǎng)頁(yè)和文件的HTTP和FTP命令,用于告訴你惡意軟件連接到的地址的IP地址和主機(jī)名等類似信息。
有時(shí),即使用于編寫(xiě)字符串的語(yǔ)言也有可能暗示惡意軟件二進(jìn)制文件的來(lái)源國(guó),盡管這可能是偽造的。你甚至可以在一個(gè)字符串中找到一些文本,它們用網(wǎng)絡(luò)用語(yǔ)解釋了惡意二進(jìn)制文件的用途。
字符串還可以顯示有關(guān)二進(jìn)制文件的更多技術(shù)信息。例如,你可能會(huì)發(fā)現(xiàn)有關(guān)用于創(chuàng)建二進(jìn)制文件的編譯器、編寫(xiě)二進(jìn)制文件所使用的編程語(yǔ)言、嵌入式腳本或HTML等信息。
雖然惡意軟件作者可以對(duì)所有這些痕跡進(jìn)行混淆、加密和壓縮等處理,但是即便是高水平的惡意軟件作者也經(jīng)常會(huì)暴露并留下一些痕跡,因此在分析惡意軟件時(shí),對(duì)鏡像的字符串進(jìn)行細(xì)致檢查顯得尤為重要。
1. 使用字符串程序
查看文件中所有字符串的標(biāo)準(zhǔn)方法是使用命令行工具strings,按照以下語(yǔ)法進(jìn)行使用:
- $ strings filepath | less
該命令將文件中的所有字符串逐行打印到終端上。在末尾添加 | less可以防止字符串在終端上跨屏顯示。默認(rèn)情況下,strings命令查找所有最小長(zhǎng)度為4字節(jié)的可打印字符串,但是你可以設(shè)置不同的最小長(zhǎng)度并更改“命令手冊(cè)”中所列各種其他參數(shù)。
我建議只使用默認(rèn)的最小字符串長(zhǎng)度4,但是你可以使用-n選項(xiàng)更改最小字符串長(zhǎng)度。例如,“string -n 10 filepath”只提取最小長(zhǎng)度為10字節(jié)的字符串。
2. 分析鏡像字符串
現(xiàn)在我們鏡像了一個(gè)惡意軟件程序的可打印字符串,但是挑戰(zhàn)在于要理解這些字符串的含義。例如,假設(shè)我們將ircbot.exe中的字符串鏡像到ircbotstring.txt文件中,這在本文前面的內(nèi)容中,我們使用pefile庫(kù)已經(jīng)進(jìn)行了探討,如下所示:
- $ strings ircbot.exe > ircbotstring.txt
ircbotstring.txt的內(nèi)容包含數(shù)千行文本,但其中一些行應(yīng)該突出顯示出來(lái)。例如,代碼清單1-7顯示了從字符串鏡像中提取出來(lái)的一串以單詞DOWNLOAD開(kāi)頭的行。
- 代碼清單1-7 顯示惡意軟件可以將攻擊者指定的文件下載到目標(biāo)計(jì)算機(jī)的字符串輸出

這些行表示ircbot.exe將嘗試把攻擊者指定的文件下載到目標(biāo)計(jì)算機(jī)上。
我們來(lái)嘗試分析另一個(gè)。代碼清單1-8所示的字符串鏡像表明ircbot.exe可以起到Web服務(wù)器的作用,在目標(biāo)機(jī)器上偵聽(tīng)來(lái)自攻擊者的連接。
- 代碼清單1-8 顯示惡意軟件有一個(gè)攻擊者可以連接的HTTP服務(wù)器的字符串輸出

代碼清單1-8顯示了ircbot.exe用于實(shí)現(xiàn)HTTP服務(wù)器的各種HTTP樣板程序。此HTTP服務(wù)器可能允許攻擊者通過(guò)HTTP連接到目標(biāo)計(jì)算機(jī)以發(fā)出命令,例如獲取受害者桌面的屏幕截圖并將其回傳給攻擊者的命令。
我們?cè)谡麄€(gè)代碼清單中看到了HTTP功能的證據(jù)。例如,從Internet資源請(qǐng)求數(shù)據(jù)的GET方法❶。HTTP/1.0 200 OK❷這一行是一個(gè)返回狀態(tài)代碼200的HTTP字符串,表明HTTP網(wǎng)絡(luò)事務(wù)都運(yùn)行良好,而Server:myBot❸表明HTTP服務(wù)器的名稱是myBot,這是ircbot.exe附加的一個(gè)內(nèi)置HTTP服務(wù)器。
所有這些信息都有助于理解和阻止特定的惡意軟件樣本或惡意活動(dòng)。例如,知道惡意軟件樣本有一個(gè)HTTP服務(wù)器,當(dāng)你連接到它時(shí),它會(huì)輸出特定的字符串,這樣你就可以借此掃描你的網(wǎng)絡(luò)來(lái)識(shí)別受感染的主機(jī)。
05 小結(jié)
在本文中,你大致對(duì)靜態(tài)惡意軟件分析有了一定的認(rèn)識(shí),其中包括在不實(shí)際運(yùn)行的情況下檢查惡意軟件程序。
你了解了定義Windows操作系統(tǒng).exe和.dll文件的PE文件格式,還了解了如何使用Python庫(kù)pefile解析實(shí)際場(chǎng)景中的惡意軟件ircbot.exe二進(jìn)制文件。
你還使用圖像分析和字符串分析等靜態(tài)分析技術(shù),從惡意軟件樣本中提取更多的信息。