Windows核心新手上路1——掛鉤SSDT

whatday發表於2013-07-29

Windows核心新手上路1——掛鉤SSDT

        這個系列記錄學習我學習windows核心的點點滴滴,高手請直接無視。

        文章核心內容:掛鉤SSDT中函式列NtOpenProcess,NtDuplicateObject,NtCreateThread,NtOpenThread,NtWriteVirtualMemory,過濾程式操作來保護目標程式空間。

 

SSDT的全稱是System Services Descriptor Table,系統服務描述符表。這個表把ring3的Win32 API和ring0的核心API聯絡起來。SSDT並不僅僅只包含一個龐大的地址索引表,它還包含著一些其它有用的資訊,諸如地址索引的基地址、服務函式個數等。

SSDT管的是與系統相關的函式(kernel32.dll、ntdll.dll)。通過修改此表的函式地址可以對常用windows函式及API進行hook,從而實現對一些關心的系統動作進行過濾、監控的目的。一些HIPS、防毒軟體、系統監控、登錄檔監控軟體往往會採用此介面來實現自己的監控模組。

SSDT在Win32子系統的核心實現是NTOSKRNL.EXE,匯出表名是 KeServiceDescriptorTable,對應系統程式一般有System

SSDT結構:

typedef struct tagSSDT {

PULONG pSSDTBase;                                  //SSDT在記憶體中的基址

PVOID    pServiceCounterTable;

ULONG  uNumberOfServices;                 //SSDT項個數

PUCHAR         pParamTableBase;

} SSDT, *PSSDT; //SSDT

1    如何掛鉤SSDT

首先關閉CR0防寫(通過改變CR0暫存器的WP位),然後用新的函式地址替換原來SSDT中的函式地址,最後恢復CR0防寫。

掛鉤SSDT中函式列NtOpenProcess,NtDuplicateObject,NtCreateThread,NtOpenThread,NtWriteVirtualMemory,過濾程式操作來保護目標程式空間。

1.1NtOpenProcess

在Windows作業系統中,kernel32!OpenProcess通過呼叫ntdll!NtOpenProcess最終轉到核心態的nt!NtOpenProcess,通過掛鉤NtOpenProcess,可以過濾和攔截程式開啟其他程式的操作。

在自定義的NtOpenProcess函式中,首先獲取要開啟的程式PID,判斷該PID是否是被保護的程式,如果是被保護的程式,則去掉開啟許可權中的相應許可權,如果是開啟本系統R3程式,還要去掉結束程式的許可權,最終,再呼叫真實的NtOpenProcess函式,最後返回給R3的程式控制程式碼就無法讀寫操作受保護的程式,惡意程式也無法結束目標程式。

通過程式控制程式碼獲取PID

判斷是否受保護的PID

如果是

        做一些許可權的處理….

        呼叫真實NtOpenProcess

如果否

        呼叫真實的NtCreateThread

程式碼1.1 MyNtOpenProcess

1.2NtDuplicateObject

Windows系統提供了一個函式DuplicateHandle,用於從其他程式複製一個控制程式碼到當前程式,而且csrss.exe程式會儲存所有程式的控制程式碼,通過呼叫DuplicateHandle從csrss中複製控制程式碼,可以間接的達到呼叫OpenProcess獲取目標程式控制程式碼的目的。

在定義的NtDuplcateObject函式中,首先呼叫真實的NtDuplicateObject,如果呼叫成功,判斷最後返回的控制程式碼是不是受保護程式的控制程式碼,如果是受保護的程式控制程式碼,則關閉之。通過這樣的過濾,惡意程式無法通過呼叫DuplicateHandle來開啟受保護的程式。

1.3NtCreateThread

R3中在程式中和其他程式中建立執行緒(分別呼叫CreateThread和CreateRemoteThread)最終通過ntdll!NtCreateThread轉到核心態的nt!CreateThread,通過過濾nt!CreateThread可以防止惡意程式在受保護的程式中建立遠端執行緒(即呼叫CreateRemoteThread)。實現的MyNtCreateThread處理流程如程式碼1.2所示:

通過程式控制程式碼獲取PID

判斷是否受保護的PID

如果是

        返回STATUS_ACCESS_DENIED

如果否

        呼叫真實的NtCreateThread

程式碼1.2 MyNtCreateThread

1.4NtOpenThread

在windows作業系統中,通過呼叫OpenThread可以獲取目標執行緒的控制程式碼,進一步通過此控制程式碼操作目標執行緒。防密碼竊取系統掛鉤了NtOpenThread來防止惡意程式操作受保護程式的執行緒。

在自定義的NtOpenThread函式中,首先獲取執行緒所在程式的PID,然後判斷該PID是否被保護,如果是被保護的PID,則直接返回STATUS_ACCESS_DENIED,否則呼叫真實的NtOpenThread。

1.5NtWriteVirtualMemory

在windows作業系統中,程式可以呼叫kernel32!WriteProcessMemory來寫其他程式記憶體,kernel32!WriteProcessMemory通過ntdll!NtWriteVirtualMemory轉到核心態的nt!NtWriteVirtualMemory。通過掛鉤nt!NtWriteVirtualMemory來防目惡意程式寫受保護的程式記憶體。虛擬碼如程式碼1.3所示。

通過程式控制程式碼獲取PID

判斷是否受保護的PID

如果是

        返回STATUS_ACCESS_DENIED

如果否

        呼叫真實的NtWriteVirtualMemory

程式碼1.3 MyNtWriteVirtualMemory

相關文章