1 #ifdef __cplusplus 2 extern "C" 3 { 4 #endif 5 #include <ntddk.h> 6 #ifdef __cplusplus 7 } 8 #endif 9 10 typedef struct _ServiceDescriptorTable { 11 unsigned int* ServiceTableBase; //System Service Dispatch Table 的基地址 12 unsigned int* ServiceCounterTable; 13 //包含着 SSDT 中每一個服務被調用次數的計數器。這個計數器通常由sysenter 更新。 14 unsigned int NumberOfServices;//由 ServiceTableBase 描述的服務的數目。 15 unsigned char* ParamTableBase; //包含每一個系統服務參數字節數表的基地址-系統服務參數表 16 }*PServiceDescriptorTable; 17 18 extern "C" extern PServiceDescriptorTable KeServiceDescriptorTable; 19 20 typedef NTSTATUS(*MYNTOPENPROCESS)( 21 OUT PHANDLE ProcessHandle, 22 IN ACCESS_MASK AccessMask, 23 IN POBJECT_ATTRIBUTES ObjectAttributes, 24 IN PCLIENT_ID ClientId );//定義一個函數指針,用於下面對O_NtOpenProcess進行強制轉換 25 26 ULONG O_NtOpenProcess = 0; 27 28 extern "C" NTSTATUS 29 PsLookupProcessByProcessId( 30 IN HANDLE ProcessId, 31 OUT PEPROCESS *Process 32 ); 33 34 void PageProtectOff()//關閉頁面保護 35 { 36 __asm{ 37 cli 38 mov eax,cr0 39 and eax,not 10000h 40 mov cr0,eax 41 } 42 } 43 void PageProtectOn()//打開頁面保護 44 { 45 __asm{ 46 mov eax,cr0 47 or eax,10000h 48 mov cr0,eax 49 sti 50 } 51 } 52 53 // 判斷是否打開的是本身想保護的進程 54 BOOLEAN ProtectProcess(HANDLE ProcessId,char *str_ProtectObjName) 55 { 56 NTSTATUS status; 57 PEPROCESS process_obj; 58 59 if(!MmIsAddressValid(str_ProtectObjName))//這個條件是用來判斷目標進程名是否有效 60 { 61 return FALSE; 62 } 63 if(ProcessId == 0)//這個條件是用來排除System Idle Process進程的干擾 64 { 65 return FALSE; 66 } 67 status=PsLookupProcessByProcessId(ProcessId, &process_obj);//這句用來獲取目標進程的EPROCESS結構 68 if(!NT_SUCCESS(status)) 69 { 70 KdPrint(("我錯了,這個是錯誤號:%X---這個是進程ID:%d\n",status,ProcessId)); 71 return FALSE; 72 } 73 if(!strcmp((char *)process_obj + 0x174, str_ProtectObjName))//進行比較 74 { 75 ObDereferenceObject(process_obj);//對象計數器減1,爲了恢復對象管理器計數,便於回收 76 return TRUE; 77 } 78 ObDereferenceObject(process_obj); 79 return FALSE; 80 //使用了PsLookupProcessByProcessId後,必須用ObDereferenceObject回收! 81 //PsLookupProcessByProcessId獲取指定進程的EPROCESS結構,目的就是獲取進程名 82 } 83 NTSTATUS MyNtOpenProcess ( 84 __out PHANDLE ProcessHandle, 85 __in ACCESS_MASK DesiredAccess, 86 __in POBJECT_ATTRIBUTES ObjectAttributes, 87 __in_opt PCLIENT_ID ClientId 88 ) 89 { 90 if(ProtectProcess(ClientId->UniqueProcess,"notepad.exe")) // 若是打開的進程是目標進程 91 { 92 KdPrint(("%s打開文件失敗\n",(char *)PsGetCurrentProcess()+0x174)); 93 return STATUS_UNSUCCESSFUL; // 這是一個關鍵,設置STATUS_UNSUCCESSFUL,CE就會提示打開不成功 94 } 95 96 return ((MYNTOPENPROCESS)O_NtOpenProcess)(ProcessHandle,//處理完本身的任務後,調用原來的函數,讓其它進程正常工做 97 DesiredAccess, 98 ObjectAttributes, 99 ClientId); 100 } 101 102 103 VOID UnHookSsdt() 104 { 105 PageProtectOff(); 106 KeServiceDescriptorTable->ServiceTableBase[122] = O_NtOpenProcess; //恢復ssdt中原來的函數地址 107 PageProtectOn(); 108 } 109 NTSTATUS HookSsdt() 110 { 111 // 一、在ssdt_hook()函數中保存要hook函數的(NtOpenProcess)地址 112 O_NtOpenProcess = KeServiceDescriptorTable->ServiceTableBase[122]; 113 PageProtectOff(); 114 // 二、將原來ssdt中所要hook的函數地址換成咱們本身的函數地址 115 KeServiceDescriptorTable->ServiceTableBase[122] = (unsigned int)MyNtOpenProcess; 116 // 此時咱們用CE打開被保護的進程,就會調用咱們本身的函數 117 PageProtectOn(); 118 119 return STATUS_SUCCESS; 120 } 121 VOID DriverUnload(PDRIVER_OBJECT pDriverObject) 122 { 123 UnHookSsdt(); 124 KdPrint(("Driver Unload Success !\n")); 125 } 126 127 extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath ) 128 { 129 KdPrint(("Welcome to My Driver\n")); 130 pDriverObject->DriverUnload = DriverUnload; 131 /* 全部函數的地址 132 for (int i = 0; i < KeServiceDescriptorTable->NumberOfServices; i++) 133 { 134 KdPrint(("NumberOfService[%d]-------%X\n", i, KeServiceDescriptorTable->ServiceTableBase[i])); 135 }*/ 136 HookSsdt(); 137 return STATUS_SUCCESS; 138 }