当打开任务管理器时,选择一个进程并结束进程这个过程,可以详细的分为以下几步:
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命令还是任务管理器都不能杀死进程的效果
#include <ntddk.h>#include <ntstatus.h>// 记录原函数的地址ULONG uOldNtOpenProcess;//内核之SSDT-HOOK//系统服务表typedef struct _KSYSTEM_SERVICE_TABLE{PULONG ServiceTableBase; //函数地址表的首地址PULONG ServiceCounterTableBase;//函数表中每个函数被调用的次数ULONG NumberOfService; //服务函数的个数ULONG ParamTableBase; //参数个数表首地址}KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;//服务描述符typedef struct _KSERVICE_TABLE_DESCRIPTOR{KSYSTEM_SERVICE_TABLE ntoskrnl;//ntoskrnl.exe的服务函数,SSDTKSYSTEM_SERVICE_TABLE win32k; //win32k.sys的服务函数,ShadowSSDTKSYSTEM_SERVICE_TABLE notUsed1;//暂时没用1KSYSTEM_SERVICE_TABLE notUsed2;//暂时没用2}KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;//定义HOOK的函数的类型typedef NTSTATUS(NTAPI* FuZwOpenProcess)(_Out_ PHANDLE ProcessHandle,_In_ ACCESS_MASK DesiredAccess,_In_ POBJECT_ATTRIBUTES ObjectAttributes,_In_opt_ PCLIENT_ID ClientId);//自写的函数声明NTSTATUS NTAPI MyZwOpenProcess(_Out_ PHANDLE ProcessHandle,_In_ ACCESS_MASK DesiredAccess,_In_ POBJECT_ATTRIBUTES ObjectAttributes,_In_opt_ PCLIENT_ID ClientId);// KeServiceDescriptorTable 为 ntoskrnl.exe 所导出的全局变量extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;//记录系统的该函数FuZwOpenProcess g_OldZwOpenProcess;//服务描述符表指针KSERVICE_TABLE_DESCRIPTOR* g_pServiceTable = NULL;//要保护进程的IDULONG g_Pid = 1624;//安装钩子NTSTATUS HookNtOpenProcess();//卸载钩子NTSTATUS UnHookNtOpenProcess();//关闭页写入保护void ShutPageProtect();//开启页写入保护void OpenPageProtect();//卸载驱动void DriverUnload(DRIVER_OBJECT* obj);/***驱动入口主函数***/NTSTATUS DriverEntry(DRIVER_OBJECT* driver, UNICODE_STRING* path){KdPrint(("驱动启动成功!\n"));//安装钩子HookNtOpenProcess();driver->DriverUnload = DriverUnload;return STATUS_SUCCESS;}//卸载驱动void DriverUnload(DRIVER_OBJECT* obj){//卸载钩子UnHookNtOpenProcess();KdPrint(("驱动卸载成功!\n"));}NTSTATUS HookNtOpenProcess(){NTSTATUS Status;Status = STATUS_SUCCESS;//1.关闭页只读保护ShutPageProtect();//2.修改SSDT表uOldNtOpenProcess = KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[0x7a];KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[0x7a] =(ULONG)MyZwOpenProcess;//3.开启页只读保护OpenPageProtect();return Status;}//卸载钩子NTSTATUS UnHookNtOpenProcess(){NTSTATUS status;status = STATUS_SUCCESS;//1.关闭页只读保护ShutPageProtect();//2.写入原来的函数到SSDT表内KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[0x7a] = uOldNtOpenProcess;//3.开启页只读保护OpenPageProtect();return status;}//关闭页只读保护void _declspec(naked) ShutPageProtect(){__asm{push eax;mov eax, cr0;and eax, ~0x10000;mov cr0, eax;pop eax;ret;}}//开启页只读保护void _declspec(naked) OpenPageProtect(){__asm{push eax;mov eax, cr0;or eax, 0x10000;mov cr0, eax;pop eax;ret;}}//自写的函数NTSTATUS NTAPI MyZwOpenProcess(_Out_ PHANDLE ProcessHandle,_In_ ACCESS_MASK DesiredAccess,_In_ POBJECT_ATTRIBUTES ObjectAttributes,_In_opt_ PCLIENT_ID ClientId){//当此进程为要保护的进程时if (ClientId->UniqueProcess == (HANDLE)g_Pid){//设为拒绝访问DesiredAccess = 0;}//调用原函数return NtOpenProcess(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);}
