其实InlineHook 不像想象的那么复杂。如果你慢慢的学习研究还是很好理解的。
我在看雪http://bbs.pediy.com/showthread.php?t=98493 看了这篇文章,做了一下修改。这里说说我的心得体会吧!
我们看到很多文章都说是修改前五个字节,其实这是不完全正确的说法,如果你熟悉InlineHook的话,可以换成这个函数地址范围内的任意五个字节,
但是要确保这个五个字节的格式为{E9,xx,xx,xx,xx} 其中XX表示地址。
下面的代码我会注释,写上我的理解。
整个代码的效果就是——当你使用任务管理器结束一个记事本进程(notepad.exe)的时候,系统提示无法终止进程,如下图所示。
好了,可以去试试了。
//HookObReferenceObjectByHandle------DetourMyObReferenceObjectByHa ndle----------UnHookObReferenceObjectByHandle
//完整代码分析如下:
//=======================================inline HOOK ObReferenceObjectByHandle===========================
//ObReferenceObjectByHandle是ntoskrnl.exe导出函数,采用HOOK前五个字节的方式
#include "ntddk.h"
//关闭内存保护
#define DisableMemProtect()\
{\
__asm cli\
__asm mov eax,cr0\
__asm push eax\
__asm and eax,(~0x10000)\
__asm mov cr0,eax\
}
//恢复内存保护
#define RecoverMemProtect()\
{\
__asm pop eax\
__asm or eax,0x10000\
__asm mov cr0,eax\
__asm sti\
}
//全局变量
unsigned char OriginalBytes[5]={0}; //保存原始函数前五个字节
unsigned char JmpAddress[5]={0xE9,0,0,0,0}; //跳转到HOOK函数的地址 E9 是JMP的机器码
extern POBJECT_TYPE *PsProcessType;
NTKERNELAPI NTSTATUS ObReferenceObjectByHandle(
IN HANDLE Handle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_TYPE ObjectType OPTIONAL,
IN KPROCESSOR_MODE AccessMode,
OUT PVOID *Object,
OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL);
//HOOK函数 这个函数功能就是,在系统调用ObReferenceObjectByHandle函数时
//进行其他操作,具体操作看下文的定义
NTSTATUS DetourMyObReferenceObjectByHandle(
IN HANDLE Handle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_TYPE ObjectType OPTIONAL,
IN KPROCESSOR_MODE AccessMode,
OUT PVOID *Object,
OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL);
void HookObReferenceObjectByHandle()
{
//赋值前面定义的数组
KIRQL Irql;
KdPrint(("\n[ObReferenceObjectByHandle] :0x%x",ObReferenceObjectByHandle)); //地址验证
//保存函数前五个字节内容
RtlCopyMemory(OriginalBytes,(unsigned char *)ObReferenceObjectByHandle,5);
//保存新函数五个字节之后偏移
//Jmp[0]= E9
//Jmp[1..4] 其实就是一个地址
*(ULONG *)(JmpAddress+1)=(ULONG)DetourMyObReferenceObjectByHandle-((ULONG)ObReferenceObjectByHandle+5);
KdPrint(("\n[JmpAddress] :0x%x",
(ULONG)DetourMyObReferenceObjectByHandle-((ULONG)ObReferenceObjectByHandle+5))); //地址验证
//开始inline hook
DisableMemProtect(); //关闭内存写保护
Irql=KeRaiseIrqlToDpcLevel();//提升IRQL中断级
//函数开头五个字节写JMP
RtlCopyMemory((unsigned char *)ObReferenceObjectByHandle,JmpAddress,5);
KeLowerIrql(Irql); //恢复Irql中断级别
RecoverMemProtect(); //恢复内存写保护
}
_declspec (naked) NTSTATUS OriginalObReferenceObjectByHandle(
IN HANDLE Handle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_TYPE ObjectType OPTIONAL,
IN KPROCESSOR_MODE AccessMode,
OUT PVOID *Object,
OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
{
_asm
{
mov edi,edi
push ebp
mov ebp,esp
mov eax,ObReferenceObjectByHandle
add eax,5
jmp eax
}
}
NTSTATUS DetourMyObReferenceObjectByHandle(
IN HANDLE Handle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_TYPE ObjectType OPTIONAL,
IN KPROCESSOR_MODE AccessMode,
OUT PVOID *Object,
OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
{
NTSTATUS status;
//调用原函数
status=OriginalObReferenceObjectByHandle(Handle,
DesiredAccess,
ObjectType,
AccessMode,
Object,
HandleInformation);
if((status==STATUS_SUCCESS)&&(DesiredAccess==1))
{
if(ObjectType== *PsProcessType)
{
// 0x174 ImageFileName XP
//0x16c ImageFileName Win7
//if( _stricmp((char *)((ULONG)(*Object)+0x174),"notepad.exe")==0)//XP
if( _stricmp((char *)((ULONG)(*Object)+0x16c),"notepad.exe")==0)//WIN7 注释掉这一句 回复上一句 就可以在XP 使用
{
ObDereferenceObject(*Object);
return STATUS_INVALID_HANDLE;
}
}
}
return status;
}
//取消HOOK
void UnHookObReferenceObjectByHandle()
{
//把五个字节再写回到原函数
KIRQL Irql;
DisableMemProtect(); //关闭内存写保护
Irql=KeRaiseIrqlToDpcLevel(); //提升IRQL到Dpc
RtlCopyMemory((unsigned char *)ObReferenceObjectByHandle,OriginalBytes,5);
KeLowerIrql(Irql); //恢复到原来的中断级别
RecoverMemProtect(); //恢复内存保护
}
//卸载驱动
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
UnHookObReferenceObjectByHandle();
DbgPrint("inline hook success unload.\n");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING InlineHook)
{
NTSTATUS status = 0;
UNICODE_STRING DriverNameString;
PDRIVER_OBJECT pDriverObject;
HookObReferenceObjectByHandle();
DriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}