话说来看雪注册已半个月有余了,可是天天在线也不见KX增长。
老话说狗急了跳墙,人急了就会自己动手了。
说一个恢复InlineHook的方法,但是比较猥琐。而且高手直接飘过吧~~~~~~
咱就以某个游戏的保护措施为列吧,看好了这里不是讲如何过这个保护的,而是对她猥琐一下。
这个游戏在内核中HOOK了很多函数,就以KeAttachProcess为例。
在没运行游戏之前

代码:
kd> u KeAttachProcess
nt!KeAttachProcess:
804f88cc  8bff  mov  edi,edi
804f88ce  55  push  ebp
804f88cf  8bec  mov  ebp,esp
804f88d1  56  push  esi
804f88d2  57  push  edi
运行游戏之后被修改成……请看图

很明显它是在KeAttachProcess函数开头进行了HOOK并且转到的地址仍然是一条
JMP语句跳到另外一个地方,至于它为什么这么做。我分析可能是用一条线程不停的写
最后那条JMP语句比较方便。扯远了……
那么我们怎么恢复KeAttachProcess呢,正常的情况下只要将它头部的几条重新写进去就可以了
可我们今天要猥琐一点,偏要脱裤子放屁。 有时候脱裤子放屁也是一种艺术。
不废话了,图解它的HOOK原理

而我们要做的呢,看下图

好了,整个原理都看过图了。下面上代码就OK了
代码:
//Driver.c
#include <ntddk.h>
#include <wdm.h>
#include <windef.h>

#define NAKED __declspec(naked)    //定义裸体函数
#define PAGEDCODE code_seg("PAGE")  //分页
#define LOCKEDCODE code_seg()    //非分页
#define INITCODE code_seg("INIT")  //初始化时载入内存而后卸载
//保存被HOOK函数开头的前5条指令
#pragma pack(1)
typedef struct _TOP5CODE
{
  UCHAR  instruction;  //指令
  ULONG  address;    //地址
}TOP5CODE,*PTOP5CODE;
#pragma pack( )

BYTE  *KeAttachProcessAddress      = NULL;  //AttachProcess函数地址

//卸载函数
VOID  DriverUnload(IN PDRIVER_OBJECT  pDriverObject)
{
  KdPrint(("Enter DriverUnload\n"));
}

//获取函数地址
ULONG MyGetFunAddress( IN PCWSTR FunctionName)
{
  UNICODE_STRING UniCodeFunctionName;
  RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
  return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );   
}

//中继函数
#pragma LOCKEDCODE
static NAKED VOID  MyKeAttachProcessRelay()
{
  __asm
  {
    mov  edi,edi
    push  ebp
    mov  ebp,esp
    push  esi
    mov  eax,KeAttachProcessAddress
    add  eax,6
    jmp  eax  
  }
}

//入口函数
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{
  TOP5CODE    *top5code  = NULL;
  BYTE      *jmpAddress  = NULL;              //保存GPK修改内容的地址
  BYTE      JmpMyAttachProcess[5]  = {0xE9,0,0,0,0};  //跳转到HOOK函数的地址
  KIRQL      Irql;

  //获取函数地址
  KeAttachProcessAddress  = (BYTE*)MyGetFunAddress(L"KeAttachProcess");
  //将指针指向AttachProcessAddress函数头部
  top5code = (TOP5CODE*)KeAttachProcessAddress;
  jmpAddress = (BYTE*)top5code->address;
  //计算jmpAddress与MyKeAttachProcess的相对地址
  *(ULONG *)(JmpMyAttachProcess+1)=(ULONG)MyKeAttachProcessRelay-((ULONG)jmpAddress+5);

  __asm
  {
    cli
      mov eax,cr0
      and eax,not 10000h
      mov cr0,eax
  }
  //提升IRQL中断级
  Irql=KeRaiseIrqlToDpcLevel();
  //写入JMP语句
  RtlCopyMemory((BYTE*)jmpAddress,JmpMyAttachProcess,5);
  //恢复Irql
  KeLowerIrql(Irql);
  __asm
  {
    mov    eax,cr0
    or    eax,10000h
    mov    cr0,eax
    sti
  }

  //设置卸载函数
  DriverObject->DriverUnload = DriverUnload;
  
  return STATUS_SUCCESS;
}

当然这种猥琐也可以用在SSDT HOOK 上面。
就是到被修改的地址开始出写一句JMP 跳转回原始函数的开始处。