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

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

生活随笔

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

编程问答

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

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

1.緒

本論文研究的主要內(nèi)容正如其題目所示是設(shè)計(jì)并編寫(xiě)一個(gè)先進(jìn)的反病毒引擎。首先需要對(duì)這先進(jìn)二字做一個(gè)解釋,何為先進(jìn)?眾所周知,傳統(tǒng)的反病毒軟件使用的是基于特征碼的靜態(tài)掃描技術(shù),即在文件中尋找特定十六進(jìn)制串,如果找到,就可判定文件感染了某種病毒。但這種方法在當(dāng)今病毒技術(shù)迅猛發(fā)展的形勢(shì)下已經(jīng)起不到很好的作用了。原因我會(huì)在以下的章節(jié)中具體描述。因此本論文將不對(duì)殺毒引擎中的特征碼掃描和病毒代碼清除模塊做分析。我們要討論的是為應(yīng)付先進(jìn)的病毒技術(shù)而必需的兩大反病毒技術(shù)--虛擬機(jī)和實(shí)時(shí)監(jiān)控技術(shù)。具體什么是虛擬機(jī),什么是實(shí)時(shí)監(jiān)控,我會(huì)在相應(yīng)的章節(jié)中做詳盡的介紹。這里我要說(shuō)明的一點(diǎn)是,這兩項(xiàng)技術(shù)雖然在前人的工作中已有所體現(xiàn)(被一些國(guó)內(nèi)外先進(jìn)的反病毒廠(chǎng)家所使用),但出于商業(yè)目的,這些技術(shù)并沒(méi)有被完全公開(kāi),所以你無(wú)論從書(shū)本文獻(xiàn)還是網(wǎng)路上的資料中都無(wú)法找到關(guān)于這些技術(shù)的內(nèi)幕。而我會(huì)在相關(guān)的章節(jié)中剖析大量的程序源碼(主要是2.4節(jié)中的一個(gè)完整的虛擬機(jī)源碼)或是逆向工程代碼(3.3.3節(jié)和3.4.3節(jié)中三個(gè)我逆向工程的某著名反病毒軟件的實(shí)時(shí)監(jiān)控驅(qū)動(dòng)程序及客戶(hù)程序的反匯編代碼),并同時(shí)公布一些我個(gè)人挖掘的操作系統(tǒng)內(nèi)部未公開(kāi)的機(jī)制和數(shù)據(jù)結(jié)構(gòu)。另外我在文中會(huì)大量地提到或引用一些關(guān)于系統(tǒng)底層奧秘的大師級(jí)經(jīng)典圖書(shū),這算是給喜愛(ài)系統(tǒng)級(jí)編程但又苦于找不到合適教材的朋友開(kāi)了一份書(shū)單。下面就開(kāi)始進(jìn)入論文的正題。

?

1.1課題背景

本論文涉及的兩個(gè)主要技術(shù),也是當(dāng)今反病毒界使用的最為先進(jìn)的技術(shù)中的兩個(gè),究竟是作何而用的呢?首先說(shuō)說(shuō)虛擬機(jī)技術(shù),它主要是為查殺加密變形病毒而設(shè)計(jì)的。簡(jiǎn)單地來(lái)說(shuō),所謂虛擬機(jī)并不是個(gè)虛擬的機(jī)器,說(shuō)得更合適一些應(yīng)該是個(gè)虛擬CPU(用軟件實(shí)現(xiàn)的CPU),只不過(guò)病毒界都這么叫而已。它的作用主要是模擬INTEL X86 CPU的工作過(guò)程來(lái)解釋執(zhí)行可執(zhí)行代碼,與真正的CPU一樣能夠取指,譯碼并執(zhí)行相應(yīng)機(jī)器指令規(guī)定的操作。當(dāng)然什么是加密變形病毒,它們?yōu)槭裁葱枰惶摂M執(zhí)行以及怎樣虛擬執(zhí)行等問(wèn)題會(huì)在合適的章節(jié)中得到解答。再說(shuō)另一個(gè)重頭戲--實(shí)時(shí)監(jiān)控技術(shù),它的用處更為廣泛,不僅局限于查殺病毒。被實(shí)時(shí)監(jiān)控的對(duì)象也很多,如中斷(Intmon),頁(yè)面錯(cuò)誤(Pfmon),磁盤(pán)訪(fǎng)問(wèn)(Diskmon等等。用于殺毒的監(jiān)控主要是針對(duì)文件訪(fǎng)問(wèn),在你要對(duì)一個(gè)文件進(jìn)行訪(fǎng)問(wèn)時(shí),實(shí)時(shí)監(jiān)控會(huì)先檢查文件是否為帶毒文件,若是,則由用戶(hù)選擇是清除病毒還是取消此次操作請(qǐng)求。這樣就給了用戶(hù)一個(gè)相對(duì)安全的執(zhí)行環(huán)境。但同時(shí),實(shí)時(shí)監(jiān)控會(huì)使系統(tǒng)性能有所下降,不少殺毒軟件的用戶(hù)都抱怨他們的實(shí)時(shí)監(jiān)控讓系統(tǒng)變得奇慢無(wú)比而且不穩(wěn)定。這就給我們的設(shè)計(jì)提出了更高的要求,即怎樣在保證準(zhǔn)確攔截文件操作的同時(shí),讓實(shí)時(shí)監(jiān)控占用的系統(tǒng)資源更少。我會(huì)在病毒實(shí)時(shí)監(jiān)控一節(jié)中專(zhuān)門(mén)討論這個(gè)問(wèn)題。這兩項(xiàng)技術(shù)在國(guó)內(nèi)外先進(jìn)的反病毒廠(chǎng)家的產(chǎn)品中都有使用,雖然它們的源代碼沒(méi)有公開(kāi),但我們還是可以通過(guò)逆向工程的方法來(lái)窺視一下它們的設(shè)計(jì)思路。其實(shí)你用一個(gè)十六進(jìn)制編輯器來(lái)打開(kāi)它們的可執(zhí)行文件,也許就會(huì)看到一些沒(méi)有剝掉的調(diào)試符號(hào)、變量名字或輸出信息,這些蛛絲馬跡對(duì)于理解代碼的意圖大有裨益。同時(shí),在反病毒軟件的安裝目錄中后綴為.VXD.SYS就是執(zhí)行實(shí)時(shí)監(jiān)控的驅(qū)動(dòng)程序,可以拿來(lái)逆向一下(參看我在后面分析驅(qū)動(dòng)源代碼中的討論)。相信至此,我們對(duì)這兩項(xiàng)技術(shù)有了一個(gè)大體的了解。后面我們將深入到技術(shù)的細(xì)節(jié)中去。

?

1.2當(dāng)今病毒技術(shù)的發(fā)展?fàn)顩r

要討論怎樣反病毒,就必須從病毒技術(shù)本身的討論開(kāi)始。正是所謂知己知彼,百戰(zhàn)不殆。其實(shí),我認(rèn)為目前規(guī)定研究病毒技術(shù)屬于違法行為存在著很大的弊端。很難想象一個(gè)毫無(wú)病毒寫(xiě)作經(jīng)驗(yàn)的人會(huì)成為殺毒高手。據(jù)我了解,目前國(guó)內(nèi)一些著名反病毒軟件公司的研發(fā)隊(duì)伍中不乏病毒寫(xiě)作高手。只不過(guò)他們將同樣的技術(shù)用到了正道上,以。所以我希望這篇論文能起到拋磚引玉的作用,期待著有更多的人會(huì)將病毒技術(shù)介紹給大眾。當(dāng)今的病毒與DOSWIN3.1時(shí)代下的從技術(shù)角度上看有很多不同。我認(rèn)為最大的轉(zhuǎn)變是:引導(dǎo)區(qū)病毒減少了,而腳本型病毒開(kāi)始泛濫。原因是在當(dāng)今的操作系統(tǒng)下直接改寫(xiě)磁盤(pán)的引導(dǎo)區(qū)會(huì)有一定的難度(DOS則沒(méi)有保護(hù),允許調(diào)用INT13直接寫(xiě)盤(pán)),而且引導(dǎo)區(qū)的改動(dòng)很容易被發(fā)現(xiàn),所以很少有人再寫(xiě)了;而腳本病毒以其傳播效率高且容易編寫(xiě)而深得病毒作者的青睞。當(dāng)然由于這兩種病毒用我上面說(shuō)過(guò)的基于特征碼的靜態(tài)掃描技術(shù)就可以查殺,所以不在我們的討論之列。我要討論的技術(shù)主要來(lái)自于二進(jìn)制外殼型病毒(感染文件的病毒),并且這些技術(shù)大都和操作系統(tǒng)底層機(jī)制或386以上CPU的保護(hù)模式相關(guān),所以值得研究。大家都知道DOS下的外殼型病毒主要感染16位的COMEXE文件,由于DOS沒(méi)有保護(hù),它們能夠輕松地進(jìn)行駐留,減少可用內(nèi)存(通過(guò)修改MCB鏈),修改系統(tǒng)代碼,攔截系統(tǒng)服務(wù)或中斷。而到了WIN9XWINNT/2000時(shí)代,想寫(xiě)個(gè)運(yùn)行其上的32WINDOWS病毒絕非易事。由于頁(yè)面保護(hù),你不可能修改系統(tǒng)的代碼頁(yè)。由于I/O許可位圖中的規(guī)定,你也不能進(jìn)行直接端口訪(fǎng)問(wèn)。在WINDOWS中你不可能像在DOS中那樣通過(guò)截獲INT21H來(lái)攔截所有文件操作。總之,你以一個(gè)用戶(hù)態(tài)程序運(yùn)行,你的行為將受到操作系統(tǒng)嚴(yán)格的控制,不可能再象DOS下那樣為所欲為了。另外值得一提的是,WINDOWS下采用的可執(zhí)行文件格式和DOS下的EXE截然不同(普通程序采用PE格式,驅(qū)動(dòng)程序采用LE),所以病毒的感染文件的難度增大了(PELE比較復(fù)雜,中間分了若干個(gè)節(jié),如果感染錯(cuò)了,將導(dǎo)致文件不能繼續(xù)執(zhí)行)。因?yàn)楫?dāng)今病毒的新技術(shù)太多,我不可能將它們逐一詳細(xì)討論,于是就選取了一些重要并具有代表性的在本章的各小節(jié)中進(jìn)行討論。

?

1.2.1系統(tǒng)核心態(tài)病毒

在介紹什么是系統(tǒng)核心態(tài)病毒之前,有必要討論一下核心態(tài)與用戶(hù)態(tài)的概念。其實(shí)只要隨便翻開(kāi)一本關(guān)于386保護(hù)模式匯編程序設(shè)計(jì)的教科書(shū),都可以找到對(duì)這兩個(gè)概念的講述。386及以上的CPU實(shí)現(xiàn)了4個(gè)特權(quán)級(jí)模式(WINDOWS只用到了其中兩個(gè)),其中特權(quán)級(jí)0Ring0)是留給操作系統(tǒng)代碼,設(shè)備驅(qū)動(dòng)程序代碼使用的,它們工作于系統(tǒng)核心態(tài);而特權(quán)極3Ring3)則給普通的用戶(hù)程序使用,它們工作在用戶(hù)態(tài)。運(yùn)行于處理器核心態(tài)的代碼不受任何的限制,可以自由地訪(fǎng)問(wèn)任何有效地址,進(jìn)行直接端口訪(fǎng)問(wèn)。而運(yùn)行于戶(hù)態(tài)的代碼則要受到處理器的諸多檢查,它們只能訪(fǎng)問(wèn)映射其地址空間的頁(yè)表項(xiàng)中規(guī)定的在用戶(hù)態(tài)下可訪(fǎng)問(wèn)頁(yè)面的虛擬地址,且只能對(duì)任務(wù)狀態(tài)段(TSS)中I/O許可位圖(I/O Permission Bitmap)中規(guī)定的可訪(fǎng)問(wèn)端口進(jìn)行直接訪(fǎng)問(wèn)(此時(shí)處理器狀態(tài)和控制標(biāo)志寄存器EFLAGS中的IOPL通常為0,指明當(dāng)前可以進(jìn)行直接I/O的最低特權(quán)級(jí)別是Ring0)。以上的討論只限于保護(hù)模式操作系統(tǒng),像DOS這種實(shí)模式操作系統(tǒng)則沒(méi)有這些概念,其中的所有代碼都可被看作運(yùn)行在核心態(tài)。既然運(yùn)行在核心態(tài)有如此之多的優(yōu)勢(shì),那么病毒當(dāng)然沒(méi)有理由不想得到Ring0。處理器模式從Ring3Ring0的切換發(fā)生在控制權(quán)轉(zhuǎn)移時(shí),有以下兩種情況:訪(fǎng)問(wèn)調(diào)用門(mén)的長(zhǎng)轉(zhuǎn)移指令CALL,訪(fǎng)問(wèn)中斷門(mén)或陷阱門(mén)的INT指令。具體的轉(zhuǎn)移細(xì)節(jié)由于涉及復(fù)雜的保護(hù)檢查和堆棧切換,不再贅述,請(qǐng)參閱相關(guān)資料。現(xiàn)代的操作系統(tǒng)通常使用中斷門(mén)來(lái)提供系統(tǒng)服務(wù),通過(guò)執(zhí)行一條陷入指令來(lái)完成模式切換,在INTEL X86上這條指令是INT,如在WIN9X下是INT30(保護(hù)模式回調(diào)),在Linux下是INT80,在WINNT/2000下是INT2E。用戶(hù)模式的服務(wù)程序(如系統(tǒng)DLL)通過(guò)執(zhí)行一個(gè)INTXX來(lái)請(qǐng)求系統(tǒng)服務(wù),然后處理器模式將切換到核心態(tài),工作于核心態(tài)的相應(yīng)的系統(tǒng)代碼將服務(wù)于此次請(qǐng)求并將結(jié)果傳給用戶(hù)程序。下面就舉例子說(shuō)明病毒進(jìn)入系統(tǒng)核心態(tài)的方法。在WIN9X下進(jìn)程虛擬地址空間中映射共享系統(tǒng)代碼的部分(3G--4G)中除了最上面4M頁(yè)表有頁(yè)面保護(hù)外其它地方可由用戶(hù)程序讀寫(xiě)。如果你用Softice(系統(tǒng)級(jí)調(diào)試器)的PAGE命令查看這些地址的頁(yè)屬性,則你會(huì)驚奇地發(fā)現(xiàn)U RW位,這說(shuō)明這些地址可從用戶(hù)態(tài)直接讀出或?qū)懭搿_@意味著任何一個(gè)用戶(hù)程序都能夠在其運(yùn)行過(guò)程中惡意或無(wú)意地破壞操作系統(tǒng)代碼頁(yè)。由此病毒就可以在GDT(全局描述符表),LDT(局部描述符表)中隨意構(gòu)造門(mén)描述符并借此進(jìn)入核心態(tài)。當(dāng)然,也不一定要借助門(mén)描述,還有許多方法可以得到Ring0。據(jù)我所知的方法就不下10余種之多,如通過(guò)調(diào)用門(mén)(Callgate),中斷門(mén)(Intgate),陷阱門(mén)(Trapgate),異常門(mén)(Fault),中斷請(qǐng)求(IRQs),端口(Ports),虛擬機(jī)管理器(VMM),回調(diào)(Callback),形式轉(zhuǎn)換(Thunks),設(shè)備IO控制(DeviceIOControl,API函數(shù)(SetThreadContext,中斷2E服務(wù)(NTKERN.VxD。由于篇幅的限制我不可能將所有的方法逐一描述清楚,這里我僅選取最具有代表性的CIH病毒1.5版開(kāi)頭的一段代碼。

人們常說(shuō)CIH病毒運(yùn)用了VXD(虛擬設(shè)備驅(qū)動(dòng))技術(shù),其實(shí)它本身并不是VXD。只不過(guò)它利用WIN9X上述漏洞,在IDT(中斷描述符表)中構(gòu)造了一個(gè)DPL(段特權(quán)級(jí))為3的中斷門(mén)(意味著可以從Ring3下執(zhí)行訪(fǎng)問(wèn)該中斷門(mén)的INT指令),并使描述符指向自己私有地址空間中的一個(gè)需要工作在Ring0下的函數(shù)地址。這樣一來(lái)CIH就可以通過(guò)簡(jiǎn)單的執(zhí)行一條INTXX指令(CIH選擇使用INT3,是為了使同樣接掛INT3的系統(tǒng)調(diào)試器Softice無(wú)法正常工作以達(dá)到反跟蹤的目的)進(jìn)入系統(tǒng)核心態(tài),從而調(diào)用系統(tǒng)的VMMVXD服務(wù)。以下是我注釋的一段CIH1.5的源代碼:

; *************************************

; * 修改IDT以求得核心態(tài)特權(quán)級(jí) *

; *************************************

push eax

sidt [esp-02h] ;取得IDT表基地址

pop ebx

add ebx, HookExceptionNumber*08h+04h ZF = 0

cli ;讀取修改系統(tǒng)數(shù)據(jù)時(shí)先禁止中斷

mov ebp, [ebx]

mov bp, [ebx-04h] ;取得原來(lái)的中斷入口地址

lea esi, MyExceptionHook-@1[ecx] ;取得需要工作在Ring0的函數(shù)的偏移地址

push esi

mov [ebx-04h], si

shr esi, 16

mov [ebx+02h], si ;設(shè)置為新的中斷入口地址

pop esi

; *************************************

; * 產(chǎn)生一個(gè)異常來(lái)進(jìn)入Ring0 *

; *************************************

int HookExceptionNumber ;產(chǎn)生一個(gè)異常

當(dāng)然,后面還有恢復(fù)原來(lái)中斷入口地址和異常處理幀的代碼。

剛才所討論的技術(shù)僅限于WIN9X,想在WINNT/2000下進(jìn)入Ring0則沒(méi)有這么容易。主要的原因是WINNT/2000沒(méi)有上述的漏洞,它們的系統(tǒng)代碼頁(yè)面(2G--4G)有很好的頁(yè)保護(hù)。大于0x80000000的虛擬地址對(duì)于用戶(hù)程序是不可見(jiàn)的。如果你用SofticePAGE命令查看這些地址的頁(yè)屬性,你會(huì)發(fā)現(xiàn)S位,這說(shuō)明這些地址僅可從核心態(tài)訪(fǎng)問(wèn)。所以想在IDTGDT隨意構(gòu)造描述符,運(yùn)行時(shí)修改內(nèi)核是根本做不到的。所能做的僅是通過(guò)加載一個(gè)驅(qū)動(dòng)程序,使用它來(lái)做你在Ring3下做不到的事情。病毒可以在它們加載的驅(qū)動(dòng)中修改內(nèi)核代碼,或?yàn)椴《颈旧韯?chuàng)建調(diào)用門(mén)(利用NTNtoskrnl.exe導(dǎo)出的未公開(kāi)的系統(tǒng)服務(wù)KeI386AllocateGdtSelectorsKeI386SetGdtSelectorKeI386ReleaseGdtSelectors)。如Funlove病毒就利用驅(qū)動(dòng)來(lái)修改系統(tǒng)文件(Ntoskrnl.exeNtldr)以繞過(guò)安全檢查。但這里面有兩個(gè)問(wèn)題,其一是驅(qū)動(dòng)程序從哪里來(lái),現(xiàn)代病毒普遍使用一個(gè)稱(chēng)為“Drop”的技術(shù),即在病毒體本身包含驅(qū)動(dòng)程序二進(jìn)制碼(可以進(jìn)行壓縮或動(dòng)態(tài)構(gòu)造文件頭),在病毒需要使用時(shí),動(dòng)態(tài)生成驅(qū)動(dòng)程序并將它們?nèi)拥酱疟P(pán)上,然后馬上通過(guò)在SCM(服務(wù)控制管理器)注冊(cè)并最終調(diào)用StartService來(lái)使驅(qū)動(dòng)程序得以運(yùn)行;其二是加載一個(gè)驅(qū)動(dòng)程序需要管理員身份,普通帳號(hào)在調(diào)用上述的加載函數(shù)時(shí)會(huì)返回失敗(安全子系統(tǒng)要檢查用戶(hù)的訪(fǎng)問(wèn)令牌(Token)中有無(wú)SeLoadDriverPrivilege特權(quán)),但多數(shù)用戶(hù)在大多時(shí)候登錄時(shí)會(huì)選擇管理員身份,否則連病毒實(shí)時(shí)監(jiān)控驅(qū)動(dòng)也同樣無(wú)法加載,所以留給病毒的機(jī)會(huì)還是很多的。

?

1.2.2駐留病毒

駐留病毒是指那些在內(nèi)存中尋找合適的頁(yè)面并將病毒自身拷貝到其中且在系統(tǒng)運(yùn)行期間能夠始終保持病毒代碼的存在。駐留病毒比那些直接感染(Direct-action)型病毒更具隱蔽性,它通常要截獲某些系統(tǒng)操作來(lái)達(dá)到感染傳播的目的。進(jìn)入了核心態(tài)的病毒可以利用系統(tǒng)服務(wù)來(lái)達(dá)到此目的,如CIH病毒通過(guò)調(diào)用一個(gè)由VMM導(dǎo)出的服務(wù)VMMCALL _PageAllocate在大于0xC0000000的地址上分配一塊頁(yè)面空間。而處于用戶(hù)態(tài)的程序要想在程序退出后仍駐留代碼的部分于內(nèi)存中似乎是不可能的,因?yàn)闊o(wú)論用戶(hù)程序分配何種內(nèi)存都將作為進(jìn)程占用資源的一部分,一旦進(jìn)程結(jié)束,所占資源將立即被釋放。所以我們要做的是分配一塊進(jìn)程退出后仍可保持的內(nèi)存。

病毒寫(xiě)作小組29A的成員GriYo 運(yùn)用的一個(gè)技術(shù)很有創(chuàng)意:他通過(guò)CreateFileMappingA MapViewOfFile創(chuàng)建了一個(gè)區(qū)域?qū)ο蟛⒂成渌囊粋€(gè)視口到自己的地址空間中去,并把病毒體搬到那里,由于文件映射所在的虛擬地址處于共享區(qū)域(能夠被所有進(jìn)程看到,即所有進(jìn)程用于映射共享區(qū)內(nèi)虛擬地址的頁(yè)表項(xiàng)全都指向相同的物理頁(yè)面),所以下一步他通過(guò)向EXPlorer.exe中注入一段代碼(利用WriteProcessMemory來(lái)向其它進(jìn)程的地址空間寫(xiě)入數(shù)據(jù)),而這段代碼會(huì)從Explorer.exe的地址空間中再次申請(qǐng)打開(kāi)這個(gè)文件映射。如此一來(lái),即便病毒退出,但由于Explorer.exe還對(duì)映射頁(yè)面保持引用,所以一份病毒體代碼就一直保持在可以影響所有進(jìn)程的內(nèi)存頁(yè)面中直至Explorer.exe退出。

另外還可以通過(guò)修改系統(tǒng)動(dòng)態(tài)連接模塊(DLL)來(lái)進(jìn)行駐留。WIN9X下系統(tǒng)DLL(如Kernel32.dll 映射至BFF70000)處于系統(tǒng)共享區(qū)域(2G-3G),如果在其代碼段空隙中寫(xiě)入一小段病毒代碼則可以影響其它所有進(jìn)程。但Kernel32.dll的代碼段在用戶(hù)態(tài)是只能讀不能寫(xiě)的。所以必須先通過(guò)特殊手段修改其頁(yè)保護(hù)屬性;而在WINNT/2000下系統(tǒng)DLL所在頁(yè)面被映射到進(jìn)程的私有空間(如Kernel32.dll 映射至77ED0000)中,并具有寫(xiě)時(shí)拷貝屬性,即沒(méi)有進(jìn)程試圖寫(xiě)入該頁(yè)面時(shí),所有進(jìn)程共享這個(gè)頁(yè)面;而當(dāng)一個(gè)進(jìn)程試圖寫(xiě)入該頁(yè)面時(shí),系統(tǒng)的頁(yè)面錯(cuò)誤處理代碼將收到處理器的異常,并檢查到該異常并非訪(fǎng)問(wèn)違例,同時(shí)分配給引發(fā)異常的進(jìn)程一個(gè)新頁(yè)面,并拷貝原頁(yè)面內(nèi)容于其上且更新進(jìn)程的頁(yè)表以指向新分配的頁(yè)。這種共享內(nèi)存的優(yōu)化給病毒的寫(xiě)作帶來(lái)了一定的麻煩,病毒不能象在WIN9X下那樣僅修改Kernel32.dll一處代碼便可一勞永逸。它需要利用WriteProcessMemory來(lái)向每個(gè)進(jìn)程映射Kernel32.dll的地址寫(xiě)入病毒代碼,這樣每個(gè)進(jìn)程都會(huì)得到病毒體的一個(gè)副本,這在病毒界被稱(chēng)為多進(jìn)程駐留或每進(jìn)程駐留(Muti-Process Residenceor Per-Process Residence )。

?

1.2.3截獲系統(tǒng)操作

截獲系統(tǒng)操作是病毒慣用的伎倆。DOS時(shí)代如此,WINDOWS時(shí)代也不例外。在DOS下,病毒通過(guò)在中斷向量表中修改INT21H的入口地址來(lái)截獲DOS系統(tǒng)服務(wù)(DOS利用INT21H來(lái)提供系統(tǒng)調(diào)用,其中包括大量的文件操作)。而大部分引導(dǎo)區(qū)病毒會(huì)接掛INT13H(提供磁盤(pán)操作服務(wù)的BIOS中斷)從而取得對(duì)磁盤(pán)訪(fǎng)問(wèn)的控制。WINDOWS下的病毒同樣找到了鉤掛系統(tǒng)服務(wù)的辦法。比較典型的如CIH病毒就是利用了IFSMGR.VXD(可安裝文件系統(tǒng))提供的一個(gè)系統(tǒng)級(jí)文件鉤子來(lái)截獲系統(tǒng)中所有文件操作,我會(huì)在相關(guān)章節(jié)中詳細(xì)討論這個(gè)問(wèn)題,因?yàn)?/span>WIN9X下的實(shí)時(shí)監(jiān)控也主要利用這個(gè)服務(wù)。除此之外,還有別的方法。但效果沒(méi)有這個(gè)系統(tǒng)級(jí)文件鉤子好,主要是不夠底層,會(huì)丟失一些文件操作。

其中一個(gè)方法是利用APIHOOK,鉤掛API函數(shù)。其實(shí)系統(tǒng)中并沒(méi)有現(xiàn)成的這種服務(wù),有一個(gè)SetWindowsHookEx可以鉤住鼠標(biāo)消息,但對(duì)截獲API函數(shù)則無(wú)能為力。我們能做的是自己構(gòu)造這樣的HOOK。方法其實(shí)很簡(jiǎn)單:比如你要截獲Kernel32.dll導(dǎo)出的函數(shù)CreateFile,只須在其函數(shù)代碼的開(kāi)頭(BFF7XXXX)加入一個(gè)跳轉(zhuǎn)指令到你的鉤子函數(shù)的入口,在你的函數(shù)執(zhí)行完后再跳回來(lái)。如下圖所示:

;; Target Function(要截獲的目標(biāo)函數(shù))

……

TargetFunction:(要截獲的目標(biāo)函數(shù)入口)

jmp DetourFunction(跳到鉤子函數(shù),5個(gè)字節(jié)長(zhǎng)的跳轉(zhuǎn)指令)

TargetFunction+5:

push edi

……

;; Trampoline(你的鉤子函數(shù))

……

TrampolineFunction:(你的鉤子函數(shù)執(zhí)行完后要返回原函數(shù)的地方)

push ebp

mov ebp,esp

push ebx

push esi(以上幾行是原函數(shù)入口處的幾條指令,共5個(gè)字節(jié))

jmp TargetFunction+5(跳回原函數(shù))

……

但這種方法截獲的僅僅是很小一部分文件打開(kāi)操作。

WIN9X下還有一個(gè)鮮為人知的截獲文件操作的辦法,說(shuō)起來(lái)這應(yīng)該算是WIN9X的一大后門(mén)。它就是Kernel32.dll中一個(gè)未公開(kāi)的叫做VxdCall0API函數(shù)。反匯編這個(gè)函數(shù)的代碼如下:

mov eax,dWord ptr [esp+00000004h] ;取得服務(wù)代號(hào)

pop dword ptr [esp] ;堆棧修正

call fword ptr csBFFC9004] ;通過(guò)一個(gè)調(diào)用門(mén)調(diào)用3B段某處的代碼

如果我們繼續(xù)跟蹤下去,則會(huì)看到:

003B:XXXXXXXX int 30h ;這是個(gè)用以陷入VWIN32.VXD的保護(hù)模式回調(diào)

有關(guān)VxdCall的詳細(xì)內(nèi)容,請(qǐng)參看Matt Pietrek的《Windows 95 System Programming Secrets》。

當(dāng)服務(wù)代號(hào)為0X002A0010時(shí),保護(hù)模式回調(diào)會(huì)陷入VWIN32.VXD中一個(gè)叫做VWIN32_Int21Dispatch的服務(wù)。這正說(shuō)明了WIN9X還在依賴(lài)于MSDos,盡管微軟聲稱(chēng)WIN9X不再依賴(lài)于MSDos。調(diào)用規(guī)范如下:

my_int21hush ecx

push eax ;類(lèi)似DOSINT21HAX中傳入的功能號(hào)

push 002A0010h

call dword ptr [ebp+a_VxDCall]

ret

我們可以將上面VxdCall0函數(shù)的入口處第三條遠(yuǎn)調(diào)用指令訪(fǎng)問(wèn)的Kernel32.dll數(shù)據(jù)段中用戶(hù)態(tài)可寫(xiě)地址BFFC9004Υ?FWORD`六個(gè)字節(jié)改為指向我們自己鉤子函數(shù)的地址,并在鉤子中檢查傳入服務(wù)號(hào)和功能號(hào)來(lái)確定是否是請(qǐng)求VWIN32_Int21Dispatch中的某個(gè)文件服務(wù)。著名的HPS病毒就利用了這個(gè)技術(shù)在用戶(hù)態(tài)下直接截獲系統(tǒng)中的文件操作,但這種方法截獲的也僅僅是一小部分文件操作。

?

1.2.4加密變形病毒

加密變形病毒是虛擬機(jī)一章的重點(diǎn)內(nèi)容,將放到相關(guān)章節(jié)中介紹。

?

1.2.5反跟蹤/反虛擬執(zhí)行病毒

反跟蹤/反虛擬執(zhí)行病毒和虛擬機(jī)聯(lián)系密切,所以也將放到相應(yīng)的章節(jié)中介紹。

?

1.2.6直接API調(diào)用

直接API調(diào)用是當(dāng)今WIN32病毒常用的手段,它指的是病毒在運(yùn)行時(shí)直接定位API函數(shù)在內(nèi)存中的入口地址然后調(diào)用之的一種技術(shù)。普通程序進(jìn)行API調(diào)用時(shí),編譯器會(huì)將一個(gè)API調(diào)用語(yǔ)句編譯為幾個(gè)參數(shù)壓棧指令后跟一條間接調(diào)用語(yǔ)句(這是指Microsoft編譯器,Borland編譯器使用JMP DWORD PTR [XXXXXXXXh])形式如下:

push arg1

push arg2

……

call dword ptr[XXXXXXXXh]

地址XXXXXXXXh在程序映象的導(dǎo)入(Import Section)段中,當(dāng)程序被加載運(yùn)行時(shí),由裝入器負(fù)責(zé)向里面添入API函數(shù)的地址,這就是所謂的動(dòng)態(tài)鏈接機(jī)制。病毒由于為了避免感染一個(gè)可執(zhí)行文件時(shí)在文件的導(dǎo)入段中構(gòu)造病毒體代碼中用到的API的鏈接信息,它選擇運(yùn)用自己在運(yùn)行時(shí)直接定位API函數(shù)地址的代碼。

其實(shí)這些函數(shù)地址對(duì)于操作系統(tǒng)的某個(gè)版本是相對(duì)固定的,但病毒不能依賴(lài)于此。現(xiàn)在較為流行的做法是先定位包含API函數(shù)的動(dòng)態(tài)連接庫(kù)的裝入基址,然后在其導(dǎo)出段(Export Section)中尋找到需要的API地址。后面一步幾乎沒(méi)有難度,只要你熟悉導(dǎo)出段結(jié)構(gòu)即可。關(guān)鍵在于第一步--確定DLL裝入地址。其實(shí)系統(tǒng)DLL裝入基址對(duì)于操作系統(tǒng)的某個(gè)版本也是固定的,但病毒為確保其穩(wěn)定性仍不能依賴(lài)這一點(diǎn)。目前病毒大都利用一個(gè)叫做結(jié)構(gòu)化異常處理的技術(shù)來(lái)捕獲病毒體引發(fā)的異常。這樣一來(lái)病毒就可以在一定內(nèi)存范圍內(nèi)搜索指定的DLLDLL使用PE格式,頭部有固定標(biāo)志),而不必?fù)?dān)心會(huì)因引發(fā)頁(yè)面錯(cuò)誤而被操作系統(tǒng)殺掉。

由于異常處理和后面的反虛擬執(zhí)行技術(shù)密切相關(guān),所以特將結(jié)構(gòu)化異常處理簡(jiǎn)單解釋如下:

共有兩類(lèi)異常處理:最終異常處理每線(xiàn)程異常處理

其一:最終異常處理

當(dāng)你的進(jìn)程中無(wú)論哪個(gè)線(xiàn)程發(fā)生了異常,操作系統(tǒng)將調(diào)用你在主線(xiàn)程中調(diào)用SetUnhandledExceptionFilter建立的異常處理函數(shù)。你也無(wú)須在退出時(shí)拆去你安裝的處理代碼,系統(tǒng)會(huì)為你自動(dòng)清除。

PUSH OFFSET FINAL_HANDLER

CALL SetUnhandledExceptionFilter

……

CALL ExitProcess

************************************

FINAL_HANDLER:

……

;(eax=-1 reload context and continue)

MOV EAX,1

RET program entry point

……

code covered by final handler

……

code to provide a polite exit

……

eax=1 stops display of closure box

eax=0 enables display of the box

其二:每線(xiàn)程異常處理

FS中的值是一個(gè)十六位的選擇子,它指向包含線(xiàn)程重要信息的數(shù)據(jù)結(jié)構(gòu)TIB,線(xiàn)程信息塊。其的首雙字節(jié)指向我們稱(chēng)為ERR的結(jié)構(gòu):1st dword +0 pointer to next err strUCture (下一個(gè)err結(jié)構(gòu)的指針)2nd dword +4 pointer to own exception handler (當(dāng)前一級(jí)的異常處理函數(shù)的地址)所以異常處理是呈練狀的,如果你自己的處理函數(shù)捕捉并處理了這個(gè)異常,那么當(dāng)你的程序發(fā)生了異常時(shí),操作系統(tǒng)就不會(huì)調(diào)用它缺省的處理函數(shù)了,也就不會(huì)出現(xiàn)一個(gè)討厭的執(zhí)行了非法操作的紅叉。

下面是cih的異常段:

MyVirusStart:

push ebp

lea eax, [esp-04h*2]

xor ebx, ebx

xchg eax, fsebx] ;交換現(xiàn)在的err結(jié)構(gòu)和前一個(gè)結(jié)構(gòu)的地址

eax=前一個(gè)結(jié)構(gòu)的地址

fs0]=現(xiàn)在的err結(jié)構(gòu)指針(在堆棧上)

call @0

@0:

pop ebx

lea ecx, StopToRunVirusCode-@0[ebx] ;你的異常處理函數(shù)的偏移

push ecx ;你的異常處理函數(shù)的偏移壓棧

push eax ;前一個(gè)err結(jié)構(gòu)的地址壓棧

;構(gòu)造err結(jié)構(gòu),記這時(shí)候的esp(err結(jié)構(gòu)指針)esp0

……

StopToRunVirusCode:

@1 = StopToRunVirusCode

xor ebx, ebx ;發(fā)生異常時(shí)系統(tǒng)在你的練前又加了一個(gè)err結(jié)構(gòu),

;所以要先找到原來(lái)的結(jié)構(gòu)地址

mov eax, fsebx] 取現(xiàn)在的err結(jié)構(gòu)的地址eax

mov esp, [eax] 取下個(gè)結(jié)構(gòu)地址即eps0esp

RestoreSE: ;沒(méi)有發(fā)生異常時(shí)順利的回到這里,你這時(shí)的esp為本esp0

pop dword ptr fsebx] ;彈出原來(lái)的前一個(gè)結(jié)構(gòu)的地址到fs:0

pop eax ;彈出你的異常處理地址,平棧而已

?

1.2.7病毒隱藏

實(shí)現(xiàn)進(jìn)程或模塊隱藏應(yīng)該是一個(gè)成功病毒所必須具備的特征。在WIN9XKernel32.dll有一個(gè)可以使進(jìn)程從進(jìn)程管理器進(jìn)程列表中消失的導(dǎo)出函數(shù)RegisterServiceProcess ,但它不能使病毒逃離一些進(jìn)程瀏覽工具的監(jiān)視。但當(dāng)你知道這些工具是如何來(lái)枚舉進(jìn)程后,你也會(huì)找到對(duì)付這些工具相應(yīng)的辦法。進(jìn)程瀏覽工具在WIN9X下大都使用一個(gè)叫做ToolHelp32.dll的動(dòng)態(tài)連接庫(kù)中的Process32FirstProcess32Next兩個(gè)函數(shù)來(lái)實(shí)現(xiàn)進(jìn)程枚舉的;而在WINNT/2000里也有PSAPI.DLL導(dǎo)出的EnumProcess可用以實(shí)現(xiàn)同樣之功能。所以病毒就可以考慮修改這些公用函數(shù)的部分代碼,使之不能返回特定進(jìn)程的信息從而實(shí)現(xiàn)病毒的隱藏。但事情遠(yuǎn)沒(méi)有想象中那么簡(jiǎn)單,俗話(huà)說(shuō)道高一尺,魔高一丈,此理不謬。由于現(xiàn)在很多逆項(xiàng)工程師的努力,微軟力圖隱藏的許多秘密已經(jīng)逐步被人們所挖掘出來(lái)。當(dāng)然其中就包括WINDOWS內(nèi)核使用的管理進(jìn)程和模塊的內(nèi)部數(shù)據(jù)結(jié)構(gòu)和代碼。比如WINNT/2000用由ntoskrnl.exe導(dǎo)出的內(nèi)核變量PsInitialSystemProcess所指向的進(jìn)程Eprocess塊雙向鏈表來(lái)描述系統(tǒng)中所有活動(dòng)的進(jìn)程。如果進(jìn)程瀏覽工具直接在驅(qū)動(dòng)程序的幫助下從系統(tǒng)內(nèi)核空間中讀出這些數(shù)據(jù)來(lái)枚舉進(jìn)程,那么任何病毒也無(wú)法從中逃脫。有關(guān)Eprocess的具體結(jié)構(gòu)和功能,請(qǐng)參看David A.SolomonMark E.Russinovich的《InsideWindows2000》第三版。

?

1.2.8病毒特殊感染法

對(duì)病毒稍微有些常識(shí)的人都知道,普通病毒是通過(guò)將自身附加到宿主尾部(如此一來(lái),宿主的大小就會(huì)增加),并修改程序入口點(diǎn)來(lái)使病毒得到擊活。但現(xiàn)在不少病毒通過(guò)使用特殊的感染技巧能夠使宿主大小及宿主文件頭上的入口點(diǎn)保持不變。附加了病毒代碼卻使被感染文件大小不變聽(tīng)起來(lái)讓人不可思議,其實(shí)它是利用了PE文件格式的特點(diǎn):PE文件的每個(gè)節(jié)之間留有按簇大小對(duì)齊后的空洞,病毒體如果足夠小則可以將自身分成幾份并分別插入到每個(gè)節(jié)最后的空隙中,這樣就不必額外增加一個(gè)節(jié),因而文件大小保持不變。著名的CIH病毒正是運(yùn)用這一技術(shù)的典型范例(它的大小只有1K左右)。病毒在不修改文件頭入口點(diǎn)的前提下要想獲得控制權(quán)并非易事:入口點(diǎn)不變意味著程序是從原程序的入口代碼處開(kāi)始執(zhí)行的,病毒必須要將原程序代碼中的一處修改為導(dǎo)向病毒入口的跳轉(zhuǎn)指令。原理就是這樣,但其中還存在很多可討論的地方,如在原程序代碼的何處插入這條跳轉(zhuǎn)指令。一些查毒工具掃描可執(zhí)行文件頭部的入口點(diǎn)域,如果發(fā)現(xiàn)它指向的地方不正常,即不在代碼節(jié)而在資源節(jié)或重定位節(jié)中,則有理由懷疑文件感染了某種病毒。所以剛才討論那種病毒界稱(chēng)之為EPO(入口點(diǎn)模糊)的技術(shù)可以很好的對(duì)付這樣的掃描,同時(shí)它還是反虛擬執(zhí)行的重要手段。

另外值得一提的是現(xiàn)在不少病毒已經(jīng)支持對(duì)壓縮文件的感染。如Win32.crypto病毒就可以感染ZIPARJ RARACECAB 等諸多類(lèi)型的壓縮文件。這些病毒的代碼中含有對(duì)特定壓縮文件類(lèi)型解壓并壓縮的代碼段,可以先把壓縮文件中的內(nèi)容解壓出來(lái),然后對(duì)合適的文件進(jìn)行感染,最后再將感染后文件壓縮回去并同時(shí)修改壓縮文件頭部的校驗(yàn)和。目前不少反病毒軟件都支持查多種格式的壓縮文件,但對(duì)有些染毒的壓縮文件無(wú)法殺除。原因我想可能是怕由于某種緣故,如解壓或壓縮有誤,校驗(yàn)和計(jì)算不對(duì)等,使得清除后壓縮文件格式被破壞。病毒卻不用對(duì)用戶(hù)的文件損壞負(fù)責(zé),所以不存在這種擔(dān)心。?

總結(jié)

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

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