SSDT HOOK驱动保护原理

A、初识内核进程相关结构

 B、内核函数PsGetCurrentProcess

 C、进程保护原理

 D、实例测试

dd nt!KeServiceDescriptorTable

NTSTATUS NtOpenProcess(

  __out     PHANDLE ProcessHandle,

  __in      ACCESS_MASK DesiredAccess,

  __in      POBJECT_ATTRIBUTES ObjectAttributes,
 

  __in_opt  PCLIENT_ID ClientId
);

typedef struct _CLIENT_ID {

    HANDLE UniqueProcess;//进程PID

    HANDLE UniqueThread; //线程PID

} CLIENT_ID;

dt _CLIENT_ID

dt _eprocess

dt -v -r _eprocess (加上-v -r显示详细结构)

MyNtOpenProcess()

{ 如果要打开进程是我们要保护的

   ProcessHandle=NULL

 不是

 ProcessHandle=NtOpenProcess()//HANDLE hProcess

}

#pragma once

#ifdef __cplusplus

extern "C"

{

#endif

#include <NTDDK.h> //这里包含需要用C方式编译的头文件

#ifdef __cplusplus

}

#endif 

#include <windef.h>

 bool ssdthook_flag=false;

extern "C" extern PServiceDescriptorTable KeServiceDescriptorTable;

//extern "C" NTSTATUS __stdcall   PsLookupProcessByProcessId( IN ULONG ulProcId, OUT PEPROCESS * pEProcess );

// 定义一下NtOpenProcess的原型

 extern "C"    typedef  NTSTATUS     (__stdcall NTOPENPROCESS)(  OUT PHANDLE ProcessHandle,

IN ACCESS_MASK AccessMask,

 IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId );

 NTOPENPROCESS   *  RealNtOpenProcess;

  PEPROCESS  EP;

// 真实的函数地址

ULONG     RealServiceAddress;

HANDLE     MyPID; //要保护的进程ID

// 自定义的NtOpenProcess函数

#pragma PAGECODE

//************************************

extern "C" NTSTATUS __stdcall MyNtOpenProcess( OUT     PHANDLE ProcessHandle,

                                                                           IN     ACCESS_MASK DesiredAccess,

                                                                           IN     POBJECT_ATTRIBUTES ObjectAttributes,

                                                                           IN     PCLIENT_ID ClientId )

{

         NTSTATUS     rc;

         HANDLE       PID;

         KdPrint(("++++++++++++Entry MyNtOpenProcess int   ++++++++++++++\n")); 

         rc = (NTSTATUS)RealNtOpenProcess( ProcessHandle, DesiredAccess, ObjectAttributes, ClientId );        

         if( (ClientId != NULL) )

         {

                  PID = ClientId->UniqueProcess;  

                  KdPrint(( "------------------------- PID=%d--------------\n",(int*)PID ));

                  // 如果是被保护的PID,直接返回权限不足,并将句柄设置为空

                  if(PID == MyPID)

                  {

                   KdPrint(( "++++++++++++++++++++++++++++被保护进程 MyPID=%d++++++++++++++++++++++++\n",MyPID ));

                           ProcessHandle = NULL; //这个是关键

                           rc = STATUS_ACCESS_DENIED;

                           //PsLookupProcessByProcessId((ULONG)PID,&EP);

                           EP=PsGetCurrentProcess();                   

                           KdPrint(("AAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACESS Process Name  --:%s--  AAAAAAAAAAAAAAAAAA \n",(PTSTR)((ULONG)EP+0x174)));

                  KdPrint(( "++++++++++++++++++++++++++++=======================================================+++++++++++++++++++++++\n" ));

                  }

         }

         return rc;

}

#pragma PAGECODE

VOID Hook()

{

         KdPrint(("++++++++++++++++++++HOOK START +++++++++++++++++++++++++++++++ ---------------------------------\n"));

        LONG *SSDT_Adr,SSDT_NtOpenProcess_Cur_Addr,t_addr;

         KdPrint(("驱动成功被加载中.............................\n"));

         //读取SSDT表中索引值为0x7A的函数

         //poi(poi(KeServiceDescriptorTable)+0x7a*4)

         t_addr=(LONG)KeServiceDescriptorTable->ServiceTableBase;

         KdPrint(("当前ServiceTableBase地址为%x \n",t_addr));

         SSDT_Adr=(PLONG)(t_addr+0x7A*4);

         KdPrint(("当前t_addr+0x7A*4=%x \n",SSDT_Adr));

         SSDT_NtOpenProcess_Cur_Addr=*SSDT_Adr;    

         RealServiceAddress = *SSDT_Adr;

         RealNtOpenProcess = ( NTOPENPROCESS *)RealServiceAddress;

         KdPrint(( "真实的NtOpenProcess地址: %x\n",(int) RealServiceAddress ));

         KdPrint((" 伪造NTOpenProcess地址: %x\n", (int)MyNtOpenProcess )); 

         __asm //去掉页面保护

         {

                      cli

                           mov eax,cr0

                           and eax,not 10000h //and eax,0FFFEFFFFh

                           mov cr0,eax

         }

         *SSDT_Adr= (ULONG)MyNtOpenProcess;

         __asm

         {

                    mov     eax, cr0

                    or     eax, 10000h

                    mov     cr0, eax

                    sti

         }  

         return;

}

//////////////////////////////////////////////////////

#pragma PAGECODE

VOID UnHook()

{

         ULONG Old_ssdt;

         Old_ssdt = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;

  if    (ssdthook_flag)

  {    ssdthook_flag=false;

         __asm

         {

                  cli

                           mov     eax, cr0

                           and     eax, not 10000h

                           mov     cr0, eax

         }

         // 还原SSDT

         *((ULONG*)Old_ssdt) = (ULONG)RealServiceAddress;

         __asm

         {

                  mov     eax, cr0

                  or     eax, 10000h

                  mov     cr0, eax

                  sti

         }

         KdPrint(("UnHook还原SSDT OK \n"));

  }        

         return;

}

#define   hook_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_NEITHER,FILE_ANY_ACCESS)

#define unhook_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_NEITHER,FILE_ANY_ACCESS)

猜你喜欢

转载自blog.csdn.net/zang141588761/article/details/82778724