YLLEN

要去看埃菲尔铁塔的顶

欢迎关注本人微博:t.cn/RGSLVUk

SSDT HOOK (演示:进程保护)

    

目标API : NtOpenProcess

 

相关结构 

    SSDT结构体

#pragma pack(1)
typedef struct _ServiceDescriptorTable
{
PULONG ServiceTableBase;  
PULONG ServiceCounterTable;
unsigned int NumberOfServices;
PVOID paramTableBase;
}*PServiceDescriptorTable ,ServiceDescriptorTable;
#pragma pack()

 

// 由 ntoskrnl 模块 导出的变量
__declspec(dllimport) ServiceDescriptorTable KeServiceDescriptorTable;

 

 

NTSTATUS
    NtOpenProcess
 (
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in_opt PCLIENT_ID ClientId
 );

 

   根据 进程ID 获得进程对象

NTSTATUS
PsLookupProcessByProcessId(
     IN HANDLE ProcessId,
     OUT PEPROCESS *Process
 );

 

 

代码: 


 演示 用于保护 calc.exe  进程


//ssdt.h

#include "ntddk.h"

#pragma pack(1)
typedef struct _ServiceDescriptorTable
{
PULONG ServiceTableBase;  
PULONG ServiceCounterTable;
unsigned int NumberOfServices;
PVOID paramTableBase;
}*PServiceDescriptorTable ,ServiceDescriptorTable;
#pragma pack()

__declspec(dllimport) ServiceDescriptorTable KeServiceDescriptorTable;

void Driver_Unload(IN PDRIVER_OBJECT pDriverObject);


typedef NTSTATUS
 (*NTOPENPROCESS)
 (
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in_opt PCLIENT_ID ClientId
 );
 
 
NTSTATUS

PsLookupProcessByProcessId(
    IN HANDLE ProcessId,
    OUT PEPROCESS *Process
    );

 

 

#include "SSDT.h"

int g_OldAddr;


NTSTATUS ProtectJudge( PCLIENT_ID ClientId ,char* ProcessName)
{

PEPROCESS p_eprocess;
NTSTATUS  status;
char* ImageFileName;
 
if(! MmIsAddressValid(ProcessName))  //判断参数是否有效
 {
  return STATUS_UNSUCCESSFUL;
 }
 
ImageFileName = ( (char*)PsGetCurrentProcess() + 0x174);  //实际测试这个返回的是一个结构体
 //DbgPrint("PsGetCurrentProcess(): %x , this:: %x",PsGetCurrentProcess(),ImageFileName);
 //DbgPrint("NtOpenProcess %d from: %s", ClientId->UniqueProcess,ImageFileName );
 
status =  PsLookupProcessByProcessId(ClientId->UniqueProcess , &p_eprocess);
 

 //DbgPrint("p_eprocess %x", p_eprocess );
 
if(!NT_SUCCESS(status))     // PsLookupProcessByProcessId调用失败
 {
  DbgPrint("PsLookupProcessByProcessId error code: %x ",status );
  return STATUS_UNSUCCESSFUL;
 }
 
ObDereferenceObject(p_eprocess);
   
ImageFileName = (char*)p_eprocess + 0x174 ;

   
if(! strcmp(ImageFileName , ProcessName)  )  //保护计算器
 {
   return STATUS_SUCCESS;
 }
 
return STATUS_UNSUCCESSFUL;

}

 


NTSTATUS
MyNTOpenProcess
 (
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in_opt PCLIENT_ID ClientId
 )
 {
 
  NTSTATUS status;
 
  status = ProtectJudge(ClientId , "calc.exe");
  
  if(NT_SUCCESS(status))  //判断是否是需要保护的进程
  {
   DbgPrint("Protect Successful!");
   return STATUS_UNSUCCESSFUL;
  }
 
  return ((NTOPENPROCESS)g_OldAddr)(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);
 }

 

// 开启/取消 页保护
VOID PAGEPROTECTON()
{
__asm
 {
   mov eax,cr0
   or eax , 10000h
   mov cr0 ,eax
   sti
 }

}

VOID PAGEPROTECTOFF()
{

__asm
 {
   cli
   mov eax , cr0
   and eax , not 10000h
   mov cr0,eax
 }
}


NTSTATUS ssdt_hook()
{
int u_index;
// DbgPrint("123");
// KdPrint("----%x-----",(PULONG)KeServiceDescriptorTable.ServiceTableBase);
DbgPrint("----%x-----",(PULONG)KeServiceDescriptorTable.ServiceTableBase);
// DbgPrint("456");
// for( u_index=0 ; u_index < KeServiceDescriptorTable.NumberOfServices ; u_index++)
// {
//  DbgPrint("[%d] , %x", u_index , KeServiceDescriptorTable.ServiceTableBase[u_index]);
// }
 //保存
g_OldAddr = (int)KeServiceDescriptorTable.ServiceTableBase[122];
 
PAGEPROTECTOFF();
  KeServiceDescriptorTable.ServiceTableBase[122] = (int)MyNTOpenProcess;
PAGEPROTECTON();
 
return STATUS_SUCCESS;
}

 

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject , PUNICODE_STRING RegistryPath)
{


DbgPrint(("DriverEntry"));
if(!NT_SUCCESS(ssdt_hook()))
 {
  DbgPrint(("error"));
 }
pDriverObject->DriverUnload = Driver_Unload;
return STATUS_SUCCESS;
}

 

//  122 是NtOpenProcess 对应在SSDT表中的下标
VOID Driver_Unload(IN PDRIVER_OBJECT pDriverObject)
{
 
  PAGEPROTECTOFF();
   KeServiceDescriptorTable.ServiceTableBase[122] = (int)g_OldAddr;
  PAGEPROTECTON();
 
DbgPrint(("Driver_Unload finish.."));
}

    SSDT是 ring3 到ring0 中用于查找系统功能调用而由Windows Kernel 组织的一张表,

ring3层的API以外壳形式 将参数,系统调用号 传给ring0 层 , 由ring0层再根据SSDT查表后调用真实功能.

 

评论

© YLLEN | Powered by LOFTER