本發(fā)明屬于網(wǎng)絡(luò)安全技術(shù)領(lǐng)域,具體涉及一種動(dòng)態(tài)鏈接庫(kù)缺失的可執(zhí)行程序的動(dòng)態(tài)分析方法。
背景技術(shù):
隨著計(jì)算機(jī)技術(shù)和互聯(lián)網(wǎng)技術(shù)的不斷發(fā)展,人們的生活的方方面面都越來(lái)越離不開(kāi)計(jì)算機(jī)和計(jì)算機(jī)上運(yùn)行的軟件。惡意軟件竊取個(gè)人數(shù)據(jù)和商業(yè)機(jī)密,發(fā)送垃圾郵件,控制用戶(hù)電腦,對(duì)遠(yuǎn)程服務(wù)器發(fā)動(dòng)拒絕服務(wù)攻擊,給個(gè)人和企業(yè)造嚴(yán)重的困擾和經(jīng)濟(jì)損失。為了逃避檢測(cè),惡意軟件往往藏身很多無(wú)害的軟件中。要從大量的可執(zhí)行程序樣本中檢測(cè)和清除惡意軟件,首先要獲得可執(zhí)行程序樣本的基本信息和程序行為,并從中提取、總結(jié)惡意軟件所具有的特征??蓤?zhí)行程序分析技術(shù)可以幫助研究人員獲得這些信息??蓤?zhí)行程序分析技術(shù)主要有靜態(tài)分析和動(dòng)態(tài)分析。
靜態(tài)分析不運(yùn)行程序樣本,通過(guò)靜態(tài)掃描程序樣本,能夠快速獲得其基本信息:文件大小,文件類(lèi)型,文件內(nèi)容哈希,編譯連接器版本,是否加殼等。它還可以對(duì)程序樣本進(jìn)行靜態(tài)的語(yǔ)義分析,構(gòu)建程序控制流圖和數(shù)據(jù)依賴(lài)圖,嘗試?yán)斫獬绦蛐袨?,推斷程序意圖。靜態(tài)分析通常借助特征字符串或特定的代碼、數(shù)據(jù)片段對(duì)惡意代碼進(jìn)行檢測(cè)。但是靜態(tài)分析容易受到加殼,混淆,多態(tài)與變質(zhì)等技術(shù)的干擾;缺乏輸入、環(huán)境變量等運(yùn)行時(shí)信息,使得靜態(tài)的惡意程序行為分析的多數(shù)努力等于在做無(wú)用功并且誤報(bào)率高。
動(dòng)態(tài)分析通過(guò)在一個(gè)可控的模擬的真實(shí)環(huán)境里實(shí)際運(yùn)行程序樣本,給予程序輸入,觀察記錄程序樣本運(yùn)行時(shí)行為:文件操作,注冊(cè)表操作,網(wǎng)絡(luò)操作,內(nèi)存讀寫(xiě)等。其天然具有抗加密、混淆、多態(tài)等優(yōu)勢(shì),并且給以惡意輸入數(shù)據(jù),更有針對(duì)性,誤報(bào)率低,模擬的真實(shí)環(huán)境,更能反映程序樣本在實(shí)際主機(jī)上的真實(shí)行為。因而越來(lái)越受到安全研究人員和安全廠商的重視。
要想觀察到可執(zhí)行程序樣本的真實(shí)行為,就需要首先讓程序樣本真正的運(yùn)行起來(lái)。但是這個(gè)前提并不能總得到滿(mǎn)足,其中一種情況就是缺少程序樣本所依賴(lài)的其它程序組件,如外部動(dòng)態(tài)鏈接庫(kù)(dll)文件。有的時(shí)候,能獲得可執(zhí)行程序樣本的主體,卻無(wú)法獲得這些dll文件,從而導(dǎo)致無(wú)法啟動(dòng)程序樣本,動(dòng)態(tài)分析失敗。這種情況在分析惡意軟件樣本的時(shí)候更為普遍:為了逃避檢測(cè)將自身分拆成多個(gè)文件,以及功能插件化、模塊化開(kāi)發(fā)等原因,惡意軟件將程序的部分功能或惡意功能寫(xiě)到外部的dll文件,在程序啟動(dòng)時(shí)由windows加載器加載這些外部的dll。因此,需要一種方法來(lái)解決程序樣本由于缺乏依賴(lài)的外部dll而無(wú)法啟動(dòng)的問(wèn)題。
既然程序樣本因?yàn)橐蕾?lài)外部的dll而無(wú)法啟動(dòng),那么一種思路就是滿(mǎn)足程序樣本的這種依賴(lài)。通過(guò)分析程序樣本的導(dǎo)入表結(jié)構(gòu),得到程序樣本導(dǎo)入的所有dll,即其所依賴(lài)的所有的外部dll文件,然后對(duì)比分析環(huán)境所提供的dll文件和收集到與此程序樣本所依賴(lài)的dll文件,找出分析環(huán)境中缺失的dll文件,然后修改程序樣本的導(dǎo)入表,將分析環(huán)境中沒(méi)有的dll從導(dǎo)入表中移除,這樣程序樣本就能正常啟動(dòng)起來(lái)。但是這個(gè)方法需要對(duì)程序樣本的導(dǎo)入表和pe頭部結(jié)構(gòu)進(jìn)行修改,破壞了程序樣本的完整性,如果程序樣本有自我校驗(yàn)功能,當(dāng)其檢測(cè)到自身被修改時(shí),可能不正常運(yùn)行或是直接結(jié)束運(yùn)行,分析平臺(tái)就沒(méi)法獲得程序樣本正常運(yùn)行時(shí)的各種行為。另一種思路就是想辦法滿(mǎn)足程序樣本的這種依賴(lài),在無(wú)法收集到程序樣本所依賴(lài)的外部dll的時(shí)候,自動(dòng)化的生成其所需dll文件,使程序樣本成功啟動(dòng)。
技術(shù)實(shí)現(xiàn)要素:
本發(fā)明提供一種動(dòng)態(tài)鏈接庫(kù)缺失的可執(zhí)行程序的動(dòng)態(tài)分析方法,通過(guò)分析程序樣本的導(dǎo)入表,獲得其導(dǎo)入的動(dòng)態(tài)鏈接庫(kù)及其對(duì)應(yīng)的導(dǎo)入函數(shù)信息,然后修改一個(gè)預(yù)先編譯好的導(dǎo)出了若干函數(shù)的dll的導(dǎo)出表,使其導(dǎo)出程序樣本所需導(dǎo)入函數(shù),并修改該dll的名稱(chēng)使之與程序樣本導(dǎo)入的dll名稱(chēng)相對(duì)應(yīng),從而生成程序樣本所缺失的dll文件,使程序樣本可以被動(dòng)態(tài)分析。
一種動(dòng)態(tài)鏈接庫(kù)缺失的可執(zhí)行程序的動(dòng)態(tài)分析方法,包括如下步驟:
1)預(yù)先生成一種子dll;
2)判斷待分析的程序樣本是否具有合法的導(dǎo)入表,如是,則執(zhí)行步驟3),否則終止對(duì)該樣本的分析并輸出錯(cuò)誤信息;
3)通過(guò)解析導(dǎo)入表結(jié)構(gòu),提取程序樣本導(dǎo)入的dll信息;
4)針對(duì)程序樣本導(dǎo)入的每一個(gè)dll都生成種子dll的一個(gè)拷貝,并修改該拷貝名稱(chēng)使之與所針對(duì)的dll名稱(chēng)一致;
5)根據(jù)步驟3)得到的dll信息,對(duì)生成的dll拷貝的導(dǎo)出表進(jìn)行修改,使其形成程序樣本依賴(lài)的dll。
進(jìn)一步地,還包括:6)根據(jù)步驟5)形成全部程序樣本導(dǎo)入的dll,將這些dll移動(dòng)到用戶(hù)指定目錄,并向用戶(hù)報(bào)告生成結(jié)果。
進(jìn)一步地,步驟1)中所述種子dll導(dǎo)出了足夠多函數(shù)。
進(jìn)一步地,步驟1)中根據(jù)分析平臺(tái)的系統(tǒng)版本,編譯所述種子dll;所述種子dll導(dǎo)出了的函數(shù)的個(gè)數(shù)不小于9999個(gè)。
進(jìn)一步地,步驟1)中編譯所述種子dll的同時(shí)記錄分析平臺(tái)所有的系統(tǒng)dll名稱(chēng);步驟3)提取程序樣本導(dǎo)入的dll信息時(shí),排除步驟1)中記錄的系統(tǒng)dll。
進(jìn)一步地,通過(guò)解析程序樣本的文件頭,判斷程序樣本是否具有合法的導(dǎo)入表。
進(jìn)一步地,步驟3)中所述程序樣本導(dǎo)入的dll信息包括:程序樣本導(dǎo)入的所有dll名稱(chēng)及導(dǎo)入的各dll對(duì)應(yīng)的函數(shù)信息。
進(jìn)一步地,所述函數(shù)信息包括按名稱(chēng)導(dǎo)入的函數(shù)的信息和按序號(hào)導(dǎo)入的函數(shù)的信息。
進(jìn)一步地,按序號(hào)導(dǎo)入的函數(shù)的信息包括按函數(shù)序號(hào)導(dǎo)入的函數(shù)的序號(hào)值,按名稱(chēng)導(dǎo)入的函數(shù)的信息包括按函數(shù)名稱(chēng)導(dǎo)入的函數(shù)的字符串名和hint值。
進(jìn)一步地,步驟5)中對(duì)dll拷貝的導(dǎo)出表進(jìn)行修改過(guò)程中,對(duì)于按名稱(chēng)導(dǎo)入的函數(shù),在導(dǎo)出表中隨機(jī)選取一項(xiàng),修改其導(dǎo)出的函數(shù)名稱(chēng),使之與導(dǎo)入的函數(shù)名稱(chēng)相同;對(duì)于按序號(hào)導(dǎo)入的函數(shù),檢查導(dǎo)出表中是否導(dǎo)出了具有該序號(hào)的函數(shù)。
通過(guò)上述技術(shù)方案,本發(fā)明通過(guò)靜態(tài)掃描的方式,生成程序樣本所依賴(lài)dll文件,無(wú)需執(zhí)行程序樣本,快速安全。并且,本發(fā)明不會(huì)修改程序樣本,因而在滿(mǎn)足程序樣本的外部dll依賴(lài)的同時(shí),能夠避免觸發(fā)程序樣本完整性校驗(yàn)。最后,本發(fā)明不光可以為可執(zhí)行的程序樣本生成所依賴(lài)的外部dll文件,同時(shí)也可以為dll生成其所依賴(lài)的其它dll文件,當(dāng)獲得程序樣本的部分dll,而這些dll還對(duì)其它dll有依賴(lài)時(shí),由于dll和可執(zhí)行程序采用同樣的文件格式(pe格式),因而可以從其文件頭中的導(dǎo)入表獲取其所依賴(lài)的其它dll的信息,故采用同樣的方法,本發(fā)明也能解決這類(lèi)些依賴(lài)問(wèn)題。
附圖說(shuō)明
圖1為本發(fā)明一實(shí)施例中動(dòng)態(tài)鏈接庫(kù)缺失的可執(zhí)行程序的動(dòng)態(tài)分析方法的流程示意圖。
具體實(shí)施方式
本發(fā)明的工作原理:
一個(gè)dll想要導(dǎo)出某些函數(shù)給其它模塊使用時(shí),會(huì)將這些函數(shù)的信息聲明在其導(dǎo)出表結(jié)構(gòu)中,以便外部的程序能夠在dll中找到這些被導(dǎo)出的函數(shù)。函數(shù)的導(dǎo)出方式有兩種,按函數(shù)名稱(chēng)導(dǎo)出或按函數(shù)序號(hào)導(dǎo)出。當(dāng)程序需要使用外部的函數(shù)時(shí),會(huì)在其pe文件頭的導(dǎo)入表結(jié)構(gòu)中聲明需要引入的函數(shù)名稱(chēng)或是函數(shù)序號(hào),以及這些函數(shù)存在于哪些dll文件中。windows加載器在啟動(dòng)程序時(shí),根據(jù)程序的導(dǎo)入表,為程序加載相應(yīng)的dll到虛擬地址空間中,并根據(jù)被導(dǎo)入的函數(shù)名稱(chēng)或函數(shù)序號(hào),從被加載的dll中找到這些函數(shù)的真實(shí)地址并予以引用。為了能使程序正常的啟動(dòng),程序的導(dǎo)入表結(jié)構(gòu)應(yīng)該是正確的,即使程序可能是惡意的。
下面結(jié)合附圖詳細(xì)說(shuō)明本發(fā)明所提供的技術(shù)方案:
如圖1所示,在一實(shí)施例中,提供的一種動(dòng)態(tài)鏈接庫(kù)缺失的可執(zhí)行程序的動(dòng)態(tài)分析方法,包括步驟:
1.種子dll的生成和系統(tǒng)dll列表的獲取
首先需要生成一個(gè)特殊的dll,稱(chēng)為種子dll,由它為模板,生成所有程序樣本導(dǎo)入的dll。該dll導(dǎo)出的函數(shù)個(gè)數(shù)應(yīng)該足夠多,因?yàn)槌绦蛟诎葱蛱?hào)導(dǎo)入函數(shù)時(shí),序號(hào)值一般與要導(dǎo)入的dll中的函數(shù)個(gè)數(shù)有對(duì)應(yīng)關(guān)系,但也可以指定為任意值,不過(guò)這樣并沒(méi)有什么實(shí)際意義。導(dǎo)出9999個(gè)函數(shù),在多數(shù)情況下應(yīng)該夠用了。當(dāng)然,導(dǎo)出的函數(shù)個(gè)數(shù)并不限于該數(shù)值,本領(lǐng)域技術(shù)人員當(dāng)可根據(jù)實(shí)際的運(yùn)行環(huán)境和需求進(jìn)行選取,在理解本發(fā)明核心主旨的前提下,知悉如何滿(mǎn)足“足夠多”的需求。
此外,dll的名稱(chēng)(dll文件頭部導(dǎo)出表結(jié)構(gòu)中域name1指示的該dll的真實(shí)名字,不是dll文件名)和導(dǎo)出函數(shù)的名稱(chēng)應(yīng)該足夠長(zhǎng),因?yàn)樵谛薷暮瘮?shù)名或dll名稱(chēng)時(shí),只能從長(zhǎng)的改為短的,例如,名稱(chēng)長(zhǎng)度為128個(gè)字符多數(shù)情況下是足夠的。同樣地,該名稱(chēng)長(zhǎng)度同樣不限于該例舉的數(shù)值。
種子dll的版本應(yīng)該和分析平臺(tái)的系統(tǒng)版本相兼容,種子dll同時(shí)按函數(shù)名稱(chēng)和序號(hào)值導(dǎo)出函數(shù)。
為了能夠減少不必要的工作量,從分析平臺(tái)的系統(tǒng)目錄(一般是c:\windows\system和c:\windows\system32)中提取所有dll名稱(chēng),當(dāng)程序樣本需要導(dǎo)入的為這些系統(tǒng)dll時(shí),直接跳過(guò)。
2.判斷程序樣本是否有合法的導(dǎo)入表結(jié)構(gòu)
解析程序樣本的文件頭,若其不是pe文件或沒(méi)有合法的導(dǎo)入表結(jié)構(gòu),跳過(guò)該樣本。直接判斷為無(wú)效程序。
3.提取程序樣本導(dǎo)入的dll及相對(duì)應(yīng)的導(dǎo)入函數(shù)
解析程序樣本pe文件頭中的導(dǎo)入表結(jié)構(gòu)image_import_descriptor,獲取程序樣本導(dǎo)入dll模塊名稱(chēng),再根據(jù)image_thunk_data得到按函數(shù)序號(hào)導(dǎo)入的函數(shù)的序號(hào)值,得到按函數(shù)名稱(chēng)導(dǎo)入的函數(shù)的字符串名和hint值。
4.生成程序樣本依賴(lài)的外部dll
針對(duì)程序樣本導(dǎo)入的每一個(gè)dll,先將步驟1中生成的種子dll拷貝一份,文件名改為導(dǎo)入的dll名稱(chēng)。然后修改拷貝后的種子dll的導(dǎo)出表結(jié)構(gòu)image_export_directorystruct中指定的模塊真實(shí)名稱(chēng)為導(dǎo)入的dll名稱(chēng)。
接著根據(jù)步驟3提取到的對(duì)應(yīng)的導(dǎo)入函數(shù)信息,修改拷貝后的種子dll的導(dǎo)出表結(jié)構(gòu),修改方法為:只按序號(hào)導(dǎo)入的函數(shù),檢查該序號(hào)是否被導(dǎo)出,若導(dǎo)出,則跳過(guò),否則輸出錯(cuò)誤信息并終止該dll的生成過(guò)程,繼續(xù)嘗試生成下一被導(dǎo)入的dll。按函數(shù)名導(dǎo)入的函數(shù),若其hint值為零,則在導(dǎo)出表中addressofnames域指出的導(dǎo)出函數(shù)名列表中隨機(jī)選擇一項(xiàng),修改該項(xiàng)值為導(dǎo)入函數(shù)名稱(chēng)字符串;若其hint值不為零,則選擇在導(dǎo)出表中由addressofnames域指出的導(dǎo)出函數(shù)名列表里以hint值為下標(biāo)(下標(biāo)編號(hào)從0開(kāi)始)的那一項(xiàng),修改其值為導(dǎo)入函數(shù)名稱(chēng)字符串,若hint值大于導(dǎo)出的函數(shù)個(gè)數(shù),輸出錯(cuò)誤信息并終止該dll的生成過(guò)程,繼續(xù)嘗試生成下一被導(dǎo)入的dll。
5.輸出生成結(jié)果
待程序樣本導(dǎo)入的每個(gè)dll都按步驟4處理完成后,將成功生成的dll移動(dòng)到用戶(hù)指定的目錄中,并向用戶(hù)報(bào)告生成結(jié)果。
本發(fā)明提出的動(dòng)態(tài)鏈接庫(kù)缺失的可執(zhí)行程序的動(dòng)態(tài)分析方法,對(duì)于本領(lǐng)域的技術(shù)人員而言,在遵循本發(fā)明核心主旨的前提下,可以根據(jù)需要自己編譯合適的種子dll,設(shè)計(jì)導(dǎo)入表解析和導(dǎo)出表修改方法,從而快速高效地生成程序樣本所依賴(lài)的外部dll文件。
盡管為說(shuō)明目的公開(kāi)了本發(fā)明的具體實(shí)施例和附圖,其目的在于幫助理解本發(fā)明的內(nèi)容并據(jù)以實(shí)施,但是本領(lǐng)域的技術(shù)人員可以理解:在不脫離本發(fā)明及所附的權(quán)利要求的精神和范圍內(nèi),各種替換、變化和修改都是可能的。因此,本發(fā)明不應(yīng)局限于最佳實(shí)施例和附圖所公開(kāi)的內(nèi)容,本發(fā)明要求保護(hù)的范圍以權(quán)利要求書(shū)界定的范圍為準(zhǔn)。