干貨分享惡意樣本分析手冊——常用方法篇

      網(wǎng)友投稿 1254 2022-05-29

      圖解惡意樣本分析的常用方法,你與安全專家的差距只有一篇文章!

      文章目錄

      文件識別

      靜態(tài)分析

      采用反病毒引擎掃描

      計算哈希值

      查找字符串

      查找導(dǎo)入函數(shù)

      解析宏

      偵殼操作

      動態(tài)調(diào)試

      單步跟蹤法

      ESP定律法

      單步跟蹤法

      UPX

      單步跟蹤法

      ESP定律法

      內(nèi)存鏡像法

      脫殼

      ASPack

      FSG

      FSG變形殼

      FSG2.0

      內(nèi)存鏡像法

      巧方法

      附加數(shù)據(jù)的處理

      PECompact1.84

      nspack

      Yoda

      多線程調(diào)試

      調(diào)試子進(jìn)程

      SYS調(diào)試

      環(huán)境搭建

      配置虛擬機(jī)

      windbg配置

      設(shè)置windows內(nèi)核符號表

      尋找DriverEntry

      DLL調(diào)試

      JS調(diào)試

      Alert方法

      Console方法

      JS斷點(diǎn)調(diào)試

      debugger方法

      【干貨分享】惡意樣本分析手冊——常用方法篇

      .net調(diào)試

      文件識別

      常見的可執(zhí)行程序格式有PE,ELF,MACH-O等,不同的格式有不同的標(biāo)志信息(參考理論篇),知道了目標(biāo)文件的格式后才能確定對應(yīng)的分析方法和分析工具。

      可以使用16進(jìn)制解析器載入可執(zhí)行程序,然后查看是哪種類型的文件。

      圖:PE文件格式

      圖:ELF文件格式

      一般二進(jìn)制文件的前四個字節(jié)為文件格式的magic,可以通過從網(wǎng)絡(luò)搜索獲得文件的信息,或者使用相關(guān)的工具(PEID,file)等進(jìn)行自動識別。

      靜態(tài)分析

      靜態(tài)分析技術(shù)通常是研究惡意代碼的第一步。靜態(tài)分析指的是分析程序指令與結(jié)構(gòu)來確定目標(biāo)程序的功能的過程。在這個時候,病毒本身并不在運(yùn)行狀態(tài)。我們一般采用以下幾種方式進(jìn)行靜態(tài)分析:

      采用反病毒引擎掃描

      如果尚不確定目標(biāo)程序是否為病毒程序,我們可以首先采用多個不同的反病毒軟件來掃描一下這個文件,看是否有哪個引擎能夠識別它。(www.virscan.org、www.virustotal.com?)

      注意:只能通過MD5值查詢,不允許將樣本進(jìn)行上傳。

      圖 35:VitusTotal檢測結(jié)果界面

      計算哈希值

      哈希是一種用來唯一標(biāo)識目標(biāo)程序的常用方法。目標(biāo)程序通過一個哈希算法,會產(chǎn)生出一段唯一的用于標(biāo)識這個樣本的哈希值,我們可以將這個值理解為是目標(biāo)程序的指紋。常用的哈希算法有MD5、Sha-1以及CRC32等。由于僅僅采用一種算法,特別是MD5算法,有可能使得不同程序產(chǎn)生同樣的哈希結(jié)果,所以一般會運(yùn)用多種哈希驗(yàn)證文件的唯一性。

      圖 36:計算文件校驗(yàn)碼

      查找字符串

      程序中的字符串就是一串可打印的字符序列,一個程序通常都會包含一些字符串,比如打印輸出信息、連接的URL,或者是程序所調(diào)用的API函數(shù)等。從字符串中進(jìn)行搜索是獲取程序功能提示的一種簡單方法。(在IDA和OD中都可以查找字符串)并不是所有的字符串都是有意義的,但是利用這個結(jié)果,也能夠給我們的靜態(tài)分析帶來很大的便利了。

      圖 37:查看字符串信息

      查找導(dǎo)入函數(shù)

      如果軟件被加殼的話,那么導(dǎo)入表中的函數(shù)會很少,所以可以從這里判斷文件是否被加殼。如果沒有加殼,那么導(dǎo)入表中會列出程序使用的大部分函數(shù)(除去程序動態(tài)獲得的),我們就可以通過這些函數(shù)大致判斷一下程序的行為。

      解析宏

      使用IDA反匯編程序的時候,IDA并不會將宏的名字解析出來,相反,它只會使用宏對應(yīng)的數(shù)字進(jìn)行顯示,如下如所示:

      如果只看這些數(shù)字,完全無法得知什么情況,好在IDA提供了解析機(jī)制,可以將數(shù)字轉(zhuǎn)換為宏名。在對應(yīng)的數(shù)字上右鍵,選擇Enum:

      然后在彈出的對話框中選擇對應(yīng)的宏即可!

      替換后的結(jié)果如下,這樣的話,就方便了靜態(tài)查看代碼。

      偵殼操作

      病毒木馬編寫者經(jīng)常會使用加殼技術(shù)來讓他們的惡意程序難以被檢測或分析。正常的程序總是會包含很多字符串。而加了殼的惡意代碼通過分析所得到的可打印字符串就會很少。如果查找出的程序的字符串很少時,那么這個程序就很有可能是加了殼的。此時往往就需要使用其它方法來進(jìn)一步檢測它們的行為。(常用PEiD進(jìn)行查殼)

      圖 38:查殼

      動態(tài)調(diào)試

      使用調(diào)試器對病毒進(jìn)行分析在反病毒工作中扮演著十分重要的角色。調(diào)試器允許你查看任意內(nèi)存地址的內(nèi)容、寄存器的內(nèi)容以及每個函數(shù)的參數(shù)。調(diào)試器也允許你在任意時刻改變關(guān)于程序執(zhí)行的任何東西。比如你可以在任意時刻改變一個變量的值——前提是你需要獲得關(guān)于這個變量足夠的信息,包括在內(nèi)存中的位置。在實(shí)際的動態(tài)調(diào)試過程中,最常用的是OllyDBG和WinDbg,前者是病毒分析人員使用最多的調(diào)試器,缺點(diǎn)是不支持內(nèi)核調(diào)試,如果想調(diào)試內(nèi)核,WinDbg基本上就是唯一的選擇了。雖然IDA Pro也能夠進(jìn)行動態(tài)調(diào)試,但是它遠(yuǎn)遠(yuǎn)不如OD方便。因此在實(shí)際分析的過程中,往往是將二者結(jié)合使用的。因?yàn)槿绻肐DA Pro在靜態(tài)分析中遇到了十分抽象的函數(shù),那么用OD動態(tài)地執(zhí)行一下,該函數(shù)的功能往往就能一目了然了。關(guān)于常用工具OllyDbg和Windbg的使用方法請參考工具篇。

      脫殼

      攻擊者為了保護(hù)攻擊代碼,提高分析難度,避免被殺毒軟件查殺,經(jīng)常對可執(zhí)行程序進(jìn)行加殼來達(dá)到以上目的,本節(jié)對一些常見的殼的脫殼方法進(jìn)行介紹(關(guān)于殼的基本信息可以參考文件封裝篇)。

      將UPX加殼程序使用OD打開時出現(xiàn)下面的對話框,選擇“否”。

      單步跟蹤法的原則是實(shí)現(xiàn)向下的跳轉(zhuǎn),越過向上的跳轉(zhuǎn),如果越過了某一個向上的跳轉(zhuǎn)后,程序跑飛了,那么再次調(diào)試到那個跳轉(zhuǎn)語句的時候就實(shí)現(xiàn)其跳轉(zhuǎn),然后再按照實(shí)現(xiàn)向下跳轉(zhuǎn),忽略向上跳轉(zhuǎn)的原則進(jìn)行調(diào)試。

      如上圖所示,jnz為向上的跳轉(zhuǎn),而且它的下一句代碼也是向上的跳轉(zhuǎn),這時就需要在jmp的下面設(shè)置斷點(diǎn),直接讓程序越過這兩個跳轉(zhuǎn)。不能在下面的nop語句上f4運(yùn)行到光標(biāo),否則程序會跑飛。

      按照這套法則,很快就會找到關(guān)鍵句popad,那么程序的入口就在附近了。如下圖所示,并且再看程序的地址,jmp跳轉(zhuǎn)的目標(biāo)地址為0x004010CC,這條指令所在的地址為0x0040EA0F,可見這是一個很大的跳轉(zhuǎn),說明0x004010CC即是OEP。(一般有很大的跳轉(zhuǎn)的話,很快就會到達(dá)程序的OEP)

      跳轉(zhuǎn)之后,就到達(dá)程序OEP。

      開始進(jìn)行脫殼,這里使用OD插件進(jìn)行脫殼,選擇“插件”->”O(jiān)llyDump”->”脫殼在當(dāng)前調(diào)試進(jìn)程”。

      因?yàn)檫@里入口點(diǎn)地址正是我們的OEP:10CC,所以不需要修正,直接點(diǎn)擊脫殼。如果脫殼后的程序無法運(yùn)行,還需要進(jìn)行修正。這里使用方式1脫殼之后,可以運(yùn)行,不需要修正;使用方式2脫殼之后,無法運(yùn)行,可以使用Import REConstructor進(jìn)行修正。在軟件的下拉框中選中要進(jìn)行脫殼的程序(這里使用的是upx.exe),然后修改OEP為我們找到的值:0x10CC。

      點(diǎn)擊AutoSearch或者GetImports獲取導(dǎo)入函數(shù),然后點(diǎn)擊showinvalid顯示無效的函數(shù),沒有的話就點(diǎn)擊FixDump,選取要修正的應(yīng)用程序,之后,會在應(yīng)用程序所在的文件夾下生成一個原文件名加下劃線的應(yīng)用程序。比如原始文件名為xxx.exe,那么Import REConstructor生成的文件名為xxx_.exe。至此,脫殼完畢。

      關(guān)鍵句運(yùn)行之后,ESP的值會改變!

      右鍵ESP,選擇Follow in Dump。

      在ESP地址處設(shè)置硬件訪問斷點(diǎn)。

      設(shè)置完斷點(diǎn)之后,可以選擇Debug->Hardware breakpoints查看硬件斷點(diǎn)是否設(shè)置成功。

      F9運(yùn)行程序,程序停在關(guān)鍵句附近,接著要刪除設(shè)置的硬件斷點(diǎn),直接店家上圖所示的Delete即可。找到OEP之后再進(jìn)行脫殼。

      首先需要對OD進(jìn)行設(shè)置,忽略所有異常

      在內(nèi)存窗口中找到程序的.rsrc段,按f2鍵設(shè)置斷點(diǎn),shift+f9運(yùn)行程序,斷下之后,在程序的代碼段按f2設(shè)置斷點(diǎn)。

      shift+f9運(yùn)行,程序?qū)⑼T贠EP附近。

      ASPack

      脫ASPack殼可以使用上面所說的單步跟蹤法,ESP定律法和內(nèi)存鏡象法,這里以單步跟蹤法進(jìn)行演示,其他兩種方法的思路如上所述。

      單步跟蹤法除了上面說的跳轉(zhuǎn)規(guī)則外,還有一個規(guī)則需要遵從,那就是近c(diǎn)all f7進(jìn)入,遠(yuǎn)call f8跳過。如果跳過了某個函數(shù)之后程序跑飛,那么再次調(diào)試時f7進(jìn)入此函數(shù)即可。

      如下所示,載入程序后即可看到一個call指令,那么這個函數(shù)就需要進(jìn)入跟蹤。

      接著按照跳轉(zhuǎn)指令和call指令規(guī)則進(jìn)行跟蹤。

      跟蹤到如上圖所示的地址后,就快到大OEP了,可見這個程序采用的是push/ret的方式進(jìn)行跳轉(zhuǎn)的,而且跳轉(zhuǎn)的跨度很到,從0x004243BA處跳轉(zhuǎn)到0x00402360。跳轉(zhuǎn)之后即到OEP,接著按照上面所說的方式進(jìn)行脫殼。

      FSG

      按照前面講解的原則對fsg殼進(jìn)行單步跟蹤需要細(xì)心,拿此例來說,單步跟蹤的時候,看到如下所示的語句:

      這個跳轉(zhuǎn)并沒有實(shí)現(xiàn),但是程序的OEP就在0x004010CC,我們可以跟隨到這個地址里面查看代碼,直接在這個地址右鍵,選擇follow:

      但是并沒有看到我們想要的代碼:

      遇到這種情況,直接右鍵,選擇Analysis->Analyse code,就可以將這些機(jī)器碼轉(zhuǎn)為匯編碼:

      使用ESP定律法單步跟蹤的時候,要時刻注意著ESP值的變化,當(dāng)ESP的值發(fā)生變化后,就安裝上面所說的方法設(shè)置硬件訪問斷點(diǎn),然后運(yùn)行程序,程序?qū)⑼V乖趏ep附近,然后在單步跟蹤,很快就將找到程序OEP。

      FSG變形殼

      FSG變形殼在找OEP的方法和FSG的查找方法一樣,只是在脫殼的時候有點(diǎn)區(qū)別,按照FSG的脫殼方法找到OEP之后,進(jìn)行脫殼,使用OD的插件進(jìn)行脫殼,發(fā)現(xiàn)程序無法運(yùn)行,然后再對其導(dǎo)入表進(jìn)行修正。使用Import REConstructor載入目標(biāo)程序,修改OEP,點(diǎn)擊show Invalid會看到一些無效的程序。

      在這些無效的程序上右鍵,選擇cut thunks,接著點(diǎn)擊Fix Dump選擇我們脫下來的程序。但是修正之后發(fā)現(xiàn)仍然無法運(yùn)行,將修復(fù)后的程序使用OD載入,直接F9運(yùn)行,看到OD中斷到下圖所示的位置:

      第一種方法,將int 0x13使用nop覆蓋:

      第二種方法,將jle改為jmp強(qiáng)制跳轉(zhuǎn),越過int 0x13:

      修改之后,保存文件,就可以運(yùn)行了。也可以使用16進(jìn)制工具打開文件,找到相應(yīng)的位置,修改數(shù)據(jù)并保存。

      FSG2.0

      使用ESP定律法和單步跟蹤法結(jié)合可以很快找到程序的OEP,這里重點(diǎn)講解脫殼后的修復(fù)問題。

      使用Import REConstructor載入程序后,點(diǎn)擊Get Import可以看到只有37個函數(shù),這是很不正常的,而且沒有無效的指針。如果直接進(jìn)行Fix Dump程序依然無法執(zhí)行。

      可以看到上圖中IAT表的大小只有0x94,這是不對的,需要對IAT進(jìn)行修復(fù),這里介紹兩種方法,第一種方法是通過OD,當(dāng)我們找到OEP的時候,可以看到下圖所示的情況:

      函數(shù)GetCommandLineA所在的地址是0x4063E4,在dump窗口(左下窗口)中定位到這個函數(shù)的地址:

      向上找,直到遇到一堆00,此時就找到了IAT表的開始地址,如下圖所示,開始地址是0x004062E4。

      然后在往后找,同樣是找00,即IAT的結(jié)尾。可以看到它結(jié)尾

      的地址是0x00406E00。

      所以IAT的大小為0x00406E00-0x004062E4=0xB1C,接著就把RVA和Size寫入Import REConstructor中。

      cut掉無效的函數(shù)指針,選取我們脫殼后的應(yīng)用程序進(jìn)行Dump即可。

      第二種方法和第一種類似,都需要找到IAT的RVA進(jìn)行修改,不同的是不需要計算Size的值,隨便寫一個比較大的值,比如0x1000就行,這樣的話,肯定會有很多無效的函數(shù)指針,當(dāng)我們查看這些無效指針的反匯編代碼時,會提示ReadError。

      這種情況下,直接把無效的指針cut掉即可。

      PECompact1.84

      使用單步跟蹤法對PECompact殼進(jìn)行調(diào)試的時候,會看到有些向上的跳轉(zhuǎn),如果我們在這些跳轉(zhuǎn)的下面下斷點(diǎn)運(yùn)行程序的話,程序?qū)⑴茱w,這個時候,就需要在這些跳轉(zhuǎn)的前面,找一個沒有實(shí)現(xiàn)的大跳轉(zhuǎn),跟隨進(jìn)去,設(shè)置斷點(diǎn),然后運(yùn)行程序,使用這種方法,一般很快就可以找到OEP。

      例如:

      有一個向上的jmp跳轉(zhuǎn),如果在它下面設(shè)置斷點(diǎn)并運(yùn)行程序的話,程序就將跑飛,這時,需要重新載入程序,在這個jmp前面找到一個沒有實(shí)現(xiàn)的大跳轉(zhuǎn)。

      跟隨進(jìn)這個跳轉(zhuǎn)地址,設(shè)置斷點(diǎn)運(yùn)行程序

      按照這個思路進(jìn)行調(diào)試,即可找到程序OEP,接下來就可以進(jìn)行脫殼。

      nspack

      對于nspack的殼,最簡單的方法就是使用esp定律法,當(dāng)然,使用前面所說的其他方法也可以找到OEP。

      Yoda

      首先使用peid查看一下殼,可以看到是yoda1.2的殼

      使用OD載入程序,忽略所有異常,找到內(nèi)存的.rsrc段,設(shè)置斷點(diǎn)后運(yùn)行程序,然后再在代碼段設(shè)置斷點(diǎn),運(yùn)行程序,就可直接到達(dá)程序的OEP,脫這個殼的重點(diǎn)在于修復(fù)方面。按照上述方法進(jìn)行脫殼,使用Import REConstructor進(jìn)行修復(fù),發(fā)現(xiàn)大部分的指針都是無效的。

      點(diǎn)擊Show Invalid顯示無效指針,然后右鍵選擇Trace Level1進(jìn)行修復(fù)。

      修復(fù)之后,所有的指針都有效了

      然后再選擇目標(biāo)程序進(jìn)行fix dump。

      還有一個方法是單獨(dú)尋找,比如在如下圖所示的情況下:

      右鍵目標(biāo)指針,選擇16進(jìn)制查看。

      我們選擇的指針就是第一行那個,庫文件是advapi32,函數(shù)名為RegSetValueExA:

      然后雙擊剛才選擇的指針,查找對應(yīng)的動態(tài)庫和函數(shù)名

      點(diǎn)擊OK之后,就會發(fā)現(xiàn)指針已被修復(fù)。

      當(dāng)然這種方法適合無效指針較少的情況。修復(fù)完之后,選擇脫殼后的文件進(jìn)行Fix即可。

      打開OD,對OD進(jìn)行設(shè)置。

      選擇SFX->Trace real entry bytewise。

      然后載入目標(biāo)程序,OD將自動停在OEP處。這種方法可以嘗試使用,不保證適用于每一種殼。

      首先使用peid對目標(biāo)程序進(jìn)行查殼,從peid的顯示信息上看,可以看到這是北斗殼,Overlay表示有附加數(shù)據(jù)。

      這個殼比較簡單,重點(diǎn)講解是脫殼后的修復(fù),這里介紹兩種方法。

      第一種方法是使用16進(jìn)制編輯器載入原始的目標(biāo)程序,從數(shù)據(jù)末尾向上找,一直找到全為0的位置。

      從CA00開始復(fù)制,一直復(fù)制到數(shù)據(jù)末尾,然后打開修復(fù)后的文件,在數(shù)據(jù)的末尾將復(fù)制的數(shù)據(jù)粘貼進(jìn)去即可。

      第二種方法和第一種類似,只是找的速度相對較快,使用peid查看程序的節(jié)信息。

      我們需要關(guān)注的是R偏移和R大小,找最后一個區(qū)段,使用0x400+0xC600=0xCA00,然后在16進(jìn)制查看器中定位到這個地址,即是我們復(fù)制的數(shù)據(jù)的開始地址。

      多線程調(diào)試

      OD調(diào)試軟件時,它每次只能跟一個線程,如果遇到的軟件創(chuàng)建了很多線程,那么調(diào)試起來就比較麻煩了,本節(jié)介紹一下多線程的調(diào)試方法。

      首先看一下線程創(chuàng)建的函數(shù):

      HANDLE CreateThread(

      LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD

      SIZE_T dwStackSize,//initialstacksize

      LPTHREAD_START_ROUTINE lpStartAddress,//threadfunction

      LPVOID lpParameter,//threadargument

      DWORD dwCreationFlags,//creationoption

      LPDWORD lpThreadId//threadidentifier

      )

      重點(diǎn)看第三個和第四個函數(shù),其中第三個參數(shù)指定了新線程的入口地址,第四個參數(shù)為新線程所需的參數(shù),當(dāng)程序調(diào)用此函數(shù)來創(chuàng)建線程的時候,定位到線程的入口地址設(shè)置斷點(diǎn),一般情況下,程序會在后面調(diào)用Sleep或WaitForSingleObject函數(shù),這樣的話,程序的控制權(quán)就到了新線程里面。

      如果程序沒有調(diào)用Sleep或WaitForSingleObject函數(shù),那么可以修改函數(shù)的代碼,強(qiáng)制程序調(diào)用這兩個函數(shù),這樣程序就轉(zhuǎn)到新線程中執(zhí)行。另一種方法是修改程序的EIP,使其指向新線程入口,如果有參數(shù)的話,還要修改寄存器的值,使其指向參數(shù)地址,不過這種方法可能會造成寄存器內(nèi)容不正確,環(huán)境異常,從而造成程序執(zhí)行崩潰。

      還有一種方法來調(diào)試多線程。如果程序多次調(diào)用CreateThread,確定一個我們打算調(diào)試的線程,并讓這個線程創(chuàng)建成功,當(dāng)程序再調(diào)用CreateThread創(chuàng)建線程的時候,直接修改此函數(shù),讓它直接返回,這樣就不會再創(chuàng)建線程了,我們就可以只調(diào)試一個線程。

      調(diào)試子進(jìn)程

      有些樣本并不是單獨(dú)運(yùn)行的,它在運(yùn)行過程中可能會創(chuàng)建子進(jìn)程來完成惡意功能,遇到這種情況,就需要進(jìn)入子進(jìn)程中進(jìn)行調(diào)試。

      如果父進(jìn)程創(chuàng)建子進(jìn)程時是以suspended的方式創(chuàng)建的,那么父進(jìn)程會向子進(jìn)程進(jìn)行代碼注入,寫入之后會調(diào)用ResumeThread函數(shù)恢復(fù)子進(jìn)程的運(yùn)行。遇到這種情況,要確定父進(jìn)程寫入代碼的地址,當(dāng)代碼寫入之后,調(diào)用ResumeThread恢復(fù)子進(jìn)程運(yùn)行前,附加到子進(jìn)程中,在代碼注入的地址下斷點(diǎn)并F9讓子進(jìn)程運(yùn)行。這時再回到父進(jìn)程中,運(yùn)行函數(shù)ResumeThread,這樣子進(jìn)程就可以斷在代碼注入的地址了。

      還有一種創(chuàng)建子進(jìn)程的方式,就只是簡單的開啟一個子進(jìn)程運(yùn)行,這種情況比較簡單,需要注意的一點(diǎn)就是父進(jìn)程創(chuàng)建子進(jìn)程時傳給子進(jìn)程的參數(shù),使用OD打開要運(yùn)行的子進(jìn)程,傳入所需的參數(shù)即可開始調(diào)試。

      PS:如果使用windbg調(diào)試的話,可以使用命令.childdbg 1開啟子進(jìn)程調(diào)試。

      SYS調(diào)試

      sys是驅(qū)動文件,相對于應(yīng)用程序來說,它的調(diào)試難度稍微大一點(diǎn),調(diào)試sys需要進(jìn)行雙機(jī)調(diào)試,而前提就是搭建雙機(jī)調(diào)試的環(huán)境。

      環(huán)境搭建

      1.打開vmware中對應(yīng)的虛擬機(jī)設(shè)置界面,如下圖:

      2.查看是否已經(jīng)有端口存在,如果有的話需要移除,否則windbg與vmware連接不上,比如下圖,就需要將打印機(jī)移除。

      3.添加串口。

      4.在硬件類型窗口中選擇串行端口,并點(diǎn)擊下一步。

      5.在串行端口類型窗口下選擇輸出到命名管道,然后點(diǎn)擊下一步。

      6.指定插槽。

      配置如下圖所示,其中命名管道的com_1為管道名稱,可以作改動,但是在用windbg進(jìn)行連接的時候也要注意名字的一致,我這里保留默認(rèn)名。兩臺機(jī)器,一臺為【該端是服務(wù)器】保留默認(rèn)設(shè)置,最后一個下拉框選擇【另一端是應(yīng)用程序】。最后注意吧【啟動時連接】的復(fù)選框選上。

      然后點(diǎn)擊【完成】按鈕即可完成配置。

      7.完成串行端口添加。

      配置虛擬機(jī)

      打開虛擬機(jī)中windows的系統(tǒng)盤,找到boot.ini文件,如果不顯示這個文件的話,在文件夾選項(xiàng)中設(shè)置為“顯示所有文件”,“不隱藏系統(tǒng)保護(hù)文件”,然后就可以看到boot.ini文件了。

      打開boot.ini文件后,原始內(nèi)容如下

      [boot loader]

      timeout=30

      default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS

      [operating systems]

      multi(0)disk(0)rdisk(0)partition(1)\WINDOWS=”Microsoft Windows XP Professional” /noexecute=optin /fastdetect

      將最后一行復(fù)制并粘貼在[operating systems]下,然后修改一些參數(shù)即可

      [boot loader]

      timeout=30

      default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS

      [operating systems]

      multi(0)disk(0)rdisk(0)partition(1)\WINDOWS=”XP Debug”? /fastdetect /debug /debugport=com1 /buadrate=115200

      multi(0)disk(0)rdisk(0)partition(1)\WINDOWS=”Microsoft Windows XP Professional” /noexecute=optin /fastdetect

      windbg配置

      下面設(shè)置調(diào)試機(jī)上的windbg啟動參數(shù),使之連接一個管道,并把這個管道當(dāng)作一個串口來處理,首先建立一個windbg.exe的快捷方式,然后右鍵快捷方式圖標(biāo)選擇屬性,在屬性對話框的目標(biāo)一欄加上空格后添加windbg.exe -b -k com:pipe,port=\\.\pipe\com_1,baud=115200,pipe,然后點(diǎn)擊保存即可。

      要進(jìn)行雙機(jī)調(diào)試的話,在虛擬機(jī)啟動時,選擇啟動調(diào)試程序,當(dāng)虛擬機(jī)啟動起來之后,再開啟windbg就可以連接到虛擬機(jī)中。

      設(shè)置windows內(nèi)核符號表

      打開windbg,選擇菜單“File”->”Symbol File Path”,然后填寫:

      srv*c:\Symbols*http://msdl.microsoft.com/download/symbols

      如下圖,如果我們選擇了Reload,那么相當(dāng)于輸入了.reload命令,這時開始下載符號。

      以上方法是設(shè)置是WinDbg自動用HTTP協(xié)議從微軟的網(wǎng)站上下載所需的符號表。下載完后可以在C:\Symbols目錄中查看,這個路徑也可以指定為其它路徑。

      尋找DriverEntry

      首先使用命令uf nt!IopLoadDriver查看驅(qū)動加載的入口,針對32位程序和64位程序,入口處的代碼不一樣,32位下的代碼如下

      nt!IopLoadDriver+0x663:

      805a07c9 ffb570ffffff??? push??? dword ptr [ebp-90h]

      805a07cf 57????????????? push??? edi

      805a07d0 ff572c????????? call??? dword ptr [edi+2Ch]

      805a07d3 3bc3??????????? cmp???? eax,ebx

      805a07d5 8b8d68ffffff??? mov???? ecx,dword ptr [ebp-98h]

      805a07db 8945ac????????? mov???? dword ptr [ebp-54h],eax

      805a07de 8901??????????? mov???? dword ptr [ecx],eax

      805a07e0 0f8c91200500??? jl????? nt!IopLoadDriver+0x67c (805f2877)

      64位下的代碼如下:

      nt!IopLoadDriver+0x9fe:

      fffff80002cb545e 488bd6????????? mov???? rdx,rsi

      fffff80002cb5461 488bcb????????? mov???? rcx,rbx

      fffff80002cb5464 ff5358????????? call??? qword ptr [rbx+58h]

      fffff80002cb5467 4c8b15da3bdaff? mov???? r10,qword ptr [nt!PnpEtwHandle (fffff80002a59048)]

      fffff80002cb546e 8bf8??????????? mov???? edi,eax

      fffff80002cb5470 898424e0000000? mov???? dword ptr [rsp+0E0h],eax

      fffff80002cb5477 4c3bd5????????? cmp???? r10,rbp

      fffff80002cb547a 0f848e000000??? je????? nt!IopLoadDriver+0xaae (fffff80002cb550e)

      可以通過搜索上述代碼中加紅的代碼定位到關(guān)鍵點(diǎn),然后bp下斷點(diǎn),之后輸入”g”讓虛擬機(jī)運(yùn)行,回到使用軟件KmdManager加載驅(qū)動,打開KmdManager,界面如下:

      將sys文件拖入上圖所示的窗口中,在小方框中打勾(可以在卸載驅(qū)動的時候再在下面的打勾),如下圖所示:

      然后點(diǎn)擊Reg`nRun加載驅(qū)動,會看到斷點(diǎn)斷在我們設(shè)置的地方,然后F11進(jìn)入就達(dá)到了DriverEntry開始調(diào)試。

      注意:32位的驅(qū)動程序要在32位系統(tǒng)下調(diào)試,64的驅(qū)動程序要在64位系統(tǒng)下調(diào)試。

      DLL調(diào)試

      使用OD調(diào)試動態(tài)庫時有兩種打開方式,第一種比較簡單,直接將dll文件拖入OD即可,OD自身會自動識別出來當(dāng)前文件是動態(tài)庫文件,然后啟用loadll.exe來加載此動態(tài)庫文件。

      另一種方法是通過OD打開rundll32.exe,傳入動態(tài)庫文件的路徑作為參數(shù)來進(jìn)行調(diào)試。

      上面兩種是比較直接的方式,但是有的dll文件會在od載入并斷下來時,就已經(jīng)執(zhí)行完了惡意代碼,遇到這種情況,就需要下面介紹的一種調(diào)試技巧。

      選擇菜單欄的Options->Debugging options。

      在彈出的窗口中選擇Events,勾選Break on new module(dll).然后點(diǎn)擊OK。

      這樣的話,在新模塊載入的時候,OD會斷下來。此時注意Executable modules窗口的變化,這里會顯示動態(tài)庫加載的內(nèi)存地址。

      如圖所示,我們的目標(biāo)動態(tài)庫的基地址是0x10000000。然后使用IDA打開目標(biāo)文件,找到想要下斷點(diǎn)的地址,以下圖為例:

      假如我們想要在sub_1000824C處設(shè)置斷點(diǎn),直接在OD中,定位到這個地址,然后設(shè)置斷點(diǎn)即可。如果在IDA中顯示的地址是0x2000824C,那么我們在OD中的0x2000824C地址處是找不到對應(yīng)的代碼的。這時需要計算代碼的偏移,很明顯,我們可以知道這個地址的RVA是824C,然后在OD中,將這個偏移加上OD加載的基地址0x10000000即可得到對應(yīng)代碼的絕對地址。然后設(shè)置斷點(diǎn)運(yùn)行程序即可(此時可以取消先前設(shè)置的Break on new module斷點(diǎn)了)。

      JS調(diào)試

      目前使用JS來執(zhí)行惡意功能或者下載惡意組件的情況已經(jīng)很平常了,所以這里介紹一下關(guān)于js的調(diào)試方法。

      大部分的js腳本都是經(jīng)過混淆或者加密的,靜態(tài)分析的話根本不可能,一般在分析之前都需要對js腳本進(jìn)行一下美化,推薦美化網(wǎng)站:http://jsbeautifier.org/

      下面進(jìn)入正題,講解js的調(diào)試方法。

      Alert方法

      在互聯(lián)網(wǎng)剛剛起步的時代,網(wǎng)頁前端還主要以內(nèi)容展示為主,瀏覽器腳本還只能為頁面提供非常簡單的輔助功能的時候。那個時候,網(wǎng)頁主要運(yùn)行在以IE6為主的瀏覽器中,JS的調(diào)試功能還非常弱,只能通過內(nèi)置于Window對象中的alert方法來調(diào)試,在網(wǎng)頁中按F12鍵,點(diǎn)擊Console按鈕。

      直接在這里輸入想要查看的值即可。如下圖所示,我們輸入var a = ‘a(chǎn)bc’;alert(a);瀏覽器即彈出對話框,顯示變量a的值。

      Console方法

      隨著js能做的事情越來越多,責(zé)任越來越大,地位也越來越重要,傳統(tǒng)的alert調(diào)試方法漸漸的跟不上技術(shù)前進(jìn)的節(jié)奏,alert調(diào)試方式彈出的調(diào)試信息,窗口不太美觀,而且會遮擋頁面內(nèi)容,另外,使用alert方法,必須在程序邏輯中添加alert(xxx)的語句才能正常工作,比較麻煩,對于開發(fā)人員來說,后期還要手動清除這些代碼。為了避免這種手續(xù),出現(xiàn)了console的調(diào)試方法。

      和alert方法類似,只是將語句換成console即可。

      也可以在js惡意腳本中添加console語句,輸出想要查看的目標(biāo)值。

      JS斷點(diǎn)調(diào)試

      JS斷點(diǎn)調(diào)試,即是在瀏覽器開發(fā)者工具中為JS代碼添加斷點(diǎn),讓js執(zhí)行到某一位置停止,方便我們對該處的代碼進(jìn)行分析和邏輯處理。為了方便說明,我們先準(zhǔn)備一段示例代碼:

      使用sources斷點(diǎn)

      方法一:使用前面說的,在源碼中添加alert或者console,添加后如下所示:

      結(jié)果為:

      這種方法需要我們手動添加代碼,比較麻煩,下面就使用斷點(diǎn)來調(diào)試

      方法二:點(diǎn)擊F12,找到sources菜單,在左側(cè)樹中找到對應(yīng)的文件,然后點(diǎn)擊行號來添加或刪除斷點(diǎn)

      設(shè)置完斷點(diǎn)后,刷新頁面,程序?qū)⒃跀帱c(diǎn)處停下來,在sources界面中會看到當(dāng)前作用域中所有的變量和值。

      如果想一行一行的跟蹤代碼,可以使用瀏覽器提供的調(diào)試按鈕:

      這六個按鈕的功能依次為:

      Pause/Resume script execution:暫停/恢復(fù)腳本執(zhí)行(程序執(zhí)行到下一斷點(diǎn)停止)。

      Step over next function call:執(zhí)行到下一步的函數(shù)調(diào)用(跳到下一行)。

      Step into next function call:進(jìn)入當(dāng)前函數(shù)。

      Step out of current function:跳出當(dāng)前執(zhí)行函數(shù)。

      Deactive/Active all breakpoints:關(guān)閉/開啟所有斷點(diǎn)(不會取消)。

      Pause on exceptions:異常情況自動斷點(diǎn)設(shè)置

      通過使用這幾個鍵,就可以像調(diào)試可執(zhí)行程序一樣進(jìn)行調(diào)試了。

      需要注意的一點(diǎn)是,直接在代碼區(qū)打印變量值的功能是在較新版本的Chrome瀏覽器中才新增的功能,如果你還在使用較老版本的Chrome瀏覽器,可能無法直接在斷點(diǎn)的情況下查看變量信息,此時你可以將鼠標(biāo)移動到變量名上短暫停頓則會出現(xiàn)變量值。也可以在右邊Watch面板中輸入變量值來查看,此方法同樣適用于表達(dá)式。此外,你還可以在斷點(diǎn)情況下,切換到Console面板,直接在控制臺輸入變量名稱,回車查看變量信息。

      debugger方法

      這種方法是在源程序中添加“debugger;”語句,這樣當(dāng)代碼執(zhí)行到該語句的時候就會自動斷下來,接下去的操作就和上面介紹的斷點(diǎn)調(diào)試方法類似了。

      .net調(diào)試

      調(diào)試分析.net程序,首選的工具就是dnspy,這是一款集靜態(tài)分析與動態(tài)調(diào)試于一體的強(qiáng)大工具。

      直接使用dnspy打開目標(biāo)應(yīng)用程序,界面上顯示的信息告訴了我們函數(shù)的入口點(diǎn),直接點(diǎn)擊Main即可進(jìn)入到main函數(shù)處。

      或者右鍵左邊的樹結(jié)構(gòu),在彈出對話框中選擇Go to Entry Point也可以跳轉(zhuǎn)到程序入口點(diǎn)。關(guān)于dnspy的詳細(xì)使用方法,請參考工具篇的說明。

      找到程序入口后,就可以在關(guān)鍵的地方設(shè)置斷點(diǎn)(F9設(shè)置斷點(diǎn)),然后選擇菜單欄上的調(diào)試按鈕開始調(diào)試。

      點(diǎn)擊上述按鈕后,會彈出一個對話框,在對話框中選擇要調(diào)試的程序和對應(yīng)的參數(shù)就可以開始進(jìn)行調(diào)試了。

      如果程序沒有經(jīng)過混淆的話,dnspy基本可以解析處源碼,所以.net的程序一般都是經(jīng)過混淆的,如果知道它使用的混淆方法,可以在網(wǎng)上搜索對應(yīng)的去混淆的工具,如果不知道的話,只有通過動態(tài)調(diào)試之后,自己對函數(shù)名或者變量名進(jìn)行重命名,方法是在目標(biāo)變量名或者函數(shù)名上右鍵選擇Edit Method。

      如果要修改類名的話,選擇的是Edit Type。

      在調(diào)試過程中,如果想要查看變量的值,直接將鼠標(biāo)放到變量上就將顯示變量的類型和值。

      通用安全

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:python并發(fā)編程之多線程
      下一篇:鯤鵬軟件遷移微認(rèn)證之學(xué)習(xí)筆記
      相關(guān)文章
      亚洲AV蜜桃永久无码精品| 国产aⅴ无码专区亚洲av麻豆| 亚洲中文字幕久久精品无码喷水| 亚洲国产精品无码久久久秋霞1| 亚洲欧洲久久精品| 亚洲色欲色欲综合网站| 亚洲成AV人片在线观看WWW| 国产成人亚洲综合色影视| 中文字幕精品亚洲无线码二区| 亚洲人成网站在线观看青青| 亚洲国产成人精品无码久久久久久综合| 亚洲AV无码一区二区三区性色| 亚洲国产精品无码久久98| 亚洲人成网站999久久久综合| 亚洲色大成网站www尤物| 中文字幕乱码亚洲无线三区| 亚洲五月综合缴情婷婷| 亚洲久悠悠色悠在线播放| 一本色道久久88亚洲精品综合| 在线aⅴ亚洲中文字幕| 亚洲日韩av无码中文| 亚洲AV成人影视在线观看| 亚洲色丰满少妇高潮18p| 日本亚洲中午字幕乱码| 亚洲VA综合VA国产产VA中| 亚洲一区日韩高清中文字幕亚洲 | 亚洲精品国产免费| 亚洲免费在线视频观看| 97久久国产亚洲精品超碰热| 中文字幕亚洲综合久久综合| 色偷偷噜噜噜亚洲男人| 亚洲第一区精品观看| 中文字幕在亚洲第一在线| 精品亚洲综合在线第一区| 亚洲网站在线观看| 亚洲免费在线视频观看| 亚洲成av人无码亚洲成av人| 亚洲AV无码乱码在线观看性色扶| 国产成人麻豆亚洲综合无码精品| 亚洲av色影在线| 亚洲一级毛片免费看|