HooK SSDT

来源:互联网 发布:淘宝的驱鼠器有用吗 编辑:程序博客网 时间:2024/05/21 19:28
//转 
#include <ntddk.h>
//目的:实现当程序使用NTOpentProcess函数打开指定进程InstDrv.exe时,失败


#pragma pack(1)
typedef struct ServiceDescriptorEntry {  
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase;
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
}ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma  pack()


ULONG srcAddr;//保存NTOPENPROCESS函数原来地址


typedef NTSTATUS (*NTOPENPROCESS) (//定义一个函数指针,作类型转换
  __out PHANDLE ProcessHandle,
  __in ACCESS_MASK DesiredAccess,
  __in POBJECT_ATTRIBUTES ObjectAttributes,
  __in_opt PCLIENT_ID ClientId
  );




NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId,PEPROCESS *Process);//WDK中没有,必须声明


extern PServiceDescriptorTableEntry_t KeServiceDescriptorTable;


void PageProtectOn()
{
 __asm
    {//恢复页保护
        mov eax, cr0
        or eax, 0x10000
        mov cr0, eax
        sti
    }
    
}








void PageProtectOff()
{
__asm
{//去除页保护
cli
mov eax, cr0 //cr0为寄存器,可参考IA-32 Intel架构软件开发人员手册 卷3: 系统编程指南
and eax, not 0x10000
mov cr0, eax
}


};






BOOLEAN ProtectProcess(ULONG ID,char * protectName)
{


NTSTATUS status;


PEPROCESS process;//每个进程都有一个 EPROCESS 结构,里面保存着进程的各种信息,和相关结构的指针。


status=PsLookupProcessByProcessId((HANDLE)ID,&process);




if(ID==0)


return FALSE;






if(!MmIsAddressValid(protectName))//内存是否可读 


        return FALSE;








if(!NT_SUCCESS(status))




KdPrint(("根据ID查询进程失败,error code:%x--进程ID:%d",status,ID));

return FALSE ;


}




if(strstr((char*)process+0x174,protectName)!=0)//返回找到字符串的地址。ox174为_eprocess结构中的ImageFileName,在windbg中输入 dt _eprocess 调试所得数值


{   KdPrint(("不滤过的进程名字:%s",protectName));
  
ObDereferenceObject(process);//一定要用,将计数清0 

return TRUE;


}


else


KdPrint(("滤过的进程名字:%s",(char*)process+0x174));






ObDereferenceObject(process);






return FALSE;




}


NTSTATUS NewNtOpenProcess (
  __out PHANDLE ProcessHandle,
  __in ACCESS_MASK DesiredAccess,
  __in POBJECT_ATTRIBUTES ObjectAttributes,
  __in_opt PCLIENT_ID ClientId
  )
{




   KdPrint(("调用该函数的程序名字:%s",(UCHAR *)PsGetCurrentProcess()+0x174));




   if(ProtectProcess(ClientId->UniqueProcess,"InstDrv"))//当保护的进程为InstDrv时,不允许执行
   {
  return STATUS_UNSUCCESSFUL;
   }
   


   return ((NTOPENPROCESS)srcAddr)(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);//转换地址为函数类型




}


NTSTATUS HookNTOpenProcess()
{




NTSTATUS Status;
    ULONG u_index;


Status=STATUS_SUCCESS;


PageProtectOff();
    
srcAddr= KeServiceDescriptorTable->ServiceTableBase[122];//保存原来的值 
    KeServiceDescriptorTable->ServiceTableBase[122]=(unsigned int)NewNtOpenProcess;  //122为NTOpenProcess的数组位置


    PageProtectOn();
    
return Status;


};


















VOID DriverUnload(PDRIVER_OBJECT driver)
{


//恢复
PageProtectOff();
KeServiceDescriptorTable->ServiceTableBase[122]=srcAddr;


PageProtectOn();
}


//DriverEntry,入口函数。相当于main
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{


HookNTOpenProcess();

driver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}