孟晨宇 阮陽 王佳偉 周潔 康曉鳳
摘要:進程(Process)是操作系統(tǒng)進行資源分配和調(diào)度的基本單位,是Windows系列操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)。進程隱藏雖然能夠為計算機取證提供便利,但是增加了檢測系統(tǒng)中運行的惡意代碼的難度。在深入研究Windows進程隱藏技術(shù)的基礎(chǔ)上,針對常用進程隱藏技術(shù)的特點,提出幾種Windows操作系統(tǒng)下檢測隱藏進程的方法。這些方法能夠準確、快速地檢測操作系統(tǒng)中隱藏的進程。
關(guān)鍵詞:系統(tǒng)內(nèi)核安全;進程隱藏;進程檢測;Rootkit
DOIDOI:10.11907/rjdk.161009
中圖分類號:TP306+.2
文獻標識碼:A 文章編號:1672-7800(2016)005-0188-03
0 引言
Rootkit是一個功能強大的工具包。它由一些小程序組成,能夠使攻擊者持續(xù)隱蔽地訪問計算機上的“root”用戶。即Rootkit是能夠持久、隱蔽、且可靠地運行于計算機上的一組程序或代碼。在上述Rootkit描述中關(guān)鍵詞是“隱蔽”,即隱藏代碼和數(shù)據(jù),其中進程隱藏是Windows Rootkit技術(shù)中典型的一種。對于一些計算機取證工具來說,進程隱藏能夠為其帶來便利,同時將系統(tǒng)中的防護進程隱藏起來,也可以阻止惡意程序?qū)τ跉⒍拒浖母蓴_,使防護效果更加有效。但是進程隱藏技術(shù)也是一把雙刃劍,它能夠使惡意代碼潛行在內(nèi)核中,不被發(fā)現(xiàn),當隱藏技術(shù)被用于惡意代碼時,會給安全帶來毀滅性的打擊。所以,準確檢測出系統(tǒng)隱藏進程十分必要。
1 進程隱藏技術(shù)
Rootkit所采用的大部分技術(shù)和技巧都用于在計算機上隱藏代碼和數(shù)據(jù)。絕大多數(shù)Rootkit都可實現(xiàn)文件、目錄和進程等信息的隱藏[1]。從隱藏時采用的手段看,進程隱藏技術(shù)機理主要歸結(jié)為兩類:一是通過修改程序執(zhí)行,截獲所有訪問隱蔽資源的請求,稱為修改程序執(zhí)行路徑(Modify Execution Path,MEP)技術(shù);二是直接修改操作系統(tǒng)用于監(jiān)控系統(tǒng)資源的數(shù)據(jù),稱為直接內(nèi)核對象操作(Direct Kernel Object Manipulation DKOM)技術(shù)。這兩種機理分別對應(yīng)攔截掛鉤隱藏技術(shù)及直接修改內(nèi)核數(shù)據(jù)隱藏技術(shù)。
1.1 攔截掛鉤(MEP)隱藏技術(shù)
所謂攔截掛鉤技術(shù)即通過掛鉤系統(tǒng)函數(shù)或相關(guān)處理例程,使其先轉(zhuǎn)向事先編寫好的函數(shù)處理,實現(xiàn)過濾參數(shù)、修改目標函數(shù)處理結(jié)果、刪除特定進程信息,從而實現(xiàn)進程隱藏。按照掛鉤位置不同,掛鉤攔截技術(shù)可分為用戶態(tài)掛鉤和內(nèi)核態(tài)掛鉤兩類。用戶態(tài)鉤子屬于Windows操作系統(tǒng)3環(huán)(用戶態(tài))下的攔截。一般情況下,3環(huán)進程使用CreateToolhelp32Snapshot等函數(shù)查詢進程列表信息。Rootkit針對此類函數(shù)設(shè)置API鉤子,在API鉤子中刪除被掛鉤函數(shù)返回的特定進程信息,從而隱藏特定進程[2]。Windows平臺下的應(yīng)用程序一般都會調(diào)用Kernel32.dll中的相應(yīng)函數(shù),接著再跳轉(zhuǎn)到Ntdll.dll中的相關(guān)函數(shù),最后由Sysenter 或 int 2E指令使調(diào)用跳轉(zhuǎn)到內(nèi)核層,具體執(zhí)行過程如圖1實線部分所示。通過分析Windows API調(diào)用過程得知,也可以通過掛鉤Ntdll.dll中的ZwQuerySystemInformation更好地實現(xiàn)進程隱藏[3]。在Windows系統(tǒng)中,要列出系統(tǒng)正在運行的所有進程信息,3環(huán)下的程序最終都會調(diào)用Ntdll.dll中的ZwQuerySystemInformation,因此在所有進程中均對Ntdll.dll中的該函數(shù)掛鉤即可實現(xiàn)進程隱藏。該方法幾乎是用戶態(tài)掛鉤最有效的進程隱藏方式。
內(nèi)核態(tài)掛鉤常用的方法是掛鉤系統(tǒng)服務(wù)調(diào)用表(System Service Dispatch Table)即Hook SSDT,SSDT[4]表中的第一項是系統(tǒng)服務(wù)的索引號,第二項是索引對應(yīng)系統(tǒng)服務(wù)函數(shù)在Ntoskrnl.exe 進程空間中的地址。ZwQuerySystemInformation在SSDT中的索引號為0xAD,通過該索引找到對應(yīng)的函數(shù)地址,并將其修改為可過濾特定進程信息的函數(shù)地址,即可實現(xiàn)進程隱藏。
1.2 修改內(nèi)核數(shù)據(jù)(DKOM)隱藏技術(shù)
掛鉤的隱藏技術(shù)非常容易被檢測到,而DKOM直接操縱內(nèi)核數(shù)據(jù)隱藏進程極難檢測,是現(xiàn)階段隱藏進程最有效的方法。正常環(huán)境下,更改進程或者令牌等內(nèi)核對象時需要深入到內(nèi)核對象管理器中,而DKOM繞過對象管理器,從而繞過所有關(guān)于對象的常規(guī)檢測。Windows NT系列的操作系統(tǒng)利用可執(zhí)行對象EPROCESS[5]描述進程信息。進程對象EPROCESS中有LIST_ENTRY結(jié)構(gòu)成員,它包含指針FLINK和BLINK。這兩個指針分別指向當前進程描述符的前方進程和后方進程,該結(jié)構(gòu)將所有進程的EPROCESS結(jié)構(gòu)連接成一個雙向鏈表。通過遍歷EPROCESS結(jié)構(gòu)中的雙向鏈表,將需要隱藏進程的EPROCESS從鏈表中摘去,即可實現(xiàn)特定進程在操作系統(tǒng)中的隱藏[1]。從圖2定位進程鏈表路徑圖中可以看出PsGetCurrentProcess找到當前正在運行進程的ETHREAD指針,從ETHREAD結(jié)構(gòu)沿著KTHREAD結(jié)構(gòu)中的指針可以找到當前進程的EPROCESS結(jié)構(gòu),然后遍歷雙向鏈表,通過進程標識符(Process Identifier,PID)或進程名定位特定進程的EPROCESS結(jié)構(gòu),以達到定位進程路徑的目的,然后再將此進程的EPROCESS從雙向鏈表中摘除,摘除后該特定進程的運行不會受到特殊影響,直接使用操作系統(tǒng)提供的服務(wù)已無法發(fā)現(xiàn)該進程。
無論是掛鉤隱藏技術(shù),還是直接操縱內(nèi)核數(shù)據(jù)隱藏方式,都有一定弊端?,F(xiàn)階段,高效的進程隱藏方案往往結(jié)合掛鉤和直接操縱內(nèi)核數(shù)據(jù)兩種方法,通過交叉使用用戶態(tài)與內(nèi)核態(tài)的技術(shù),并利用其它輔助手段,如抹掉窗口標題等,從而實現(xiàn)進程隱藏??傊[藏進程技術(shù)的最終目的是使進程隱匿于系統(tǒng)之中,并對進程檢測造成一定干擾。
2 隱藏進程檢測技術(shù)
對于Windows平臺下的進程隱藏檢測技術(shù),常用的檢測方法有枚舉進程窗口、遍歷當前進程的句柄表、遍歷csrss.exe進程句柄指針和遍歷PspCidTable的句柄表等。
2.1 常規(guī)檢測技術(shù)
2.1.1 直接調(diào)用內(nèi)核函數(shù)
用戶態(tài)掛鉤技術(shù)通過掛鉤系統(tǒng)API函數(shù)或者Ntdll.dll中導(dǎo)出的函數(shù),消除相應(yīng)進程信息,從而實現(xiàn)特定進程隱藏。所以不調(diào)用系統(tǒng)在3環(huán)下設(shè)置的API來發(fā)送調(diào)用請求就能排除其掛鉤干擾[3]。3環(huán)直接調(diào)用內(nèi)核API是指不通過Ntdll.dll的跳轉(zhuǎn)直接進入內(nèi)核,調(diào)用相應(yīng)查詢函數(shù),用戶態(tài)內(nèi)核請求在Ntdll.dll中通過Sysenter或int 2E指令進入內(nèi)核。用戶態(tài)需要使用內(nèi)核函數(shù)枚舉系統(tǒng)進程時,可以直接通過Sysenter或int 2E指令偽造請求傳入內(nèi)核,其具體實現(xiàn)方式如圖1虛線所示。該方法可以檢測所有通過用戶態(tài)掛鉤技術(shù)隱藏的進程,但對于內(nèi)核掛鉤及直接操縱內(nèi)核數(shù)據(jù)隱藏方法并沒有明顯效果。
2.1.2 遍歷當前進程的句柄表
EPROCESS的地址加上0x0c4,就可以得到當前進程的句柄表。進程句柄表中包含HandleTableList雙鏈指針,遍歷雙鏈可以枚舉出除 Idle以外的所有進程信息,因此可以通過遍歷當前進程 EPROCESS中的句柄表雙鏈指針得到一組進程的映像。
2.1.3 遍歷PspCidTable的句柄表
PspCidTable是獨立的句柄表,不屬于任何進程,是內(nèi)核未導(dǎo)出的HANDLE_TABLE結(jié)構(gòu),通過它可以訪問系統(tǒng)的任何對象,它保存著所有進程對象指針。該句柄表在NT操作系統(tǒng)下采用動態(tài)分配的三層表結(jié)構(gòu)。首先使用一層表結(jié)構(gòu),如果線程和進程過多,則會啟用兩層表或三層表結(jié)構(gòu)。定位該表常用的方法是通過PsLookupProcessByProcessId。該函數(shù)內(nèi)部會引用PspCidTable,通過查找此函數(shù)的前幾十個字節(jié)找到 PspCidTable變量,即可找到PspCidTable的地址。此后,可通過EnumHandleProcedure或PsLookupProcessByProcessId遍歷該表直接枚舉進程,從而檢測出被隱藏的進程。
2.2 其它檢測技術(shù)
2.2.1 掛鉤SwapContext函數(shù)
Windows系統(tǒng)中每個線程上下文的切換都由內(nèi)核中的SwapContext函數(shù)來實現(xiàn)[6]。執(zhí)行函數(shù)時,ESI中存放的是即將被換出的當前線程指針,EDI中存放的是當前即將被換入的線程的指針。根據(jù)該原理,掛鉤此函數(shù),在鉤子函數(shù)中確認EDI所指向的線程中的KTHREAD是否指向一個位于正常雙向鏈表中的EPROCESS結(jié)構(gòu)。若不是,則表明該進程是一個被DKOM隱藏的進程。因為系統(tǒng)切換所有線程上下文都要使用SwapContext函數(shù),所以只要對該函數(shù)掛鉤,即可檢測隱藏進程。
2.2.2 遍歷csrss.exe進程句柄指針
Windows操作系統(tǒng)下子進程的服務(wù)進程Csrss.exe包含除 Idle、system、smss 以及 csrss 以外的所有進程信息。動態(tài)鏈接庫 Csrsvr.dll是其核心,幾乎所有與初始化進程相關(guān)的工作都是在其中執(zhí)行的[7]。Csrsvr.dll中擁有一個指針成員CsrRootProcess,該指針指向一個包含ListLink指針成員的結(jié)構(gòu)體CSR_PROCESS,指針ListLink將系統(tǒng)內(nèi)進程連接起來形成鏈表,遍歷整個鏈表即可得到所有進程的列表。獲取未導(dǎo)出指針CsrRootProcess的一種有效方法是通過函數(shù)CsrLockProcessByClientId,執(zhí)行時會在寄存器ESI中存入其值。導(dǎo)出函數(shù)的入口地址可以直接得到,在此基礎(chǔ)上加上相應(yīng)的偏移量就能讀出 CsrRootProcess 的地址。
3 結(jié)語
Windows平臺下的進程隱藏與檢測技術(shù)是相輔相成的。進程隱藏技術(shù)一直致力于抹除操作系統(tǒng)中的進程信息,同時干擾進程檢測的正常工作。由于進程與系統(tǒng)之間存在各種各樣的內(nèi)在聯(lián)系,通過挖掘這種聯(lián)系,進程檢測技術(shù)也能夠采用相應(yīng)的解決方案找到隱藏的進程。這兩種技術(shù)就是在這種矛盾中互相促進,逐步發(fā)展完善的。
參考文獻:
[1]GREG HOGLUND,JAMES BUTLER.Rootkits——Windows內(nèi)核的安全防護[M].韓志文,譯. 北京:清華大學(xué)出版社,2007.
[2]王雷,凌翔. Windows Rootkit進程隱藏與檢測技術(shù)[J].計算機工程,2010,36(5):144-142.
[3]潘愛民. Windows內(nèi)核原理與實現(xiàn)[M].北京:電子工業(yè)出版社,2010.
[4]BORATE M, DABAK P, PHADKE S. Undocumented Windows NT[M].New York, NY, USA: John Wiley & Sons, Inc., 1999.
[5]RUSSINOVICH M, SOLOMON D. Microsoft Windows internals[M].New York:Microsoft Press, 2005.
[6]林衛(wèi)亮,王軼駿,薛質(zhì).Win32 Rootkit 的進程隱藏檢測技術(shù)[J].信息安全與通信保密,2009(3):62-63.
[7]張登銀,陳召國.Windows平臺下Rootkit進程檢測[J].計算機技術(shù)與發(fā)展,2011,21(7):141-144.
(責任編輯:陳福時)