專利名稱:一種繞過掛鉤的方法和裝置的制作方法
技術(shù)領(lǐng)域:
本發(fā)明涉及計算機(jī)安全技術(shù),尤其涉及一種繞過掛鉤的方法和裝置。
背景技術(shù):
計算機(jī)及網(wǎng)絡(luò)技術(shù)的迅猛發(fā)展極大地促進(jìn)了信息交互。但是,與 此同時,計算機(jī)病毒也伴隨技術(shù)的發(fā)展而不斷地演化更新,從初期的 惡作劇游戲發(fā)展到今日,計算機(jī)病毒已經(jīng)嚴(yán)重威脅到了人們對計算機(jī) 的正常使用。由此,如何防范病毒侵襲已然成為人們關(guān)注的一個焦點。
隨著病毒檢測技術(shù)的發(fā)展,病毒與殺毒軟件的對抗手段也不斷地
更新,Rootkit技術(shù)應(yīng)運而生。目前的Rootkit主要為惡意程序提供隱 藏文件、注冊表、進(jìn)程、模塊等功能,而實現(xiàn)這一系列隱藏功能最常 用的方法就是掛鉤系統(tǒng)調(diào)用。
掛鉤(Hooking)是一種修改執(zhí)行路徑的技術(shù),通過修改正常的 調(diào)用流程來激活鉤子處理函數(shù)。這種技術(shù)被安全軟件和惡意程序廣泛 地使用。不同的是,安全軟件通過掛鉤來實現(xiàn)監(jiān)控等技術(shù),而惡意程 序則通過掛鉤來實現(xiàn)隱藏等惡意行為。當(dāng)前有兩種常用的掛鉤方法。
第一種方法是基于地址替換的掛鉤方法。如果在內(nèi)存中某個位置 以某種格式存放著一個函數(shù)地址,那么可以通過把這個地址替換為鉤 子處理函數(shù)的地址來實現(xiàn)掛鉤。使用這種方法最典型的有IAT掛鉤、 IDT掛鉤(修改描述符中的異常處理地址)等。
第二種方法是基于指令替換的掛鉤方法?;谥噶钐鎿Q的掛鉤方 法是指通過修改執(zhí)行路徑上的一條或幾條指令來達(dá)到跳轉(zhuǎn)到鉤子處 理函數(shù)地址的掛鉤方式。最常見的基于指令替換的鉤子是修改函數(shù)入 口的5個字節(jié)為jmp,這樣當(dāng)該函數(shù)被調(diào)用時便會跳轉(zhuǎn)到其鉤子處理 函數(shù)中?;谥噶钐鎿Q的掛鉤方式比較通用,但不如地址替換的掛鉤方式 穩(wěn)定。 一般安全軟件多以地址替換的掛鉤方式為主了,而惡意軟件則 多用指令替換的掛鉤方法。
目前的安全類軟件在面對惡意軟件的鉤子時, 一般會采取以下三 種方式來繞過。
第一種繞過方式是選擇更為底層的API進(jìn)行調(diào)用。比如發(fā)現(xiàn) nt!NtCreateFile被掛鉤后選擇更為底層的nt!IoCreateFile進(jìn)行調(diào)用。然 而,底層是一個相對的概念,安全軟件可以選擇更為底層一些的調(diào)用, 惡意程序同樣可以,所以這并不能成為一個有效解決方案。
第二種繞過方式是直接恢復(fù)鉤子。比如發(fā)現(xiàn)nt!NtCreateFile的入 口被掛鉤,便從ntoskrnl.exe中定位到nt!NtCreateFile的代碼,并把 入口的代碼直接復(fù)制到內(nèi)存中的nt!NtCreateFile入口處,然后再進(jìn)行 調(diào)用,這樣原來的鉤子就完全失效了。這種方法也可以恢復(fù)基于地址 替換的鉤子。然而,直接恢復(fù)內(nèi)存中的鉤子是非常蠻橫的一種做法, 因為程序是無法清晰地區(qū)分一個鉤子是安全軟件掛接的還是惡意程 序掛接的。所以在恢復(fù)惡意程序的鉤子的同時,極有可能把一些安全 軟件的鉤子也一并恢復(fù)掉,這會使得某些安全軟件部分功能受到影響 或功能完全失效,反而會給系統(tǒng)帶來額外的威脅。另外,內(nèi)存中恢復(fù) 這些可重入的函數(shù)在多CPU系統(tǒng)是非常不穩(wěn)定的。
第三種繞過方式是抽取部分指令做trampoline。比如發(fā)現(xiàn) nt!NtCreateFile的入口代碼被掛鉤,便從ntoskrnl.exe中定位到 nt!NtCreateFile的代碼并把入口的幾個字節(jié)(這里不妨假設(shè)是5個) 復(fù)制到一個緩沖區(qū)中,并在后面添加一條指令:jmpnt!NtCreateFile+5, 這樣就構(gòu)造了一個trampoline,從而直接調(diào)用該trampoline就可以繞 過函數(shù)入口的鉤子。這種方法在這三種方式中是相對最好的,因為這 種方法并不直接恢復(fù)指令,所以既不會出現(xiàn)多CPU上的重入不穩(wěn)定 性又不會影響其他安全軟件的功能。然而,這種繞過方法的缺點也是 顯而易見的如果鉤子修改的指令比較多,那么就需要抽取至少同樣 多的指令,這時就不可避免地遇到一些帶有相對偏移的跳轉(zhuǎn)指令,這 時指令抽取的復(fù)雜度就極大地增加了 ,絕大多數(shù)情況會導(dǎo)致抽取的指令執(zhí)行異常。
由于惡意程序的掛鉤不僅給用戶發(fā)現(xiàn)病毒、清除病毒帶來了很大 的困難,而且也給安全軟件的掃描帶來了更大的挑戰(zhàn),所以,迫切需 要一種安全的繞過惡意程序掛鉤的方法來解決這類問題。
發(fā)明內(nèi)容
本發(fā)明的目的在于提供一種繞過掛鉤的方法和裝置,其能夠繞過 惡意程序和其他程序的掛鉤。
為了實現(xiàn)本發(fā)明的目的,按照本發(fā)明的一種繞過掛鉤的方法,包 括步驟
在內(nèi)存中已存在程序模塊的原始映像的情況下,在所述內(nèi)存中加
載所述程序模塊的另一映像;
計算所述另一映像與所述原始映像之間的基址差;以及 計算所述原始映像的函數(shù)的地址與所述基址差之和,作為所述另
一映像的函數(shù)的地址。
為了實現(xiàn)本發(fā)明的目的,按照本發(fā)明的一種繞過掛鉤的裝置,包
括
加載模塊,用于在內(nèi)存中已存在程序模塊的原始映像的情況下, 在所述內(nèi)存中加載所述程序模塊的另一映像;
基址差計算模塊,用于計算所述另一映像與所述原始映像之間的 基址差;以及
地址計算模塊,用于計算所述原始映像的函數(shù)的地址與所述基址 差之和,作為所述另一映像的函數(shù)的地址。
圖1示出了程序模塊的原始映像和Shadow映像的函數(shù)調(diào)用示意 圖。 , 圖2示出了本發(fā)明一個實施例的繞過掛鉤的方法流程示意圖。圖3示出了本發(fā)明一個實施例的繞過掛鉤的裝置示意圖。 優(yōu)選實施方式
本發(fā)明用于繞過掛鉤的方法稱為Shadow映像法,其核心思想是:
在內(nèi)存中己存在程序模塊的一個映像(稱作原始映像)的情況下,在
內(nèi)存中再加載該程序模塊的另一映像(稱作shadow映像),然后,計 算該程序模塊的shadow映像與該程序模塊的原始映像之間的基址 差,最后,計算原始映像中的函數(shù)的地址與基址差之和,作為該程序 模塊的函數(shù)的地址,這樣,對程序模塊的函數(shù)的調(diào)用都是從該程序模 塊的shadow映像而不是從該程序模塊的原始映像中進(jìn)行調(diào)用,從而 就繞過了惡意程序或其他程序在該程序模塊的原始映像中的掛鉤。
圖1示出了程序模塊的原始映像和Shadow映像的函數(shù)調(diào)用示意 圖。從圖1中可以看出,對于常規(guī)調(diào)用,例如調(diào)用程序模塊ntoskml.exe 中的函數(shù)nt!NtCreateFile將調(diào)用程序模塊ntoskrnl.exe的原始映像中 的函數(shù)nt!NtCreateFile,這樣,如果程序模塊ntoskml.exe的原始映像 中的函數(shù)nt!NtCreateFile已經(jīng)被掛鉤,那么這個鉤子不會受到任何影 響,將會發(fā)揮作用。
然而,在本發(fā)明中,通過在內(nèi)存中加載程序模塊ntoskml.exe的 shadow映{象shadow ntoskrnl.exe,這是一個禾口禾呈序模塊ntoskml.exe 的原始映像幾乎相同的映像,那么對程序模塊ntoskml.exe中的函數(shù) nt!NtCreateFile的調(diào)用可以通過對shadow映像shadowntoskrnl.exe中 的函數(shù)nt!NtCreateFile (即圖中的shadowed nt!NtCreateFile)的調(diào)用 來實現(xiàn)。
基于這樣的設(shè)計,如果可以保證程序模塊ntoskml.exe的shadow 映像shadow ntoskml.exe是干凈的、未被掛鉤的,那么對程序模塊 ntoskml.exe的shadow映像的API函數(shù)(即圖中的shadowed API)的 調(diào)用就可以認(rèn)為是可靠的。
這不僅對程序模塊ntoskml.exe是這樣,對其他的程序模塊逸這樣。下面以PE格式的程序模塊A為例,結(jié)合圖2所示的流程示意圖, 詳細(xì)描述本發(fā)明一個實施例的繞過掛鉤的方法。以下以A來表示原 始映像;A'來表示shadow映像。
如圖2所示,首先,根據(jù)模塊A中的節(jié)表來確定映像A'的大小 (步驟SIO)。然后,根據(jù)所確定的大小,在虛擬內(nèi)存中為映像A'分 配虛擬內(nèi)存(步驟S20)。接著,根據(jù)模塊A的節(jié)表中所描述的各個 節(jié)數(shù)據(jù)或代碼的位置,在該分配的虛擬內(nèi)存的相應(yīng)位置中,為映像A' 填充各個節(jié)數(shù)據(jù)(步驟S30)。
然后,在模塊A引入其他程序模塊的導(dǎo)出函數(shù)的情況下,在A' 的函數(shù)導(dǎo)入表中填充所引入的其他程序模塊的導(dǎo)出函數(shù)地址(步驟 S40)。其中,為了確保安全地繞過掛鉤,需要按照本發(fā)明的方法遞歸 地加載各個需要引入的模塊的shadow映像。
接下來,基于映像A的基址來重定位映像A,(步驟S50),具體 的重定位處理在下面詳細(xì)說明。
上述步驟S10- S50構(gòu)成了程序模塊A的shadow映像A'的加載 過程。
然后,計算映像A'與映像A之間的基址差(步驟S60)。 最后,計算程序映像A的函數(shù)的地址與基址差之和,作為映像A' 的函數(shù)的地址(步驟S70)。
下面,詳細(xì)描述程序模塊A的shadow映像A'的重定位處理。 shadow映像的重定位處理是本發(fā)明的一個關(guān)鍵技術(shù)特征。通常 情況下,在內(nèi)存中加載程序模塊的映像時會根據(jù)該映像在內(nèi)存中的基 址來重定位該映像的代碼對絕對地址的引用,以使該映像中的代碼可 以正確地引用絕對地址上的數(shù)據(jù)。然而,程序模塊的shadow映像比 較特殊,因為它被加載的目的是為了得到一份原始的且沒有被掛鉤的 代碼,然而在程序模塊的shadow映像載入到內(nèi)存之前,與其對應(yīng)的 程序模塊的原始映像已經(jīng)加載到內(nèi)存中并完成了初始化。在這"情況 下,如果調(diào)用shadow映像的初始化代碼來對shadow模塊進(jìn)行初始化,則在很多情況下會出現(xiàn)問題。比如,在內(nèi)存中已經(jīng)存在程序模塊
ntoskrnl.exe的原始映像的情況下,對程序模塊ntoskrnl.exe的shadow 映像進(jìn)行初始化是不會成功的。因此,如果按照常規(guī)重定位方法來重 定位shadow映像,則調(diào)用shadow映像中的函數(shù)就會因為引用了未被 初始化的數(shù)據(jù)而產(chǎn)生異常。
在本發(fā)明的一個實施例中,基于程序模塊A的原始映像的基址 來對程序模塊A的shadow映像A'進(jìn)行重定位,以解決上述問題。下 面以一個簡單例子來進(jìn)行說明。
假設(shè)程序模塊A的原始映像的基址是0x01000000,即被加載到 內(nèi)存的地址0x01000000處,且程序模塊A的原始映像有如下代碼
mov eax, dword ptr [ 0x01002040 ]
mov dword ptr [ ebx ], eax
這段代碼引用了絕對地址0x01002040,并把絕對地址
寫入到地址[ebx]中。
當(dāng)程序模塊A的shadow映像A,加載到內(nèi)存地址0x11000000 處時,如果按照常規(guī)重定位方法來處理程序模塊A的shadow映像 A',則在程序模塊A的shadow映像A,中上面這兩條指令會被修正 為-
mov eax, dword ptr [ Ox 11002040 ] mov dword ptr [ ebx ], eax
由于無法再次初始化程序模塊A的shadow映像A',所以當(dāng)執(zhí) 行到程序模塊A的shadow映像A,中的這兩條指令時,由于地址 0x11002040處的數(shù)據(jù)可能是無效的,所以這就很有可能會引發(fā)異常。
然而,在本發(fā)明中根據(jù)程序模塊A的原始映像的基址來重定位 程序模塊A的shadow映像A,,所以在程序模塊A的shadow映像 A,中上面這兩天指令被修正為
mov eax, dword ptr [ 0x01002040 ]
mov dword ptr [ ebx ], eax
這樣程序模塊A的shadow映像A,就可以引用程序模塊A的 原始映像的全局?jǐn)?shù)據(jù)了,這樣既保證了全局的數(shù)據(jù)的唯一性,又安全地繞過了程序模塊A的原始映像中可能存在的鉤子。
圖3示出了本發(fā)明一個實施例的繞過掛鉤的裝置示意圖。如圖所
示,該繞過掛鉤的裝置IO包括加載模塊101,用于在內(nèi)存中已存
在程序模塊的原始映像的情況下,在所述內(nèi)存中加載所述程序模塊的
另一映像;基址差計算模塊103,用于計算所述另一映像與所述原始 映像之間的基址差;以及,地址計算模塊105,用于計算所述原始映 像的函數(shù)的地址與所述基址差之和,作為所述另一映像的函數(shù)的地 址。
其中,加載模塊101進(jìn)一步包括確定模塊201,用于確定所述 另一映像的大??;分配模塊203,用于根據(jù)所述確定的大小,給所述 另一映像分配虛擬內(nèi)存;寫入模塊205,用于在所述分配的虛擬內(nèi)存 中寫入所述另一映像的各個節(jié)數(shù)據(jù),以及當(dāng)所述另一映像存在函數(shù)導(dǎo) 入表時在所述另一映像的函數(shù)導(dǎo)入表中寫入所述另一映像引用的各 個函數(shù)地址;以及,重定位模塊207,用于基于所述原始映像的基址, 重定位所述另一映像。
雖然在上面實施例中,以PE格式的程序模塊為例描述了本發(fā)明,
但是本發(fā)明并不局限用于PE格式的程序模塊。實際上,本發(fā)明也可
以用于其它格式的程序模塊,例如ELF格式的程序模塊。
本領(lǐng)域技術(shù)人員應(yīng)當(dāng)理解, 一些二進(jìn)制映像不包含函數(shù)導(dǎo)入表, 甚至一些二進(jìn)制映像格式在設(shè)計上本身就不存在函數(shù)導(dǎo)入表,所以程
序模塊的shadow映像的加載過程相應(yīng)地沒有包括在shadow映像的函 數(shù)導(dǎo)入表中填充所引入的函數(shù)地址的這一步驟。
本領(lǐng)域技術(shù)人員應(yīng)當(dāng)理解,本發(fā)明不但可以應(yīng)用于WINDOWS 操作系統(tǒng),而且也可以應(yīng)用于諸如UNIX、LINUX等這樣的操作系統(tǒng)。
本領(lǐng)域技術(shù)人員應(yīng)當(dāng)理解,本發(fā)明所公開的繞過掛鉤的方法和裝 置,可以在不偏離發(fā)明實質(zhì)的情況下,做出各種修改和變形。因此, 本發(fā)明的保護(hù)范圍由所附的權(quán)利要求書來確定。
權(quán)利要求
1、一種繞過掛鉤的方法,包括步驟在內(nèi)存中已存在程序模塊的原始映像的情況下,在所述內(nèi)存中加載所述程序模塊的另一映像;計算所述另一映像與所述原始映像之間的基址差;以及計算所述原始映像的函數(shù)的地址與所述基址差之和,作為所述另一映像的函數(shù)的地址。
2、 如權(quán)利要求l所述的方法,其中,所述加載步驟進(jìn)一步包括: 確定所述另一映像的大?。桓鶕?jù)所述確定的大小,給所述另一映像分配虛擬內(nèi)存;以及 在所述分配的虛擬內(nèi)存中寫入所述另 一 映像的各個節(jié)數(shù)據(jù)。
3、 如權(quán)利要求2所述的方法,其中,所述加載步驟還包括 基于所述原始映像的基址,重定位所述另一映像。
4、 如權(quán)利要求2所述的方法,其中,當(dāng)所述另一映像中存在函 數(shù)導(dǎo)入表時,所述加載步驟還包括在所述另一映像的函數(shù)導(dǎo)入表中寫入所述另一映像引入的各個 函數(shù)地址。
5、 一種繞過掛鉤的裝置,包括加載模塊,用于在內(nèi)存中已存在程序模塊的原始映像的情況下, 在所述內(nèi)存中加載所述程序模塊的另 一 映像;基址差計算模塊,用于計算所述另一映像與所述原始映像之間的 基址差;以及地址計算模塊,用于計算所述原始映像的函數(shù)的地址與所述基址 差之和,作為所述另一映像的函數(shù)的地址。
6、 如權(quán)利要求5所述的裝置,其中,所述加載模塊進(jìn)一步包括-確定模塊,用于確定所述另一映像的大小;分配模塊,用于根據(jù)所述確定的大小,給所述另一映像分配虛擬 內(nèi)存;寫入模塊,用于在所述分配的虛擬內(nèi)存中寫入所述另一映像的各 個節(jié)數(shù)據(jù);以及重定位模塊,用于基于所述原始映像的基址,重定位所述另一映像。
7、 如權(quán)利要求6所述的裝置,其中,當(dāng)所述另一映像中存在函 數(shù)導(dǎo)入表時,所述寫入模塊還用于在所述另一映像的函數(shù)導(dǎo)入表中寫 入所述另一映像引用的各個函數(shù)地址。
全文摘要
本發(fā)明涉及一種繞過掛鉤的方法和裝置,該方法包括在內(nèi)存中已存在程序模塊的原始映像的情況下,在所述內(nèi)存中加載所述程序模塊的另一映像;計算所述另一映像與所述原始映像之間的基址差;以及,計算所述原始映像的函數(shù)的地址與所述基址差之和,作為所述另一映像的函數(shù)的地址。本發(fā)明通過加載程序模塊的另一映像并調(diào)用該另一映像中的函數(shù),從而就繞過了惡意程序或其他程序在該程序模塊的原始映像中的掛鉤。
文檔編號G06F21/00GK101414338SQ200710162448
公開日2009年4月22日 申請日期2007年10月15日 優(yōu)先權(quán)日2007年10月15日
發(fā)明者軍 周 申請人:北京瑞星國際軟件有限公司