| 
 | 
 
本文将提及到两种Inline Hook,分别是修改头五个字节的jmp Hook以及修改Call指令后4个字节的Call Hook。特点在于没有内嵌汇编,纯C的代码。 
首先先谈Head Inline Hook。 
首先挂钩的时候要注意哪些问题呢? 
1.写入保护。写入保护位于cr0寄存器第15位,为一代表开启,为零代表关闭。但实验证明修改cr0寄存器属于危险行为,而且在不使用类似于__writecr0之类的WDK内置宏的情况下,是需要内嵌汇编的。这里将使用映射MDL的方式实现绕过写入保护。 
2.指令屑。其实这已经不能算是问题了,因为有反汇编引擎。但如果仅仅修改5个字节,虽然执行不存在问题,但像WinDbg之类的软件查看函数就会出现异常,而且,假设要对一个不能只Patch5个字节的函数来说,我们Hook之后,别的驱动想对这个函数进行Call Hook就会出现问题。所以,还得把剩余的字节全部填充NOP指令才行。 
- void Hook (PVOID Func,PVOID New_Func,PVOID Proxy_Func)
 
 - {
 
 -         PMDL MdlForFunc;
 
 -         PVOID Msct;
 
 -         PVOID HookCode=NULL;
 
 -         ULONG PatchSize;
 
 -         KIRQL oldIrql;
 
 -         BYTE g_HookCode[5]={0xE9,0,0,0,0};//相对跳转
 
 -         BYTE Jmp_Orig_Code[7]={0xEA,0,0,0,0,0x08,0x00 }; //绝对地址跳转
 
 -         PatchSize=GetPatchSize(Func,5);//获得要Patch的字节数 
 
 -         //构造Proxy_Func
 
 -         RtlCopyMemory((PBYTE)Proxy_Func,(PBYTE)Func,PatchSize);//实现原函数头
 
 -         *((PULONG)(Jmp_Orig_Code+1))=(ULONG)((PBYTE)Func+PatchSize );//原函数+N 地址
 
 -         RtlCopyMemory((PBYTE)Proxy_Func+PatchSize,Jmp_Orig_Code,7);//绝对地址跳转
 
 -         *((ULONG*)(g_HookCode+1))=(ULONG)New_Func-(ULONG)Func-5;//计算JMP 地址
 
 -         HookCode=ExAllocatePool(NonPagedPool,PatchSize);
 
 -         RtlCopyMemory(HookCode,g_HookCode,5);
 
 -         memset((PVOID)((ULONG)HookCode+5),0x90,PatchSize-5);
 
 -         MdlForFunc=MmCreateMdl(NULL,Func,PatchSize);
 
 -         if(MdlForFunc)
 
 -         {
 
 -                 MmBuildMdlForNonPagedPool(MdlForFunc);
 
 -                 MdlForFunc->MdlFlags=MdlForFunc->MdlFlags|MDL_MAPPED_TO_SYSTEM_VA;
 
 -                 __try
 
 -                 {
 
 -                         MmProbeAndLockPages(MdlForFunc,KernelMode,IoWriteAccess);
 
 -                 }
 
 -                       __except(EXCEPTION_EXECUTE_HANDLER)
 
 -                 {
 
 -                         IoFreeMdl(MdlForFunc);;
 
 -                 }
 
 -                 Msct=MmMapLockedPagesSpecifyCache(MdlForFunc,KernelMode,MmWriteCombined,NULL,FALSE,0);
 
 -                 oldIrql=KeRaiseIrqlToDpcLevel();
 
 -                 RtlCopyMemory(Msct,HookCode,PatchSize);
 
 -                 KeLowerIrql(oldIrql);
 
 -                 MmUnmapLockedPages(Msct,MdlForFunc);
 
 -                 MmUnlockPages(MdlForFunc);
 
 -                 IoFreeMdl(MdlForFunc);
 
 -         }
 
 -         ExFreePool(HookCode);
 
 - }
 
  复制代码 
还有UnHook的代码: 
- void UnHook (PVOID Func,PVOID Proxy_Func)
 
 - {
 
 -         PMDL MdlForFunc;
 
 -         PVOID Msct;
 
 -         ULONG PatchSize;
 
 -         KIRQL f_oldirql;
 
 -         PatchSize=GetPatchSize(Proxy_Func,5);
 
 -         MdlForFunc=MmCreateMdl(NULL,Func,PatchSize);
 
 -         if(MdlForFunc)
 
 -         {
 
 -                 MmBuildMdlForNonPagedPool(MdlForFunc);
 
 -                 MdlForFunc->MdlFlags=MdlForFunc->MdlFlags|MDL_MAPPED_TO_SYSTEM_VA;
 
 -                 __try
 
 -                 {
 
 -                         MmProbeAndLockPages(MdlForFunc,KernelMode,IoWriteAccess);
 
 -                 }
 
 -                       __except(EXCEPTION_EXECUTE_HANDLER)
 
 -                 {
 
 -                         IoFreeMdl(MdlForFunc);
 
 -                 }
 
 -                 Msct=MmMapLockedPagesSpecifyCache(MdlForFunc,KernelMode,MmWriteCombined,NULL,FALSE,0);
 
 -                 f_oldirql=KeRaiseIrqlToDpcLevel();
 
 -                 RtlCopyMemory(Msct,Proxy_Func,PatchSize);
 
 -                 KeLowerIrql(f_oldirql);
 
 -                 MmUnmapLockedPages(Msct,MdlForFunc);
 
 -                 MmUnlockPages(MdlForFunc);
 
 -                 IoFreeMdl(MdlForFunc);
 
 -         }
 
 - }
 
  复制代码 
说白了这里只是补充了第一期TP的学习笔记中《TP的学习笔记:实现安全Inline Hook模块+动态确定SSDT服务号(NT5)》一文的代码而已。并且还修正了NT6系列操作系统蓝屏的问题,也补充了修复指令屑BUG的问题。 
接下来是Call Hook。 
其实Call Hook就没啥说的了,同样是把暴力修改cr0寄存器改成了映射MDL,不过我发现上次的TP的学习笔记中使用自旋锁是没必要的,因此改良后代码是这样的: 
- void CallAddrHook(PVOID StartAddr,PVOID OldAddr,PVOID NewAddr)
 
 - {
 
 -         PUCHAR cPtr, pOpcode;
 
 -         ULONG Length,Tmp;
 
 -         PMDL pMdl;
 
 -         PVOID Msct;
 
 -         for (cPtr=StartAddr;(ULONG)cPtr<(ULONG)StartAddr+0x1000;cPtr += Length)
 
 -         {
 
 -                 Length = SizeOfCode(cPtr, &pOpcode);//计算当前指令长度
 
 -                 if (!Length) break;
 
 -                 if (Length ==5 && *cPtr==0xE8)// 当前长度5 且第一字节为E8 
 
 -                 {//因为CALL用的是相对偏移  所以我们还需要进行计算相对偏移
 
 -                         if((ULONG)OldAddr-(ULONG)cPtr-5==*(PULONG)(cPtr+1)) //判断当前是否为OldAddr的CALL相对地址 
 
 -                         {
 
 -                                 Tmp=(ULONG)NewAddr-(ULONG)cPtr-5;//我们的CALL地址相对偏移
 
 -                                 pMdl=MmCreateMdl(NULL,(PVOID)(cPtr+1),4);
 
 -                                 if(pMdl)
 
 -                                 {
 
 -                                         //进行HOOK操作
 
 -                                         MmBuildMdlForNonPagedPool(pMdl);
 
 -                                         pMdl->MdlFlags=pMdl->MdlFlags|MDL_MAPPED_TO_SYSTEM_VA;
 
 -                                         __try
 
 -                                         {
 
 -                                                 MmProbeAndLockPages(pMdl,KernelMode,IoWriteAccess);
 
 -                                         }
 
 -                                         __except(EXCEPTION_EXECUTE_HANDLER)
 
 -                                         {
 
 -                                                 IoFreeMdl(pMdl);
 
 -                                         }
 
 -                                         Msct=MmMapLockedPagesSpecifyCache(pMdl,KernelMode,MmWriteCombined,NULL,FALSE,0);
 
 -                                         f_oldirql=KeRaiseIrqlToDpcLevel();
 
 -                                         InterlockedExchange(Msct,Tmp);//直接替换为我们的FAKE函数地址   
 
 -                                         KeLowerIrql(f_oldirql);
 
 -                                         MmUnmapLockedPages(Msct,pMdl);
 
 -                                         MmUnlockPages(pMdl);
 
 -                                         IoFreeMdl(pMdl);
 
 -                                 }
 
 -                         }
 
 -                 }
 
 -         }
 
 - }
 
  复制代码 
希望这篇文章发表后,我不会再看到那些改cr0的Hook代码了。。。。。。 |   
 
评分
- 
查看全部评分
 
 
 
 
 
 |