天天看點

Windows Rootkit 技術分析

現在很多人對rootkit認識不夠,可以說空白。而此文的目的就是讓大家認識rootkit→了解rootkit。也讓一些想研究它的人把這篇文章當作一個參考或是入門級的指導。

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

*轉載請保留文章完整,謝謝!

*Date:2005/9/11 祝童童生日快樂。也紀念世貿大廈

*作者:sunwear [E.S.T]

*ps:很多人問我[E.S.T]是什麼……其實就是一個技術小組 :)

*E-mail:shellcoder[0x40]163[0x2E]com , sunwear[0x40]eviloctal[0x2E]com

*QQ:625185

*http://blog.csdn.net/sunwear

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

List:

一,前言

二,簡介

三,rootkit的一些以公開的隐藏技術

四,一些隐藏技術的應對方法

五,about ring0 rootkit

六,rootkit的檢測

七,參考資料,推薦 :)

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

一.先說幾句與技術無關的話。

現在很多人對rootkit認識不夠,可以說空白。而此愚文的目的就是讓菜鳥認識rootkit→了解rootkit。也讓一些想研究它的人把這篇文章當作一個參考或是入門級的指導。文章中介紹的rootkit的隐藏方法隻是一部分。還有很多技術沒有提到,另外還有一些未公開的技術。有些地方我未引用代碼,因為不想占用過多的篇幅。以免有玩弄代碼的嫌疑,不過寫完以後還是覺得代碼太多,請個位見諒。一-三的内容适合菜鳥看,也許第四部分之後對很多人來說都有些意義吧。如果高手不幸看到了,請準備好,不要吐到螢幕上或身上。

以往的文章寫的比較亂,而且格式不公正,這樣的形式寫文章也是第一次。以前文章中引用代碼和文字也沒有詳細說明,再此也對作者表示謙意。感謝XX提的這個建議。

今天是9月11号,慶祝一下童童的生日。順便為911事件中的遇難者祈禱。同時也感謝MGF病毒的作者指點。

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

二.簡單的說說rootkit.

Rootkit的曆史已經很悠久了。存在于windows,unix,linux等作業系統中,不隻局限在windows,此文我隻以windows平台為例來說rootkit。Root在英語中是根,紮根的意思,kit是包的意思。rootkit我們可以把它了解成一個利用很多技術來潛伏在你系統中的一個後門,并且包含了一個功能比較多的程式包,例如有、清除日志,添加使用者,b7cmdshell,添加删除啟動服務等功能。當然它的設計者也要用一些技術來隐藏自己,確定不被發現。隐藏包括隐藏程序,隐藏檔案,端口,或句柄,系統資料庫的項,鍵值等等。總之,寫rootkit的人是狡盡乳汁利用很多辦法不被發現。

現在人們最熟悉的windows rootkit 就是hacker defender和ntrootkit了,還有使用了baiyuanfan在XCON提出的ring3 rootkit新思路的byshell,呵呵。而linux下就是knark了。

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

三.rootkit的一些以公開的隐藏技術以及檢測技術。

1. 删除程序雙項鍊上的程序對象。

ps:用的似乎很多,連現在的一些盜号的程式也利用上了

現在所有人檢視程序一般都是通過任務管理器(taskmgr.exe)來檢視。了解一些程式設計知識的人都知道,任務管理器枚舉程序資訊是靠的NtQuerySystemInformation 也就是ZwQuerySystemInformation 函數。衆所周知,這個Native Api (本機API)枚舉程序是要通過程序活動連結清單的。我們就來看看這個結構。

typedef struct _OBJECT_ATTRIBUTES

{

ULONG Length;

HANDLE RootDirectory;

PUNICODE_STRING ObjectName;

ULONG Attributes;

PVOID SecurityDescriptor;

PVOID SecurityQualityOfService;

} OBJECT_ATTRIBDTES, *POBJECT_ ATTRIBUTES;

typedef struct _IO_STATUS_BLOCK

{

NTSTATDS Status;

ULONG Information;

}IO_STATUS_BLOCK , * PIO_STATUS_BLOCK ;

typedef struct _LIST_ENTRY

{

Struct _LIST_ENTRY *Flink;

Struct _LIST_ENTRY *Blink;

}LIST_ENTRY, *PLIST_ENTRY;

雙向連結清單的典型例子就是程序和線程鍊。内部變量PsActiveProcessHead是一個LIST_ENTRY結構,在ntoskrnl.exe的資料段中,指定了系統程序清單的第一個成員。仔細想想,如果我們将程序對象從程序雙向連結清單中移除,那麼調用NtQuerySystemInformation來枚舉程序的任務管理器taskmgr.exe中就不會看到我們的程序了。那麼就有人會擔心了。如果程序從連結清單中删除,那還會被運作麼?答案是,會。因為windows的ds,也就是線程分派器,也叫任務排程配置設定器(dispatcher scheduler)使用的是另一個資料結構,也就是說,進線程是否被排程處理與程序雙向活動連結清單無關,不會被CPU忽略,不必擔心。2003年pjf在安全焦點上提出的就是這個方法且給出了這個方法的實作代碼。文章結尾處的參考資料中我會給出這個文章的URL。

2.修改系統調用表(sst)

rootkit可以通過在系統調用表中添加添加自己的服務然後運作想要執行的任務。He4HookInv就是這樣。He4HookInv也是一個比較有名的windows rootkit。下面我們來看看He4HookInv具體的實作過程。在以前人們不知道它是如何實作的這些,一些介紹rootkit的文章也是提到一點,不過隻知道是修改的SST,細節也沒有過多描述。直到phrack雜志公布了He4HookInv的一些細節。

He4Hook在不同版本所使用的方法是有所不同的。公布的方法中有兩種。這裡隻說說第一種方法。如果想了解第二種方法和原版就看文章結尾的參考資料吧(phrack的連接配接)。

ZwCreateFile, ZwOpenFile,IoCreateFile,ZwQueryDirectoryFile, ZwClose 這些函數在Ntdll.dll中是這樣實作的。

mov eax, NumberFunction

lea edx, [esp+04h]

int 2eh; Syscall interface

當然Ntdll.dll是一個main gate,真正的函數調用是在Ntoskrnl中完成的。關于本機API的,可以看參考資料中我寫的另一篇文章《淺析本機API》。

EAX中儲存着系統調用号。int 2Eh代表轉到中斷描述符表IDT位置0x2E處的中斷處理程式。中斷處理程式把EAX裡的值作為查找表中的索引,去找到最終的目标函數。這個表就是系統服務表SST。ntoskrnl通過KeServiceDescriptorTable符号,導出了主要SDT的一個指針。我們可以通過KeServiceDescriptorTable來通路SDT。現在來看看KeServiceDescriptorTable的結構。

typedef struct SystemServiceDescriptorTable

{

SSD SystemServiceDescriptors[4];

} SSDT, *LPSSDT;

Other structures:

typedef VOID *SSTAT[];

typedef unsigned char SSTPT[];

typedef SSTAT *LPSSTAT;

typedef SSTPT *LPSSTPT;

typedef struct SystemServiceDescriptor

{

LPSSTAT lpSystemServiceTableAddressTable;

ULONG dwFirstServiceIndex;

ULONG dwSystemServiceTableNumEntries;

LPSSTPT lpSystemServiceTableParameterTable;

} SSD, *LPSSD;

KeServiceDescriptorTable 指向的DescriptorTable 隻能從核心模式通路。在使用者模式下,有一個未輸出的KeServiceDescriptorTableShadow 。底層服務有 :

KeServiceDescriptorTable->SystemServiceDescriptors[0]

KeServiceDescriptorTableShadow->SystemServiceDescriptors[0]

核心模式圖形化使用者界面服務(GUI):

KeServiceDescriptorTableShadow->SystemServiceDescriptors[1]

在WinNt4(SP3-6)和Win2k build 2195之前的所有版本中,DescriptorTable的其他的元素在寫入時是空閑的,表中每個元素為SSID結構,包含有以下資料:

lpSystemServiceTableAddressTable 指針表,當相關系統調用啟用時,它指向被調用的函數記憶體位址數組。

dwFirstServiceIndex 指向第一個函數的開始位址

dwSystemServiceTableNumEntries 表中服務數目

lpSystemServiceTableParameterTable 表示出入棧的位元組數目

為了取得系統調用,He4HookInv 用一個指針替代了KeServiceDescriptorTable->SystemServiceDescriptos[0].lpSystemServiceTableAddressTableIn中存儲的位址,而指向其所屬表。

你可以通過在系統調用表中添加自己的服務而界入He4HookInv。He4HookInv将更新以下兩表:

- KeServiceDescriptorTable

- KeServiceDescriptorTableShadow.

但是,如果He4HookInv隻更新KeServiceDescriptorTable ,新的服務項在使用者模式下将不能被調用。為了定位KeServiceDescriptorTable Shadow ,将用到以下技術:KeAddSystemServiceTable 函數能向核心驅動層添加服務,而且能向兩個表中同時添加。如果它的0訓示符是相同的,通過掃描KeAddSystemServiceTable 函數代碼就可以找到shadow 表的位址,具體可以在He4HookInv.c檔案中的FindShadowTable(void)函數中檢視是怎麼實作的。如果這個辦法失敗,He4Hook使用一個寫死的位址((KeServiceDescriptorTable-0x230)來定位ShadowTable的位置.這個位址從WinNT-sp3來就沒有變過.另外一個問題是如何找到系統服務的編号,這個其實很簡單,由于系統服務的函數體都具有以下形式(mov eax, NumberFunction),是以我們隻要把系統服務的函數位址加上1bytes,就可以得到系統服務對應的編号。

He4HookInv利用的第二個方法就是修改檔案系統驅動中DRIVER_OBJECT的回調表,這裡就不在詳細說明了。

3.端口隐藏

很多人檢查自己中沒中木馬或後門,都會一些方法來檢視自己本機所開的端口來判斷是否有木馬監聽,而有些rootkit就開始想如何隐藏端口了。

最簡單的枚舉目前所開放的端口資訊是調用iphlpapi.dll中的AllocateAndGetTcpTableFromStack和AllocateAndGetUdpTableFromStack函數,或者AllocateAndGetTcpExTableFromStack和AllocateAndGetUdpExTableFromStack函數。

DWORD WINAPI AllocateAndGetTcpTableFromStack(

OUT PMIB_TCPTABLE *pTcpTable,

IN BOOL bOrder,

IN HANDLE hAllocHeap,

IN DWORD dwAllocFlags,

IN DWORD dwProtocolVersion;

);

DWORD WINAPI AllocateAndGetUdpTableFromStack(

OUT PMIB_UDPTABLE *pUdpTable,

IN BOOL bOrder,

IN HANDLE hAllocHeap,

IN DWORD dwAllocFlags,

IN DWORD dwProtocolVersion;

);

DWORD WINAPI AllocateAndGetTcpExTableFromStack(

OUT PMIB_TCPTABLE_EX *pTcpTableEx,

IN BOOL bOrder,

IN HANDLE hAllocHeap,

IN DWORD dwAllocFlags,

IN DWORD dwProtocolVersion;

);

DWORD WINAPI AllocateAndGetUdpExTableFromStack(

OUT PMIB_UDPTABLE_EX *pUdpTableEx,

IN BOOL bOrder,

IN HANDLE hAllocHeap,

IN DWORD dwAllocFlags,

IN DWORD dwProtocolVersion;

);

還有另外一種方法。當程式建立了一個套接字并開始監聽時,它就會有一個為它和打開端口的打開句柄。我們在系統中枚舉所有的打開句柄并通過NtDeviceIoControlFile把它們發送到一個特定的緩沖區中,來找出這個句柄是否是一個打開端口的。這樣也能給我們有關端口的資訊。因為打開句柄太多了,是以我們隻檢測類型是File并且名字是/Device/Tcp或/Device/Udp的。打開端口隻有這種類型和名字。

而通過察看iphlpapi.dll的代碼。就會發現這些函數同樣都是調用NtDeviceIoControlFile并發送到一個特定緩沖區來獲得系統中所有打開端口的清單。也就是說,我們挂接NtDeviceIoControlFile函數就可以隐藏端口。

我們來看看NtDeviceIoControlFile的原型

NTSTATUS NtDeviceIoControlFile(

IN HANDLE FileHandle

IN HANDLE Event OPTIONAL,

IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,

IN PVOID ApcContext OPTIONAL,

OUT PIO_STATUS_BLOCK IoStatusBlock,

IN ULONG IoControlCode,

IN PVOID InputBuffer OPTIONAL,

IN ULONG InputBufferLength,

OUT PVOID OutputBuffer OPTIONAL,

IN ULONG OutputBufferLength

);

我們來看看《The Undocumented Functions-Microsoft Windows NT_2000》中對這些參數的描述

FileHandle

HANDLE to Device Object opened as a file.

Event

Optional HANDLE to Event Object signalled on the end of processing request.

ApcRoutine

Optional pointer to user's APC Routine called on the end of processing request.

ApcContext

User's parameter to ApcRoutine.

IoStatusBlock

IO result of call.

IoControlCode

IO Control code [IOCTL_*].

InputBuffer

User's allocated buffer with input data.

InputBufferLength

Length of InputBuffer, in bytes.

OutputBuffer

User's allocated buffer for result data.

OutputBufferLength

Length of OutputBuffer, in bytes.

主要的就是FileHandle,IoStatusBlock,IoControlCode,IoControlCode,InputBufferLength,OutputBuffer,OutputBufferLength。

摘自《在NT系列作業系統裡讓自己“消失”》。

還有關于端口隐藏的技術就不提了 因為在我說的文章中已經說的很清楚了,是以在寫就是浪費篇幅了。

jiurl也曾經提到過了一種隐藏端口的方法,并且給出了代碼。在參考資料中有文章URL。

4 檔案隐藏。

在WINNT裡在某些目錄中尋找某個檔案的方法是枚舉它裡面所有的檔案和它的子目錄下的所有檔案。檔案的枚舉是使用NtQueryDirectoryFile函數。

NTSTATUS NtQueryDirectoryFile(

IN HANDLE FileHandle,

IN HANDLE Event OPTIONAL,

IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,

IN PVOID ApcContext OPTIONAL,

OUT PIO_STATUS_BLOCK IoStatusBlock,

OUT PVOID FileInformation,

IN ULONG FileInformationLength,

IN FILE_INFORMATION_CLASS FileInformationClass,

IN BOOLEAN ReturnSingleEntry,

IN PUNICODE_STRING FileName OPTIONAL,

IN BOOLEAN RestartScan

);

在《The Undocumented Functions-Microsoft Windows NT_2000》中對這些參數的描述

FileHandle

HANDLE to File Object opened with FILE_DIRECTORY_FILE option and FILE_LIST_DIRECTORY access.

Event

Optional HANDLE to Event Object signaled after query complete.

ApcRoutine

Optinal pointer to user's APC routine queued after query complete.

ApcContext

Parameter for ApcRoutine.

IoStatusBlock

IO result of call.

FileInformation

User's allocated buffer for output data.

Length

Length of FileInformation buffer, in bytes.

FileInformationClass

Information class. Can be one of:

FileDirectoryInformation

FileFullDirectoryInformation

FileBothDirectoryInformation

FileNamesInformation

FileOleDirectoryInformation

ReturnSingleEntry

If set, only one entry is returned.

FileMask

If specified, only information about files matches this wildchar mask will be returned.

RestartScan

Used with ReturnSingleEntry parameter. If set, NtQueryDirectoryFile continue enumeration after last enumerated element in previous call. If no, returns the first entry in directory.

與隐藏檔案相關的重要參數是FileHandle,FileInformation,FileInformationClass.

FileInformationClass中的相關資訊過多,隻說其中重要的四個。

FileDirectoryInformation

FileFullDirectoryInformation

FileBothDirectoryInformation

FileNamesInformation

要寫入FileInformation的FileDirecoryInformation記錄的結構:

typedef struct _FILE_DIRECTORY_INFORMATION {

ULONG NextEntryOffset;

ULONG Unknown;

LARGE_INTEGER CreationTime;

LARGE_INTEGER LastAccessTime;

LARGE_INTEGER LastWriteTime;

LARGE_INTEGER ChangeTime;

LARGE_INTEGER EndOfFile;

LARGE_INTEGER AllocationSize;

ULONG FileAttributes;

ULONG FileNameLength;

WCHAR FileName[1];

} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;

FileFullDirectoryInformation:

typedef struct _FILE_FULL_DIRECTORY_INFORMATION {

ULONG NextEntryOffset;

ULONG Unknown;

LARGE_INTEGER CreationTime;

LARGE_INTEGER LastAccessTime;

LARGE_INTEGER LastWriteTime;

LARGE_INTEGER ChangeTime;

LARGE_INTEGER EndOfFile;

LARGE_INTEGER AllocationSize;

ULONG FileAttributes;

ULONG FileNameLength;

ULONG EaInformationLength;

WCHAR FileName[1];

} FILE_FULL_DIRECTORY_INFORMATION, *PFILE_FULL_DIRECTORY_INFORMATION;

FileBothDirectoryInformation:

typedef struct _FILE_BOTH_DIRECTORY_INFORMATION {

ULONG NextEntryOffset;

ULONG Unknown;

LARGE_INTEGER CreationTime;

LARGE_INTEGER LastAccessTime;

LARGE_INTEGER LastWriteTime;

LARGE_INTEGER ChangeTime;

LARGE_INTEGER EndOfFile;

LARGE_INTEGER AllocationSize;

ULONG FileAttributes;

ULONG FileNameLength;

ULONG EaInformationLength;

UCHAR AlternateNameLength;

WCHAR AlternateName[12];

WCHAR FileName[1];

} FILE_BOTH_DIRECTORY_INFORMATION, *PFILE_BOTH_DIRECTORY_INFORMATION;

FileNamesInformation:

typedef struct _FILE_NAMES_INFORMATION {

ULONG NextEntryOffset;

ULONG Unknown;

ULONG FileNameLength;

WCHAR FileName[1];

} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;

這個函數在FileInformation中寫入這些結構的一個清單。對我們來說在這些結構類型中隻有3個變量是重要的。

NextEntryOffset是這個清單中項的偏移位址。第一個項在位址FileInformation+0處,是以第二個項在位址是FileInformation+第一個項的NextEntryOffset。最後一個項的NextEntryOffset是0。

FileName是檔案全名。

FileNameLength是檔案名長度。

如果我們想要隐藏一個檔案,我們需要分别通知這4種類型,對每種類型的傳回記錄我們需要和我們打算隐藏的檔案比較名字。如果我們打算隐藏第一個記錄,我們可以把後面的結構向前移動,移動長度為第一個結構的長度,這樣會導緻第一個記錄被改寫。如果我們想要隐藏其它任何一個,隻需要很容易的改變上一個記錄的NextEntryOffset的值就行。如果我們要隐藏最後一個記錄就把它的NextEntryOffset改為0,否則NextEntryOffset的值應為我們想要隐藏的那個記錄和前一個的NextEntryOffset值的和。然後修改前一個記錄的Unknown變量的值,它是下一次搜尋的索引。把要隐藏的記錄之前一個記錄的Unknown變量的值改為我們要隐藏的那個記錄的Unkown變量的值即可。

如果沒有原本應該可見的記錄被找到,我們就傳回STATUS_NO_SUCH_FILE。

#define STATUS_NO_SUCH_FILE 0xC000000F

同隐藏端口一樣。具體請看《在NT系列作業系統裡讓自己“消失”》。

5,在說一下baiyuanfan在xcon上提出的ring3 rootkit思路。就是通過挂接本機API實作同步與異步端口複用。利用自删除和複活來隐藏痕迹,不被檢測到。

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

四。一些隐藏技術的應對方法

像剛才提到的将程序對象從程序雙向連結清單中删除就有辦法突破。剛才其實聰明的人已經想到了。NtQuerySystemInformation所需要的連結清單已經被做了手腳。但windows dispatcher scheduler跟他所用的連結清單不一樣。那麼我門可以通過讀取windows dispatcher scheduler所用的另一個連結清單來列出程序。也就是說可以直接通過讀取KiWaitInListHead和KiWaitOutListHead來列舉程序,這樣就突破了修改雙向連結清單隐藏程序的方法。pjf的通過讀取KiWaitInListHead列出隐藏的程序中給出了代碼。

不過這種檢測方法不久又被突破了,就是替換核心的程序連結清單。

還有人提出使用HOOK SwapContext方法來檢測。隻要被處理器排程的線程就逃不掉。

有些人對這個函數不大了解。我來說說這個函數吧。

WINDOWS 2K/NT/XP系統中,處理器的排程對象是線程,在非SMP的OS中某時間段内目前 CPU 處理的程序隻可能有一個。每個程序配置設定特定的 CPU 時間片來達到執行目的,而系統的 CPU 時鐘中斷确定了每個程序配置設定的時間片。也就是當系統 CPU 時鐘中斷觸發時,産生的程序排程請求。處理器時鐘中斷發生的時候會調用KiDispatchInterrupt(),比較目前程序配置設定的時間片,如用完後會調用 KiQuantumEnd() 根據各線程優先級等資訊用特定的排程算法選擇新的線程(ETHREAD),然後将其傳回值,一個 ETHREAD 結構作為參數,來調用 SwapContext() 設定 ETHREAD,EPROCESS 中的各項參數,并替換 KPCR 中的相應結構完成線程切換,排程到另一個程序(EPROCESS)的線程(ETHREAD)繼續執行。可以說CPU的線程切換離不開SwapContext函數,當然,rootkit所執行線程的都會通過SwapContext函數來切換使之被CPU處理。

而在這之後有人就提出自己替換線程的排程就可以躲過這種檢測。

在我看來,這種檢測方法會占用很大的資源,畢竟CPU的線程切換非常頻繁。如果誰有條件可以自己看看,一秒内會發生多少次的線程切換。

在第六部分我會說一下rootkit的檢測。

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

五,about ring0 rootkit

有矛就有盾,有木馬就有防毒軟體,但在這場雙方之間永無休止的拉鋸戰中,木馬始終處于劣勢地位,尤其是現在,防毒軟體對木馬的絞殺,真是到了“無所不用其極”的地步。防毒軟體憑什麼能夠長期居于優勢地位?原因隻有一個:防毒軟體/防火牆先入為主,具有以RING0為主、RING3為輔,大小通吃的天然優勢。木馬和防毒軟體/防火牆的戰争,是一場不對稱的戰争,就象基地和美國那樣。木馬從一個赤裸裸的網絡軟體遠端控制軟體,發展到反彈型木馬,DLL型木馬,到現在的“隐身”型木馬,身上穿的聖衣越來越厚。但是一個新木馬剛剛誕生,很快就被防毒軟體收集特征碼,列入黑名單,被到處追殺。當今“好木馬”的必須具備無程序,無端口,難清除等特征。但是在傳統的RING3裡,在下認為木馬技術已經沒有多少發展空間,必須到RING0去,在平等的條件下和防毒軟體/防火牆放手一博。向RING0進軍,已經是木馬新的發展方向。

和傳統的木馬相比,RING0木馬有什麼優勢?讓我們看看:

1,無程序。

RING0木馬編譯後是一個SYS檔案,它和DLL檔案那樣,是插入到程序裡運作的。但DLL插入的是位址在0x80000000下的使用者區,而RING0木馬插入到位址在0x80000000以上的系統區,而且所有程序共享,隻要它本身不提供unload例程,幾乎不可能被解除安裝,而且沒有多少個工具可以列舉系統裡裝載的SYS子產品。

2,無端口。

RING0木馬可以直接控制網卡收發包,系統和防火牆根本不知道,是以它可以使用任何端口,任何協定。或者通過使防火牆的NDIS驅動失效,突破防火牆的封堵。

3,難發現,難清除,生存能力強。但是,要寫出這樣一匹好馬,需要對系統核心和通訊協定非常熟悉的高手才能勝任,尤其要對ntoskrnl.exe,hal.dll,ndis.sys三個系統子產品導出的函數要非常熟悉才行。另外安裝RING0木馬需要管理者及以上的權限,如果你隻獲得了肉機的GUEST權限,還要想辦法提升權限才行。以上對RING0木馬的描述隻是一個構想而已,本人沒有用代碼實作過,也不知道有沒有人寫出了這樣的木馬,希望有人指正指正。不過對于程式設計愛好者來說,這是一個很大的挑戰,能夠寫出來,足以證明你的能力了!

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

六,rootkit的檢測

rootkit和病毒一樣,都被防毒軟體廠商“關注”,正如上面about ring0 rootkit中說的一樣,是一場永無休止的拉鋸戰。很多熱愛技術的人,也喜歡挑戰他們,是以rootkit的檢測技術也不斷增加。比如EPA(執行路徑分析)。rootkit如果通過修改系統調用來實作隐藏目的(就像文章第三部分中提到的一樣。),那麼肯定會與正常的系統有所不同,當系統調用的路徑發生變化的時候,我們通過之間的對比分析,就可以檢測到rootkit的存在。當然,這樣做也是有缺點的。每次系統調用發生時都要做檢查,那麼就像上面HOOK SwapContext一樣。都會消耗系統的很多資源。其二,實作起來有難度。

還有就是反病毒的方法,就像對付病毒一樣。不過這樣的方法很被動。而且未公開的rootkit比較多,是以并不是非常有效。

還有一種新生的檢測方法,就是微分測試(Differential testing)。不過很容易突破。估計後面的 rootkit就可以饒過了……。

檢測一些rootkit,各位可以使用pjf的icesword,是一款非常優秀的檢測工具了。ICE的枚舉程序用了不隻一種方法。不要以為他什麼都可以查到。ps:不過在使用的時候不要呼出softice,否則會崩潰,這是因為ice的反調試機制。也可以試試zzzevazzz的knlsc。不過檢測到了以後也是非常難完全清除的,弄不好會造成系統出現故障。提早防備還是比較重要的。下面來說一些可以預防rootkit的方法。至于防禦rootkit,還是必備防毒軟體,一些已經以知的rootkit還會被清除。而一些設定可以阻止rootkit植入,例如禁止通路/Device/PhysicalMemory 。禁止驅動加載系統調用。不過如果設定的太嚴格會出問題,記得我當時胡亂設定,導緻植入rootkit的時候BSOD.....

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

七,參考資料:

1.http://www.phrack.org/phrack/62/p62-0x06_Kernel_Mode_Backdoors_for_Windows_NT.txt <firew0rker>

2.http://www.blackhat.com/presentations/bh-usa-03/bh-us-03-rutkowski/rutkowski-antirootkit.zip <Jan K. Rutkowski>

3.http://www.eviloctal.com/forum/htm_data/15/0506/11387.html <Jan Krzysztof Rutkowski>

4.http://www.xfocus.net/articles/200403/680.html <Holy_Father>

5.http://www.eviloctal.com/forum/htm_data/24/0509/14187.html <The Undocumented Functions-Microsoft Windows NT_2000>

6.http://he4dev.e1.bmstu.ru/HookSysCall/

7.http://blog.csdn.net/sunwear/archive/2004/10/03/123751.aspx <sunwear>

8.http://www.xfocus.net/articles/200309/610.html <pjf>

9.http://www.eviloctal.com/forum/htm_data/13/0502/7858.html <pjf>

10.http://www.eviloctal.com/forum/htm_data/26/0412/5226.html <jiurl>

11.http://www.rootkit.com/newsread_print.php?newsid=170 <kimmo >

12.http://www.xfocus.net/articles/200404/693.html

13.http://www.xfocus.net/projects/Xcon/2005/Xcon2005_Baiyuanfan.pdf <baiyuanfan>

14.http://www.xfocus.net/projects/Xcon/2005/Xcon2005_Shok.pdf <shok>

推薦:

1.http://www.rootkit.com/

2.http://www.phrack.org/

3.http://www.eviloctal.com/

4.http://www.xfocus.net/

5.http://www.securiteam.com/

6.http://www.retcvc.com/

7.http://www.driverdevelop.com/

繼續閱讀