看流星社区

 找回密码
 注册账号
查看: 1798|回复: 0

驱动模仿360和某游戏保护hook KiFastCallEntry监控系统调用

[复制链接]

该用户从未签到

发表于 2013-5-5 09:43:25 | 显示全部楼层 |阅读模式
KiFastCallEntry,是所有api函数的必经之路。。。。在这里做HOOK 是最好的。
360和某些游戏保护都是采用以下的源码写的。

#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;
}
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-5-15 07:58

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表