当打开任务管理器时,选择一个进程并结束进程这个过程,可以详细的分为以下几步:
    1) taskmgr 进程首先获取要结束的进程句柄,通过 OpenProcess()这个下API,OpenProcess 调用在Kernel32.dll 中;
    2)系统捕获API调用,转到Ring0 级下,从 SSDT中取得对应的 RintOpenProcess 的入口地址,执行相应操作,此过程在 ntdll.dll 中;
    3)完成NtOpenProcess 操作后转回Ring3 级下返回 OpenProcess 函数返回taskmgr进程,因此获取了要结束的进程的句柄;
    4)taskmgr 执行 TerminateProcess()这个 Ring3 下的 API,传入进程句试结束进程;
    5)系统捕获API调用,再次转到 Ring0 级下,从SSDT中取得对应的PI:NtTerminateProcess 的入口地址,执行结束进程操作;
    6、完成 NtTerminateProcess 操作后转回 Ring3 级下返回 TerminatePro数,继而返回taskmgr 进程,完成结束进程过程;
    在这一个流程中,SSDT起到了重要的作用。于是针对这一流程可以hook ssdt,改变这处流程的处理,从而达到无论是用taskkill命令还是任务管理器都不能杀死进程的效果

    1. #include <ntddk.h>
    2. #include <ntstatus.h>
    3. // 记录原函数的地址
    4. ULONG uOldNtOpenProcess;
    5. //内核之SSDT-HOOK
    6. //系统服务表
    7. typedef struct _KSYSTEM_SERVICE_TABLE
    8. {
    9. PULONG ServiceTableBase; //函数地址表的首地址
    10. PULONG ServiceCounterTableBase;//函数表中每个函数被调用的次数
    11. ULONG NumberOfService; //服务函数的个数
    12. ULONG ParamTableBase; //参数个数表首地址
    13. }KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
    14. //服务描述符
    15. typedef struct _KSERVICE_TABLE_DESCRIPTOR
    16. {
    17. KSYSTEM_SERVICE_TABLE ntoskrnl;//ntoskrnl.exe的服务函数,SSDT
    18. KSYSTEM_SERVICE_TABLE win32k; //win32k.sys的服务函数,ShadowSSDT
    19. KSYSTEM_SERVICE_TABLE notUsed1;//暂时没用1
    20. KSYSTEM_SERVICE_TABLE notUsed2;//暂时没用2
    21. }KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
    22. //定义HOOK的函数的类型
    23. typedef NTSTATUS(NTAPI* FuZwOpenProcess)(
    24. _Out_ PHANDLE ProcessHandle,
    25. _In_ ACCESS_MASK DesiredAccess,
    26. _In_ POBJECT_ATTRIBUTES ObjectAttributes,
    27. _In_opt_ PCLIENT_ID ClientId
    28. );
    29. //自写的函数声明
    30. NTSTATUS NTAPI MyZwOpenProcess(
    31. _Out_ PHANDLE ProcessHandle,
    32. _In_ ACCESS_MASK DesiredAccess,
    33. _In_ POBJECT_ATTRIBUTES ObjectAttributes,
    34. _In_opt_ PCLIENT_ID ClientId
    35. );
    36. // KeServiceDescriptorTable 为 ntoskrnl.exe 所导出的全局变量
    37. extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;
    38. //记录系统的该函数
    39. FuZwOpenProcess g_OldZwOpenProcess;
    40. //服务描述符表指针
    41. KSERVICE_TABLE_DESCRIPTOR* g_pServiceTable = NULL;
    42. //要保护进程的ID
    43. ULONG g_Pid = 1624;
    44. //安装钩子
    45. NTSTATUS HookNtOpenProcess();
    46. //卸载钩子
    47. NTSTATUS UnHookNtOpenProcess();
    48. //关闭页写入保护
    49. void ShutPageProtect();
    50. //开启页写入保护
    51. void OpenPageProtect();
    52. //卸载驱动
    53. void DriverUnload(DRIVER_OBJECT* obj);
    54. /***驱动入口主函数***/
    55. NTSTATUS DriverEntry(DRIVER_OBJECT* driver, UNICODE_STRING* path)
    56. {
    57. KdPrint(("驱动启动成功!\n"));
    58. //安装钩子
    59. HookNtOpenProcess();
    60. driver->DriverUnload = DriverUnload;
    61. return STATUS_SUCCESS;
    62. }
    63. //卸载驱动
    64. void DriverUnload(DRIVER_OBJECT* obj)
    65. {
    66. //卸载钩子
    67. UnHookNtOpenProcess();
    68. KdPrint(("驱动卸载成功!\n"));
    69. }
    70. NTSTATUS HookNtOpenProcess()
    71. {
    72. NTSTATUS Status;
    73. Status = STATUS_SUCCESS;
    74. //1.关闭页只读保护
    75. ShutPageProtect();
    76. //2.修改SSDT表
    77. uOldNtOpenProcess = KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[0x7a];
    78. KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[0x7a] =(ULONG)MyZwOpenProcess;
    79. //3.开启页只读保护
    80. OpenPageProtect();
    81. return Status;
    82. }
    83. //卸载钩子
    84. NTSTATUS UnHookNtOpenProcess()
    85. {
    86. NTSTATUS status;
    87. status = STATUS_SUCCESS;
    88. //1.关闭页只读保护
    89. ShutPageProtect();
    90. //2.写入原来的函数到SSDT表内
    91. KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[0x7a] = uOldNtOpenProcess;
    92. //3.开启页只读保护
    93. OpenPageProtect();
    94. return status;
    95. }
    96. //关闭页只读保护
    97. void _declspec(naked) ShutPageProtect()
    98. {
    99. __asm
    100. {
    101. push eax;
    102. mov eax, cr0;
    103. and eax, ~0x10000;
    104. mov cr0, eax;
    105. pop eax;
    106. ret;
    107. }
    108. }
    109. //开启页只读保护
    110. void _declspec(naked) OpenPageProtect()
    111. {
    112. __asm
    113. {
    114. push eax;
    115. mov eax, cr0;
    116. or eax, 0x10000;
    117. mov cr0, eax;
    118. pop eax;
    119. ret;
    120. }
    121. }
    122. //自写的函数
    123. NTSTATUS NTAPI MyZwOpenProcess(
    124. _Out_ PHANDLE ProcessHandle,
    125. _In_ ACCESS_MASK DesiredAccess,
    126. _In_ POBJECT_ATTRIBUTES ObjectAttributes,
    127. _In_opt_ PCLIENT_ID ClientId
    128. )
    129. {
    130. //当此进程为要保护的进程时
    131. if (ClientId->UniqueProcess == (HANDLE)g_Pid)
    132. {
    133. //设为拒绝访问
    134. DesiredAccess = 0;
    135. }
    136. //调用原函数
    137. return NtOpenProcess(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);
    138. }