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 }