您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關內核級木馬有什么危害,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
內核級木馬一個無進程、無DLL、無啟動項的、集多種Rootkit技術特征的獨立功能遠程控制后門程序。其利用線程注射DLL到系統進程,解除DLL映射并刪除自身文件和啟動項,關機時恢復。它是內核級的木馬程序,主要部分工作在Ring0,因此有很強的隱蔽性和殺傷力。
目前,傳統應用層木馬由于當下一些主動防御軟件,殺毒的免費使用,各類反病毒工具對其技倆了如指掌,而木馬能帶來巨大危害的主要原因在其隱蔽性,各類反病毒工具的快速發展就導致木馬謀取利益的成本大幅度提高,其帶來的利益以及威脅程度呈現逐年下降的趨勢。由于傳統應用層木馬的隱蔽性大幅度下降,黑客為了提升帶來的效益以及獲得被控主機更加持久的控制權,因而提升木馬的隱藏技術就顯得更加迫在眉睫。
內核級木馬的隱藏主要使用內核Rootkit技術,內核Rootkit程序在使得遠程黑客能夠更長期的享有目標機器的底層系統控制權的同時在很大程度上不被殺毒軟件發現,從而對被控主機造成更加嚴重的安全威脅,此外內核Rootkit不僅僅存在于Windows系統中,同樣存在于LINUX等其他系統中。
而對于信息安全工作者,找出防御內核級木馬的最有效途徑自然是要深入了解內核木馬的工作機制,內核Rootkit攻擊技術,內核Rootkit隱藏技術,掌握其規律和特性,才能更好的找到應對此類木馬的措施,以及對未來可能出現的安全隱患做好一些提前的防備。
內核級木馬隱藏主要有進程隱藏,文件隱藏,自啟動隱藏,通信隱藏等,主要于木馬的架構有關,那么對于一些主從型內核級木馬,木馬涉及到的功能模塊越多自然對應涉及的隱藏項也就越多,甚至有時候還要做注冊表隱藏,服務隱藏等。
進程隱藏最初技術體系為最簡單的混淆字符隱藏,如系統進程名為svchost.exe,木馬進程名改為svch0st.exe隱藏,緊接著到注冊服務隱藏,dll注入隱藏。現在內核級木馬大部分通過進程控制塊中的活動進程鏈表(ActiveProcessLinks)中摘除自身來達到隱藏,或通過從PspCidTable表中摘除自身等方法來達到隱藏目的。
文件隱藏最初是通過存放于敏感目錄(系統目錄)并混淆文件名來實現,后來有些人通過掛鉤應用層上的FindFirstFile,FindNextFile等API來實現該目的,現在在內核層隱藏文件方法一般試用FSDHook或FSD Inline Hook來實現。
自啟動隱藏先后經歷了添加注冊表Run值,修改系統啟動文件,注冊為服務,修改定時程序,感染系統文件技術來實現,現在黑客開始關注于在硬盤固件,bios等地方做手腳來實現自啟動隱藏。
對于通信隱藏來說,現在有些研究者已經實現了NDIS小端口驅動層的隱藏,不過主流的木馬仍然在TDI層面上通信或者在NDIS中間層上通信。
應用層級隱藏技術由于處在ring3層,一般難以抵抗通過從內核層獲取相應的信息的一些軟件的檢測,而在內核級隱藏技術中,由于各種方案有著不同的特點、所要達到的目的不同因而這些方案所使用的隱藏技術也各有差異,這一節中,將重點分析內核級木馬可能用到的一些隱藏技術。
對于應用層級的木馬,自啟動的方法可謂是五花八門,有捆綁文件、修改注冊表項、加自啟動快捷方式等,但是安全軟件對應用層的檢查比較嚴格,雖說對于內核層的自啟動方法也有檢查,不過相對來說,內核級的自啟動一般要更有效一些。常見的內核級木馬自啟動方法主要有以下幾點:
(1)注冊為后臺服務
跟應層級木馬自啟動中的注冊為服務的原理一樣,只不過前者是將應用程序注冊為系統服務,這兒是把寫好的驅動程序注冊為系統服務,進而實現自啟動。這種方法主要是把驅動程序注冊為系統的一個服務(一般使用SCM ( Services Control Manager)接口來實現服務的安裝、啟動、停止等,使用這種方式加載的驅動程序是不可分頁的,不需要考慮分頁的問題,另外,一般也不會由于驅動的加載導致BSOD),在注冊表中生成[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\“ServiceName”]子鍵,再在其中設置好自己的一些啟動參數,如ImagePath等。普通的驅動程序一般就是采用這種方法加載的,內核級木馬的驅動模塊當然也可以使用這種方法,但由于涉及到在注冊表中插入鍵值,首先,在加載的時候可能被攔截,另外,若是加載成功了,也需要在后續的代碼中對該注冊表項和服務項做隱藏。
(2)使用Native API ZwSetSystemInformation()
該方法使用了未文檔化的API函數ZwSetSystemInformation(),可以在不創建注冊表鍵的情況下實現驅動的加載,但是由于驅動程序的分頁性,若在驅動運行過程中,通過該種方法加載的內核木馬驅動被頁換出,則對其的訪問就會導致BSOD[11]。因而,若要使用該種方案,還需針對分頁問題進行一定的設計,如migbot是通過將全部的操作代碼復制到不分頁的內存池來實現這個目的。
一般在應用層級實現的文件隱藏都是基于偽裝,而并不是真正意義上的隱藏,也可以說只是在視覺上欺騙了用戶,如將文件名修改為酷似系統文件的名字(通過使用一些易混淆的字符來實現)等。在內核中,可以通過修改文件操作時的內核處理流程來實現對文件的隱藏,進而使用戶無法在系統中通過工具(使用同種或更上層方法來枚舉文件的工具)來查看被隱藏的文件。常見的內核層的文件隱藏技術一般有一下幾種:
(1)Hook ZwQueryDirectoryFile()函數
在Windows中,實現文件的枚舉操作,最后都是調用Native API(in ntdll.dll)函數NtQueryDirectoryFile()來實現,接著通過中斷進入內核,進而通過查詢SSDT(System ServicesDescriptor Table,系統服務描述符表)表獲得相應的函數ZwQueryDirectoryFile()的地址,進而調用真正的函數執行體來完成對文件的枚舉。Hook SSDT表隱藏文件主要是篡改函數在SSDT表中的真實地址,讓程序在枚舉文件信息時首先進入修改后的地址對應的函數中執行,接著對待隱藏文件的信息進行過濾,讓應用層以及通過該種機制獲取文件信息的工具法枚舉到被隱藏的文件。
(2)文件過濾驅
1) 過濾驅動程序:
對于文件過濾驅動來說,主要是截獲上層文件操作請求,根據需要的功能做相應的處理。
2) 文件系統驅動程序(FSD,File System Driver):
它是Windows下標準的核心層驅動程序,主要負責處理用戶與磁盤等存儲介質之間的存儲信息以及維護各種文件系統(如FAT32、NTFS等)的磁盤結構。
3) 設備驅動程序:
主要是跟相應的硬件打交道,直接依附于相應的硬件設備。磁盤及其他的存儲驅動程序主要是實現存儲設備的管理、存儲等。通過文件過濾驅動實現文件的隱藏,主要是通過設置IRP_MJ_DIRECTORY_ CONTROL分發函數,并在其中設置回調函數,這樣發送給文件系統中卷設備的IRP,在從文件系統驅動返回時,將會觸發回調函數的執行,在回調函數中將需要過濾的文件從返回的FILE_BOTH_DIR_INFORMATION結構鏈表中刪除,這樣就可以實現對指定文件隱藏的功能。
內核級木馬在進程隱藏上,不斷發展了好多方法,不過從根本上來說,主要是通過鉤掛內核函數、修改內核返回信息(文件鏈表或句柄表)來實現進程隱藏的。主要的有內核掛鉤、DKOM技術、抹掉進程句柄等。
(1)內核掛鉤
SSDT實現了從用戶態函數到內核態函數的引導。當掛鉤 SSDT之后,進程枚舉、查詢類函數(一般都是掛鉤ZwQuerySystemInformation()函數)對應的內核服務函數在SSDT表中的地址被修改。這樣,當產生進程枚舉的調用時,就會運行修改后的函數,接著在修改后的函數中
首先獲取完整的進程信息,然后查找需要隱藏的進程信息,對其實行過濾,再把處理后的結果返回給上層,這樣就可以使最終的用戶層的用戶看不到隱藏后的進程。另外的一種內核鉤實現進程隱藏的方法是掛鉤IDT ( Interrupt Dispatch Table,中斷調度表)。在Windows系統中,用戶層的API函數都是通過軟中斷進入內核的。當軟中斷出現時,系統就會從IDT表中調用相應的中斷服務處理例程,對應INT 2E中斷的服務處理程序為KiSystemService()。該程序又會調用SSDT表中的函數實現最終的調用。因而,通過掛鉤IDT,修改中斷響應過程,就可以實現對進程信息的監視和修改,達到隱藏的目的。
(2)DKOM技術
DKOM(Direct Kernel ObjectManipulation,直接內核對象操作)實現進程隱藏使用的是另外一種機制。跟上面提到的內核鉤子相比,隱藏性更好,相比來說,一般也不容易被檢測到。說到使用該機制隱藏進程,不得不提到Windows下跟進程相關的一個數據結構EPROCESS。
在Windows中,使用雙向鏈表的典型示例就是進程和線程的數據結構。對于進程來說,每個進程都擁有自己的EPROCESS數據結構,用來描述進程的地址空間、進程名、線程等信息。該結構中的ActiveProcessLinks字段是一個LIST_ENTRY結構,所有進程的EPROCESS結構被LIST_ENTRY鏈接成一個雙向鏈表。這樣,使用該結構,我們可以很容易的遍歷該鏈表,找到需要的LIST_ENTRY結構。
不過,EPROCESS結構在內存中的位置幾乎在OS的每個發布版本中都會發生改變,這就給我們在內存找到進程的EPROCESS帶來了一些麻煩。好在通過PsGetCurrentProcess()函數始終能找到指向當前運行的進程的指針,進而找到當前進程的EPROCESS結構。然后以當前進程指針為終止判斷條件,遍歷EPROCESS雙向鏈表,就一定能定位到需要隱藏的進程。
當找到需要隱藏的進程的結構后,通過修改其LIST_ENTRY中的Flink和Blink的值,將待隱藏的進程的前一個LIST_ENTRY結構(Previous Entry)的Flink指針指向下一個LIST_ENTRY結構(Next Entry),而下一個結構的Blink指向前一個結構。另外,為了防止因指針指向無效內存區域導致系統崩潰,將待摘除的進程的LIST_ENTRY結構中的Flink和Blink指向自身。這樣就完成了脫鏈,系統就無法通過這種方法列舉被隱藏進程的信息其中實線表示的是實際的進程鏈表的情形,而虛線表示的是刪除待隱藏的進程結構后的進程鏈表的情形),從而實現進程的隱藏。需要指出的是,摘除進程鏈表中的被隱藏進程結構后,并不會影響進程的調度執行,這是由于Windows是基于線程來實行任務調度的。
(3)抹掉進程句柄
兩種常用的抹掉進程句柄的做法分別是抹掉CSRSS句柄表中的待隱藏進程句柄和抹掉PspCidTable中的待隱藏進程句柄。
(1)抹掉CSRSS
句柄表中的進程信息一個進程在創建的時候,系統會為其分配一個句柄表。該句柄表主要是供內核對象調用。實際上,其是一個結構體數組,數組中的每個元素包含了以下三項:指向一個內核對象的指針、訪問掩碼、與對象句柄的繼承相關的一些標志等。對于進程對象來說,其對象指針也放在句柄表中,通過遍歷CSRSS句柄表,可以根據需要過濾的特定進程的信息,實現進程的隱藏。
(2) 抹掉PspCidTable中的進程信息
PspCidTable是一個特殊的句柄表,跟普通的句柄表相比,主要區別在于該句柄表中存放的是系統中的進程對象體EPROCESS、線程對象體ETHREAD等。因而通過該句柄表可以遍歷系統中的所有進程(IceSword工具就是使用這種方法來枚舉進程的)。不過該句柄表并未導出,因而使用該方法隱藏進程需要自己定位PspCidTable的地址。一般是通過PsLookupProcessByProcessId()函數來搜索定位的。定位好后,就可以從中過濾掉待隱藏進程的句柄,不過使用該方法時,有一點需要注意的是若被隱藏的進程退出時,需要重新恢復原先的進程對象(恢復原先的表的結構),否則,當調用ExDestroyHandle()銷毀句柄,若遇到不存在的句柄(內核中訪問未知的內存地址),就會導致BSOD。
同內核模式的網絡編程接口相比,用戶模式的網絡編程雖說在隱蔽性上稍微差一些,不過其實現起來簡單、可以使用大量的內置函數。但是,為了追求更好的隱蔽性,內核級的隱藏技術顯得尤為重要,畢竟一個木馬不可能沒有通信模塊,否則其功能將無法實現。在Windows中,OSI的網絡模型與Windows系統結構的概略映射。
其中網絡應用程序即用戶編寫的基于Winsock API的通訊代碼;網絡API DLL則給上層的應用程序提供網絡的接口,以便通過進一步調用下層的協議驅動等完成最后的通信;TDI(Transport DataInterface,傳輸數據接口)客戶是網絡API的核心態的驅動程序,它可根據相應的網絡標準格式化相應的數據包,傳送給協議驅動;TDI傳送器即NDIS(Network Driver Interface Specification,網絡驅動接口規范)協議驅動程序,它接受上層傳送過來的數據包,接著根據不同的需求,按照不同的協議(TCP、IPX等)給數據包添加相應的協議頭,以便提供給下層做進一步的處理;NDIS庫則在為其上下層提供接口,同時也隱藏了設備的細節,使協議驅動程序跟網卡驅動程序通信時不用考慮設備相關性,直接通過這些接口透明地進行通信。
通過以上的分析,一般在內核層,要實現通信隱藏,要么是Hook網絡API共同調用的函數,要么就得深入更內核,在TDI、NDIS協議驅動或NDIS中間層驅動程序等上做過濾操作。常見的通信隱藏方法有以下幾種:
(1)Hook ZwDeviceIoControlFile()
Netstat、Fport等獲取端口列表的工具,一般是通過iphlpapi.dll中提供的函數AllocateAndGetTcpTableFromStack()等來獲取端口相關的信息的。而這些函數最后又都是通過調用NtDeviceIoControlFile()這個Native API 來進入內核的。因而在SSDT中通過Hook該函數對應的函數ZwDeviceIoControlFile(),對返回的端口信息進行過濾,就可以將特定的端口隱藏掉。讓用戶無法通過一些常用的工具枚舉到木馬開啟的通信端口,進而實現端口隱藏來進行隱蔽通信。不過對于像卡巴斯基防火墻等通過TDI過濾驅動來獲取網絡連接、保證通信安全的軟件,該方法一般難以逃避檢測。
(2)TDI過濾驅動
應用層的網絡應用程序要發送或接收數據,都得通過下層的驅動程序來格式化這些數據。那么只要在上層的IRP到達之后,根據自己的需求設定過濾規則,對特定的信息進行過濾,會使用戶層的一些檢測工具或使用同種機制實施過濾的防火墻無法查看到自己已經處理過的通信信息。不過該過濾驅動位于TcpIp.sys之上,屬于UpperDriver,若一些檢測工具或防火墻是通過TcpIp.sys來獲取通信的信息的,那么該種方法就無法對特定的數據包實施過濾,也就難以逃避檢測。
(3)NDIS過濾驅動
NDIS是Microsoft 和3COM公司聯合制定的網絡驅動接口規范,其包括NDISProtocol Driver(NDIS協議驅動)、NDIS Intermediate Driver(NDIS中間層驅動)、NDIS MiniPortDriver(NDIS微端口驅動,有的文獻中也稱之為NDIS小端口驅動)。在這三個層次的驅動中,在后兩個上可以獲取系統的網絡通信的相關信息,如源地址、目的地址等,這樣就可以在這兩個層次較為方便的獲得關于通信隱藏的依據,進而將這些信息直接發往自己的木馬功能模塊或者調用原先的流程繼續傳遞。直接發往木馬模塊的通信信息由于沒有通過系統的常規流程,因而,基于這些流程中間一些層次上的檢測工具或防火墻將無法截獲到這些信息。
驅動模塊隱藏主要實現對內核通信模塊、木馬功能模塊等驅動程序的模塊的隱藏,防止用戶通過一些軟件查看到系統中已加載的驅動模塊,進而發現非法的木馬驅動模塊。對于驅動模塊的隱藏,使用的是DKOM技術,其跟前面分析的用于進程隱藏的DKOM技術原理一樣,只不過實現進程隱藏操作的是EPROCESS結構,而要實現驅動模塊的隱藏操作的卻是MODULE_ENTRY結構鏈表。
在MODULE_ENTRY結構(以下簡稱為“結構1”)中,記錄了內核中驅動的一些信息,如驅動路徑、驅動名等,該結構實際上是_LDR_DATA_TABLE_ENTRY(以下簡稱為“結構2”)的一個簡化結構,只是選取了跟模塊相關的一些字段來組成結構體MODULE_ENTRY的,其中變量1對應于結構2中的InInitializationOrderLinks;變量2是為了保證跟_LDR_DATA_TABLE_ENTRY中字段的偏移一致而添加的一個變量;變量3、4、5、6、7對應分別是結構2中的DllBase、EntryPoint、SizeOfImage、FullDllName、BaseDllName。從MODULE_ENTRY的結構可以看出其第一個參數是LIST_ENTRY結構。對應的_LIST_ENTRY的結構如下:
typedef struct _LIST_ENTRY{
struct _LIST_ENTRY*Flink;
struct _LIST_ENTRY*Blink;
} LIST_ENTRY, *PLIST_ENTRY;
其中Flink參數實現指向下一個鏈表結構,若無后續節點,則將其指向鏈表頭,若當前的節點是鏈表頭結點,則Flink指向鏈表的第一個節點,若鏈表為空,則Flink指向表頭本身;Blink
參數實現指向前一個鏈表結構,若無前驅節點,則其指向鏈表的頭節點,若當前的節點是鏈表頭,則Blink指向鏈表的最后一個節點,若鏈表為空,則Blink指向鏈表頭本身。
這樣,只要順著MODULE_ENTRY雙向鏈表,就可以找到準備隱藏的驅動模塊,只要從中刪除該節點,使用這種機制獲取驅動模塊列表的工具將無法找到被隱藏的驅動模塊。刪除前后的MODULE_ENTRY,實線是未修改的鏈表結構,虛線是修改后的鏈表結構。同進程刪除鏈表的處理類似,為了防止因指針指向無效內存區域導致系統崩潰,刪除操作后,將待摘除的模塊的LIST_ENTRY結構中的Flink和Blink指向自身。
若要實現對注冊表中一些鍵值的隱藏,只需打破這種正常的調用機制,在其中某個易于操作的環節將鍵值過濾掉即可。對于內核層來說,通過掛鉤或修改SSDT表、ntoskrnl.exe等中的相關函數等,就可以完成該功能。
看完上述內容,你們對內核級木馬有什么危害有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。