首页
论坛
专栏
课程

[系统底层] [求助]inline hook -- KiInsertQueueApc 怎么会蓝啊

2008-3-22 12:04 12607

[系统底层] [求助]inline hook -- KiInsertQueueApc 怎么会蓝啊

2008-3-22 12:04
12607
inline hook --  KiInsertQueueApc 。但是总是BSOD,之前俺已经得到KiInsertQueueApc的地址了,至于inline hook部分,就是很普通的code了:

BYTE g_HookCode[5] = { 0xe9, 0, 0, 0, 0 };
BYTE g_OrigCode[5] = { 0 }; // 原函数的前字节内容
BYTE jmp_orig_code[7] = { 0xEA, 0, 0, 0, 0, 0x08, 0x00 };

BOOL g_bHooked = FALSE;

//
// 停止inline hook
//
VOID UnHookKiInsertQueueApc ()
{
    KIRQL  oldIrql;

    WPOFF();
    oldIrql = KeRaiseIrqlToDpcLevel();
   
    RtlCopyMemory ( (BYTE*)KiInsertQueueApc, g_OrigCode, 5 );

    KeLowerIrql(oldIrql);
    WPON();

    g_bHooked = FALSE;
}

//
// 开始inline hook --  KiInsertQueueApc
//
VOID HookKiInsertQueueApc ()
{
    KIRQL  oldIrql;

    if ( KiInsertQueueApc == NULL) {
        DbgPrint("KiInsertQueueApc == NULL\n");
        return;
    }

    //DbgPrint("开始inline hook --  KiInsertQueueApc\n");
    DbgPrint( "KiInsertQueueApc的地址t0x%08x\n", (ULONG)KiInsertQueueApc );
    // 保存原函数的前字节内容
    RtlCopyMemory (g_OrigCode, (BYTE*)KiInsertQueueApc, 5);
    *( (ULONG*)(g_HookCode + 1) ) = (ULONG)fake_KiInsertQueueApc - (ULONG)KiInsertQueueApc - 5;
   
   
    // 禁止系统写保护,提升IRQL到DPC
    WPOFF();
    oldIrql = KeRaiseIrqlToDpcLevel();

   
    RtlCopyMemory ( (BYTE*)KiInsertQueueApc, g_HookCode, 5 );
    *( (ULONG*)(jmp_orig_code + 1) ) = (ULONG) ( (BYTE*)KiInsertQueueApc + 5 );
   
    RtlCopyMemory ( (BYTE*)Proxy_KiInsertQueueApc, g_OrigCode, 5);
    RtlCopyMemory ( (BYTE*)Proxy_KiInsertQueueApc + 5, jmp_orig_code, 7);

    // 恢复写保护,降低IRQL
    KeLowerIrql(oldIrql);
    WPON();

    g_bHooked = TRUE;
   
   
}

//
// 跳转到我们的函数里面进行预处理
//
VOID
fake_KiInsertQueueApc (
    PKAPC Apc,
    KPRIORITY Increment
    )
{
    // 预处理

    DbgPrint("inline hook --  KiInsertQueueApc 成功\n");
    Proxy_KiInsertQueueApc( Apc, Increment );
}

//
// 代理函数,负责跳转到原函数中继续执行
//
__declspec (naked)
VOID
Proxy_KiInsertQueueApc (
    PKAPC Apc,
    KPRIORITY Increment
    )
{
    __asm {  // 共字节
        _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90  // 前字节实现原函数的头字节功能
            _emit 0x90  // 这个填充jmp
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90  // 这字节保存原函数+5处的地址
            _emit 0x90  
            _emit 0x90  // 因为是长转移,所以必须是0x0080
    }
}

想来想去都不知道是哪里出问题了。神秘的 KiInsertQueueApc 啊。到底问题出在哪里呀?

下面是Dump 文件的分析 --

BugCheck D1, {0, 2, 0, 0}

Probably caused by : ntoskrnl.exe ( nt!KiTrap0E+233 )

Followup: MachineOwner
---------

kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.
Arguments:
Arg1: 00000000, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000000, value 0 = read operation, 1 = write operation
Arg4: 00000000, address which referenced memory

Debugging Details:
------------------

READ_ADDRESS:  00000000

CURRENT_IRQL:  2

FAULTING_IP:
+0
00000000 ??              ???

PROCESS_NAME:  services.exe

DEFAULT_BUCKET_ID:  INTEL_CPU_MICROCODE_ZERO

BUGCHECK_STR:  0xD1

TRAP_FRAME:  f9ce5c94 -- (.trap 0xfffffffff9ce5c94)
ErrCode = 00000000
eax=00000201 ebx=00000000 ecx=00000009 edx=8055af48 esi=80d72958 edi=ffad2d38
eip=00000000 esp=f9ce5d08 ebp=ffad2d38 iopl=0         nv up ei pl nz na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010206
00000000 ??              ???
Resetting default scope

LAST_CONTROL_TRANSFER:  from 00000000 to 804e287f

FAILED_INSTRUCTION_ADDRESS:
+0
00000000 ??              ???

STACK_TEXT:  
f9ce5c94 00000000 badb0d00 8055af48 80562b40 nt!KiTrap0E+0x233
WARNING: Frame IP not in any known module. Following frames may be wrong.
f9ce5d04 ffad2d38 00000000 00000000 80590709 0x0
f9ce5d10 80590709 ffad2d38 80d72900 f9ce5d48 0xffad2d38
f9ce5d48 804df7ec 80d72958 7c94da87 000c5ac0 nt!NtQueueApcThread+0x80
f9ce5d48 7c92eb94 80d72958 7c94da87 000c5ac0 nt!KiFastCallEntry+0xf8
007dfe28 7c92e249 7c94da32 000001ac 7c94da87 0x7c92eb94
007dfe60 7c94dcb2 000001ac 00000000 007dfe80 0x7c92e249
007dfe70 01010bf2 000c5ac0 010144cb 007dfe8c 0x7c94dcb2
007dfe80 010144e3 00000438 007dfed8 7c947911 0x1010bf2
007dfe8c 7c947911 00000438 000c5a00 000c5ac0 0x10144e3
007dffa4 806efc35 7c947569 000d1a90 007dffec 0x7c947911
007dffa4 007dff74 7c947569 000d1a90 007dffec hal!HalpApcInterrupt+0xc5
7c99c3a0 00000000 00000000 00000000 00000000 0x7dff74

STACK_COMMAND:  kb

FOLLOWUP_IP:
nt!KiTrap0E+233
804e287f f7457000000200  test    dword ptr [ebp+70h],20000h

SYMBOL_STACK_INDEX:  0

SYMBOL_NAME:  nt!KiTrap0E+233

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: nt

IMAGE_NAME:  ntoskrnl.exe

DEBUG_FLR_IMAGE_TIMESTAMP:  45e54711

FAILURE_BUCKET_ID:  0xD1_CODE_AV_NULL_IP_nt!KiTrap0E+233

BUCKET_ID:  0xD1_CODE_AV_NULL_IP_nt!KiTrap0E+233

Followup: MachineOwner
---------

还忘大牛指点一二啊

[公告][征集寄语] 看雪20周年年会 | 感恩有你,一路同行

最新回复 (18)
forgot 26 2008-3-22 12:23
2
0
好像Proxy_KiInsertQueueApc 没处理 fake_KiInsertQueueApc 的 stackframe,出来之前要leave一次
sudami 25 2008-3-22 13:08
3
0
是不是这样:

//
// 代理函数,负责跳转到原函数中继续执行
//
__declspec (naked)
VOID
Proxy_KiInsertQueueApc (
    PKAPC Apc,
    KPRIORITY Increment
    )
{
    __asm {  // 共字节
        _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90  // 前字节实现原函数的头字节功能
            _emit 0x90  // 这个填充jmp
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90  // 这字节保存原函数+5处的地址
            _emit 0x90  
            _emit 0x90  // 因为是长转移,所以必须是0x0080
    }

    __asm {
                add esp,8
                pop ebp
                ret 8
        }

}

偶对堆栈平衡还不是很熟悉,还忘forgot牛提示一下~
forgot 26 2008-3-22 13:17
4
0
后面都跳走了,你pop ebp有啥用啊

__declspec (naked)
VOID
Proxy_KiInsertQueueApc (
/*PKAPC Apc,
KPRIORITY Increment*////////////////////这个不能再搞了。。。
)
{
__asm { // 共字节
leave////////////////////////////////////fixup
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90 // 前字节实现原函数的头字节功能
_emit 0x90 // 这个填充jmp
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90 // 这字节保存原函数+5处的地址
_emit 0x90
_emit 0x90 // 因为是长转移,所以必须是0x0080
}
sudami 25 2008-3-22 13:41
5
0
哦,俺试试看。

先谢过~

----------------------------------------
按照forgot同学的提示改了之后,还是蓝:

PAGE_FAULT_IN_NONPAGED_AREA

偶看看dump文件~~~~~
forgot 26 2008-3-22 14:07
6
0
你把编译出的代码看看就知道了

naked的怎么传参数的?
sudami 25 2008-3-22 14:31
7
0
naked是裸函数,若函数需要返回,得由调用者自己来做.

//
// 开始inline hook --  KiInsertQueueApc
//
VOID HookKiInsertQueueApc ()
{
        KIRQL  oldIrql;

        if ( KiInsertQueueApc == NULL) {
                DbgPrint("KiInsertQueueApc == NULL\n");
                return;
        }

        //DbgPrint("开始inline hook --  KiInsertQueueApc\n");
        DbgPrint( "KiInsertQueueApc的地址:\t0x%08x\n", (ULONG)KiInsertQueueApc );
        // 保存原函数的前5字节内容
        RtlCopyMemory (g_OrigCode, (BYTE*)KiInsertQueueApc, 5);
        *( (ULONG*)(g_HookCode + 1) ) = (ULONG)fake_KiInsertQueueApc - (ULONG)KiInsertQueueApc - 5;
       
       
        // 禁止系统写保护,提升IRQL到DPC
        WPOFF();
        oldIrql = KeRaiseIrqlToDpcLevel();

       
        RtlCopyMemory ( (BYTE*)KiInsertQueueApc, g_HookCode, 5 );
        *( (ULONG*)(jmp_orig_code + 1) ) = (ULONG) ( (BYTE*)KiInsertQueueApc + 5 );
       
        RtlCopyMemory ( (BYTE*)Proxy_KiInsertQueueApc + 7, g_OrigCode, 5);
        RtlCopyMemory ( (BYTE*)Proxy_KiInsertQueueApc + 12, jmp_orig_code, 7);

        // 恢复写保护,降低IRQL
        KeLowerIrql(oldIrql);
        WPON();

        g_bHooked = TRUE;
       
       
}

//
// 跳转到我们的函数里面进行预处理
//
VOID
fake_KiInsertQueueApc (
        PKAPC Apc,
        KPRIORITY Increment
        )
{
        // 预处理
           // 这里仅仅是测试,看是否成功,所以就只打印一个消息   

        DbgPrint("inline hook --  KiInsertQueueApc 成功\n");
        Proxy_KiInsertQueueApc();
}

//
// 代理函数,负责跳转到原函数中继续执行
//
__declspec (naked)
VOID
Proxy_KiInsertQueueApc ()
{
        __asm {  //共7字节
                add esp, 8
                pop ebp
                ret 8
        }


        __asm {  // 共12字节
                _emit 0x90
                        _emit 0x90
                        _emit 0x90
                        _emit 0x90
                        _emit 0x90  // 前5字节实现原函数的头5字节功能
                        _emit 0x90  // 这个填充jmp
                        _emit 0x90
                        _emit 0x90
                        _emit 0x90
                        _emit 0x90  // 这4字节保存原函数+5处的地址
                        _emit 0x90  
                        _emit 0x90  // 因为是长转移,所以必须是 0x0080
        }
}

这是修改后的code,红色部分即是.

加载后蓝掉:

BAD_POOL_CALLER (c2)
The current thread is making a bad pool request. Typically this is at a bad IRQL level or double freeing the same allocation, etc.
Arguments:
Arg1: 00000040, Attempt to free usermode address to kernel pool
Arg2: 00000000, Starting address
Arg3: 80000000, Start of system address space
Arg4: 00000000, 0


Debugging Details:
------------------


FAULTING_IP:
nt!NtQueueApcThread+98
805fab23 bb010000c0 mov ebx,0C0000001h

BUGCHECK_STR: 0xc2_40

DEFAULT_BUCKET_ID: INTEL_CPU_MICROCODE_ZERO

PROCESS_NAME: services.exe

LAST_CONTROL_TRANSFER: from 8054b0a8 to 8053454e

STACK_TEXT:
f8600cac 8054b0a8 000000c2 00000040 00000000 nt!KeBugCheckEx+0x1b
f8600ce8 8054bd8b 00000000 00000000 80590709 nt!MiFreePoolPages+0x94
f8600d28 805fab23 00000000 80590709 f8600d64 nt!ExFreePoolWithTag+0x1b7
f8600d48 804df7ec 80d82c20 7c94da87 000d1a60 nt!NtQueueApcThread+0x98
f8600d48 7c92eb94 80d82c20 7c94da87 000d1a60 nt!KiFastCallEntry+0xf8
WARNING: Frame IP not in any known module. Following frames may be wrong.
007dfe60 00000000 00000000 00000000 00000000 0x7c92eb94


STACK_COMMAND: kb

FOLLOWUP_IP:
nt!NtQueueApcThread+98
805fab23 bb010000c0 mov ebx,0C0000001h

SYMBOL_STACK_INDEX: 3

SYMBOL_NAME: nt!NtQueueApcThread+98

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: nt

IMAGE_NAME: ntoskrnl.exe

DEBUG_FLR_IMAGE_TIMESTAMP: 45e54711

FAILURE_BUCKET_ID: 0xc2_40_nt!NtQueueApcThread+98

BUCKET_ID: 0xc2_40_nt!NtQueueApcThread+98

Followup: MachineOwner
---------



很是无语~
forgot 26 2008-3-22 16:11
8
0
太衰了,你怎么改成这样了。。。
zhuwg 11 2008-3-22 19:25
9
0
你是怎么写的代码啊?
Proxy_KiInsertQueueApc ()
{
  __asm {  //共7字节
    add esp, 8
    pop ebp
    ret 8
  }

  __asm {  // 共12字节
    _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90  // 前5字节实现原函数的头5字节功能
      _emit 0x90  // 这个填充jmp
      _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90  // 这4字节保存原函数+5处的地址
      _emit 0x90  
      _emit 0x90  // 因为是长转移,所以必须是 0x0080
  }
}

那个前面的你怎么能够这样写
你没有明白hook代码怎么运转啊

你是怎么写的代码啊?
Proxy_KiInsertQueueApc ()
{
  __asm {  // 共12字节
    _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90  // 前5字节实现原函数的头5字节功能
      _emit 0x90  // 这个填充jmp
      _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90  // 这4字节保存原函数+5处的地址
      _emit 0x90  
      _emit 0x90  // 因为是长转移,所以必须是 0x0080
  }
}
先去你的函数 回来以后直接call原始函数?
发现你写代码顺序有问题啊
hook应该是KiInsertQueueApc-
MyKiInsertQueueApc-OldKiInsertQueueApc-MyKiInsertQueueApc-回上层

建议你使用MSREM的hooklib
fancily 2008-3-22 19:35
10
0
现在还看不懂...偶也要学了....
combojiang 26 2008-3-24 09:58
11
0
这么写不会有问题。
#include <ntddk.h>
#include <ntifs.h>
ULONG g_KiInsertQueueApc;
char g_oricode[8];
ULONG g_uCr0;
char *non_paged_memory;

void WPOFF()
{
   
    ULONG uAttr;
   
    _asm
    {
        push eax;
        mov eax, cr0;
        mov uAttr, eax;
        and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
        mov cr0, eax;
        pop eax;
        cli
    };
   
    g_uCr0 = uAttr; //保存原有的 CRO 屬性
   
}

VOID WPON()
{
   
    _asm
    {
        sti
        push eax;
        mov eax, g_uCr0; //恢復原有 CR0 屬性
        mov cr0, eax;
        pop eax;
    };
   
}

__declspec(naked) my_function_detour_KiInsertQueueApc()
{
        __asm
        {               
                mov edi,edi
                push ebp
                mov        ebp, esp
                push ecx
                mov eax,ecx
                _emit 0xEA
                _emit 0xAA
                _emit 0xAA
                _emit 0xAA
                _emit 0xAA
                _emit 0x08
                _emit 0x00
        }
}

ULONG GetFunctionAddr( IN PCWSTR FunctionName)
{
    UNICODE_STRING UniCodeFunctionName;
    RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
    return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );   

}

//根据特征值,从KeInsertQueueApc搜索中搜索KiInsertQueueApc
ULONG FindKiInsertQueueApcAddress()
{
        char * Addr_KeInsertQueueApc = 0;
        int i = 0;
        char Findcode[] = { 0xE8, 0xcc, 0x29, 0x00, 0x00 };
        ULONG Addr_KiInsertQueueApc = 0;
    Addr_KeInsertQueueApc = (char *) GetFunctionAddr(L"KeInsertQueueApc");
        for(i = 0; i < 100; i ++)
        {
        if( Addr_KeInsertQueueApc[i] == Findcode[0] &&
                        Addr_KeInsertQueueApc[i + 1] == Findcode[1] &&
                        Addr_KeInsertQueueApc[i + 2] == Findcode[2] &&
                        Addr_KeInsertQueueApc[i + 3] == Findcode[3] &&
                        Addr_KeInsertQueueApc[i + 4] == Findcode[4]
                        )
                {
                        Addr_KiInsertQueueApc = (ULONG)&Addr_KeInsertQueueApc[i] + 0x29cc + 5;
                        break;
                }
        }
        return Addr_KiInsertQueueApc;
}

VOID DetourFunctionKiInsertQueueApc()
{

        char *actual_function = (char *)g_KiInsertQueueApc;
        unsigned long detour_address;
        unsigned long reentry_address;
        KIRQL oldIrql;
        int i = 0;

        char newcode[] = { 0xEA, 0x44, 0x33, 0x22, 0x11, 0x08, 0x00, 0x90 };

        reentry_address = ((unsigned long)g_KiInsertQueueApc) + 8;

        non_paged_memory = ExAllocatePool(NonPagedPool, 256);
       
        for(i=0;i<256;i++)
        {
                ((unsigned char *)non_paged_memory)[i] = ((unsigned char *)my_function_detour_KiInsertQueueApc)[i];
        }

        detour_address = (unsigned long)non_paged_memory;
       
        *( (unsigned long *)(&newcode[1]) ) = detour_address;

        for(i=0;i<200;i++)
        {
                if( (0xAA == ((unsigned char *)non_paged_memory)[i]) &&
                        (0xAA == ((unsigned char *)non_paged_memory)[i+1]) &&
                        (0xAA == ((unsigned char *)non_paged_memory)[i+2]) &&
                        (0xAA == ((unsigned char *)non_paged_memory)[i+3]))
                {
                        *( (unsigned long *)(&non_paged_memory[i]) ) = reentry_address;
                        break;
                }
        }

    oldIrql = KeRaiseIrqlToDpcLevel();
        for(i=0;i < 8;i++)
        {
                g_oricode[i] = actual_function[i];
                actual_function[i] = newcode[i];
        }
    KeLowerIrql(oldIrql);
}

VOID UnDetourFunction()
{
    char *actual_function = (char *)g_KiInsertQueueApc;
        KIRQL oldIrql;
        int i = 0;
       
        WPOFF();
        oldIrql = KeRaiseIrqlToDpcLevel();

        for(i=0;i < 8;i++)
        {
                actual_function[i] = g_oricode[i];
        }
    KeLowerIrql(oldIrql);
    WPON();
        ExFreePool(non_paged_memory);
}

VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
        DbgPrint("My Driver Unloaded!");
        UnDetourFunction();
}

NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
        DbgPrint("My Driver Loaded!");
        theDriverObject->DriverUnload = OnUnload;
               
    g_KiInsertQueueApc = FindKiInsertQueueApcAddress();
        DetourFunctionKiInsertQueueApc();

        return STATUS_SUCCESS;
}
combojiang 26 2008-3-24 11:04
12
0
这样也可以。
#include <ntddk.h>
#include <ntifs.h>
#include <windef.h>
ULONG g_KiInsertQueueApc;
ULONG g_uCr0;

BYTE g_HookCode[5] = { 0xe9, 0, 0, 0, 0 };
BYTE g_OrigCode[5] = { 0 }; // 原函数的前字节内容
BYTE jmp_orig_code[7] = { 0xEA, 0, 0, 0, 0, 0x08, 0x00 };

BOOL g_bHooked = FALSE;

VOID
fake_KiInsertQueueApc (
    PKAPC Apc,
    KPRIORITY Increment
    );
   
VOID
Proxy_KiInsertQueueApc (
    PKAPC Apc,
    KPRIORITY Increment
    );

void WPOFF()
{
   
    ULONG uAttr;
   
    _asm
    {
        push eax;
        mov eax, cr0;
        mov uAttr, eax;
        and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
        mov cr0, eax;
        pop eax;
        cli
    };
   
    g_uCr0 = uAttr; //保存原有的 CRO 屬性
   
}

VOID WPON()
{
   
    _asm
    {
        sti
        push eax;
        mov eax, g_uCr0; //恢復原有 CR0 屬性
        mov cr0, eax;
        pop eax;
    };
   
}

//
// 停止inline hook
//
VOID UnHookKiInsertQueueApc ()
{
    KIRQL  oldIrql;

    WPOFF();
    oldIrql = KeRaiseIrqlToDpcLevel();
   
    RtlCopyMemory ( (BYTE*)g_KiInsertQueueApc, g_OrigCode, 5 );

    KeLowerIrql(oldIrql);
    WPON();

    g_bHooked = FALSE;
}

//
// 开始inline hook --  KiInsertQueueApc
//
VOID HookKiInsertQueueApc ()
{
    KIRQL  oldIrql;

    if (g_KiInsertQueueApc == 0) {
        DbgPrint("KiInsertQueueApc == NULL\n");
        return;
    }

    //DbgPrint("开始inline hook --  KiInsertQueueApc\n");
    DbgPrint( "KiInsertQueueApc的地址t0x%08x\n", (ULONG)g_KiInsertQueueApc );
    // 保存原函数的前字节内容
    RtlCopyMemory (g_OrigCode, (BYTE*)g_KiInsertQueueApc, 5);
    *( (ULONG*)(g_HookCode + 1) ) = (ULONG)fake_KiInsertQueueApc - (ULONG)g_KiInsertQueueApc - 5;
   
   
    // 禁止系统写保护,提升IRQL到DPC
    WPOFF();
    oldIrql = KeRaiseIrqlToDpcLevel();

    RtlCopyMemory ( (BYTE*)g_KiInsertQueueApc, g_HookCode, 5 );
    *( (ULONG*)(jmp_orig_code + 1) ) = (ULONG) ( (BYTE*)g_KiInsertQueueApc + 5 );
   
    RtlCopyMemory ( (BYTE*)Proxy_KiInsertQueueApc, g_OrigCode, 5);
    RtlCopyMemory ( (BYTE*)Proxy_KiInsertQueueApc + 5, jmp_orig_code, 7);

    // 恢复写保护,降低IRQL
    KeLowerIrql(oldIrql);
    WPON();

    g_bHooked = TRUE;
   
   
}

//
// 跳转到我们的函数里面进行预处理
//
__declspec (naked)
VOID
fake_KiInsertQueueApc (
    PKAPC Apc,
    KPRIORITY Increment
    )
{
       

    // 去掉DbgPrint,不然这个hook会产生递归
    //DbgPrint("inline hook --  KiInsertQueueApc 成功\n");
  
          __asm
          {
               jmp Proxy_KiInsertQueueApc
          }
}

//
// 代理函数,负责跳转到原函数中继续执行
//
__declspec (naked)
VOID
Proxy_KiInsertQueueApc (
    PKAPC Apc,
    KPRIORITY Increment
    )
{
       
    __asm {  // 共字节
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90  // 前字节实现原函数的头字节功能
            _emit 0x90  // 这个填充jmp
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90  // 这字节保存原函数+5处的地址
            _emit 0x90  
            _emit 0x90  // 因为是长转移,所以必须是0x0080
    }
}

ULONG GetFunctionAddr( IN PCWSTR FunctionName)
{
    UNICODE_STRING UniCodeFunctionName;
    RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
    return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );   

}

//根据特征值,从KeInsertQueueApc搜索中搜索KiInsertQueueApc
ULONG FindKiInsertQueueApcAddress()
{
        char * Addr_KeInsertQueueApc = 0;
        int i = 0;
        char Findcode[] = { 0xE8, 0xcc, 0x29, 0x00, 0x00 };
        ULONG Addr_KiInsertQueueApc = 0;
    Addr_KeInsertQueueApc = (char *) GetFunctionAddr(L"KeInsertQueueApc");
        for(i = 0; i < 100; i ++)
        {
        if( Addr_KeInsertQueueApc[i] == Findcode[0] &&
                        Addr_KeInsertQueueApc[i + 1] == Findcode[1] &&
                        Addr_KeInsertQueueApc[i + 2] == Findcode[2] &&
                        Addr_KeInsertQueueApc[i + 3] == Findcode[3] &&
                        Addr_KeInsertQueueApc[i + 4] == Findcode[4]
                        )
                {
                        Addr_KiInsertQueueApc = (ULONG)&Addr_KeInsertQueueApc[i] + 0x29cc + 5;
                        break;
                }
        }
        return Addr_KiInsertQueueApc;
}

VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
        DbgPrint("My Driver Unloaded!");
        UnHookKiInsertQueueApc();
}

NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
        DbgPrint("My Driver Loaded!");
        theDriverObject->DriverUnload = OnUnload;
               
  g_KiInsertQueueApc = FindKiInsertQueueApcAddress();
        HookKiInsertQueueApc();

        return STATUS_SUCCESS;
}
sudami 25 2008-3-24 12:18
13
0
感谢combojiang大叔。偶去试验下
无聊仔 2008-3-24 13:06
14
0
学习中……
uncledo 2008-4-3 10:32
15
0
12楼的回答可以给我们菜鸟们当科普教材了,谢谢了

我在网吧测试成功,但我的特征码不一样,我的特征码是
char Findcode[] = { 0xE8, 0xB8, 0x29, 0x00, 0x00 };
gdlian 2008-4-26 23:58
16
0
把工程发上来,让我好好看看
nuke 2008-5-2 02:40
17
0
combojiang 的教程非常好,
本来机器上没搜到原始KiInsertQueueApc入口
刚想到特征码会有不同,
尝试了各种不同inline hook方法,
经常BSOD,唉
多试试看~
HSQ 8 2008-5-2 10:43
18
0
不错,下来研究下
lOOp 2008-5-22 22:25
19
0
Addr_KiInsertQueueApc = (ULONG)&Addr_KeInsertQueueApc[i] + 0x29cc + 5;
  这句没有搞明白
我机子上的代码是这样的
nt!KeInsertQueueApc:
804fb8f8 8bff            mov     edi,edi
804fb8fa 55              push    ebp
................
804fb933 e8b8290000      call    nt!KiInsertQueueApc (804fe2f0)
哪位大虾解释一下  谢谢了
游客
登录 | 注册 方可回帖
返回