阅读背景:

inlinehook(0环)

来源:互联网 
#include <ntddk.h>

//如何对函数做inlinehook?
//首先,弄清楚您要inlinehook的函数的定义。
//然后,获得要inline hook的函数的地址:
//如果是未导出的,根据特征码,暴力搜索内存;
//如果是导出的,可以直接使用函数名称做为它的地址或者使用MmGetSystemRoutineAddress
//拿到它的地址。如:
//NTKERNELAPI
//BOOLEAN
//KeInsertQueueApc (
//                IN PKAPC        Apc,
//                IN PVOID        SystemArgument1,
//                IN PVOID        SystemArgument2,
//                IN KPRIORITY    Increment
//                );
//那么KeInsertQueueApc就是该函数的首地址了。注意加上NTKERNELAPI。否则得用MmGetSystemRoutineAddress来拿地址
//
//拿到地址后,就可以做inlineHOOK了。
//将该地址的前五个字节,换成jmp T_MyFunc - Func - 5这个地方
//在T_MyFunc里压栈参数,调用MyFunc。执行完MyFunc之后,再JUMP到Func+5的地方执行。
//在卸载函数里,恢复Func,去掉inline hook

//所以,inlinehook一个Func函数,有如下几个任务:
//1。弄清要hook的函数Func的定义
//2。找到该函数Func的地址
//3。写出T_MyFunc,在里面将参数传给 MyFunc处理,然后跳转到Func后面执行
//4。实现 MyFunc函数,做你自己的处理
//5。inline hook函数,实现inlinehook,将Func函数跳转到T_MyFunc执行。在DriverEntry里调用
//6。inline hook卸载函数,在DriverUnload里调用

//要hook的函数声名
typedef NTSTATUS (*FuncDefine)(
                    PEPROCESS Process,
                    NTSTATUS ExitStatus
                    );
FuncDefine FuncAddress= NULL;
//未导出的函数声名
typedef NTSTATUS (*NTQUERYSYSTEMINFORMATION)(
                IN ULONG    SystemInformationClass,
                OUT PVOID   SystemInformation,
                IN ULONG    SystemInformationLength,
                OUT PULONG  ReturnLength OPTIONAL);
typedef unsigned long DWORD;    
NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;
//系统已加载的模块信息
#define SystemModuleInformation 11  
//用于记录模块信息的结构体
typedef struct _SYSTEM_MODULE_INFORMATION
{
    ULONG  Reserved[2];
    PVOID  Base;
    ULONG  Size;
    ULONG  Flags;
    USHORT Index;
    USHORT Unknown;
    USHORT LoadCount;
    USHORT ModuleNameOffset;
    CHAR   ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

PVOID GetFunctionAddressFromKernelMemory(VOID)
{

    ULONG                       size            = 0;
    ULONG                       index           = 0;
    PULONG                      buf             = NULL;
    ULONG                       i               = 0;
    PSYSTEM_MODULE_INFORMATION  module          = NULL;
    PVOID                       driverAddress   = 0;
    ULONG                       ntosknlBase     = 0;
    ULONG                       ntosknlEndAddr  = 0;
    ULONG                       curAddr         = 0;
    NTSTATUS                    status          = 0;
    ULONG                       retAddr         = 0;

    // 在内存中的函数的特征码
    ULONG code1_sp2=0x8b55ff8b,code2_sp2=0xa16456ec,code3_sp2=0x00000124,code4_sp2=0x3b08758b;
    //先查询获取大小
    NtQuerySystemInformation(SystemModuleInformation,&size, 0, &size);
    //再分配内存
    if(NULL==(buf = (PULONG)ExAllocatePoolWithTag(PagedPool, size, 'NLNI')))
    {
        DbgPrint("failed alloc memory failed \n");
        return 0;
    }
    //再查询
    status=NtQuerySystemInformation(SystemModuleInformation,buf, size , 0);
    if(!NT_SUCCESS( status ))
    {
        DbgPrint("failed query\n");
        return 0;
    }
    //保存相关信息
    module = (PSYSTEM_MODULE_INFORMATION)(( PULONG )buf + 1);
    ntosknlEndAddr=(ULONG)module->Base+(ULONG)module->Size;
    ntosknlBase=(ULONG)module->Base;
    curAddr=ntosknlBase;
    //已经保存了信息 释放刚才的缓冲区内存
    ExFreePool(buf);
    //暴力搜索内存 
    for (i=curAddr;i<=ntosknlEndAddr;i++)
    {
        if ((*((ULONG *)i)==code1_sp2)&&
            (*((ULONG *)(i+4))==code2_sp2)&&
            (*((ULONG *)(i+8))==code3_sp2)&&
            (*((ULONG*)(i+12))==code4_sp2)) 

        {
            retAddr=i;
            DbgPrint("adress is:%x",retAddr);
            return (PVOID)retAddr;

        }
    }
    return NULL;
}

ULONG GetFunctionAddr( IN PCWSTR FunctionName)

{
    UNICODE_STRING UniCodeFunctionName;

    RtlInitUnicodeString( &UniCodeFunctionName,FunctionName );
    return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );
}

NTSTATUS CheckFuncIsHook()
{
    int             i       = 0;
    char            *addr   = (char *)FuncAddress;
    char            code[]  = { 0x8b, 0xff, 0x55, 0x8b, 0xec};

    while(i<5)
    {
        DbgPrint("0x%02X", (unsigned char)addr[i]);
        if(addr[i] != code[i])
        {
            return STATUS_UNSUCCESSFUL;
        }
        i++;
    }
    return STATUS_SUCCESS;
}

int MyFunc(PEPROCESS Process,
           NTSTATUS ExitStatus
           )
{
    DbgPrint("MyFunc hello\n");
    return 1;
}

_declspec(naked) T_MyFunc(
                        PEPROCESS Process,
                        NTSTATUS ExitStatus
                        )
{
    _asm
    {
            mov edi, edi
            push ebp
            mov ebp ,esp
            //参数压栈,传给MyFunc
            push [ebp+0ch]
            push [ebp+8]
            call MyFunc 
            cmp eax,1
            jz end
            mov eax,FuncAddress 
            add eax,5 
            jmp eax

end:
        //恢复栈
        pop ebp
        retn 8
    }
}

VOID InlineHookFunc()
{ 

    int             JmpOffSet   = 0;
    unsigned char   JmpCode[5]  = { 0xe9, 0x00, 0x00, 0x00, 0x00 };
    KIRQL           oldIrql     = 0;

    if (FuncAddress == 0)
    {
        DbgPrint("Func NOT FOUND\n");
        return;
    }

    DbgPrint("Func is found at:0x%08x\n", (ULONG)FuncAddress );

    DbgPrint("T_MyFunc is:%x\n",T_MyFunc);
    JmpOffSet= (char*)T_MyFunc - (char*)FuncAddress - 5;
    DbgPrint("JmpOffSet is:%x\n",JmpOffSet);
    RtlCopyMemory ( JmpCode+1, &JmpOffSet, 4 );

    _asm
    {
        CLI
        MOV EAX, CR0
        AND EAX, NOT 10000H
        MOV CR0, EAX
    }
    oldIrql = KeRaiseIrqlToDpcLevel();
    RtlCopyMemory ( FuncAddress, JmpCode, 5 );
    DbgPrint("FuncAddress is hook now \n");
    KeLowerIrql(oldIrql);

    _asm
    {
        MOV EAX, CR0
        OR EAX, 10000H
        MOV CR0, EAX
        STI
    }

}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    //  在win2000上是三字节
    //  push ebp
    //  mov ebp, esp
    //        
    //  到了winxp以及后续系统上,则变成了五字节
    //  mov edi, edi
    //  push ebp
    //  mov ebp, esp
    //  函数的序言

    //恢复HOOK

    KIRQL           oldIrql = 0;
    LARGE_INTEGER   Delay   = {0};
    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 ( FuncAddress, Code, 5 );
    __asm
    {
        MOV   eax, CR0
        OR    eax, 10000H
        MOV   CR0, eax
        STI
    }
    KeLowerIrql(oldIrql);

    DbgPrint("Goodbye driver\n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
    //未导出的函数
    FuncAddress = GetFunctionAddressFromKernelMemory();
    //导出的函数
    //FuncAddress = GetFunctionAddr(L"FuncName");

    if(STATUS_SUCCESS != CheckFuncIsHook())
    {
        DbgPrint("Func Match Failed !");
        return STATUS_UNSUCCESSFUL;
    }
    //inline hook它
    InlineHookFunc();

    pDriverObject->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;

}#include <ntddk.h>

//如何对函数做inlinehook?
//首先,弄清楚



你的当前访问异常,请进行认证后继续阅读剩余内容。

分享到: