隨著NT內(nèi)核的大范圍普及(2000 / XP ......),一種新興的木馬——Rootkit型木馬誕生了。(Rootkit的本義并不指木馬,其意義與其本義相比有所引申,但是大量的木馬使用了Rootkit技術(shù))
當(dāng)時最具代表性的,在國外來說,是Hacker Defender(hxdef100),在國內(nèi)來說,則是大名鼎鼎的灰鴿子。
這類木馬的普遍特點是,能夠良好地隱藏自身,躲過常規(guī)分析手段和殺軟的檢測,包括注冊表關(guān)鍵位置隱藏,文件隱藏等等,這些木馬一度讓當(dāng)時的殺軟束手無策,用戶更是摸不著頭腦,因為常規(guī)檢測方法已經(jīng)無法發(fā)現(xiàn)它們了。
于是,一類叫作ARK的工具被發(fā)明了,ARK——Anti-Rookit,反Rootkit工具,當(dāng)時在國內(nèi)的代表是Icesword、DarkSpy等, 在國外則是 RootkitDetector等。這些ARK工具同樣使用了Rootkit技術(shù),于是能夠發(fā)現(xiàn)Rootkit木馬的蹤跡。而一些殺軟為了遏制 Rootkit木馬,也在自己的殺軟中應(yīng)用了Rootkit技術(shù)。同時,越來越復(fù)雜的文件加殼技術(shù)使傳統(tǒng)特征碼殺毒引擎捉襟見肘,許多殺軟一方面大力改進(jìn)啟發(fā)式引擎,一方面融入了最初的HIPS的雛形,即簡單的注冊表控制等功能。同時一些早期的HIPS工具也開始逐漸應(yīng)用Rootkit技術(shù),如 WinPatrol、SSM等等。
時至今日,Rootkit技術(shù)已經(jīng)廣泛應(yīng)用于木馬、安全軟件、流氓軟件中?,F(xiàn)代木馬幾乎全部是Rootkit木馬,而安全軟件也幾乎都應(yīng)用了Rootkit技術(shù),臭名昭著的某"XX上網(wǎng)"中也大量應(yīng)用了Rootkit技術(shù)。
以下的"現(xiàn)代木馬"均指Rootkit木馬.
----------------------------------------------------------------------
正文
現(xiàn)代木馬如何隱藏自身?HIPS如何監(jiān)視系統(tǒng)動作?
為了解釋這個問題,首先簡介一個概念:接口。
簡單介紹如下:
以家用電器為例,我們要用影碟機(jī)看電視的時候,只需要把影碟機(jī)的接口插到電視上去就行了,我們沒有必要知道接口接進(jìn)電視里面以后是怎么走線的,因此任何一個人都會使用影碟機(jī)。
如果沒有接口,那么用影碟機(jī)的人還得知道影碟機(jī)的線具體要插到哪塊電路板上,要不要濾波,要不要做其他處理,這樣的話,會用影碟機(jī)的人就沒有幾個了。
另一個例子,一個班主任帶領(lǐng)一個班。他想知道誰沒有交作業(yè),并不需要一本一本的去翻。他只需要找學(xué)習(xí)委員這個“接口”告訴他:“我要查作業(yè)”。然后,學(xué)習(xí)委員也不必自己親自一本本去翻,他只要告訴各科課代表這些“接口”,告訴他們:“你們?nèi)ソy(tǒng)計一下各科作業(yè)?!保骺普n代表再去告訴下一層接口——小組長們: “去檢查一下你們組的作業(yè)。”,小組長檢查完作業(yè)以后,把情況報告課代表,課代表報告學(xué)習(xí)委員,學(xué)習(xí)委員報告班主任。
這樣,班主任不費(fèi)力氣的就統(tǒng)計完了作業(yè),整個過程,每個人都只負(fù)責(zé)解釋上一層的命令給下一層,直到最底層去執(zhí)行命令。
那么現(xiàn)在開始簡介NT內(nèi)核:
拿我們常用的下載工具迅雷來說.如果沒有接口,當(dāng)迅雷儲存文件的時候,就要先把文件轉(zhuǎn)成2進(jìn)制,然后計算當(dāng)前可用的空間開始于磁盤的第幾柱面...第幾扇區(qū)之類的詳細(xì)信息,然后檢查分區(qū)的文件系統(tǒng)是什么,檢查完以后,針對相應(yīng)的文件系統(tǒng)采用不同的記錄方式,甚至需要檢查硬盤的品牌,然后使用對應(yīng)的控制電流來讓硬盤將指定區(qū)域的小磁塊磁化成"1"或者"0"
現(xiàn)在來看一幅Windows NT內(nèi)核的示意圖:
(細(xì)節(jié)部分并沒有詳細(xì)畫出,這幅圖畫出了Windows NT內(nèi)核操作系統(tǒng)中,應(yīng)用程序執(zhí)行某些操作時的基本流程圖)。
當(dāng)有了接口,迅雷只需要調(diào)用相應(yīng)的Win32 API,告訴系統(tǒng),文件的位置和內(nèi)容,然后Win32 API會被Windows系統(tǒng)繼續(xù)解釋成Native API,經(jīng)過內(nèi)核調(diào)用KiSystemService處理程序,在SSDT里找到NtWriteFile函數(shù)的位置,然后繼續(xù)調(diào)用,進(jìn)一步被解釋成驅(qū)動程序指令,傳遞給文件系統(tǒng)驅(qū)動(FSD), 在這之前,如果有過濾驅(qū)動,那么先通過過濾驅(qū)動,由過濾驅(qū)動一層層解釋給下一層,最后達(dá)到FSD層,之后被進(jìn)一步解釋,直至解釋成控制硬盤讀寫的電流.每個接口要做的都只是把上一層命令解釋給下一層接口,最終難以直接使用的電流控制可以用一條簡單易記的接口調(diào)用來實現(xiàn).因而編寫軟件才顯得如此容易.
再介紹一個概念:運(yùn)行級別(ring).在x86的處理器上(主要是IntelAMD的主流處理器),可以存在四個運(yùn)行級別ring0-3,Windows NT系列系統(tǒng)(XP/2003......)使用其中的兩個,就是ring3和ring0兩個級別,用戶程序運(yùn)行于ring3級別,而ring3級別的程序不被允許直接訪問硬件,這樣一方面也是為了防止程序錯誤的操作導(dǎo)致系統(tǒng)崩潰或者硬件故障.對應(yīng)的,系統(tǒng)內(nèi)核運(yùn)行于ring0級別,擁有對全部內(nèi)存區(qū)域的訪問特權(quán),也可以直接訪問硬件.
現(xiàn)在加入運(yùn)行級別的概念,再重新看一下這幅圖:
可能有些亂,我們來整理一下.(以下的"函數(shù)",通通替換為"功能",以方便理解.)
1.首先,應(yīng)用程序產(chǎn)生一個請求,比如他要修改注冊表,那么他調(diào)用Win32 API接口中的注冊表操作相關(guān)功能.(RegOpenKey等等),實質(zhì)是調(diào)用advapi32.dll中的相應(yīng)功能.
(Win32 API的功能主要位于kernel32.dll advapi32.dll user32.dll gdi32.dll等庫中)
2.advapi32.dll中的功能受到調(diào)用,于是他繼續(xù)解釋而調(diào)用ntdll.dll中的功能(Native API接口).
(Native API的所有功能封裝于ntdll.dll,但是ntdll.dll并不是真正的執(zhí)行者,他的任務(wù)只是將調(diào)用傳到內(nèi)核.)
3.ntdll.dll 中的功能受到調(diào)用(NtCreateKey等等),于是他把對應(yīng)的功能編號存入eax寄存器,然后使用SYSENTER指令,導(dǎo)致"自陷"(早期使用觸發(fā) Int 2e中斷的方式,不過他們的效果是一樣的),KiSystemService處理程序?qū)⑦\(yùn)行.
(這個就像你在銀行里取錢,你把存單放到玻璃下面的凹槽里去,然后叫柜員,他會把存單取走,然后給你錢,看起來是你取出了錢,但事實上是銀行內(nèi)部提出的錢.ntdll.dll就是取錢人,他把功能代號(存單)放到eax寄存器里(玻璃下方的凹槽),然后引發(fā)自陷以觸發(fā)KiSystemService(叫柜員),柜員就會去實際處理交易(執(zhí)行對應(yīng)功能).)
4.KiSystemService從eax寄存器里取出功能代號,在一種叫做SDT的結(jié)構(gòu)中查找對應(yīng)的Native API函數(shù),這種結(jié)構(gòu)在系統(tǒng)中一共有4個,其中一個叫做SSDT,位于ntoskrnl.exe(或者ntkrnlpa.exe)中,記錄了系統(tǒng)關(guān)鍵功能的位置,涉及文件操作,注冊表操作,進(jìn)程操作等.還有一個叫做Shadow SSDT,位于win32k.sys中,記錄了和用戶與圖形界面有關(guān)的功能,雖然都不是非常關(guān)鍵的功能,但也包括設(shè)置系統(tǒng)鉤子等比較"特殊"的功能,另外兩個SDT的位置則預(yù)留,也就是說,有人工創(chuàng)造SDT的可能.(不過這基本上是沒有意義的)
5.找到位置后調(diào)用該功能,也就是內(nèi)核中關(guān)于該功能的實際操作被執(zhí)行,當(dāng)然,之后還是一層又一層的接口,但通常情況下,這里已經(jīng)是易于控制的最后一層接口.(某些高級木馬使用了Object Hook,也就是說存在更底層的接口被控制的可能)對于注冊表操作,他們會被解釋成Cm****系列功能,當(dāng)然最后還是要變成文件操作.
6.最后對一類特殊的調(diào)用進(jìn)行解釋,那就是調(diào)用驅(qū)動程序?qū)ο?很多功能最后會涉及到硬件操作,比如寫文件.寫文件的時候,系統(tǒng)會調(diào)用文件系統(tǒng)驅(qū)動(FSD), 如果之前有文件系統(tǒng)過濾驅(qū)動(FSD FilterDriver),那么會先通過文件系統(tǒng)過濾驅(qū)動,并經(jīng)由他們層層解釋后,最后傳給底層文件系統(tǒng)驅(qū)動(FSD),FSD是易于控制文件操作的最低一層接口.前面那個例子中,注冊表修改的操作最終被解釋為寫文件的操作(因為修改注冊表的本質(zhì)是修改Hive文件),也要經(jīng)過FSD,并經(jīng)由FSD進(jìn)一步解釋,繼續(xù)傳遞給下一層接口.
這樣就明白了,在這些調(diào)用的傳遞過程中,任何一個環(huán)節(jié)遭到了阻斷都有可能導(dǎo)致失敗.而通過"掛鉤"這些關(guān)鍵功能,就可以實現(xiàn)對這些功能的控制.
掛鉤有很多方式,但是目的只有一個,就是---比原功能更早獲得通知,然后自行決定要不要繼續(xù)把他傳遞下去,或者自行決定要不要把包含不利信息的結(jié)果傳遞回去.
(就相當(dāng)于你冒充學(xué)習(xí)委員,班主任讓你查作業(yè),你讓真正的學(xué)習(xí)委員去查作業(yè),真正的學(xué)習(xí)委員給你報了一串名單,里面有你,你把自己的名字去掉,再交給班主任.這樣就可以躲過檢查.)
比如現(xiàn)代木馬隱藏自身,他們可以修改SSDT中的文件操作功能的位置(Nt****File系列功能),讓他們指向自己,然后自己再調(diào)用真正的文件操作功能,返回信息時,他們只要把其中包含自身的信息抹掉即可.如圖,當(dāng)這樣調(diào)用結(jié)果返回給應(yīng)用程序時,其中并不包含自己(灰鴿子),應(yīng)用程序自然也就不知道灰鴿子的存在了.
設(shè)置"鉤子"的位置很多,可以選擇Win32 API下鉤,可以選擇掛鉤ntdll.dll中的函數(shù),但這是不保險的,因為他們都處于ring3級別(想起來我們的圖了么?),也就是說,你設(shè)置的鉤子可以被一個普通程序輕易繞過,或者消除.
所以大多數(shù)人選擇在SSDT/Shadow SSDT下掛鉤,或者安裝文件過濾驅(qū)動等等,這些動作受到ring0保護(hù),普通程序無法查知,也無法修改.(更高級的還有Object Hook)
同理,HIPS類軟件使用和現(xiàn)代木馬一樣的手段,實現(xiàn)對于關(guān)鍵動作的監(jiān)控.