日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

反病毒引擎设计全解(三)

發(fā)布時(shí)間:2025/3/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 反病毒引擎设计全解(三) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2.虛擬機(jī)查毒

2.1虛擬機(jī)概論

近些年,虛擬機(jī),在反病毒界也被稱為通用解密器,已經(jīng)成為反病毒軟件中最引人注目的部分,盡管反病毒者對(duì)于它的運(yùn)用還遠(yuǎn)沒(méi)有達(dá)到一個(gè)完美的程度,但虛擬機(jī)以其諸如"病毒指令碼模擬器""Stryker"等多變的名稱為反病毒產(chǎn)品的市場(chǎng)銷售帶來(lái)了光明的前景。以下的討論將把我們帶入一個(gè)精彩的虛擬技術(shù)的世界中。

首先要談及的是虛擬機(jī)的概念和它與諸如Vmware(美國(guó)VMWARE公司生產(chǎn)的一款虛擬機(jī),它支持在WINNT/2000環(huán)境下運(yùn)行如Linux等其它操作系統(tǒng))和WIN9X下的VDMDOS虛擬機(jī),它用來(lái)在32位保護(hù)模式環(huán)境中運(yùn)行16實(shí)模式代碼)的區(qū)別。其實(shí)這些虛擬機(jī)的設(shè)計(jì)思想是有淵源可尋的,早在上個(gè)世紀(jì)60年代IBM就開發(fā)了一套名為VM/370的操作系統(tǒng)。VM/370在不同的程序之間提供搶先式多任務(wù),作法是在單一實(shí)際的硬件上模式出多部虛擬機(jī)器。典型的VM/370會(huì)話,使用者坐在電纜連接的遠(yuǎn)程終端前,經(jīng)由控制程序的一個(gè)IPL命令,模擬真實(shí)機(jī)器的初始化程序裝載操作,于是 一套完整的操作系統(tǒng)被載入虛擬機(jī)器中,并開始為使用者著手創(chuàng)建一個(gè)會(huì)話。這套模擬系統(tǒng)是如此的完備,系統(tǒng)程序員甚至可以運(yùn)行它的一個(gè)虛擬副本,來(lái)對(duì)新版本進(jìn)行除錯(cuò)。Vmware與此非常相似,它作為原操作系統(tǒng)下的一個(gè)應(yīng)用程序可以為運(yùn)行于其上的目標(biāo)操作系統(tǒng)創(chuàng)建出一部虛擬的機(jī)器,目標(biāo)操作系統(tǒng)就象運(yùn)行在單獨(dú)一臺(tái)真正機(jī)器上,絲毫察覺不到自己處于Vmware的控制之下。當(dāng)在Vmware中按下電源鍵(Power On)時(shí),窗口里出現(xiàn)了機(jī)器自檢畫面,接著是操作系統(tǒng)的載入,一切都和真的一樣。而WIN9X為了讓多個(gè)程序共享CPU和其它硬件資源決定使用VMs(所有Win32應(yīng)用程序運(yùn)行在一部系統(tǒng)虛擬機(jī)上;而每個(gè)16DOS程序擁有一部DOS虛擬機(jī))。VM是一個(gè)完全由軟件虛構(gòu)出來(lái)的東西,以和真實(shí)電腦完全相同的方式來(lái)回應(yīng)應(yīng)用程序所提出的需求。從某種角度來(lái)看,你可以將一部標(biāo)準(zhǔn)的PC的結(jié)構(gòu)視為一套API。這套API的元素包括硬件I/O系統(tǒng),和以中斷為基礎(chǔ)的BIOSMS-DOSWIN9X常常以它自己的軟件來(lái)代理這些傳統(tǒng)的API元素,以便能夠?qū)φ滟F的硬件多重發(fā)訊。在VM上運(yùn)行的應(yīng)用程序認(rèn)為自己獨(dú)占整個(gè)機(jī)器,它們相信自己是從真正的鍵盤和鼠標(biāo)獲得輸入,并從真正的屏幕上輸出。稍被加一點(diǎn)限制,它們甚至可以認(rèn)為自己完全擁有CPU和全部?jī)?nèi)存。實(shí)現(xiàn)虛擬技術(shù)關(guān)鍵在于軟件虛擬化和硬件虛擬化,下面簡(jiǎn)要介紹WIN9X下的DOS虛擬機(jī)的實(shí)現(xiàn)。

當(dāng)Windows移往保護(hù)模式后,保護(hù)模式程序無(wú)法直接調(diào)用實(shí)模式的MS-DOS處理例程,也不能直接調(diào)用實(shí)模式的BIOS。軟件虛擬化就是用來(lái)描述保護(hù)模式Windows部件是如何能夠和實(shí)模式MS-DOSBIOS彼此互動(dòng)。軟件虛擬化要求操作系統(tǒng)能夠攔截企圖跨越保護(hù)模式和實(shí)模式邊界的調(diào)用,并且調(diào)整適當(dāng)?shù)膮?shù)寄存器后,改變CPU模式。WIN9X使用虛擬設(shè)備驅(qū)動(dòng)(VXD)攔截來(lái)自保護(hù)模式的中斷,通過(guò)實(shí)模式中斷向量表(IVT),將之轉(zhuǎn)換為實(shí)模式中斷調(diào)用。做為轉(zhuǎn)換的一部分,VXD必須使用置于保護(hù)模式擴(kuò)展內(nèi)存中的參數(shù),生成出適當(dāng)?shù)膮?shù),并將之放在實(shí)模式(V86)操作系統(tǒng)可以存取的地方。服務(wù)結(jié)束后,VXD在把結(jié)果交給擴(kuò)展內(nèi)存中保護(hù)模式調(diào)用端。16DOS程序中大量的21H13H中斷調(diào)用就此解決,但其中還存在不少直接端口I/O操作,這就需要引入硬件虛擬化來(lái)解決。虛擬硬件的出現(xiàn)是為了在硬件中斷請(qǐng)求線上產(chǎn)生中斷請(qǐng)求,為了回應(yīng)INOUT指令,改變特殊內(nèi)存映射位置等原因。硬件虛擬化依賴于Intel 80386+的幾個(gè)特性。其中一個(gè)是I/O許可掩碼,使操作系統(tǒng)可能誘捕(Trap)對(duì)任何一個(gè)端口的所有IN/OUT指令。另一個(gè)特性是:由硬件輔助的分頁(yè)機(jī)制,使操作系統(tǒng)能夠提供虛擬內(nèi)存,并攔截對(duì)內(nèi)存地址的存取操作,將Video RAM虛擬化是此很好的例證。最后一個(gè)必要的特性是CPU的虛擬8086V86)模式 ,讓DOS程序象在實(shí)模式中那樣地執(zhí)行。

我們下面討論用于查毒的虛擬機(jī)并不是象某些人想象的:如Vmware一樣為待查可執(zhí)行程序創(chuàng)建一個(gè)虛擬的執(zhí)行環(huán)境,提供它可能用到的一切元素,包括硬盤,端口等,讓它在其上自由發(fā)揮,最后根據(jù)其行為來(lái)判定是否為病毒。當(dāng)然這是個(gè)不錯(cuò)的構(gòu)想,但考慮到其設(shè)計(jì)難度過(guò)大(需模擬元素過(guò)多且行為分析要借助人工智能理論),因而只能作為以后發(fā)展的方向。我設(shè)計(jì)的虛擬機(jī)嚴(yán)格的說(shuō)不能稱之為虛擬機(jī)器,而叫做虛擬CPU,通用解密器等更為合適一些,但由于反病毒界習(xí)慣稱之為虛擬機(jī),所以在下面的討論中我還將延續(xù)這個(gè)名稱。查毒的虛擬機(jī)是一個(gè)軟件模擬的CPU,它可以象真正CPU一樣取指,譯碼,執(zhí)行,它可以模擬一段代碼在真正CPU上運(yùn)行得到的結(jié)果。給定一組機(jī)器碼序列,虛擬機(jī)會(huì)自動(dòng)從中取出第一條指令操作碼部分,判斷操作碼類型和尋址方式以確定該指令長(zhǎng)度,然后在相應(yīng)的函數(shù)中執(zhí)行該指令,并根據(jù)執(zhí)行后的結(jié)果確定下條指令的位置,如此循環(huán)反復(fù)直到某個(gè)特定情況發(fā)生以結(jié)束工作,這就是虛擬機(jī)的基本工作原理和簡(jiǎn)單流程。設(shè)計(jì)虛擬機(jī)查毒的目的是為了對(duì)付加密變形病毒,虛擬機(jī)首先從文件中確定并讀取病毒入口處代碼,然后以上述工作步驟解釋執(zhí)行病毒頭部的解密段(decryptor),最后在執(zhí)行完的結(jié)果(解密后的病毒體明文)中查找病毒的特征碼。這里所謂的虛擬,并非是創(chuàng)建了什么虛擬環(huán)境,而是指染毒文件并沒(méi)有實(shí)際執(zhí)行,只不過(guò)是虛擬機(jī)模擬了其真實(shí)執(zhí)行時(shí)的效果。這就是虛擬機(jī)查毒基本原理,具體介紹請(qǐng)參看后面的相關(guān)章節(jié)。

當(dāng)然,虛擬執(zhí)行技術(shù)使用范圍遠(yuǎn)不止自動(dòng)脫殼(虛擬機(jī)查毒實(shí)際上是自動(dòng)跟蹤病毒入口的解密子將加密的病毒體按其解密算法進(jìn)行解密),它還可以應(yīng)用在跨平臺(tái)高級(jí)語(yǔ)言解釋器,惡意代碼分析,調(diào)試器。如劉濤濤設(shè)計(jì)的國(guó)產(chǎn)調(diào)試器Trdos就是完全利用虛擬技術(shù)解釋執(zhí)行被調(diào)試程序的每條指令,這種調(diào)試器比較起傳統(tǒng)的斷點(diǎn)式調(diào)試器(Debug,Softice等)具有諸多優(yōu)勢(shì),如不易被被調(diào)試者察覺,斷點(diǎn)個(gè)數(shù)沒(méi)有限制等。

?

2.2加密變形病毒

前面提到過(guò)設(shè)計(jì)虛擬機(jī)查毒的目的是為了對(duì)付加密變形病毒。這一章就重點(diǎn)介紹加密變形技術(shù)。早期病毒沒(méi)有使用任何復(fù)雜的反檢測(cè)技術(shù),如果拿反匯編工具打開病毒體代碼看到的將是真正的機(jī)器碼。因而可以由病毒體內(nèi)某處一段機(jī)器代碼和此處距離病毒入口(注意不是文件頭)偏移值來(lái)唯一確定一種病毒。查毒時(shí)只需簡(jiǎn)單的確定病毒入口并在指定偏移處掃描特定代碼串。這種靜態(tài)掃描技術(shù)對(duì)付普通病毒是萬(wàn)無(wú)一失的。

隨著病毒技術(shù)的發(fā)展,出現(xiàn)了一類加密病毒。這類病毒的特點(diǎn)是:其入口處具有解密子(decryptor),而病毒主體代碼被加了密。運(yùn)行時(shí)首先得到控制權(quán)的解密代碼將對(duì)病毒主體進(jìn)行循環(huán)解密,完成后將控制交給病毒主體運(yùn)行,病毒主體感染文件時(shí)會(huì)將解密子,用隨機(jī)密鑰加密過(guò)的病毒主體,和保存在病毒體內(nèi)或嵌入解密子中的密鑰一同寫入被感染文件。由于同一種病毒的不同傳染實(shí)例的病毒主體是用不同的密鑰進(jìn)行加密,因而不可能在其中找到唯一的一段代碼串和偏移來(lái)代表此病毒的特征,似乎靜態(tài)掃描技術(shù)對(duì)此即將失效。但仔細(xì)想想,不同傳染實(shí)例的解密子仍保持不變機(jī)器碼明文(從理論上講任何加密程序中都存在未加密的機(jī)器碼,否則程序無(wú)法執(zhí)行),所以將特征碼選于此處雖然會(huì)冒一定的誤報(bào)風(fēng)險(xiǎn)(解密子中代碼缺少病毒特性,同樣的特征碼也會(huì)出現(xiàn)在正常程序中),但仍不失為一種有效的方法。由于加密病毒還沒(méi)有能夠完全逃脫靜態(tài)特征碼掃描,所以病毒寫作者在加密病毒的基礎(chǔ)之上進(jìn)行改進(jìn),使解密子的代碼對(duì)不同傳染實(shí)例呈現(xiàn)出多樣性,這就出現(xiàn)了加密變形病毒。它和加密病毒非常類似,唯一的改進(jìn)在于病毒主體在感染不同文件會(huì)構(gòu)造出一個(gè)功能相同但代碼不同的解密子,也就是不同傳染實(shí)例的解密子具有相同的解密功能但代碼卻截然不同。比如原本一條指令完全可以拆成幾條來(lái)完成,中間可能會(huì)被插入無(wú)用的垃圾代碼。這樣,由于無(wú)法找到不變的特征碼,靜態(tài)掃描技術(shù)就徹底失效了。下面先舉兩個(gè)例子說(shuō)明加密變形病毒解密子構(gòu)造,然后再討論怎樣用虛擬執(zhí)行技術(shù)檢測(cè)加密變形病毒。

著名多形病毒Marburg的變形解密子:

00401020: movsx edi,si ;病毒入口

00401023: movsx edx,bp

00401026: jmp 00408a99

......

00407400: ;病毒體入口

加密的病毒主體

00408a94: ;解密指針初始值

......

00408a99: mov dl,f7

00408a9b: movsx edx,bx

00408a9e: mov ecx,cf4b9b4f

00408aa3: call 00408ac4

......

00408ac4: pop ebx

00408ac5: jmp 00408ade

......

00408ade: mov cx,di

00408ae1: add ebx,9fdbd22d

00408ae7: jmp 00408b08

......

00408b08: add ecx,80c1fbc1

00408b0e: mov ebp,7fcdeff3 ;循環(huán)解密記數(shù)器初值

00408b13: sub cl,39

00408b16: movsx esi,si

00408b19: add dword ptr[ebx+60242dbf],9ef42073 ;解密語(yǔ)句,9ef42073是密鑰

00408b23: mov edx,6fd1d4cf

00408b28: mov di,dx

00408b2b: inc ebp

00408b2c: xor dl,a3

00408b2f: mov cx,si

00408b32: sub ebx,00000004 ;移動(dòng)解密偏移指針,逆向解密

00408b38: mov ecx,86425df9

00408b3d: cmp ebp,7fcdf599 ;判斷解密結(jié)束與否

00408b43: jnz 00408b16

00408b49: jmp 00408b62

......

00408b62: mov di,bp

00408b65: jmp 00407400 ;將控制權(quán)交給解密后的病毒體入口

?

著名多形病毒Hps的變形解密子:

005365b8: ;解密指針初始值和病毒體入口

加密的病毒主體

......

005379cd: call 005379e2

......

005379e2: pop ebx

005379e3: sub ebx,0000141a;設(shè)置解密指針初值

005379e9: ret

......

005379f0: dec edx ;減少循環(huán)記數(shù)值

005379f1: ret

......

00537a00: xor dword ptr[ebx],10e7ed59 ;解密語(yǔ)句,10e7ed59是密鑰

00537a06: ret

......

00537a1a: sub ebx,ffffffff

00537a20: sub ebx,fffffffd ;移動(dòng)解密指針,正向解密

00537a26: ret

......

00537a30: mov edx,74d9cb97 ;設(shè)置循環(huán)記數(shù)初值

00537a35: ret

......

00537a3f: call 005379cd ;病毒入口

00537a44: call 00537a30

00537a49: call 00537a00

00537a4e: call 00537a1a

00537a53: call 005379f0

00537a58: mov esi,edx

00537a5a: cmp esi,74d9c696 ;判斷解密結(jié)束與否

00537a60: jnz 00537a49

00537a66: jmp 005365b8 ;將控制權(quán)交給解密后的病毒體入口

以上的代碼看上去絕對(duì)不會(huì)是用編譯器編譯出來(lái),或是編程者手工寫出來(lái)的,因?yàn)槠渲谐涑饬舜罅康膩y數(shù)和垃圾。代碼中沒(méi)有注釋部分均可認(rèn)為是垃圾代碼,有用部分完成的功能僅是循環(huán)向加密過(guò)的病毒體的每個(gè)雙字加上或異或一個(gè)固定值。這只是變形病毒傳染實(shí)例的其中一個(gè),別的實(shí)例的解密子和病毒體將不會(huì)如此,極度變形以至讓人無(wú)法辯識(shí)。至于變形病毒的實(shí)現(xiàn)技術(shù)由于涉及復(fù)雜的算法和控制,因此不在我們討論范圍內(nèi)。

這種加密變形病毒的檢測(cè)用傳統(tǒng)的靜態(tài)特征碼掃描技術(shù)顯然已經(jīng)不行了。為此我們采取的方法是動(dòng)態(tài)特征碼掃描技術(shù),所謂動(dòng)態(tài)特征碼掃描指先在虛擬機(jī)的配合下對(duì)病毒進(jìn)行解密,接著在解密后病毒體明文中尋找特征碼。我們知道解密后病毒體明文是穩(wěn)定不變的,只要能夠得到解密后的病毒體就可以使用特征碼掃描了。要得到病毒體明文首先必須利用虛擬機(jī)對(duì)病毒的解密子進(jìn)行解釋執(zhí)行,當(dāng)跟蹤并確定其循環(huán)解密完成或達(dá)到規(guī)定次數(shù)后,整個(gè)病毒體明文或部分已被保存到一個(gè)內(nèi)部緩沖區(qū)中了。虛擬機(jī)之所以又被稱為通用解密器在于它不用事先知道病毒體的加密算法,而是通過(guò)跟蹤病毒自身的解密過(guò)程來(lái)對(duì)其進(jìn)行解密。至于虛擬機(jī)怎樣解釋指令執(zhí)行,怎樣確定可執(zhí)行代碼有無(wú)循環(huán)解密段等細(xì)節(jié)將在下一節(jié)中介紹。

?

2.3虛擬機(jī)實(shí)現(xiàn)技術(shù)詳解

有了前面關(guān)于加密變形病毒的介紹,現(xiàn)在我們知道動(dòng)態(tài)特征碼掃描技術(shù)的關(guān)鍵就在于必須得到病毒體解密后的明文,而得到明文產(chǎn)生的時(shí)機(jī)就是病毒自身解密代碼解密的完畢。目前有兩種方法可以跟蹤控制病毒的每一步執(zhí)行,并能夠在病毒循環(huán)解密結(jié)束后從內(nèi)存中讀出病毒體明文。一種是單步和斷點(diǎn)跟蹤法,和目前一些程序調(diào)試器相類似;另一種方法當(dāng)然就是虛擬執(zhí)行法。下面分別分析單步和斷點(diǎn)跟蹤法和虛擬執(zhí)行法的技術(shù)細(xì)節(jié)。單步跟蹤和斷點(diǎn)是實(shí)現(xiàn)傳統(tǒng)調(diào)試器的最根本技術(shù)。單步的工作原理很簡(jiǎn)單:當(dāng)CPU在執(zhí)行一條指令之前會(huì)先檢查標(biāo)志寄存器,如果發(fā)現(xiàn)其中的陷阱標(biāo)志被設(shè)置則會(huì)在指令執(zhí)行結(jié)束后引發(fā)一個(gè)單步陷阱INT1H。至于斷點(diǎn)的設(shè)置有軟硬之分,軟件斷點(diǎn)是指調(diào)試器用一個(gè)通常是單字節(jié)的斷點(diǎn)指令(CC,即INT3H)替換掉欲觸發(fā)指令的首字節(jié),當(dāng)程序執(zhí)行至斷點(diǎn)指令處,默認(rèn)的調(diào)試異常處理代碼將被調(diào)用,此時(shí)保存在棧中的段/偏移地址就是斷點(diǎn)指令后一字節(jié)的地址;而硬件斷點(diǎn)的設(shè)置則利用了處理器本身的調(diào)試支持,在調(diào)試寄存器(DR0--DR4)中設(shè)置觸發(fā)指令的線形地址并設(shè)置調(diào)試控制寄存器(DR7)中相關(guān)的控制位,CPU會(huì)在預(yù)設(shè)指令執(zhí)行時(shí)自動(dòng)引發(fā)調(diào)試異常。而Windows本身又提供了一套調(diào)試API,使得調(diào)試跟蹤一個(gè)程序變得非常簡(jiǎn)單:調(diào)試器本身不用接掛默認(rèn)的調(diào)試異常處理代碼,而只須調(diào)用WaitForDebugEvent等待系統(tǒng)發(fā)來(lái)的調(diào)試事件;調(diào)試器可利用GetThreadContext掛起被調(diào)試線程獲取其上下文,并設(shè)置上下文中的標(biāo)志寄存器中的陷阱標(biāo)志位,最后通過(guò)SetThreadContext使設(shè)置生效來(lái)進(jìn)行單步調(diào)試;調(diào)試器還可通過(guò)調(diào)用兩個(gè)功能強(qiáng)大的調(diào)試API--ReadProcessMemoryWriteProcessMemory來(lái)向被調(diào)試線程的地址空間中注入斷點(diǎn)指令。根據(jù)我逆向后的分析結(jié)果,VC++的調(diào)試器就是直接利用這套調(diào)試API寫成的。使用以上的調(diào)試技術(shù)既然可以寫出像VC++那樣功能齊全的調(diào)試器,那么沒(méi)有理由不能將之運(yùn)用于病毒代碼的自動(dòng)解密上。最簡(jiǎn)單的做法:創(chuàng)建待查可執(zhí)行文件為調(diào)試器的調(diào)試子進(jìn)程,然后用上述方法對(duì)其進(jìn)行單步跟蹤,每當(dāng)收到具有EXCEPTION_SINGLE_STEP異常代碼的事件時(shí)就可以分析該條以單步模式執(zhí)行的指令,最后當(dāng)判斷病毒的整個(gè)解密過(guò)程結(jié)束后即可調(diào)用ReadProcessMemory讀出病毒體明文。用單步和斷點(diǎn)跟蹤法的唯一一點(diǎn)好處就在于它不用處理每條指令的執(zhí)行--這意味著它無(wú)需編寫大量的特定指令處理函數(shù),因?yàn)樗械慕饷艽a都交由CPU去執(zhí)行,調(diào)試器不過(guò)是在代碼被單步中斷的間隙得到控制權(quán)而已。但這種方法的缺點(diǎn)也是相當(dāng)明顯的:其一容易被病毒覺察到,病毒只須進(jìn)行簡(jiǎn)單的堆棧檢查,或直接調(diào)用IsDebugerPresent就可確定自己正處于被調(diào)試狀態(tài);其二由于沒(méi)有相應(yīng)的機(jī)器碼分析模塊,指令的譯碼,執(zhí)行完全依賴于CPU,所以將導(dǎo)致無(wú)法準(zhǔn)確地獲取指令執(zhí)行細(xì)節(jié)并對(duì)其進(jìn)行有效的控制。;其三單步和斷點(diǎn)跟蹤法要求待查可執(zhí)行文件真實(shí)執(zhí)行,即其將做為系統(tǒng)中一個(gè)真實(shí)的進(jìn)程在自己的地址空間中運(yùn)行,這當(dāng)然是病毒掃描所不能允許的。很顯然,單步和斷點(diǎn)跟蹤法可以應(yīng)用在調(diào)試器,自動(dòng)脫殼等方面,但對(duì)于查毒卻是不合適的。而使用虛擬執(zhí)行法的唯一一點(diǎn)缺點(diǎn)就在于它必須在內(nèi)部處理所有指令的執(zhí)行--這意味著它需要編寫大量的特定指令處理函數(shù)來(lái)模擬每種指令的執(zhí)行效果,這里根本不存在何時(shí)得到控制權(quán)的問(wèn)題,因?yàn)榭刂茩?quán)將永遠(yuǎn)掌握在虛擬機(jī)手中。用軟件方法模擬CPU并非易事,需要對(duì)其機(jī)制有足夠的了解,否則模擬效果將與真實(shí)執(zhí)行相去甚遠(yuǎn)。舉兩個(gè)例子:一個(gè)是病毒常用的乘法后ASCII調(diào)整指令AAM,這條指令因?yàn)榇嬖谖垂_的行為從而常常被病毒用來(lái)考驗(yàn)虛擬機(jī)設(shè)計(jì)的優(yōu)劣。通常情況下AAM是雙字節(jié)指令,操作碼為D4 0A(其實(shí)0A隱含代表了操作數(shù)10);但也可作為單字節(jié)指令明確地指定第二字節(jié)除數(shù)為任意8位立即數(shù),此時(shí)操作碼僅為D4。虛擬機(jī)必需考慮到后一種指定除數(shù)的情況來(lái)保證模擬結(jié)果的正確性;還有一個(gè)例子是關(guān)于處理器響應(yīng)中斷的方式,即CPU在剛打開中斷后將不會(huì)馬上響應(yīng)中斷,而必須隔一個(gè)指令周期。如果虛擬機(jī)沒(méi)有考慮到該機(jī)制則很可能虛擬執(zhí)行流程會(huì)與真實(shí)情況不符。但虛擬執(zhí)行的優(yōu)點(diǎn)也是很明顯的,同時(shí)它正好填補(bǔ)了單步和斷點(diǎn)跟蹤法所力不能及的方面:首先是不可能被病毒覺察到,因?yàn)樘摂M機(jī)將在其內(nèi)部緩沖區(qū)中為被虛擬執(zhí)行代碼設(shè)立專用的堆棧,所以堆棧檢查結(jié)果與實(shí)際執(zhí)行無(wú)二(不會(huì)向堆棧中壓入單步和斷點(diǎn)中斷時(shí)的返回地址);其次由于虛擬機(jī)自身完成指令的解碼和地址的計(jì)算,所以能夠獲取每條指令的執(zhí)行細(xì)節(jié)并加以控制;最后,最為關(guān)鍵的一條在于虛擬執(zhí)行確實(shí)做到了虛擬執(zhí)行,系統(tǒng)中不會(huì)產(chǎn)生代表被執(zhí)行者的進(jìn)程,因?yàn)楸粓?zhí)行者的寄存器組和堆棧等執(zhí)行要素均在虛擬機(jī)內(nèi)部實(shí)現(xiàn),因而可以認(rèn)為它在虛擬機(jī)地址空間中執(zhí)行。鑒于虛擬執(zhí)行法諸多的優(yōu)點(diǎn),所以將其運(yùn)用于通用病毒體解密上是再好不過(guò)的了。

通常,虛擬機(jī)的設(shè)計(jì)方案可以采取以下三種之一:自含代碼虛擬機(jī)(SCCE緩沖代碼虛擬機(jī)(BCE有限代碼虛擬機(jī)(LCE

自含代碼虛擬機(jī)工作起來(lái)象一個(gè)真正的CPU。一條指令取自內(nèi)存,由SCCE解碼,并被傳送到相應(yīng)的模擬這條指令的例程,下一條指令則繼續(xù)這個(gè)循環(huán)。虛擬機(jī)會(huì)包含一個(gè)例程來(lái)對(duì)內(nèi)存/寄存器尋址操作數(shù)進(jìn)行解碼,然后還會(huì)包括一個(gè)用于模擬每個(gè)可能在CPU上執(zhí)行的指令的例程集。正如你所想到的,SCCE的代碼會(huì)變的無(wú)比的巨大而且速度也會(huì)很慢。然而SCCE對(duì)于一個(gè)先進(jìn)的反病毒軟件是很有用的。所有指令都在內(nèi)部被處理,虛擬機(jī)可以對(duì)每條指令的動(dòng)作做出非常詳細(xì)的報(bào)告,這些報(bào)告和啟發(fā)式數(shù)據(jù)以及通用清除模塊將相互參照形成一個(gè)有效的反毒系統(tǒng)。同時(shí),反病毒程序能夠最精確地控制內(nèi)存和端口的訪問(wèn),因?yàn)樗约禾幚淼刂返慕獯a和計(jì)算。

緩沖代碼虛擬機(jī)是SCCE的一個(gè)縮略版,因?yàn)橄鄬?duì)于SCCE它具有較小的尺寸和更快的執(zhí)行速度。在BCE中,一條指令是從內(nèi)存中取得的,并和一個(gè)特殊指令表相比較。如果不是特殊指令,則它被進(jìn)行簡(jiǎn)單的解碼以求得指令的長(zhǎng)度,隨后所有這樣的指令會(huì)被導(dǎo)入到一個(gè)可以通用地模擬所有非特殊指令的小過(guò)程中。而特殊指令,只占整個(gè)指令集的一小部分,則在特定的小處理程序中進(jìn)行模擬。BCE通過(guò)將所有非特殊指令用一個(gè)小的通用的處理程序模擬來(lái)減少它必須特殊處理的指令條數(shù),這樣一來(lái)它削減了自身的大小并提高了執(zhí)行速度。但這意味著它將不能真正限制對(duì)某個(gè)內(nèi)存區(qū)域,端口或其他類似東西的訪問(wèn),同時(shí)它也不可能生成如SCCE提供的同樣全面的報(bào)告。

有限代碼虛擬機(jī)有點(diǎn)象用于通用解密的虛擬系統(tǒng)所處的級(jí)別。LCE實(shí)際上并非一個(gè)虛擬機(jī),因?yàn)樗⒉徽嬲哪M指令,它只簡(jiǎn)單地跟蹤一段代碼的寄存器內(nèi)容,也許會(huì)提供一個(gè)小的被改動(dòng)的內(nèi)存地址表,或是調(diào)用過(guò)的中斷之類的東西。選擇使用LCE而非更大更復(fù)雜的系統(tǒng)的原因,在于即使只對(duì)極少數(shù)指令的支持便可以在解密原始加密病毒的路上走很遠(yuǎn),因?yàn)椴《緝H僅使用了INTEL指令集的一小部分來(lái)加密其主體。使用LCE,原本處理整個(gè)INTEL指令集時(shí)的大量花費(fèi)沒(méi)有了,帶來(lái)的是速度的巨大增長(zhǎng)。當(dāng)然,這是以不能處理復(fù)雜解密程序段為代價(jià)的。當(dāng)需要進(jìn)行快速文件掃描時(shí)LCE就變的有用起來(lái),因?yàn)橐粋€(gè)小型但象樣的LCE可以用來(lái)快速檢查執(zhí)行文件的可疑行為,反之對(duì)每個(gè)文件都使用SCCE算法將會(huì)導(dǎo)致無(wú)法忍受的緩慢。當(dāng)然,如果一個(gè)文件看起來(lái)可疑,LCE還可以啟動(dòng)某個(gè)SCCE代碼對(duì)文件進(jìn)行全面檢查。

下面開始介紹32位自含代碼虛擬機(jī)w32encodew32encode.cppTw32asm.hTw32asm.cpp做為查毒引擎的一部分和其它搜索清除模塊聯(lián)編為Rsengine.dll)的程序結(jié)構(gòu)和流程。由于這是一個(gè)設(shè)計(jì)完備且復(fù)雜的大型商用虛擬機(jī),其中不可避免地包含了對(duì)某些特定病毒的特定處理,為了使虛擬機(jī)模型的結(jié)構(gòu)清晰脈絡(luò)分明,分析時(shí)我將做適當(dāng)?shù)暮?jiǎn)化。w32encode的工作原理很簡(jiǎn)單:它首先設(shè)置模擬寄存器組(用一個(gè)DWORD全局變量模擬真實(shí)CPU內(nèi)部的一個(gè)寄存器,如ENEAX)的初始值,初始化執(zhí)行堆棧指針(虛擬機(jī)用內(nèi)部的一個(gè)數(shù)組static int STACK[0x20]來(lái)模擬堆棧)。然后進(jìn)入一個(gè)循環(huán),解釋執(zhí)行指令緩沖區(qū)ProgBuffer中的頭256條指令,如果循環(huán)退出時(shí)仍未發(fā)現(xiàn)病毒的解密循環(huán)則可由此判定非加密變形病毒,若發(fā)現(xiàn)了解密循環(huán)則調(diào)用EncodeInst函數(shù)重復(fù)執(zhí)行循環(huán)解密過(guò)程,將病毒體明文解密到DataSeg1DataSeg2中。相關(guān)部分代碼如下:

W32Encode0中總體流程控制部分代碼:

for (i=0;i<0x100;i++) //首先虛擬執(zhí)行256條指令試圖發(fā)現(xiàn)病毒循環(huán)解密子

{

if (InstLoc>=0x280) return(0);

if (InstLoc+ProgSeeKOFf>=ProgEndOff)

????????????? return(0); //以上兩條判斷語(yǔ)句檢查指令位置的合法性

saveinstloc(); //存儲(chǔ)當(dāng)前指令在指令緩沖區(qū)中的偏移

HasAddNewInst=0;

if (!(j=parse())) //虛擬執(zhí)行指令緩沖區(qū)中的一條指令

????????????? return(0); //遇到不認(rèn)識(shí)的指令時(shí)退出循環(huán)

if (j==2) //返回值為2說(shuō)明發(fā)現(xiàn)了解密循環(huán)

???????? break;

}

if (i==0x100) //執(zhí)行過(guò)256條指令后仍未發(fā)現(xiàn)循環(huán)則退出

return(0);

PreParse=0;

ProcessInst();

if (!EncodeInst()) //調(diào)用解密函數(shù)重復(fù)執(zhí)行循環(huán)解密過(guò)程

return(0);

?

jmp中判定循環(huán)出現(xiàn)部分代碼:

if ((loc>=0)&&(loc<InstLoc)) //若轉(zhuǎn)移后指令指針小于當(dāng)前指令指針則可能出現(xiàn)循環(huán)

if (!isinstloc(loc)) //在保存的指令指針數(shù)組InstLocArray中查找轉(zhuǎn)移后指

...... //令指針值,如發(fā)現(xiàn)則可判定循環(huán)出現(xiàn)

Else

{

......

return(2); //返回值2代表發(fā)現(xiàn)了解密循環(huán)

}

parse中虛擬執(zhí)行每條指令的過(guò)程較復(fù)雜一些:通常parse會(huì)從取得指令緩沖區(qū)ProgBuffer中取得當(dāng)前指令的頭兩個(gè)字節(jié)(包括了全部操作碼)并根據(jù)它們的值調(diào)用相應(yīng)的指令處理函數(shù)。例如當(dāng)?shù)谝粋€(gè)字節(jié)等于0F并且第二個(gè)字節(jié)位與BE后等于BE時(shí),可判定此指令為movszx并同時(shí)調(diào)用movszx進(jìn)行處理。當(dāng)執(zhí)行進(jìn)入特定指令的處理函數(shù)中時(shí),首先要通過(guò)判斷尋址方式(調(diào)用modregrmmodregrm1)確定指令長(zhǎng)度并將控制權(quán)交給saveinst函數(shù)。saveinst在保存該指令的相關(guān)信息后會(huì)調(diào)用真正指令執(zhí)行函數(shù)W32ExecuteInst。這個(gè)函數(shù)和parse非常相似,它從SaveInstBuf1中取得當(dāng)前指令的頭兩個(gè)字節(jié)并根據(jù)它們的值調(diào)用相應(yīng)的指令模擬函數(shù)以完成一條指令的執(zhí)行。相關(guān)部分代碼如下:

W32ExecuteInst中指令分遣部分代碼:

if ((c&0xf0)==0x50)

{

if (ExecutePushPop1) //模擬pushpop

return(gotonext());

return(0);

}

if (c==0x9c)

{

if (ExecutePushf()) //模擬pushf

return(gotonext());

return(0);

}

if (c==(char)0x9d)

{

if (ExecutePopf()) //模擬popf

return(gotonext());

return(0);

}

if ((c==0xf)&&((c2&0xbe)==0xbe))

{

if (i=ExecuteMovszx(0)) //模擬movszx

return(gotonext());

return(0);

}

?

2.4虛擬機(jī)代碼剖析

總體流程控制和分遣部分的相關(guān)代碼,在上一章中都已分析過(guò)了。下面分析具體的特定指令模擬函數(shù),這才是虛擬機(jī)的精華之所在。我將指令分成不依賴標(biāo)志寄存器和依賴標(biāo)志寄存器兩大類分別介紹:

?

2.4.1不依賴標(biāo)志寄存器指令模擬函數(shù)的分析

pushpop指令的模擬:

static int ExecutePushPop1(int c)

{

if (c<=0x57)

{

if (StackP<0) //入棧前檢查堆棧緩沖指針的合法性

return(0);

???? }

else if (StackP>=0x40) //出棧前檢查堆棧緩沖指針的合法性

????? return(0);

if (c<=0x57)

{

????? StackP--;

????? ENESP-=4; //如果是入棧指令則在入棧前減少堆棧指針

}

Switch

{

????? case 0x50:STACK[StackP]=ENEAX; //模擬push eax

????? break;

????? ......

????? case 0x5f:ENEDI=STACK[StackP]; //模擬push edi

????? break;

}

if (c>=0x58)

{

????? StackP++;

????? ENESP+=4; //如果是出棧指令則在出棧后增加堆棧指針

}

return(1);

}

?

2.4.2依賴標(biāo)志寄存器指令模擬函數(shù)的分析

CW32Asm類中cmp指令的模擬:

void CW32Asm:: cmpw(int c1,int c2)

{

char FlgReg;

__asm

{

mov eax,c1 //取得第一個(gè)操作數(shù)

mov ecx,c2 //取得第二個(gè)操作數(shù)

cmp eax,ecx //比較

lahf //將比較后的標(biāo)志結(jié)果裝入ah

mov FlgReg,ah //保存結(jié)果在局部變量FlgReg

}

FlagReg=FlgReg; //保存結(jié)果在全局變量FlagReg

}

CW32Asm類中jnz指令的模擬:

int CW32Asm::JNE()

{

int i;

char FlgReg=FlagReg; //用保存的FlagReg初始化局部變量FlgReg

__asm

{

mov ah,FlgReg //設(shè)置ah為保存的模擬標(biāo)志寄存器值

pushf //保存虛擬機(jī)自身當(dāng)前標(biāo)志寄存器

sahf //將模擬標(biāo)志寄存器值裝入真實(shí)標(biāo)志寄存器中

mov eax,1

jne l //執(zhí)行jnz

popf //恢復(fù)虛擬機(jī)自身標(biāo)志寄存器

xor eax,eax

l:

popf //恢復(fù)虛擬機(jī)自身標(biāo)志寄存器

mov i,eax

}

return; //返回值為1代表需要跳轉(zhuǎn)

}

?

2.5反虛擬機(jī)技術(shù)

任何一個(gè)事物都不是盡善盡美,無(wú)懈可擊的,虛擬機(jī)也不例外。由于反虛擬執(zhí)行技術(shù)的出現(xiàn),使得虛擬機(jī)查毒受到了一定的挑戰(zhàn)。這里介紹幾個(gè)比較典型的反虛擬執(zhí)行技術(shù):

首先是插入特殊指令技術(shù),即在病毒的解密代碼部分人為插入諸如浮點(diǎn),3DNOWMMX等特殊指令以達(dá)到反虛擬執(zhí)行的目的。盡管虛擬機(jī)使用軟件技術(shù)模擬真正CPU的工作過(guò)程,它畢竟不是真正的CPU,由于精力有限,虛擬機(jī)的編碼者可能實(shí)現(xiàn)對(duì)整個(gè)Intel指令集的支持,因而當(dāng)虛擬機(jī)遇到其不認(rèn)識(shí)的指令時(shí)將會(huì)立刻停止工作。但通過(guò)對(duì)這類病毒代碼的分析和統(tǒng)計(jì),我們發(fā)現(xiàn)通常這些特殊指令對(duì)于病毒的解密本身沒(méi)有發(fā)生任何影響,它們的插入僅僅是為了干擾虛擬機(jī)的工作,換句話說(shuō)就是病毒根本不會(huì)利用這條隨機(jī)的垃圾指令的運(yùn)算結(jié)果。這樣一來(lái),我們可以僅構(gòu)造一張所有特殊指令對(duì)應(yīng)于不同尋址方式的指令長(zhǎng)度表,而不必為每個(gè)特殊指令編寫一個(gè)專用的模擬函數(shù)。有了這張表后,當(dāng)虛擬機(jī)遇到不認(rèn)識(shí)的指令時(shí)可以用指令的操作碼索引表格以求得指令的長(zhǎng)度,然后將當(dāng)前模擬的指令指針(EIP)加上指令長(zhǎng)度來(lái)跳過(guò)這條垃圾指令。當(dāng)然,還有一個(gè)更為保險(xiǎn)的辦法那就是:得到指令長(zhǎng)度后,可以將這條我們不認(rèn)識(shí)的指令放到一個(gè)充滿空操作指令(NOP)的緩沖區(qū)中,接著我們將跳到緩沖區(qū)中去執(zhí)行,這等于讓真正的CPU幫我們來(lái)執(zhí)行這條指令,最后一步當(dāng)然是將執(zhí)行后真實(shí)寄存器中的結(jié)果放回我們的模擬寄存器中。這虛擬執(zhí)行和真實(shí)執(zhí)行參半方法的好處在于:即便在特殊指令對(duì)于病毒是有意義的,即病毒依賴其返回結(jié)果的情況下,虛擬機(jī)仍可保證虛擬執(zhí)行結(jié)果的正確。其次是結(jié)構(gòu)化異常處理技術(shù),即病毒的解密代碼首先設(shè)置自己的異常處理函數(shù),然后故意引發(fā)一個(gè)異常而使程序流程轉(zhuǎn)向預(yù)先設(shè)立的異常處理函數(shù)。這種流程轉(zhuǎn)移是CPU和操作系統(tǒng)相互配合的結(jié)果,并且在很大程度上,操作系統(tǒng)在其中起了很大的作用。由于目前的虛擬機(jī)僅僅模擬了沒(méi)有保護(hù)檢查的CPU的工作過(guò)程,而對(duì)于系統(tǒng)機(jī)制沒(méi)有進(jìn)行處理。所以面對(duì)引發(fā)異常的指令會(huì)有兩種結(jié)果:其一是某些設(shè)計(jì)有缺陷的虛擬機(jī)無(wú)法判斷被模擬指令的合法性,所以模擬這樣的指令將使虛擬機(jī)自身執(zhí)行非法操作而退出;其二虛擬機(jī)判斷出被模擬指令屬于非法指令,如試圖向只讀頁(yè)面寫入的指令,則立刻停止虛擬執(zhí)行。通常病毒使用該技術(shù)的目的在于將真正循環(huán)解密代碼放到異常處理函數(shù)后,如此虛擬機(jī)將在進(jìn)入異常處理函數(shù)前就停止了工作,從而使解密子有機(jī)會(huì)逃避虛擬執(zhí)行。因而一個(gè)好的虛擬機(jī)應(yīng)該具備發(fā)現(xiàn)和記錄病毒安裝異常過(guò)濾函數(shù)的操作并在其引發(fā)異常時(shí)自動(dòng)將控制轉(zhuǎn)向異常處理函數(shù)的能力。再次是入口點(diǎn)模糊(EPO)技術(shù),即病毒在不修改宿主原入口點(diǎn)的前提下,通過(guò)在宿主代碼體內(nèi)某處插入跳轉(zhuǎn)指令來(lái)使病毒獲得控制權(quán)。通過(guò)前面的分析,我們知道虛擬機(jī)掃描病毒時(shí)出于效率考慮不可能虛擬執(zhí)行待查文件的所有代碼,通常的做法是:掃描待查文件代碼入口,假如在規(guī)定步數(shù)中沒(méi)有發(fā)現(xiàn)解密循環(huán),則由此判定該文件沒(méi)有攜帶加密變形病毒。這種技術(shù)之所以能起到反虛擬執(zhí)行的作用在于它正好利用了虛擬機(jī)的這個(gè)假設(shè):由于病毒是從宿主執(zhí)行到一半時(shí)獲得控制權(quán)的,所以虛擬機(jī)首先解釋執(zhí)行的是宿主入口的正常程序,當(dāng)然在規(guī)定步數(shù)中不可能發(fā)現(xiàn)解密循環(huán),因而產(chǎn)生了漏報(bào)。如果虛擬機(jī)能增加規(guī)定步數(shù)的大小,則很有可能隨著病毒插入的跳轉(zhuǎn)指令跟蹤進(jìn)入病毒的解密子,但確定規(guī)定步數(shù)大小實(shí)在是件難事:太大則將無(wú)謂增加正常程序的檢測(cè)時(shí)間;太小則容易產(chǎn)生漏報(bào)。但我們對(duì)此也不必過(guò)于擔(dān)心,這類病毒由于其編寫技術(shù)難度較大所以為數(shù)不多。在沒(méi)有反匯編和虛擬執(zhí)行引擎的幫助下,病毒很難在宿主體內(nèi)定位一條完整指令的開始處來(lái)插入跳轉(zhuǎn),同時(shí)很難保證插入的跳轉(zhuǎn)指令的深度大于虛擬機(jī)的規(guī)定步數(shù),并且沒(méi)有把握插入的跳轉(zhuǎn)指令一定會(huì)被執(zhí)行到。

另外還有多線程技術(shù),即病毒在解密部分入口主線程中又啟動(dòng)了額外的工作線程,并且將真正的循環(huán)解密代碼放置于工作線程中運(yùn)行。由于多線程間切換調(diào)度由操作系統(tǒng)負(fù)責(zé)管理,所以我們的虛擬機(jī)只能在假定被執(zhí)行線程獨(dú)占處理器時(shí)間,即保證永遠(yuǎn)不被搶先,的前提下進(jìn)行。如此一來(lái),虛擬機(jī)對(duì)于模擬啟用多線程工作的代碼將很難做到與真實(shí)效果一致。多線程和結(jié)構(gòu)化異常處理兩種技術(shù)都利用了特定的操作系統(tǒng)機(jī)制來(lái)達(dá)到反虛擬執(zhí)行的目的,所以在虛擬CPU中加入對(duì)特定操作系統(tǒng)機(jī)制的支持將是我們今后改進(jìn)的目標(biāo)。

最后是元多形技術(shù)(MetaPolymorphy,即病毒中并非是多形的解密子加加密的病毒體結(jié)構(gòu),而整體均采用變形技術(shù)。這種病毒整體都在變,沒(méi)有所謂病毒體明文。當(dāng)然,其編寫難度是很大的。如果說(shuō)前幾種反虛擬機(jī)技術(shù)是利用了虛擬機(jī)設(shè)計(jì)上的缺陷,可以通過(guò)代碼改進(jìn)來(lái)彌補(bǔ)的話,那么這種元多形技術(shù)卻使虛擬機(jī)配合的動(dòng)態(tài)特征碼掃描法徹底失效了,我們必須尋求如行為分析等更先進(jìn)的方法來(lái)解決。? 與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的反病毒引擎设计全解(三)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。