Inline Hook

来源:互联网 发布:java经典编程 编辑:程序博客网 时间:2024/05/08 13:24
Inline Hook

什么是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真的太烂。

原创粉丝点击