(51)SSDT HOOK 实现进程保护
一、回顧
在前面的課程里,我們逆向分析了 KiSystemService / KiFastCallEntry 的部分代碼,我們發現這兩個函數找系統服務表 SystemServiceTable 的方法是通過 _KTHREAD + 0xE0 來找。
今天我們來學習另一種方法,即通過 SSDT 表找系統服務表。
二、SSDT
SSDT是內核模塊的導出變量,可通過 dd KeServiceDescriptorTable 查看:
kd> dd KeServiceDescriptorTable 80553fa0 80502b8c 00000000 0000011c 80503000 80553fb0 00000000 00000000 00000000 00000000 80553fc0 00000000 00000000 00000000 00000000 80553fd0 00000000 00000000 00000000 00000000SSDT表由四部分組成,可以理解為4張系統服務表,其中只有第一張是有效的,它表示內核函數的系統服務表。
還有一張叫做 KeServiceDescriptorTableShadow 的未導出表,它和 KeServiceDescriptorTable 的區別是它第二項里是有值的,是win32k.sys的系統服務表:
kd> dd KeServiceDescriptorTableShadow 80553f60 80502b8c 00000000 0000011c 80503000 80553f70 bf999b80 00000000 0000029b bf99a890 80553f80 00000000 00000000 00000000 00000000 80553f90 00000000 00000000 00000000 00000000KeServiceDescriptorTableShadow 是未導出的,我們通過windbg能看到是因為我們導入了PDB文件。在驅動程序里想要找到它,可以通過特征碼的方式,先找到某個使用了 KeServiceDescriptorTableShadow 的函數,然后再通過偏移找到 KeServiceDescriptorTableShadow,具體做法本文就不演示了。
而要想找到 KeServiceDescriptorTable 就簡單得多,因為它是導出的,所以我們只需要在驅動里聲明一下就能用了:
// 系統服務表 typedef struct _KSYSTEM_SERVICE_TABLE {PULONG ServiceTableBase; // 函數地址表PULONG ServiceCounterTableBase; // SSDT 函數被調用的次數ULONG NumberOfService; // 函數個數PULONG ParamTableBase; // 函數參數表 } KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;// SSDT表 typedef struct _KSERVICE_TABLE_DESCRIPTOR {KSYSTEM_SERVICE_TABLE ntoskrnl; // 內核函數KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 函數KSYSTEM_SERVICE_TABLE unUsed1;KSYSTEM_SERVICE_TABLE unUsed2; } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; // 內核導出的全局變量三、win32k.sys 系統服務表
0環代碼執行時,KPCR+0x124是當前線程 _ETHREAD,所以不要覺得驅動不是進程,0環代碼就不屬于任何線程,只要0環代碼執行,它總歸是屬于某個進程的。如果這個進程沒有給 win32k.sys 系統服務表掛物理頁,那么你訪問它就會藍屏。準確的說,只有進程使用了GDI函數,win32k.sys 系統服務表才會掛物理頁。
要想訪問 win32k.sys 系統服務表,做法是創建一個GUI進程,通過 IoControl 函數和驅動通信,驅動執行代碼時,它所屬的進程就是GUI進程,win32k.sys 系統服務表也就能訪問了。
四、SSDT HOOK 實現保護記事本進程
題目要求:
將系統服務表中某個函數改成自己的函數,使任務管理器右鍵無法關閉自己,只有點擊自己的關閉按鈕才可以正常關閉。
補充內容:
方法是SSDT HOOK NtTerminateProcess 函數,SSDT HOOK 的模板我在之前的博客里寫過,那個模板是 hook 了 NtOpenProcess 函數:
補充內容:SSDT HOOK 模板
相關API:
NTSTATUSZwTerminateProcess(IN HANDLE ProcessHandle,IN NTSTATUS ExitStatus);NTSTATUS ObReferenceObjectByHandle(IN HANDLE Handle,IN ACCESS_MASK DesiredAccess,IN POBJECT_TYPE ObjectType OPTIONAL,IN KPROCESSOR_MODE AccessMode,OUT PVOID *Object,OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL);運行結果:
用關閉按鈕可以正常關閉 notepad 1,用任務管理器無法關閉 notepad 2
代碼:
#include <ntddk.h> #include <ntstatus.h>/************************************************************************/ /* 宏定義 */ /************************************************************************/// NtTerminateProcess 系統調用號 #define NTTERMINATEPROCESS_EAX 0x101/************************************************************************/ /* 類型聲明 */ /************************************************************************/// 系統服務表 typedef struct _KSYSTEM_SERVICE_TABLE {PULONG ServiceTableBase; // 函數地址表PULONG ServiceCounterTableBase; // SSDT 函數被調用的次數ULONG NumberOfService; // 函數個數PULONG ParamTableBase; // 函數參數表 } KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;// SSDT表 typedef struct _KSERVICE_TABLE_DESCRIPTOR {KSYSTEM_SERVICE_TABLE ntoskrnl; // 內核函數KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 函數KSYSTEM_SERVICE_TABLE unUsed1;KSYSTEM_SERVICE_TABLE unUsed2; } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;typedef NTSTATUS (*NTTERMINATEPROCESS) (HANDLE ProcessHandle, NTSTATUS ExitStatus);/************************************************************************/ /* 函數聲明 */ /************************************************************************/VOID DriverUnload(PDRIVER_OBJECT pDriver); NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path); VOID PageProtectOff(); VOID PageProtectOn(); VOID HookNtTerminateProcess(); VOID UnHookNtTerminateProcess(); NTSTATUS HbgNtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus);/************************************************************************/ /* 全局變量 */ /************************************************************************/extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; // 內核導出的全局變量 ULONG uOldNtTerminateProcess; // 舊的函數地址/************************************************************************/ /* 函數定義 */ /************************************************************************/// 驅動入口 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path) {// HOOKHookNtTerminateProcess();pDriver->DriverUnload = DriverUnload;return STATUS_SUCCESS; }// 卸載驅動 VOID DriverUnload(PDRIVER_OBJECT pDriver) {UnHookNtTerminateProcess();DbgPrint("Driver unloaded.\n"); }// 關閉頁保護 VOID PageProtectOff() {__asm{cli; // 關閉中斷mov eax, cr0;and eax, not 0x10000; // WP位置0mov cr0, eax;} }// 開啟頁保護 VOID PageProtectOn() {__asm{mov eax, cr0;or eax, 0x10000; // WP位置1mov cr0, eax;sti; // 恢復中斷} }// HOOK NtTerminateProcess VOID HookNtTerminateProcess() {PageProtectOff();uOldNtTerminateProcess = KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[NTTERMINATEPROCESS_EAX];KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[NTTERMINATEPROCESS_EAX] = (ULONG)HbgNtTerminateProcess;PageProtectOn(); }// UnHOOK NtTerminateProcess VOID UnHookNtTerminateProcess() {PageProtectOff();KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[NTTERMINATEPROCESS_EAX] = uOldNtTerminateProcess;PageProtectOn(); }// 被修改的 NtTerminateProcess 函數,簡單打印參數 NTSTATUS HbgNtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus) {PEPROCESS pEprocess;NTSTATUS status;PCHAR ImageFileName;// 此API用法請看文檔status = ObReferenceObjectByHandle(ProcessHandle,FILE_ANY_ACCESS,*PsProcessType,KernelMode,&pEprocess,NULL);if (!NT_SUCCESS(status)){return status;} // 根據鏡像文件名判斷是不是要保護的進程,字符串最大長度是16,超過就會截斷,所以不用擔心越界ImageFileName = (PCHAR)pEprocess + 0x174; if (strcmp(ImageFileName, "notepad.exe") == 0){if (ProcessHandle == (HANDLE)0xFFFFFFFF){// 通過關閉按鈕關閉return ((NTTERMINATEPROCESS)uOldNtTerminateProcess)(ProcessHandle, ExitStatus); }else{// 通過任務管理器關閉DbgPrint("Terminate denied. %s: NtTerminateProcess(%x, %x)\n", ImageFileName, ProcessHandle, ExitStatus);return STATUS_ACCESS_DENIED;}} return ((NTTERMINATEPROCESS)uOldNtTerminateProcess)(ProcessHandle, ExitStatus); }總結
以上是生活随笔為你收集整理的(51)SSDT HOOK 实现进程保护的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (50)补充内容:SSDT HOOK 模
- 下一篇: (52)系统调用阶段测试——基于 SSD