inline hook KiFastCallEntry

来源:互联网 发布:淘宝倒计时怎么搞 编辑:程序博客网 时间:2024/05/21 14:54

 

#include "ntddk.h"
#include "sysenterhook.h"

#if DBG
#define dprintf DbgPrint
#else
#define dprintf(x)
#endif

#define BYTE unsigned char

#define MEM_TAG 'CQ'


#define NT_DEVICE_NAME L"//Device//sysenterhook"
#define DOS_DEVICE_NAME L"//DosDevices//sysenterhook"


NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID DrvUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
NTSTATUS DeviceIoControl(
       IN ULONG IoControlCode,
       IN PVOID InBuffer,
       IN ULONG InBufferSize,
       OUT PVOID OutBuffer,
       IN ULONG OutBufferSize,
       OUT IO_STATUS_BLOCK *IoStatus
       );

ULONG d_origKiFastCallEntry; // save nt!KiFastCallEntry address


#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma  alloc_text(PAGE, DrvUnload)
#endif

typedef NTSTATUS (*NTOPENPROCESS) (OUT PHANDLE ProcessHandle, IN ACCESS_MASK AccessMask, IN POBJECT_ATTRIBUTES ObjectAttribute, IN PCLIENT_ID ClientId);
typedef NTSTATUS (*NTCREATEFILE)(
    __out PHANDLE  FileHandle,
    __in ACCESS_MASK  DesiredAccess,
    __in POBJECT_ATTRIBUTES  ObjectAttributes,
    __out PIO_STATUS_BLOCK  IoStatusBlock,
    __in_opt PLARGE_INTEGER  AllocationSize,
    __in ULONG  FileAttributes,
    __in ULONG  ShareAccess,
    __in ULONG  CreateDisposition,
    __in ULONG  CreateOptions,
    __in_opt PVOID  EaBuffer,
    __in ULONG  EaLength
    );


NTOPENPROCESS OldNtOpenProcess;
NTCREATEFILE  OldNtCreateFile;

BYTE JmpCode[5] = {0xE9, 0, 0, 0, 0};

//原始指令
//mov edi,dword ptr[edi]
//mov ebx,dword ptr[edi+eax*4]
BYTE OrgCode[5] = {0x8B, 0x3F, 0x8B, 0x1C, 0x87};

//push 0
//retn
BYTE PushRetCode[6] = {0x68, 0, 0, 0, 0, 0xC3};

ULONG uKiFastCallEntryAddr = 0;
ULONG HookAddr = 0;
ULONG JMPRet = 0;
ULONG PushRetMem = 0;

NTSTATUS CqNtOpenProcess(  OUT PHANDLE ProcessHandle, IN ACCESS_MASK AccessMase, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId )
{


 DbgPrint("MyOpenProcess........................................../n");
 return OldNtOpenProcess(ProcessHandle, AccessMase, ObjectAttributes, ClientId);

}

NTSTATUS CqNtCreateFile(
      __out PHANDLE  FileHandle,
      __in ACCESS_MASK  DesiredAccess,
      __in POBJECT_ATTRIBUTES  ObjectAttributes,
      __out PIO_STATUS_BLOCK  IoStatusBlock,
      __in_opt PLARGE_INTEGER  AllocationSize,
      __in ULONG  FileAttributes,
      __in ULONG  ShareAccess,
      __in ULONG  CreateDisposition,
      __in ULONG  CreateOptions,
      __in_opt PVOID  EaBuffer,
      __in ULONG  EaLength
      )
{
 DbgPrint("MyCreateFile............................................/n");
 return OldNtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength);

}

//HOOK KiFastCallEntry过滤函数
__declspec(naked)void CqKiFastCallEntry()
{
 _asm
 {
  pushfd
  pushad
  mov edi,dword ptr [edi] //ssdt基地址
  mov ebx,dword ptr [edi+eax*4] //根据索引找到服务函数地址

  cmp OldNtCreateFile,ebx;//比较是否是NtCreateFile
  je Label_NtCreateFile

  cmp OldNtOpenProcess,ebx; //比较是否为NtOpenProcess
  je Label_NtOpenProcess


  popad
  popfd
  mov edi,dword ptr [edi]
  mov ebx,dword ptr [edi+eax*4]
  jmp [JMPRet];

Label_NtOpenProcess:
     popad
  popfd
  mov ebx,CqNtOpenProcess //修改NtOpenProcess为代理函数
  jmp [JMPRet];

Label_NtCreateFile:
  popad
  popfd
  mov ebx,CqNtCreateFile //修改NtCreateFile为代理函数
  jmp [JMPRet];


 }

}


NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{

 PDEVICE_OBJECT         deviceObject        = NULL;
 NTSTATUS               ntStatus;
 UNICODE_STRING         deviceNameUnicodeString;
 PDEVICE_EXTENSION      deviceExtension;
 UNICODE_STRING         deviceLinkUnicodeString;
 UNICODE_STRING         ustrNtOpenProcess = {0};
 UNICODE_STRING         ustrNtCreateFile = {0};
 KIRQL                  oldIrql;

 dprintf("entering DriverEntry/n");

 RtlInitUnicodeString(&deviceNameUnicodeString, NT_DEVICE_NAME);

 ntStatus = IoCreateDevice(
  DriverObject,
  sizeof(DEVICE_EXTENSION),
  &deviceNameUnicodeString,
  FILE_DEVICE_SYSENTERHOOK,
  0,
  TRUE,
  &deviceObject
  );

 if ( NT_SUCCESS(ntStatus) )
 {
  deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;

  RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);

  ntStatus = IoCreateSymbolicLink(
   &deviceLinkUnicodeString,
   &deviceNameUnicodeString
   );

  if ( !NT_SUCCESS(ntStatus) )
  {
   dprintf("IoCreateSymbolicLink failed/n");
  }

  DriverObject->MajorFunction[IRP_MJ_CREATE]         =
   DriverObject->MajorFunction[IRP_MJ_CLOSE]          =
   DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DrvDispatch;
  DriverObject->DriverUnload                         = DrvUnload;
 }


 if ( !NT_SUCCESS(ntStatus) )
 {

  if (deviceObject)
   IoDeleteDevice(deviceObject);
 }


    dprintf("entering DriverEntry/n");

    DriverObject->DriverUnload = DrvUnload;
  
 __asm int 3


    //获取Hook服务函数地址 NtOpenProcess和NtCreateFile为例
 RtlInitUnicodeString(&ustrNtOpenProcess, L"NtOpenProcess" );
 RtlInitUnicodeString(&ustrNtCreateFile, L"NtCreateFile");
 OldNtOpenProcess=(NTOPENPROCESS)MmGetSystemRoutineAddress( &ustrNtOpenProcess);
 OldNtCreateFile = (NTCREATEFILE)MmGetSystemRoutineAddress(&ustrNtCreateFile);

 DbgPrint("NtOpenProcess = 0x%08X/n",OldNtOpenProcess);
 DbgPrint("NtCreateFile = 0x%8X/n", OldNtCreateFile);

 __asm
 { 
  pushfd
  pushad
  mov ecx,0x176//SYSENTER_EIP_MAR(系统初始化时会使其指向KiFastCallEntry)
  rdmsr
  mov uKiFastCallEntryAddr,eax //获取KiFastCallEntry地址
  xor ecx,ecx
Label1:
     cmp ecx,0x100
  je Label3
  mov edx,DWORD ptr [eax]
  cmp edx,0x1C8B3F8B //搜索特征码,获取要Hook的位置
  je Label2
  inc eax
  inc ecx
  jmp Label1
Label2:
  mov HookAddr,eax
Label3:
  popad
  popfd
 }
 if( HookAddr==0 )
 {
  return ntStatus;
 }
 //申请内存 存放跳转指令
 PushRetMem = (ULONG)ExAllocatePoolWithTag(NonPagedPool, 6, MEM_TAG);

 if( (PVOID)PushRetMem == NULL )
 {
  return ntStatus;
 }

 DbgPrint("PushRetMem = 0x%08X/n",PushRetMem);

 //存放跳转指令jmp 相对地址 跳到 pushRetMem
 *(ULONG*)&JmpCode[1]=(ULONG)(PushRetMem) - (HookAddr + 5);
 //存放push CqKiFastCallEntry retn(跳到过滤函数)
 *(ULONG*)&PushRetCode[1] = (ULONG)CqKiFastCallEntry;
 //HOOK返回地址
 JMPRet = HookAddr + 5;

 //提升中断请求级
 oldIrql = KeRaiseIrqlToDpcLevel();

 //关闭中断
 _asm
 {
  CLI                 
  MOV    EAX, CR0 
  AND EAX, NOT 10000H
  MOV    CR0, EAX      
 }
 //把PushRetMem地址存放push CqKiFastCallEntry retn(跳到过滤函数)指令
 RtlCopyMemory((PVOID)PushRetMem,PushRetCode,6);
 //覆盖KiFastCallEntry中的特征代码为JmpCode
 RtlCopyMemory((PVOID)HookAddr,JmpCode,5);

 //开启中断
 _asm 
 {
  MOV    EAX, CR0       
  OR    EAX, 10000H           
  MOV    CR0, EAX              
  STI                   
 }
 //恢复先前中断请求级
 KeLowerIrql(oldIrql);
 DbgPrint("KiFastCallEntry = 0x%08X/n",uKiFastCallEntryAddr);
 DbgPrint("HookAddr = 0x%08X/n",HookAddr);
 /////////////////////////////////////////////

    return ntStatus;
}
NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{

 PIO_STACK_LOCATION  irpStack;
 PDEVICE_EXTENSION   deviceExtension;
 PVOID               ioBuffer;
 ULONG               inputBufferLength;
 ULONG               outputBufferLength;
 ULONG               ioControlCode;
 NTSTATUS            ntStatus;

 Irp->IoStatus.Status      = STATUS_SUCCESS;
 Irp->IoStatus.Information = 0;

 irpStack = IoGetCurrentIrpStackLocation(Irp);

 deviceExtension = DeviceObject->DeviceExtension;

 ioBuffer           = Irp->AssociatedIrp.SystemBuffer;
 inputBufferLength  = irpStack->Parameters.DeviceIoControl.InputBufferLength;
 outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

 switch (irpStack->MajorFunction)
 {
 case IRP_MJ_CREATE:

  dprintf("IRP_MJ_CREATE/n");

  break;

 case IRP_MJ_CLOSE:

  dprintf("IRP_MJ_CLOSE/n");

  break;

 case IRP_MJ_DEVICE_CONTROL:

  dprintf("IRP_MJ_DEVICE_CONTROL/n");

  ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  ntStatus = DeviceIoControl(
   ioControlCode,
   ioBuffer,
   inputBufferLength,
   ioBuffer,
   outputBufferLength,
   &Irp->IoStatus
   );

  break;
 }

 ntStatus = Irp->IoStatus.Status;

 IoCompleteRequest(Irp, IO_NO_INCREMENT);

 

 return ntStatus;
}


VOID DrvUnload(IN PDRIVER_OBJECT DriverObject)
{

 UNICODE_STRING         deviceLinkUnicodeString;

 

 RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);

 IoDeleteSymbolicLink(&deviceLinkUnicodeString);


 IoDeleteDevice(DriverObject->DeviceObject);
 if (HookAddr!=0)
 {
  KIRQL oldIrql;
  //提升中断请求级
  oldIrql = KeRaiseIrqlToDpcLevel();
  //关闭中断
  _asm
  {
   CLI               
   MOV    EAX, CR0   
   AND EAX, NOT 10000H
   MOV    CR0, EAX      
  }
  //进行还原HOOK操作
  RtlCopyMemory((PVOID)HookAddr,OrgCode,5);
  _asm 
  {
   MOV    EAX, CR0       
   OR    EAX, 10000H            
   MOV    CR0, EAX              
   STI                  
  }
  //恢复先前中断请求级
  KeLowerIrql(oldIrql);
  // 释放内存
  ExFreePool((PVOID)PushRetMem);
 }


    dprintf("unloading/n");
}

NTSTATUS DeviceIoControl(
       IN ULONG IoControlCode,
       IN PVOID InBuffer,
       IN ULONG InBufferSize,
       OUT PVOID OutBuffer,
       IN ULONG OutBufferSize,
       OUT IO_STATUS_BLOCK *IoStatus

       )

{
 NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
 switch (IoControlCode)
 {

 case IOCTL_SYSENTERHOOK_HELLO:
  {
   break;
  }

 default:
  ntStatus = STATUS_INVALID_PARAMETER;

  dprintf("unknown IRP_MJ_DEVICE_CONTROL/n");
  break;
 }

 return ntStatus;
}

原创粉丝点击