R0下Inline Hook模板

来源:互联网 发布:创维电视直播软件 编辑:程序博客网 时间:2024/06/06 03:35
 

InlineHook 已导出函数

VOID  
HookObReferenceObjectByHandle()
{  
    KIRQL Irql;
    KdPrint(("[ObReferenceObjectByHandle] :0x%x",ObReferenceObjectByHandle));  //地址验证
    //保存函数前五个字节内容
    RtlCopyMemory(OriginalBytes,(BYTE *)ObReferenceObjectByHandle,5);
    //保存新函数五个字节之后偏移地址
    *(ULONG *)(JmpAddress+1)=(ULONG)DetourMyObReferenceObjectByHandle-((ULONG)ObReferenceObjectByHandle+5);

    _asm 
    {
        push eax   
        mov eaxcr0 
        mov CR0VALUE, eax 
        and eax, 0fffeffffh  
        mov cr0eax
        pop eax
    }
    
    Irql=KeRaiseIrqlToDpcLevel();
    //函数开头五个字节写JMP 
    RtlCopyMemory((BYTE *)ObReferenceObjectByHandle,JmpAddress,5);
    KeLowerIrql(Irql);
    
    __asm  
    {       
        push eax
        mov eax, CR0VALUE 
        mov cr0eax
        pop eax
    }
}

_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  // 手动写ObReferenceObjectByHandle函数开头的五个字节, 可用WinDbg查看
        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)) // 如果是关闭软件, 从DesiredAccess == 1可知
    {   
        if(ObjectType== *PsProcessType)  
        { 
            if( _stricmp((char *)((ULONG)(*Object)+0x174),"notepad.exe")==0) 
            {   
                ObDereferenceObject(*Object);
                return STATUS_INVALID_HANDLE;
            }
        }
    }

    return status;
}

void 
UnHookObReferenceObjectByHandle()
{
    KIRQL Irql;

    _asm    
    {
        push eax
        mov eaxcr0 
        mov CR0VALUE, eax 
        and eax, 0fffeffffh  
        mov cr0eax
        pop eax        
    }
    
    Irql=KeRaiseIrqlToDpcLevel();
    //还原开头的五个字节
    RtlCopyMemory((BYTE *)ObReferenceObjectByHandle,OriginalBytes,5);
    KeLowerIrql(Irql);
    
    __asm    
    {           
        push eax
        mov eax, CR0VALUE 
        mov cr0eax
        pop eax        
    }
}




InlineHook 未已导出函数

//1、获取KeInsertQueueApc地址
ULONG GetFunctionAddr( IN PCWSTR FunctionName)     //PCWSTR常量指针,指向16位UNICODE
{
    UNICODE_STRING UniCodeFunctionName;
    RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
    return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );   
}

ULONG GetKiInsertQueueApcAddr()
{
    
/*
    804fd4d3 894728          mov     dword ptr [edi+28h],eax
    804fd4d6 e8dd340000      call    nt!KiInsertQueueApc (805009b8)
    804fd4db 8ad8            mov     bl,al
    */

    ULONG sp_code1=0x28,sp_code2=0xe8,sp_code3=0xd88a;  //特征码
    ULONG address=0;
    PUCHAR addr;
    PUCHAR p;
    addr=(PUCHAR)GetFunctionAddr(L"KeInsertQueueApc");
    for(p=addr;p<p+PAGE_SIZE;p++)
    {
        if((*(p-1)==sp_code1)&&(*p==sp_code2)&&(*(PUSHORT)(p+5)==sp_code3))
        {
            // 地址换算
            // 0x804fd4d6 + 0x000034dd + 0x5 =  0x805009b8
            address=*(PULONG)(p+1)+(ULONG)(p+5);
            break;
        }
    }
    KdPrint(("[KeInsertQueueApc] addr %x\n",(ULONG)addr));
    KdPrint(("[KiInsertQueueApc] address %x\n",address));
    return address;
}

VOID HookKiInsertQueueApc()
{   
    KIRQL Irql;

    g_KiInsertQueueApc = GetKiInsertQueueApcAddr();
    KdPrint(("[KiInsertQueueApc] KiInsertQueueApc %x\n",g_KiInsertQueueApc));

    // 保存原函数的前5字节内容
    RtlCopyMemory (OriginalBytes, (BYTE*)g_KiInsertQueueApc, 5);

    // 新函数对原函数的偏移地址
    *( (ULONG*)(JmpAddress + 1) ) = (ULONG)DetourMyKiInsertQueueApc - ((ULONG)g_KiInsertQueueApc + 5);

    WPOFF();
    Irql = KeRaiseIrqlToDpcLevel();
    RtlCopyMemory ( (BYTE*)g_KiInsertQueueApc, JmpAddress, 5 );
    KeLowerIrql(Irql);
    WPON();  
}

//原函数
_declspec (nakedVOID FASTCALL OriginalKiInsertQueueApc(IN PKAPC Apc,IN KPRIORITY Increment)
{
    _asm
    {
        //原函数前五个字节
        mov edi,edi
        push ebp
        mov ebp,esp
        
        mov eax,g_KiInsertQueueApc
        add eax,5
        jmp eax
    }
}

//处理函数
//apc--kthread--apc_state--eprocess
VOID FASTCALL DetourMyKiInsertQueueApc(IN PKAPC Apc,IN KPRIORITY Increment)
{
    ULONG thread;
    ULONG process;
    
    if(MmIsAddressValid((PULONG)((ULONG)Apc+0x008)))    //地址验证 KAPC结构+008--->kthread
        thread=*((PULONG)((ULONG)Apc+0x008));
    else
        return ;
    if(MmIsAddressValid((PULONG)((ULONG)thread+0x044))) //kthread+34-->KAPC_STATE+10-->eprocess
        process=*((PULONG)((ULONG)thread+0x044));
    else
        return ;
    if(MmIsAddressValid((PULONG)((ULONG)process+0x174)))  //eprocess+174---->进程名字
    {
        if((_stricmp((char *)((ULONG)process+0x174),"notepad.exe")==0)&&(Increment==2))
            return ;
        else
            OriginalKiInsertQueueApc(Apc,Increment);    
    }
    else
        return;
}


MJ大牛的猥琐InlineHook大法(加了点自己的注释和完善了下Unload)

先用WinDbg看下具体的函数


Hook示意图:



代码如下:

 

NTSTATUS InlineHookFuncXP(IN PVOID FuncAddress, 
                         IN PVOID NewFuncAddress) 

    //FuncAddress:orignal function address 
    //NewFuncAddress:new function address to hook 
    //if function successed,the old function which the hook function will jump to 
    //is the FuncAddress+2 

    KIRQL OldIrql ; 
    NTSTATUS stat; 

    KeAcquireSpinLock( &SDTSpinLock, &OldIrql ); 

    WPOFF(); 
    //保存原函数的头两个字节
    RtlCopyMemory(OriginalBytes,(BYTE *)ObReferenceObjectByHandle,2);

    __asm 
    { 
        push eax 
        push ecx 
        lea eax,[FuncAddress] 
        mov eax,[eax
        cmp byte ptr[eax],0x8b        
        jnz failtohook 
        cmp byte ptr[eax+1],0xff  ;判断函数开始头部是不是 "mov edi,edi" 
        jnz failtohook 
        mov ecx,0xffffffff          ;-1
loopcheck: 
        cmp byte ptr[eax+ecx],0x90 
        jnz failtohook 
        dec ecx 
        cmp ecx,0xfffffffa ;循环5次, 判断函数开始上面部分是不是"nop"
        jnz loopcheck 

        mov byte ptr[eax],0xeb    ; 短跳jmp
        mov byte ptr[eax+1],0xf9 ; 0-偏移量-指令长度 = 0x00-5-2 = f9 
        ;write the new function header:jmp short funcaddr-5(0x00-0x07) 
        mov byte ptr[eax-5],0xe9 ;远跳jmp
        ;write 1 byte :jmp xxxxx 
        mov ecx,[NewFuncAddress] 
        sub ecx,eax        ;得到跳转的相对偏移
        mov dword ptr[eax-4],ecx 
        jmp hookok 
failtohook: 
        mov stat,0xc0000001 
        jmp end 
hookok: 
        mov stat,0 
end: 
        pop ecx 
        pop eax 
    } 
    WPON(); 
    KeReleaseSpinLock( &SDTSpinLock, OldIrql ); 

    return stat; 
}

VOID UnInlineHookFuncXP(IN PVOID FuncAddress) 
{
    KIRQL OldIrql ; 
    NTSTATUS stat; 
    
    KeAcquireSpinLock( &SDTSpinLock, &OldIrql ); 
    WPOFF(); 

    // 恢复函数的前两个字节
    RtlCopyMemory((BYTE *)FuncAddress, OriginalBytes, 2);

    // 恢复函数上面的5个nop
    __asm 
    {
        push ecx 
        push eax
        lea eax,[FuncAddress] 
        mov eax,[eax]
        mov ecx,0xffffffff          ;-1
loopcheck: 
        mov byte ptr[eax+ecx],0x90 
        dec ecx 
        cmp ecx,0xfffffffa 
        jnz loopcheck 
        pop eax
        pop ecx
    }

    WPON(); 
    KeReleaseSpinLock( &SDTSpinLock, OldIrql ); 
}

 

原创粉丝点击