什么是Inline Hook?Inline Hook就是通过修改目标函数的内容,跳转到自定义函数,来实现对目标的Hook.
对于非首字节的跳转,必须在自定义函数里实现目标函数的跳转前的内容。
对于Inline Hook没有什么太多需要讲的地方,就象某人说的inline hook不是技术,只是技巧。
当目标函数导出的时候我们可以直接获取到他的地址(后面的例子即是如此)。如果没有导出,我们就需要想办法了。对于这个问题,我们有并不很理想方法:暴搜。(当目标被patch后就会产生一些问题)
暴搜的原理是:通过导出的函数通过特征码暴搜目标函数的地址。比如:函数A 调用了B。B是我们要获取的目标函数。我们可以从A的首地址线性搜索一定的长度(长度根据目标B在A位置来决定)来得到目标函数在A中调用的内存地址。然后通过下面的公式得到B函数的地址。
B函数的地址 = B在A中的地址+CALL地址+5
是不是晕了?没关系。Follow me!
PsGetNextProcessThread是一个没有被导出的函数。想得到这个函数我们可以从很多导出的函数里看到。这里我们选择nt!NtTerminateProcess。
利用我们上面的公式。目标函数的地址 8057EAEC = 80583396+FFFFB751+5 。
下面的问题是我们如何才能定位到这个地址。
我们可以从NtTerminateProcess是首地址开始扫描,根据下面的特征码来定位。
e851b7fffff 就可以找到我们的目标位置。然后利用上面的地址换算公式找到目标函数的内存地址。
下面的代码通过以导出函数进行Inline Hook.代码并非出自本人之手。对作者表示敬意。
extern "C"
{
#include "ntddk.h"
#include <windef.h>
extern POBJECT_TYPE *PsProcessType;
VOID InlineHookObReferenceObjectByHandle();
VOID UnHook();
T_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
);
}
char* ProtectName = "notepad.exe";
int MyObReferenceObjectByHandle(
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
)
{
PEPROCESS Process;
KIRQL oldIrql;
int JmpOffSet;
unsigned char Code[5]={0x8b,0xff,0x55,0x8b,0xec};
unsigned char JmpCode[5] = { 0xe9, 0x00, 0x00, 0x00, 0x00 };
if(*PsProcessType==ObjectType)//判断句柄所属对象类型是不是*PsProcessType
{
oldIrql = KeRaiseIrqlToDpcLevel();
__asm
{
CLI
MOV eax, CR0
AND eax, NOT 10000H
MOV CR0, eax
}
RtlCopyMemory ( ObReferenceObjectByHandle, Code, 5 );
ObReferenceObjectByHandle(Handle,DesiredAccess,ObjectType,AccessMode,(PVOID *)&Process,NULL);
if (_stricmp((char*)((char*)Process+0x174), ProtectName) == 0 )
{
JmpOffSet= (char*)T_ObReferenceObjectByHandle - (char*)ObReferenceObjectByHandle - 5;
RtlCopyMemory ( JmpCode+1, &JmpOffSet, 4 );
RtlCopyMemory ( ObReferenceObjectByHandle, JmpCode, 5 );
__asm
{
MOV eax, CR0
OR eax, 10000H
MOV CR0, eax
STI
}
KeLowerIrql(oldIrql);
return 1;
}
JmpOffSet= (char*)T_ObReferenceObjectByHandle - (char*)ObReferenceObjectByHandle - 5;
RtlCopyMemory ( JmpCode+1, &JmpOffSet, 4 );
RtlCopyMemory ( ObReferenceObjectByHandle, JmpCode, 5 );
__asm
{
MOV eax, CR0
OR eax, 10000H
MOV CR0, eax
STI
}
KeLowerIrql(oldIrql);
}
return 0;
}
__declspec(naked) T_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
)
{
_asm
{
mov edi,edi
push ebp
mov ebp,esp
push [ebp+0x1c]
push [ebp+0x18]
push [ebp+0x14]
push [ebp+0x10]
push [ebp+0xc]
push [ebp+8]
call MyObReferenceObjectByHandle
cmp eax,1
jz end
mov eax,ObReferenceObjectByHandle
add eax,5
jmp eax
end:
mov [ebp+8],-1
mov eax,ObReferenceObjectByHandle
add eax,5
jmp eax
}
}
VOID InlineHookObReferenceObjectByHandle()
{
int JmpOffSet;
unsigned char JmpCode[5] = { 0xe9, 0x00, 0x00, 0x00, 0x00 };
KIRQL oldIrql;
DbgPrint("T_PspTerminateProcess is:%x\n",T_ObReferenceObjectByHandle);
//计算我的函数中继地址
JmpOffSet= (char*)T_ObReferenceObjectByHandle - (char*)ObReferenceObjectByHandle - 5;
DbgPrint("JmpOffSet is:%x\n",JmpOffSet);
//INITLIZATION JMPCODE为中继函数的地址
RtlCopyMemory ( JmpCode+1, &JmpOffSet, 4 );
oldIrql = KeRaiseIrqlToDpcLevel();
_asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H
MOV CR0, EAX
}
RtlCopyMemory ( ObReferenceObjectByHandle, JmpCode, 5 );
DbgPrint("ObReferenceObjectByHandle is hook now \n");
_asm
{
MOV EAX, CR0
OR EAX, 10000H
MOV CR0, EAX
STI
}
KeLowerIrql(oldIrql);
}
VOID Unload(PDRIVER_OBJECT DriverObject)
{
KIRQL oldIrql;
LARGE_INTEGER Delay;
unsigned char Code[5]={0x8b,0xff,0x55,0x8b,0xec};
Delay.QuadPart = -5000000;
KeDelayExecutionThread(KernelMode, TRUE, &Delay);
oldIrql = KeRaiseIrqlToDpcLevel();
__asm
{
CLI
MOV eax, CR0
AND eax, NOT 10000H
MOV CR0, eax
}
RtlCopyMemory ( ObReferenceObjectByHandle, Code, 5 );
__asm{
MOV eax, CR0
OR eax, 10000H
MOV CR0, eax
STI
}
KeLowerIrql(oldIrql);
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING str)
{
DriverObject->DriverUnload = Unload;
InlineHookObReferenceObjectByHandle();
return STATUS_SUCCESS;
}
最后要说ALT+F8真的太烂。