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)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蚂蚁_CrkRes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值