国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

基于元數(shù)據(jù)和指令流的64位Windows堆棧取證

2021-01-16 02:51翟繼強(qiáng)徐曉陳攀楊海陸
關(guān)鍵詞:元數(shù)據(jù)

翟繼強(qiáng) 徐曉 陳攀 楊海陸

摘要:為解決64位Windows環(huán)境中,現(xiàn)有工具針對(duì)含有惡意進(jìn)程的轉(zhuǎn)儲(chǔ)文件中沒有堆棧幀指針和調(diào)試符號(hào)時(shí),構(gòu)建的堆棧取證會(huì)產(chǎn)生漏報(bào)問題和沒有元數(shù)據(jù)時(shí)構(gòu)建的堆棧取證會(huì)產(chǎn)生錯(cuò)報(bào)問題,提出了從內(nèi)存轉(zhuǎn)儲(chǔ)構(gòu)建堆棧跟蹤方法。從內(nèi)存轉(zhuǎn)儲(chǔ)中檢索目標(biāo)進(jìn)程的用戶上下文,確定堆棧跟蹤的起始點(diǎn),然后基于異常處理的元數(shù)據(jù)展開。如果元數(shù)據(jù)不可用,使用基于指令流的驗(yàn)證方法生成等效數(shù)據(jù)。基于框架Volatility實(shí)現(xiàn)了相應(yīng)插件,實(shí)驗(yàn)表明,方法不依賴堆棧幀指針和調(diào)試符號(hào),利用元數(shù)據(jù)可獲取更加完整的堆棧跟蹤;沒有元數(shù)據(jù)時(shí),基于指令流的驗(yàn)證可以極大地提高取證的精確性。

關(guān)鍵詞:內(nèi)存取證;Windows堆棧;元數(shù)據(jù);指令流;返回地址

DOI:10.15938/j.jhust.2021.05.007

中圖分類號(hào):TP319 文獻(xiàn)標(biāo)志碼:A 文章編號(hào):1007-2683(2021)05-0051-09

0 引言

隨著網(wǎng)絡(luò)和信息技術(shù)的迅速發(fā)展和深入應(yīng)用,以及軟件漏洞的不斷出現(xiàn),網(wǎng)絡(luò)攻擊和網(wǎng)絡(luò)犯罪問題層出不窮,造成了嚴(yán)重的網(wǎng)絡(luò)信息安全威脅[1]。堆棧跟蹤是一種分析惡意軟件的內(nèi)存取證方法[2]。堆棧是操作系統(tǒng)用于存儲(chǔ)關(guān)于每個(gè)程序的活動(dòng)子程序信息的結(jié)構(gòu),存儲(chǔ)的信息包括從調(diào)用者程序傳遞到被調(diào)用程序的參數(shù),子程序的局部變量,子程序完成后的返回的地址。堆棧跟蹤可以提取主機(jī)中程序的返回地址,從而得到調(diào)用的函數(shù)和已執(zhí)行代碼的歷史操作,這些將成為取證分析人員發(fā)現(xiàn)事件起因的重要線索[3]。

在Windows x86環(huán)境下,可以利用傳統(tǒng)技術(shù),即利用幀指針進(jìn)行堆棧跟蹤[4]。由于Microsoft采用“x64軟件約定(x64 software conventions)”,根據(jù)這些約定,64位Windows中進(jìn)程所有空間在函數(shù)開始處就預(yù)分配好,堆棧中不構(gòu)造幀指針鏈[5]。因此基于幀指針的堆棧追蹤技術(shù)對(duì)64位應(yīng)用程序無效。針對(duì)這一問題,Pshoul[6]提出基于掃描的方案并將方法實(shí)現(xiàn)為開源框架Volatility插件malthfind。但其方法在掃描堆棧時(shí)會(huì)錯(cuò)誤地將堆棧中子函數(shù)的返回地址誤識(shí)別為最終返回地址,從而造成誤報(bào);對(duì)內(nèi)存轉(zhuǎn)儲(chǔ)文件中相關(guān)展開數(shù)據(jù)結(jié)構(gòu)利用不充分,導(dǎo)致結(jié)果不完整。Otsuki等[7]在2018年DFRWS(digitalforensic research workshop,數(shù)字取證研討會(huì))上闡述了掃描驗(yàn)證的堆棧重構(gòu)方法并將方法實(shí)現(xiàn)為開源框架 Rekall插件malinfind,提高了堆棧重構(gòu)的準(zhǔn)確性。但其方法在利用元數(shù)據(jù)時(shí)未曾考慮RIP(registerinstruction pointer,寄存器指令指針)位于函數(shù)pro-log與epilog的情況,會(huì)導(dǎo)致在利用相關(guān)結(jié)構(gòu)時(shí)發(fā)生信息匹配錯(cuò)位,從而造成結(jié)果的誤報(bào);其不利用元數(shù)據(jù)時(shí),未考慮相關(guān)RSP(register stack pointer,寄存器基址指針)的偏移量且程序基本執(zhí)行語(yǔ)句僅順序執(zhí)行一次,未將堆棧中人棧數(shù)據(jù)進(jìn)行完全出棧,造成結(jié)果漏報(bào)問題。微軟(Microsoft)發(fā)布的調(diào)試工具WinDbg可以在x86或x64環(huán)境下找到一定的返回地址,但是WinDbg強(qiáng)烈依賴于調(diào)試符號(hào)(程序數(shù)據(jù)庫(kù)文件,也稱為符號(hào)文件),同時(shí)可能錯(cuò)誤地檢測(cè)堆棧區(qū)域中的普通函數(shù)指針作為返回地址。而惡意軟件大多數(shù)代碼區(qū)既沒有調(diào)試符號(hào)也沒有任何元數(shù)據(jù)[8]。

為了解決上述問題,本文提出從64位Windows的內(nèi)存轉(zhuǎn)儲(chǔ)構(gòu)建堆棧跟蹤的方法,并基于Volatility內(nèi)存取證框架設(shè)計(jì)和實(shí)現(xiàn)相應(yīng)的插件。通過實(shí)驗(yàn)測(cè)試評(píng)估了方法的精確性和完整性,確認(rèn)可以更準(zhǔn)確地對(duì)使用或不使用元數(shù)據(jù)的64位進(jìn)程構(gòu)建堆棧跟蹤。

1 Windows x64堆棧

1.1 Windows x64堆棧分配

Windows x64環(huán)境中的運(yùn)行進(jìn)程分為兩種類型:在本機(jī)環(huán)境中執(zhí)行的64位進(jìn)程;在WOW64層上執(zhí)行的32位進(jìn)程。內(nèi)存就像是所有正在運(yùn)行的進(jìn)程的游戲表,要成為游戲的一部分,應(yīng)該將數(shù)據(jù)帶到此表中。該數(shù)據(jù)包括但不限于進(jìn)程的可執(zhí)行代碼,進(jìn)程訪問的數(shù)據(jù)文件,通過Web瀏覽器訪問的URL,用戶名和密碼。Windows操作系統(tǒng)利用虛擬內(nèi)存方法管理系統(tǒng)內(nèi)存。進(jìn)程可用的所有虛擬地址集稱為虛擬地址空間,其可分為兩個(gè)范圍:用戶空間與系統(tǒng)空間。其中的用戶空間是用戶模式處理特定數(shù)據(jù)和用戶模式動(dòng)態(tài)鏈接庫(kù)(dynamic link library,DLL)文件映射到的地址范圍;系統(tǒng)空間(又稱內(nèi)核空間)是操作系統(tǒng)所在的地址范圍,只能由內(nèi)核模式代碼訪問。Windows內(nèi)存管理器使用虛擬地址描述符(virtual address descriptors,VADs)來描述進(jìn)程在分配時(shí)使用的內(nèi)存范圍[9]。當(dāng)進(jìn)程使用Virutal-Alloc函數(shù)分配內(nèi)存時(shí),內(nèi)存管理器會(huì)在VAD樹中創(chuàng)建一個(gè)條目。VAD樹本身是一個(gè)自平衡二叉樹,在任何給定節(jié)點(diǎn),可以在左子樹中找到低于當(dāng)前節(jié)點(diǎn)包含的內(nèi)存地址,在右邊可以找到較高的內(nèi)存地址。動(dòng)態(tài)內(nèi)存分配使程序能夠在運(yùn)行時(shí)分配內(nèi)存空間,一種方法是內(nèi)存池分配,其不一定是連續(xù)的,Windows以及許多其他操作系統(tǒng)提供可分配給進(jìn)程的分頁(yè)(可以駐留在物理內(nèi)存中,也可以存儲(chǔ)到磁盤)和非分頁(yè)內(nèi)存池(駐留在物理內(nèi)存中);分配動(dòng)態(tài)內(nèi)存的另一種方法是堆棧分配,以先進(jìn)后出的方式添加和移除數(shù)據(jù)[10]。

1.2 調(diào)用堆棧和堆棧幀

調(diào)用堆棧是操作系統(tǒng)用于存儲(chǔ)關(guān)于每個(gè)程序的活動(dòng)子進(jìn)程信息的結(jié)構(gòu),此結(jié)構(gòu)也稱為執(zhí)行堆棧,控制堆棧。堆棧存儲(chǔ)的信息包括從主進(jìn)程傳遞到被調(diào)用的子進(jìn)程的參數(shù),子進(jìn)程中所需的局部變量和子進(jìn)程執(zhí)行結(jié)束后的返回地址。函數(shù)的堆棧幀是ESP(extended stack pointer,擴(kuò)展棧指針)寄存器和EBP(extended base pointer,擴(kuò)展基址指針或幀指針)寄存器中包含的地址之間的內(nèi)存塊,其存儲(chǔ)在調(diào)用堆棧上,包含保存和恢復(fù)進(jìn)程狀態(tài)所需的所有信息。

根據(jù)編譯器優(yōu)化配置,可以生成不使用幀指針的函數(shù),如在集成開發(fā)環(huán)境Visual Studio下,使用FPO(frame pointer omission,幀指針缺?。┻x項(xiàng)的函數(shù)調(diào)用堆棧中不存在EBP鏈。雖然在Windows XPSP(Service Pack,補(bǔ)丁包)2之后發(fā)布的所有Win-dows x86平臺(tái)都禁用了動(dòng)態(tài)鏈接庫(kù)和可執(zhí)行文件的FPO,但惡意軟件或第三方二進(jìn)制文件可能會(huì)使用FPO。此外,還有一些函數(shù)不對(duì)所有Windows的官方二進(jìn)制文件使用幀指針,例如完全內(nèi)部函數(shù)。Windows x64平臺(tái)上的64位應(yīng)用程序通常符合x64軟件約定,它們不會(huì)構(gòu)造堆棧中的幀指針鏈,需要程序數(shù)據(jù)庫(kù)文件或其他信息才能來構(gòu)建這些應(yīng)用程序的堆棧跟蹤。

由于返回地址通常存儲(chǔ)在進(jìn)程空間中,可以使用其虛擬地址進(jìn)行訪問,而虛擬地址又存儲(chǔ)在堆棧中,從而有必要分析堆棧。

2 堆棧重構(gòu)方法分析

實(shí)現(xiàn)堆棧跟蹤基本上需要識(shí)別堆棧所有者線程使用的活動(dòng)堆棧的實(shí)際范圍,以及定位堆棧中每個(gè)返回地址的位置[11]。

2.1 具有幀指針的函數(shù)的堆棧跟蹤

Windows使用內(nèi)部數(shù)據(jù)結(jié)構(gòu)來管理內(nèi)存中的操作和對(duì)象。Windows的EPROCESS塊包含KPRO-LESS結(jié)構(gòu),也被稱為PCB(processing control block,進(jìn)程控制塊),它包含有關(guān)進(jìn)程的調(diào)度信息的內(nèi)核結(jié)構(gòu)。KPROCESS塊中偏移量0x0050處“Thread-ListHead”的LIST_ENTRY數(shù)組的每個(gè)項(xiàng)包含KTHREAD結(jié)構(gòu),KTHREAD是包含有關(guān)線程調(diào)度信息的內(nèi)核表示[12]。這個(gè)結(jié)構(gòu)主要包含:StackLimit、KernelStack、StackBase,這些信息分別提供堆棧的最大值、堆棧指針的當(dāng)前值以及堆棧的起始地址。

具有幀指針的函數(shù)通常將當(dāng)前幀指針寄存器的值推送到堆棧,對(duì)應(yīng)操作為push ebp。然后,該函數(shù)用堆棧指針當(dāng)前的值更新它,對(duì)應(yīng)操作為mov ebp,esp。由于幀指針寄存器始終指向局部緩沖區(qū)和先前存儲(chǔ)的幀指針之間的位置,局部變量和參數(shù)與EBP的偏移量保持不變,因此函數(shù)中的代碼能夠通過幀指針寄存器訪問存儲(chǔ)在堆棧中的局部變量或其函數(shù)參數(shù)。

幀指針EBP指向前一個(gè)幀指針,函數(shù)的返回地址存儲(chǔ)在堆棧中的幀指針之前。基于這些指針,可以構(gòu)造一個(gè)在當(dāng)時(shí)執(zhí)行狀態(tài)下的調(diào)用堆棧,形成一個(gè)調(diào)用函數(shù)和被調(diào)用函數(shù)的正確順序列表。

2.2 沒有幀指針的堆棧跟蹤

對(duì)于Windows堆棧中不構(gòu)造幀指針鏈的函數(shù),需要Microsoft的調(diào)式符號(hào)文件或一些額外的信息才能有效地遍歷堆棧,該額外信息以編譯器和鏈接器生成的展開信息(元數(shù)據(jù))的形式出現(xiàn)。若元數(shù)據(jù)不可用,也有不依賴于幀指針的方法可掃描堆棧的返回地址并基于找到的返回地址構(gòu)建調(diào)用堆棧[13]。其從線程環(huán)境塊(thread environment block,TEB)收集StackBase和StackLimit作為堆棧的最高(棧底為棧的最高地址)和最低地址(棧頂為棧的最低地址),并掃描它們之間的內(nèi)存區(qū)域來查找滿足以下條件的地址:指向可執(zhí)行內(nèi)存區(qū)的地址;指向前一條被調(diào)用指令的所在地址的地址[14]。通過了解這些值并將它們轉(zhuǎn)換為物理地址,可以到達(dá)與每個(gè)堆棧對(duì)應(yīng)的區(qū)域。

2.3 現(xiàn)有技術(shù)存在的問題

Windows x64已經(jīng)成為主流的操作系統(tǒng),即沒有幀指針的函數(shù)已經(jīng)非常普遍,且惡意軟件和已發(fā)布的應(yīng)用程序通常沒有調(diào)試符號(hào)和元數(shù)據(jù),此時(shí)只能使用基于掃描的技術(shù)在內(nèi)存上下文中構(gòu)建堆棧跟蹤。但是,這些技術(shù)會(huì)錯(cuò)誤檢測(cè)到普通函數(shù)指針并將堆棧中之前函數(shù)的返回地址作為本次的返回地址。另外,雖然許多現(xiàn)有方法通過Windows的TEB識(shí)別堆棧區(qū)域,但可以通過讓堆棧指針指向任意內(nèi)存區(qū)域來使其作為堆棧。所以必須確定用作堆棧的區(qū)域,建立一種更精確的方法來構(gòu)建堆棧跟蹤。

3 Windows x64堆棧跟蹤

3.1 堆棧跟蹤方法

3.1.1 獲取x64進(jìn)程的用戶上下文

操作系統(tǒng)通常在事件(如上下文切換、系統(tǒng)調(diào)用和中斷)發(fā)生時(shí)存儲(chǔ)上下文。Windows體系結(jié)構(gòu)中,用于保存上下文的結(jié)構(gòu)為TrapFrame的成員KTRAP FRAME[15]。ETHREAD的Tcb結(jié)構(gòu)中KTHREAD對(duì)象保存指向線程的最后一個(gè)KTRAPFRAME結(jié)構(gòu)的指針[16]。ETHREAD.Tcb.Previous-Mode成員表明TrapFrame成員是具有用戶上下文還是內(nèi)核上下文。因此本文提出從ETHREAD.Tcb.TrapFrame獲取目標(biāo)進(jìn)程中線程的最后一個(gè)上下文,這個(gè)上下文包含寄存器的最后一個(gè)值,例如指向堆棧頂部的RSP寄存器,以及指向下一條指令的RIP寄存器。即使RSP指向StackLimit和StackBase之間,也可以將堆棧的實(shí)際范圍視為RSP寄存器指向位置的連續(xù)頁(yè)面。Windows x64通常在發(fā)生用戶到內(nèi)核模式轉(zhuǎn)換時(shí)將所有寄存器保存到KTRAPFRAME?,F(xiàn)有的在Windows x86環(huán)境下獲得最后EBP值的方法也采用這種結(jié)構(gòu)。

3.1.2 利用元數(shù)據(jù)的堆棧重構(gòu)

每個(gè)分配堆棧空間、調(diào)用其他函數(shù)、保存非易失性寄存器或使用展開信息進(jìn)行異常處理的函數(shù)都有prolog、主體和epilog。prolog將執(zhí)行函數(shù)前的參數(shù)寄存器保存在其本地地址中,將非易失性寄存器壓入堆棧,為本地和臨時(shí)對(duì)象分配堆棧,并可建立幀指針。epilog代碼在函數(shù)的每個(gè)出口,其可將堆棧修整為固定的分配大小,釋放堆棧,通過從堆棧中彈出保存的值來恢復(fù)非易失性寄存器。默認(rèn)情況下,PE(portable executable,可移植可執(zhí)行)32+文件具有用于結(jié)構(gòu)化異常處理(structured exception handling,SEH)時(shí)堆棧展開的元數(shù)據(jù),在內(nèi)存取證中,可以基于加載到內(nèi)存中的這些展開信息來獲得堆棧跟蹤。

在x64軟件約定下用于棧展開的結(jié)構(gòu)為RUNT-IME_FUNCTION,其位于Exception Directory的.pdata部分[17]。該結(jié)構(gòu)包含3個(gè)相對(duì)虛擬地址(relative virtual addresses,RVAs),兩個(gè)相對(duì)虛擬地址指向函數(shù)的prolog和epilog,第三個(gè)指向函數(shù)的UNWIND_INFO結(jié)構(gòu)。UNWIND_INFO結(jié)構(gòu)包含一個(gè)UNWIND_CODE結(jié)構(gòu)數(shù)組,每個(gè)UNWIND_CODE表示函數(shù)中的一個(gè)操作,它會(huì)影響寄存器RSP或其他非易失性寄存器。其中,UWOP_SET_FPREG操作是通過將寄存器設(shè)置為當(dāng)前RSP的某個(gè)偏移量來建立幀指針寄存器;SAVE_NONVOL操作是將非易失性寄存器的值進(jìn)行保存;UWOP_ALLOC_SMALL和UWOP_ALLOC_LARGE操作是在堆棧上分配空間。如果函數(shù)使用幀指針在x64軟件約定下動(dòng)態(tài)分配堆??臻g,則函數(shù)的UNWIND_CODE包含UWOP_SET_FPREG代碼以指定用作幀指針的寄存器。圖1展示了這些結(jié)構(gòu)的基本關(guān)系。

在內(nèi)存轉(zhuǎn)儲(chǔ)上解釋這些數(shù)據(jù)結(jié)構(gòu),并展開堆棧來獲取先前的返回地址,恢復(fù)寄存器的值,步驟如下:

1)通過進(jìn)程用戶空間的VADs的進(jìn)程樹獲得當(dāng)前RIP指向的區(qū)域的基地址,同時(shí)檢查基地址中的PE文件標(biāo)頭的簽名來確認(rèn)當(dāng)前RIP是否指向PE32+映像文件內(nèi)部[18]。

2)獲取Exception Directory的RVA并計(jì)算該目錄的虛擬地址,可得到RUNTIME_FUNCTION結(jié)構(gòu),其范圍包含Exception Directory中的當(dāng)前RIP。

3)判斷RIP位置,此時(shí)有3種情況:①檢查從RIP開始的代碼流,若該代碼流可以與epilog的結(jié)尾部分匹配,則確定它在epilog中。此時(shí)控制權(quán)離開了該函數(shù),從UNWIND_CODE數(shù)組中向后掃描偏移量小于或等于RIP的偏移量的第一個(gè)條目,向后展開,并在處理每條指令時(shí)更新上下文記錄。在該處理之后,重復(fù)步驟2)。②從函數(shù)開始到RIP的距離小于或等于展開信息中編碼的prolog大小,則RIP在prolog內(nèi)。此時(shí)指令尚未進(jìn)入該函數(shù),該函數(shù)沒有與此異常相關(guān)聯(lián)的數(shù)據(jù)。通過從UNWINDCODE數(shù)組中向前掃描偏移量小于或等于RIP的偏移量的第一個(gè)條目,向前展開,然后取消該展開代碼數(shù)組中其余項(xiàng)的數(shù)據(jù),重復(fù)步驟2)。③如果RIP不在prolog或epilog之內(nèi),則直接利用展開數(shù)據(jù)數(shù)組信息,進(jìn)入步驟4)。

4)計(jì)算已獲取的RUNTIME_FUNCTION的Un-windData成員指向的UNWIND_INFO的虛擬地址。

5)展開RSP信息并根據(jù)UNWIND_INFO包含的每個(gè)UNWIND_CODE恢復(fù)其他寄存器。

6)如果展開信息鏈接到其他信息,則該子方法獲取到鏈接的展開信息并從步驟2)重復(fù)直到得到最后一個(gè)鏈接的展開信息。

7)在完成所有展開操作后從堆棧中彈出前一個(gè)返回地址,并將RIP設(shè)置為該值。

編譯器和鏈接器負(fù)責(zé)在構(gòu)建時(shí)將可展開信息放入可執(zhí)行文件中,同時(shí)對(duì)于動(dòng)態(tài)編譯的代碼也有展開信息,否則在異常之后就無法遍歷堆?;蛘归_堆棧。Windows的相關(guān)API應(yīng)用程序編程接口支持動(dòng)態(tài)生成代碼的異常處理,生成的展開信息以一個(gè)鏈接列表為根,其中頭部位于ntdll!RtlpDynamicFunc-tionTable。即如果在步驟1)中未找到PE簽名,也可以在該表格中獲得展開信息。在這種情況下,用以下過程替換步驟2):通過引用VAD樹獲取nt-dll.dll的基址,并計(jì)算RtlpDynamicFunctionTable的虛擬地址,可得到RUNTIME FUNCTION結(jié)構(gòu)(此方式與從Exception Directory獲取的方式相同)。

3.1.3 基于指令流的堆棧重構(gòu)

當(dāng)在代碼區(qū)的頂部檢測(cè)不到PE頭同時(shí)在Rtlp-DynamicFunctionTable中沒有找到元數(shù)據(jù),或者在獲取內(nèi)存轉(zhuǎn)儲(chǔ)時(shí),元數(shù)據(jù)尚未加載到內(nèi)存中,則采用此方法。

當(dāng)調(diào)用發(fā)生時(shí),函數(shù)指令的執(zhí)行路徑可到達(dá)當(dāng)前RIP。首先使用基于掃描的技術(shù),將檢測(cè)到所有可能的上一個(gè)返回地址標(biāo)記下來作為候選地址。然后,根據(jù)調(diào)用過程形成的指令流,找到抵達(dá)當(dāng)前RIP的那條指令,則該指令對(duì)應(yīng)的返回地址即是正確的返回地址。以圖2為例說明該子方法的過程:

1)方法從當(dāng)前RSP掃描返回地址。在圖2所示的情況下,找到Pointerl和Pointer2。

2)根據(jù)Pointer1和Pointer2獲得調(diào)用指令,分析每個(gè)調(diào)用指令要調(diào)用的函數(shù)內(nèi)部的控制流。

3)找到抵達(dá)當(dāng)前RIP的執(zhí)行路徑,并在指向該函數(shù)的調(diào)用指令之后標(biāo)記這個(gè)候選地址,路徑作為當(dāng)前路徑。在圖2的情況下,Pointer2即是正確的返回地址。

4)將確認(rèn)的返回地址設(shè)置為當(dāng)前RIP的值,并將RSP遞增8,同時(shí)設(shè)置為指向下一個(gè)返回地址的虛擬地址。

5)重復(fù)3.1.2中步驟1)。

驗(yàn)證返回地址過程如圖2中所示。

在步驟2)中,如果調(diào)用是通過寄存器的間接調(diào)用,如調(diào)用RBX(Register B Extended,擴(kuò)展B寄存器),則不能對(duì)這些候選地址執(zhí)行基于指令流的驗(yàn)證。但是如果其他候選地址沒有到達(dá)RIP的路徑,則確定在當(dāng)前RIP中候選地址為返回地址。

3.2 基于Volatility插件實(shí)現(xiàn)

Volatility框架是用于內(nèi)存取證的開源軟件,并提供可擴(kuò)展的API[19-20]。根據(jù)以上分析,利用Win-dows內(nèi)核數(shù)據(jù)將本方法實(shí)現(xiàn)為Volatility內(nèi)存分析框架的插件trastack。首先利用已經(jīng)實(shí)現(xiàn)的插件枚舉內(nèi)存轉(zhuǎn)儲(chǔ)文件包含的進(jìn)程對(duì)象,進(jìn)一步根據(jù)內(nèi)核數(shù)據(jù)結(jié)構(gòu)EPROCESS的Wow64Process成員檢查進(jìn)程是否是64位進(jìn)程,從而根據(jù)進(jìn)程的不同類型選擇不同的堆棧跟蹤方法。如果Wow64Process成員持有NULL指針,則目標(biāo)進(jìn)程為x64進(jìn)程,然后獲取進(jìn)程所對(duì)應(yīng)線程的KTRAP_FRAME結(jié)構(gòu)得到上下文內(nèi)容與堆棧范圍,利用VAD樹得到虛擬地址。由元數(shù)據(jù)是否存在分別進(jìn)行堆棧返回地址定位。

插件核心代碼如下:

trapframe=thread.Tcb.TrapFrame.dereference_as(“_KTRAP_FRAME”)

if bits64 trapframe:

address_space=thread.owning_process().get_process_address_space()

if:thread_callstack.set_bits(“64”)

current_ebp=trapframe.Rbp

thread_callstack.add_callstack_item

(CallstackItem(trapframe.Rip,trapframe.Rip))

thread_callstack.eip=True

while current_ebp:

if address_space.is_valid_address(current_ebp)and address_space.is_valid_address(current_ebp+pointer_size):

call_address=struct.unpack(unpack_size,ad-dress_space.zread(current_ebp+pointer_size,point-er_size))[0]

current_ebp=struct.unpack(unpack_size,ad-dress_space.zread(current_ebp,pointer_size))[0]

if len(thread_callstack.callstack)>1:

if current_ebp==thread_callstack.callstack[-1].frame address:

break

if call_address:thread_callstack.callstack.add_

callstack_item(CallstackItem(call_

address,current_ebp))

thread_callstack.callstack=parse_callstack_i-tems address

(thread,thread_callstack.callstack,config)

return thread callstack

插件執(zhí)行流程如圖3所示:

4 測(cè)試與分析

4.1 測(cè)試方法

針對(duì)普通用戶進(jìn)程和系統(tǒng)進(jìn)程使用物理機(jī)進(jìn)行測(cè)試;針對(duì)攻擊進(jìn)程,在VMware虛擬機(jī)監(jiān)視器上運(yùn)行的虛擬機(jī)(Virtual Machine,VM)中獲取內(nèi)存轉(zhuǎn)儲(chǔ)。默認(rèn)情況下,物理機(jī)和VM均具有4GB的內(nèi)存,安裝了Windows 7 x64 SP1。用本文實(shí)現(xiàn)的volatility插件trastack與WinDbg(WinDbg對(duì)Microsoft提供的調(diào)試符號(hào)完全支持)、文[5]方法malthfind和文[6]方法malinfind執(zhí)行結(jié)果作比較。每個(gè)樣本分別進(jìn)行10次實(shí)驗(yàn),去掉最優(yōu)結(jié)果和最劣結(jié)果后取均值得出最終結(jié)果。

4.2 評(píng)價(jià)指標(biāo)

本方法可以重構(gòu)堆棧中的返回地址,如果輸入的測(cè)試數(shù)據(jù)中原本的函數(shù)返回地址被正確識(shí)別時(shí),標(biāo)記為TP(True Positive);輸入的測(cè)試數(shù)據(jù)中子函數(shù)的返回地址被識(shí)別為最終返回地址(誤報(bào))時(shí),標(biāo)記為FP(False Positive);輸入的測(cè)試數(shù)據(jù)中原本函數(shù)的返回地址被識(shí)別為普通子函數(shù)返回地址(漏報(bào))時(shí),標(biāo)記為FN(False Negative);輸入的測(cè)試數(shù)據(jù)中子函數(shù)返回地址被正確識(shí)別時(shí),標(biāo)記為TN(TrueNegative)。則在本文中相關(guān)評(píng)價(jià)指標(biāo)精確率(Preci-sion)與召回率(Recall)如下:

4.3 實(shí)驗(yàn)結(jié)果分析

4.3.1 有元數(shù)據(jù)的進(jìn)程測(cè)試

在此測(cè)試中,對(duì)Windows x64環(huán)境中運(yùn)行有元數(shù)據(jù)的notepad.exe、explorer.exe、WINWORD.EXE、wininit.exe等進(jìn)程的轉(zhuǎn)儲(chǔ)文件進(jìn)行分析,分別執(zhí)行插件trastack、WinDbg、malthfind和malinfind進(jìn)行回溯棧。結(jié)果如表1所示。

結(jié)果表明,對(duì)于有元數(shù)據(jù)、支持Windows官方調(diào)試符號(hào)的典型可執(zhí)行文件notepad.exe、explor-er.exe、WINWORD.EXE、wininit.exe,微軟的WinD-bg可以全面并且無誤地對(duì)堆棧進(jìn)行回溯;在無法利用Windows官方調(diào)試符號(hào)的其它方法中,本文所實(shí)現(xiàn)的插件trastack利用元數(shù)據(jù)對(duì)堆棧展開回溯,執(zhí)行結(jié)果達(dá)到了與WinDbg一樣的精確率與召回率,同時(shí)用時(shí)小于WinDbg的1/2,一定程度上提高了效率;文[5]malthfind方法由于掃描時(shí)會(huì)錯(cuò)誤地將堆棧中未及時(shí)出棧的不相關(guān)返回地址識(shí)別為函數(shù)最終返回地址,造成結(jié)果精確率低同時(shí)其方法中沒有充分利用展開代碼數(shù)組(元數(shù)據(jù))信息,造成結(jié)果缺失;文[6]malinfind方法在利用元數(shù)據(jù)時(shí),未曾考慮RIP在函數(shù)prolog與epilog內(nèi)的情況,導(dǎo)致展開代碼數(shù)組信息利用出錯(cuò)從而造成返回地址覆蓋不全面且有誤報(bào),使結(jié)果不具有足夠的可信性。

至此,確認(rèn)本方法可以正確獲取在Windows x64上有元數(shù)據(jù)的進(jìn)程的堆棧跟蹤。

4.3.2 無元數(shù)據(jù)的進(jìn)程測(cè)試

在此測(cè)試中,為了模擬從沒有元數(shù)據(jù)的代碼區(qū)域獲取堆棧跟蹤的情況,WinDbg在執(zhí)行k命令之前卸載了user32.dll和notepad.exe、explorer.exe、WIN-WORD.EXE、wininit.exe的調(diào)試符號(hào),同時(shí)插件強(qiáng)制使用不利用元數(shù)據(jù)的子方法。依然利用上述進(jìn)程,插件的調(diào)試消息表明user32.dll的.pdata部分不存在,此時(shí)元數(shù)據(jù)不可用[21],插件trastack依然能獲得完整結(jié)果,同時(shí)在時(shí)間性能上,trastack所用時(shí)間僅增加了20.46%;WinDbg僅獲得了上述正確堆棧跟蹤的前兩項(xiàng),但時(shí)間上增加了74.84%;malthfind方法在無法利用元數(shù)據(jù)的情況下精確率明顯降低,但由于其方法本身不依賴于調(diào)試符號(hào),因此精確率高于Windbg,同時(shí)由于缺失元數(shù)據(jù),漏報(bào)情況增加;malinfind方法中可利用元數(shù)據(jù),其準(zhǔn)確率略高于malthfind方法,但由于其在利用子方法時(shí),RSP偏移量不夠精確,導(dǎo)致結(jié)果中有誤報(bào);沒有將返回地址循環(huán)出棧,降低了結(jié)果的召回率。實(shí)驗(yàn)結(jié)果如表2所示。

至此,確認(rèn)本法可以在沒有元數(shù)據(jù)的情況下獲得正確的結(jié)果并可以減少掃描技術(shù)中由于x64的軟件約定造成的堆棧返回地址的誤報(bào)。

4.3.3 不同進(jìn)程類型測(cè)試

為了進(jìn)一步確定方法的有效性,分別選取用戶進(jìn)程、系統(tǒng)進(jìn)程、棧溢出攻擊進(jìn)程和其他類型攻擊進(jìn)程對(duì)基于流的驗(yàn)證方法進(jìn)行堆?;厮?。其中每種進(jìn)程類型分別選取5個(gè)可執(zhí)行文件樣本;用戶進(jìn)程的樣本分別為:explorer.exe、notepad.exe、wordpad.exe、mspaint.exe、gsview.exe,系統(tǒng)進(jìn)程的樣本分別為:vschost.exe、wininit.exe、smss.exe、lsm.exe、alg.exe,棧溢出攻擊漏洞樣本為:WINWORD.EXE(CVE-2012-0158(Common Vulnerabilities&Expo-sures(通用漏洞披露),2012年,編號(hào)0158。下同),Microsoft Office 2010 SP1漏洞)、PCManFTPD2.exe(CVE-2013 X1.730,PCMan’s FTP Server 2.0.7漏洞)、EQNEDT32.EXE(CVE-2017-11882,MicrosoftOffice2010SP2漏洞)、EQNEDT32.EXE(CVE-2018-0802,Microsoft Office2013漏洞)、fcrip.exe(CVE-2019-9766,F(xiàn)ree MP3 CD Ripper2.6漏洞),其它攻擊樣本:tomcat8.exe(CVE-2018-11784,Apache Tom-cat8.5.0重定向漏洞)、devenv.exe(CVE-2019-1354,Microsoft Visual Studio 15.OGit插件遠(yuǎn)程代碼執(zhí)行漏洞)、firefox.exe(CVE-2019-17026,MozillaFirefox 72.0代碼執(zhí)行漏洞)、iexplore.exe(CVE-2020-0674,Internet Explorerl 1腳本引擎內(nèi)存損壞漏洞)、WINWORD.EXE(CVE-2020-0852,Microsoft Of-fice 2019遠(yuǎn)程代碼執(zhí)行漏)。為減輕惡意軟件對(duì)物理機(jī)的傷害,保證實(shí)驗(yàn)環(huán)境的穩(wěn)定性,惡意軟件的測(cè)試在虛擬環(huán)境下執(zhí)行。測(cè)試結(jié)果如表3所示。

實(shí)驗(yàn)結(jié)果表明在Windows x64環(huán)境下,插件可以針對(duì)微軟官方用戶進(jìn)程或非微軟用戶進(jìn)程進(jìn)行完整而正確的堆?;厮?針對(duì)系統(tǒng)進(jìn)程,由于非微軟產(chǎn)品無法利用Window調(diào)試符號(hào),本方法在執(zhí)行時(shí)會(huì)有少許漏報(bào)情況。在保證高召回率的情況下,針對(duì)提取到的堆棧結(jié)果,方法做到了一定的精確性;針對(duì)攻擊進(jìn)程,其通常利用正常進(jìn)程的漏洞,將其代碼注入相關(guān)進(jìn)程的漏洞模塊中并于執(zhí)行結(jié)束再次修改返回地址以達(dá)到隱藏目的。如實(shí)驗(yàn)中CVE-2012-0158漏洞攻擊就是利用WINWORD.EXE進(jìn)程的漏洞,其將攻擊代碼注入MSCOMCTL.OCX模塊。堆?;厮莅l(fā)現(xiàn)漏洞函數(shù)在返回地址0x275C895C處而在其執(zhí)行完后,返回地址被更改為0x41414141。這使得本方法不可避免地出現(xiàn)漏報(bào)和誤報(bào)情況。

4.3.4 不同操作系統(tǒng)版本測(cè)試

由于Windows操作系統(tǒng)現(xiàn)有版本眾多且其處于不斷更新的狀態(tài),這要求方法應(yīng)具有兼容性。實(shí)驗(yàn)選取配有不同大小內(nèi)存的主流64位Windows版本,對(duì)多個(gè)棧溢出攻擊漏洞樣本W(wǎng)INWORD.EXE(CVE-2012-0158,Microsoft Office 2010 SPl漏洞)、PCManFTPD2.exe(CVE-2013-4730,PCMan’s FTPServer 2.0.7漏洞)、EQNEDT32.EXE(CVE-2017-11882,Microsoft Office2010SP2漏洞)、EQNEDT32.EXE(CVE-2018-0802,Microsoft Office2013漏洞)、fcrip.exe(CVE-2019-9766,F(xiàn)ree MP3 CD Ripper2.6漏洞)執(zhí)行本方法進(jìn)行測(cè)試,結(jié)果如表4所示。

從實(shí)驗(yàn)結(jié)果整體上看,針對(duì)Windows7SP1版本的精確率和召回率最高,在Windows8.1版本出現(xiàn)最低精確率和召回率,但兩者召回率之差低于1%同時(shí)精確率之差低于0.2%,說明本方法具有一定的兼容性。

5 結(jié)論

本文提出并實(shí)現(xiàn)了一種從Windows x64環(huán)境的內(nèi)存轉(zhuǎn)儲(chǔ)構(gòu)建堆棧跟蹤的方法,從內(nèi)存轉(zhuǎn)儲(chǔ)中獲取每個(gè)進(jìn)程的用戶上下文,并基于異常處理的元數(shù)據(jù)展開堆棧,還實(shí)現(xiàn)了基于指令流的驗(yàn)證方法。本方法可以使用或不使用元數(shù)據(jù)獲取x64進(jìn)程的堆棧跟蹤,和傳統(tǒng)的基于掃描的技術(shù)比較,可以更準(zhǔn)確地獲得堆棧跟蹤。

由于堆棧跟蹤技術(shù)只是在當(dāng)前執(zhí)行狀態(tài)下獲取調(diào)用堆棧,對(duì)于使用等待方法而不保留線程的鉤子惡意軟件,很難有效地進(jìn)行取證。下一步考慮使用實(shí)時(shí)監(jiān)測(cè)方法,以實(shí)時(shí)獲取內(nèi)存轉(zhuǎn)儲(chǔ)從而進(jìn)行堆棧分析來解決這個(gè)問題。

參考文獻(xiàn):

[1]許洪軍,張洪,賀維.一種基于鼠標(biāo)行為的云用戶異常檢測(cè)方法[J].哈爾濱理工大學(xué)學(xué),2019,24(4):127.

[2]張瑜,劉慶中.李濤,等.內(nèi)存取證研究與進(jìn)展[J].軟件學(xué)報(bào),2015,26(5):1151

[3]SATRYA G B,KURNIAWAN F.A Novel Android Memory Foren-sics for Discovering Remnant Data[J].International journal onAdvanced Science,Engineering and Information Technology,2020,10(3):1008.

[4]CHENG Y,F(xiàn)U X,DU X,et al.A Lightweight Live Memory Fo-rensic Approach Based on Hardware Virtualization[J].Informa-tion Sciences,2016,379(1);23.

[5]COLIN R,ANDY P,CAI S S,et al.x64-software-conventions[EB/OL].Microsoft(2018-12-17)[2020-05-15].ht-tps://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx.

[6]PSHOUL D.Volatility Foundation[EB/OL].Github(2019-05-17)[2020-05-17].https://github.com/volati lityfounda-tion/community/blob/master/DimaPshoul/malthfind.py.

[7]OTSUKI Y,KAWAKOYA Y,IWAMURA M,et al.Building StackTraces from Memory Dump of Windows x64[J].Digital Investiga-tion,2018,24(S1):101.

[8]劉劍,蘇璞睿,楊珉,等.軟件與網(wǎng)絡(luò)安全研究綜述[J].軟件學(xué)報(bào),2018,29(1):42.

[9]FRANK B,ANDREAS D.Windows Memory Forensics:Detecting(Un)Intentionally Hidden Injected Code by Examining Page TableEntries[J]Digital Investigation,2019,29(S1):3.

[10]Al-SALEH M,QAWASMEH E,Al-SHARIF Z.Utilizing DebuggingInformation of Applications in Memory Forensics[J].Journal of U-niversal Computer Science,2020,28(7):805.

[11]SRIVASTAVA A,JONES J H.Detecting Code Injection by Cross-validating Stack and VAD Information in Windows Physical Memo-ry[C]//2017 IEEE Conference on Open Systems,ICOS.Miri,2017:83.

[12]BALAOURA S.Process Injection Techniques and Detection usingthe Volatility Framework[D].Piraeus:University of Piraeus,2018.25.

[13]MUTHUMANICKAM K,ILAVARASAN E.An Effective Methodfor Protecting Native API Hook Attacks in User-mode[J].Re-search Journal of Applied Sciences,Engineering and Technology,2015,9(1):33,

[14]YOSIFOVICH P,SOLOMON D A,IONESCU A.Windows Inter-nals,Part 1:System Architecture,Processes,Threads,MemoryManagement,and More[M].California:Microsoft Press,2017.

[15]NATHAN L,ANDREW C,AISHA A,et al.Memory Forensicsand the Windows Subsystem for Linux[J].Digital Investigation,2018,26(S1):3.

[16]LEE K,HWANG H,KIM K,et al.Robust Bootstrapping MemoryAnalysis Against Anti-forensics[J]Digital Investigation,2016,18(S1):23.

[17]COHEN M I.Characterization of the Windows Kernel Version Vari-ability for Accurate Memory Analysis[J].Digital Investigation,2015,12(S1):38.

[18]BRENDAN D.The VAD Tree:A Process-eye View of PhysicalMemory[J].Digital Investigation,2007,4(S1):62.

[19]RALPH P,F(xiàn)ELIX F.Styx:Countering Robust Memory Acquisi-tion[J].Digital Investigation,2018,24(S1):18.

[20]COHEN A,NISSIM N.Trusted Detection of Ransomware in a Pri-vate Cloud Using Machine Learning Methods Leveraging Meta-fea-tures from Volatile Memory[J].Expert Systems with Applications,2018,102:158.

[21]HUDA S,MIAH S,HASSAN M M,et al.Defending Unknown At-tacks on Cyber Physical Systems by Semi-supervised Approach andAvailable Unlabeled Data[J].Information Sciences,2017,379(10):211.

(編輯:溫澤宇)

收稿日期:2020-07-22

基金項(xiàng)目:國(guó)家自然科學(xué)基金(61403109);黑龍江省自然科學(xué)基金(F2016024);黑龍江省教育廳科學(xué)技術(shù)研究面上項(xiàng)目(12531121).

作者簡(jiǎn)介:徐曉(1994-),女,碩士研究生;陳攀(1994-),男,碩士研究生.

通信作者:翟繼強(qiáng)(1972-),男,博士,教授,E-mail:zaijiqiang@163.com.

猜你喜歡
元數(shù)據(jù)
元數(shù)據(jù)國(guó)際交換共享的客家古民居數(shù)字記憶工程建設(shè)
基于來源的組織機(jī)構(gòu)元數(shù)據(jù)構(gòu)建研究
元數(shù)據(jù)與社會(huì)化標(biāo)簽在微視頻搜索中的應(yīng)用
高等院校智慧校園建設(shè)規(guī)劃與實(shí)現(xiàn)
利用VB讀取中國(guó)知網(wǎng)過刊數(shù)據(jù)提取元數(shù)據(jù)的研究
財(cái)會(huì)信息資源元數(shù)據(jù)標(biāo)準(zhǔn)的研究
基于隱語(yǔ)義模型和用戶信任的個(gè)性化推薦模型
基于關(guān)聯(lián)數(shù)據(jù)的語(yǔ)義數(shù)字檔案館框架設(shè)計(jì)研究
基于角色控制的異構(gòu)數(shù)據(jù)展示在企業(yè)門戶中的應(yīng)用
基于元數(shù)據(jù)映射機(jī)制的異構(gòu)數(shù)據(jù)操作
巴彦淖尔市| 工布江达县| 东辽县| 钦州市| 凤城市| 万载县| 永仁县| 扬州市| 阳山县| 景宁| 建宁县| 溧阳市| 宿迁市| 屏边| 安新县| 保亭| 应城市| 卫辉市| 调兵山市| 手游| 大方县| 太康县| 汽车| 阆中市| 汪清县| 工布江达县| 招远市| 昭觉县| 南投市| 江阴市| 靖西县| 石河子市| 富阳市| 汝南县| 天门市| 西安市| 德江县| 巴东县| 福鼎市| 澎湖县| 团风县|