首页
论坛
课程
招聘
[原创]放个inline Hook的工程
2008-11-26 00:57 19974

[原创]放个inline Hook的工程

2008-11-26 00:57
19974
写得很简单,也是看了看雪的牛们以后自己实践了一下下,虽然简单,但还是建议菜鸟们多练手(像我一样 嘿嘿),当你能自己写个出来并跑起来,才是入门~

不说废话了,上代码,还请各位指正!

NTSTATUS 
DriverEntry(
  PDRIVER_OBJECT pDriverObj, 
  PUNICODE_STRING pRegistryString
  )
{
  NTSTATUS status = STATUS_SUCCESS;
  UNICODE_STRING ustrLinkName;
  UNICODE_STRING ustrDevName;    
  PDEVICE_OBJECT pDevObj;

  //HardCode For Searching……
  ULONG Addr_KiInsertQueueApc=0;
  CHAR FindCode[1][5]={
    {0xe8,0x4b,0x2b,0x00,0x00}
  };

  KdPrint(("==>DriverEntry\n"));
  
  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;
  }

  RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
  status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);  
  if(!NT_SUCCESS(status)) {
    IoDeleteDevice(pDevObj);  
    return status;
  }
  

  //
  // 添加执行代码
  //

  KdPrint(("Search ……\n"));
    OrigfnAddr.KiInsertQueueApc=GetTargetFnAddrFromExportedFn(FindCode[0],L"KeInsertQueueApc",100,0x2b4b);
  if (OrigfnAddr.KiInsertQueueApc!=0)
  {
    KdPrint(("We find it!Address of KiInsertQueueApc: 0x%08x\n",OrigfnAddr.KiInsertQueueApc));
  }
  else
  {
    KdPrint(("Not Find~ \n"));
    return STATUS_UNSUCCESSFUL;
  }

  status=InlineHook(OrigfnAddr.KiInsertQueueApc,(ULONG)fake_KiInsertQueueApc,(ULONG)Proxy_KiInsertQueueApc,OrigHeadCode.KiInsertQueueApc); //进行inlineHook
  if (!NT_SUCCESS(status))
  {
    return status;
  }

  KdPrint(("<==DriverEntry\n"));

  return status;
}


VOID 
DriverUnload(
  PDRIVER_OBJECT pDriverObj
  )
{  
  UNICODE_STRING strLink;
  NTSTATUS status;

  RtlInitUnicodeString(&strLink, LINK_NAME);


  //
  // 添加卸载代码
  //

  status=UnHook(OrigfnAddr.KiInsertQueueApc,OrigHeadCode.KiInsertQueueApc);
  if (!NT_SUCCESS(status))
  {
    KdPrint(("DriverUnload!UnHook Failre~"));
  }

  
  IoDeleteSymbolicLink(&strLink);
  IoDeleteDevice(pDriverObj->DeviceObject);
  KdPrint(("==>DriverUnload\n"));
}


下面是实现hook的代码:

//WriteProtect OFF/ON By MDL!
PVOID WPOFFByMdl(PVOID VirtualAddr,ULONG uLen,PMDL pMDL)
{
  PVOID MVA=NULL; //system-base VA maps physical pages that MDL describes

  pMDL=IoAllocateMdl(VirtualAddr,uLen,FALSE,FALSE,NULL);
  if (pMDL==NULL)
  {
    KdPrint(("WPOFF!IoAllocateMdl FAILURE pMdl==NULL\n"));
    return NULL;
  }

  MmBuildMdlForNonPagedPool(pMDL);

  _try
  {
    MmProbeAndLockPages(pMDL,KernelMode,IoModifyAccess);
  }
  _except(EXCEPTION_EXECUTE_HANDLER)
  {
    return NULL;
  }

  pMDL->MdlFlags|=MDL_MAPPED_TO_SYSTEM_VA;

  MVA=MmGetSystemAddressForMdlSafe(pMDL,NormalPagePriority);
  if (MVA)
  {
    KdPrint(("MVA : %x",MVA));
  }

    KdPrint(("WPOFFByMdl Successful"));
  return MVA;
}

VOID WPONByMdl(PMDL pMdl)
{
  if (pMdl==NULL)
  {
    return ;
  }

  MmUnlockPages(pMdl);
  IoFreeMdl(pMdl);


}

//Write Protect OFF/ON By CR0!
VOID WPOFFByCR0()
{
   
    ULONG uAttr;
   
    _asm
    {
        push eax;
        mov eax, cr0;
        mov uAttr, eax;
        and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
        mov cr0, eax;
        pop eax;
        cli
    };
   
    g_uCr0 = uAttr; //保存原有的 CRO 屬性
   
}

VOID WPONByCR0()
{
   
    _asm
    {
        sti
        push eax;
        mov eax, g_uCr0; //恢復原有 CR0 屬性
        mov cr0, eax;
        pop eax;
    };
   

}

///////////////////////////////////////////////////////////////////////
//Get the exported function's address
ULONG GetFunctionAddr(PCWSTR FunctionName)
{
  UNICODE_STRING uFnName;

  RtlInitUnicodeString(&uFnName,FunctionName);

  return (ULONG)MmGetSystemRoutineAddress(&uFnName);
}

//Find  address of the function that we want to hook
//
//Description:通过已知函数找我们的目标函数
//
//ARGUMENTs:
//
//FindCode:寻找目标函数(即我们要HOOK的函数)的硬编码
//ExportedFnName:已知函数名
//SearchLen:在已知函数里面的搜索长度
//Offset:相对跳转值
//
ULONG GetTargetFnAddrFromExportedFn(CHAR* FindCode,PCWSTR ExportedFnName,ULONG SearchLen,ULONG Offset)
{
  ULONG i=0,j=0;
    CHAR * Addr_ExportedFn=NULL;
  ULONG TargetFnAddr=0;

  Addr_ExportedFn=(CHAR*)GetFunctionAddr(ExportedFnName);
  if (Addr_ExportedFn==NULL)
  {
    KdPrint(("GetTargetFnAddrFromExportedFn!GetFunctionAddr FAILURE\n"));
    return 0;
  }

  for (i=0;i<SearchLen;i++)                //搜索用户指定长度的函数字节
  {
    if (Addr_ExportedFn[i]==FindCode[0])
    {
      for (j=1;j<sizeof(FindCode);j++)
      {
        if (Addr_ExportedFn[i+j]==FindCode[j])
        {
          continue;
        }
        else
        {
          break;
        }
      }

      if (j==sizeof(FindCode))
      { 
      
        TargetFnAddr=(ULONG)&Addr_ExportedFn[i]+Offset+5;  //由相对jmp的dword值得到

        break;
      }
    }
  }


  return TargetFnAddr;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//Hook Function
//
NTSTATUS InlineHook(ULONG OrigFnAddr,ULONG FakeFnAddr,ULONG ProxyFnAddr,PVOID OrigHeadCode)
{
  KIRQL oldIrql;
  BYTE  HookCode[5]={0xe9,0x00,0x00,0x00,0x00};
  BYTE  jmpCode[7]={0xEA,0x00,0x00,0x00,0x00,0x08,0x00};

  PVOID MVA=NULL;

  if (!OrigFnAddr||!FakeFnAddr||!ProxyFnAddr||!OrigHeadCode)
  {
    return STATUS_UNSUCCESSFUL;
  }

  RtlCopyMemory(OrigHeadCode,(BYTE*)OrigFnAddr,5);

  *(ULONG*)(HookCode+1)=(ULONG)FakeFnAddr-(ULONG)OrigFnAddr-5;

  *(ULONG*)(jmpCode+1)=(ULONG)((BYTE*)OrigFnAddr+0x05);// 不需要相对跳转,这里是长转移

  RtlCopyMemory((BYTE*)ProxyFnAddr,(BYTE*)OrigHeadCode,5);
  RtlCopyMemory((BYTE*)ProxyFnAddr+5,(BYTE*)jmpCode,7);

  /*WPOFFByCR0();*/                                   //这里是去掉内存写保护,两种方法,我们选择MDL的方法
  MVA=WPOFFByMdl((PVOID)OrigFnAddr,10,MDLs.KiInsertQueueApc);
  if (!MVA)
  {
    KdPrint(("WPOFFByMdl FAILURE~"));
    return STATUS_UNSUCCESSFUL;
  }

  oldIrql=KeRaiseIrqlToDpcLevel();

  /*RtlCopyMemory((BYTE*)OrigFnAddr,(BYTE*)HookCode,5);*/      //将要HOOK的函数的函数头前5个字节改写 跳到我们的fake函数里面
  RtlCopyMemory((BYTE*)MVA,(BYTE*)HookCode,5);         

  KeLowerIrql(oldIrql);

  /*WPONByCR0();*/
    WPONByMdl(MDLs.KiInsertQueueApc);    //恢复写保护

  return STATUS_SUCCESS;
}


//
// 停止inline hook
//
NTSTATUS UnHook(ULONG OrigFnAddr,PVOID OrigHeadCode)
{
    KIRQL  oldIrql;
  PVOID MVA=NULL;

  if (!OrigFnAddr||!OrigHeadCode)
  {
    return STATUS_UNSUCCESSFUL;
  }

    /*WPOFFByCR0();*/
  MVA=WPOFFByMdl((PVOID)OrigFnAddr,10,MDLs.KiInsertQueueApc);
  if (!MVA)
  {
    KdPrint(("WPOFFByMdl FAILURE~"));
    return STATUS_UNSUCCESSFUL;
  }

    oldIrql = KeRaiseIrqlToDpcLevel();
    
    RtlCopyMemory ( (BYTE*)OrigFnAddr, OrigHeadCode, 5 );

    KeLowerIrql(oldIrql);
    
  /*WPONByCR0();*/
  WPONByMdl(MDLs.KiInsertQueueApc);

  return STATUS_SUCCESS;
}

嘿嘿,大家应该能看出来,在提供的工程里面,用到了sudami同学的一些框架代码,感谢!(程序的最大价值就在于复用~ )

[招聘] 欢迎你加入看雪团队!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (22)
雪    币: 160
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
shdaianita 活跃值 2008-11-26 00:58
2
0
自己做沙发~
雪    币: 217
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
escript 活跃值 2008-11-27 10:21
3
0
INLINE HOOK的没DELPHI版本的, 用C有点吃力
雪    币: 249
活跃值: 活跃值 (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yjlmw 活跃值 2008-12-16 13:37
4
0
用C有点吃力
雪    币: 459
活跃值: 活跃值 (38)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
qihoocom 活跃值 9 2008-12-16 14:15
5
0
又是恶心的HEADER INLINE...
雪    币: 7502
活跃值: 活跃值 (112)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 活跃值 15 2008-12-16 15:24
6
0
Header Inline确实很白菜,参数好处理啊
雪    币: 496
活跃值: 活跃值 (339)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 活跃值 25 2008-12-16 15:54
7
0
连反汇编引擎都不带就开始特征匹配, 蓝死你~~~
雪    币: 459
活跃值: 活跃值 (38)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
qihoocom 活跃值 9 2008-12-16 16:26
8
0
inline hook根本没必要使用反汇编引擎~
雪    币: 496
活跃值: 活跃值 (339)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 活跃值 25 2008-12-16 16:56
9
0
不用的话,传进来的恰巧是某个数据,就崩了. 反正我是遇到过...
雪    币: 372
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ihvte 活跃值 2009-5-22 00:27
10
0
太好了。谢谢。太谢谢了。最近我也在学这个驱动。难搞啊!
雪    币: 40
活跃值: 活跃值 (117)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
网络游侠 活跃值 2009-5-22 10:11
11
0
楼主准备享受BSOD了!!!
雪    币: 325
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
morning 活跃值 1 2009-5-22 12:18
12
0
header inline hook 需要被拷贝的代码长度,需要一个指令长度表或者说反汇编引擎吧
雪    币: 206
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cutcut 活跃值 2009-5-22 18:12
13
0
那如何确定inline长度呢?我就经常就蓝了
雪    币: 206
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cutcut 活跃值 2009-5-22 18:13
14
0
还有在多 cpu/核 上如何同步cpu, 避免蓝
雪    币: 348
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
inioo 活跃值 2009-5-22 19:49
15
0
赞一个,学习了。
雪    币: 122
活跃值: 活跃值 (21)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
robin 活跃值 1 2009-5-22 20:00
16
0
楼主应该判断函数头指令长度的,如果函数头不是mov edi,edi,那就有可能不是5个字节,会有指令碎屑的。
雪    币: 235
活跃值: 活跃值 (10)
能力值: ( LV12,RANK:460 )
在线值:
发帖
回帖
粉丝
火影 活跃值 11 2009-5-24 00:42
17
0
这个用的上瓦
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
雪的思念 活跃值 2009-5-25 00:56
18
0
学习一下先感谢分享
雪    币: 31
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cuihf秋 活跃值 2009-5-25 07:33
19
0
多谢楼主分享
雪    币: 237
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wonjhoncy 活跃值 2009-6-8 21:25
20
0
OrigfnAddr.KiInsertQueueApc=GetTargetFnAddrFromExportedFn(FindCode[0],L"KeInsertQueueApc",100,0x2b4b);为什么这里传个0x2b4b呢?
雪    币: 297
活跃值: 活跃值 (16)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
pyq逍遥 活跃值 1 2009-6-8 22:25
21
0
写的不错,不过有些还看不懂
雪    币: 251
活跃值: 活跃值 (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lovesh 活跃值 2009-6-15 23:53
22
0
研究研究正在弄这方面的 嘿嘿@!·
雪    币: 135
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kieepog 活跃值 2009-8-2 17:43
23
0
先赞后学习~
游客
登录 | 注册 方可回帖
返回