能力值:
(RANK:1060 )
2 楼
好像Proxy_KiInsertQueueApc 没处理 fake_KiInsertQueueApc 的 stackframe,出来之前要leave一次
能力值:
( LV12,RANK:1010 )
3 楼
是不是这样:
//
// 代理函数,负责跳转到原函数中继续执行
//
__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牛提示一下~
能力值:
(RANK:1060 )
4 楼
后面都跳走了,你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
}
能力值:
( LV12,RANK:1010 )
5 楼
哦,俺试试看。
先谢过~
----------------------------------------
按照forgot同学的提示改了之后,还是蓝:
PAGE_FAULT_IN_NONPAGED_AREA
偶看看dump文件~~~~~
能力值:
(RANK:1060 )
6 楼
你把编译出的代码看看就知道了
naked的怎么传参数的?
能力值:
( LV12,RANK:1010 )
7 楼
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 ---------
很是无语~
能力值:
(RANK:1060 )
8 楼
太衰了,你怎么改成这样了。。。
能力值:
( LV12,RANK:470 )
9 楼
你是怎么写的代码啊?
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
能力值:
( LV2,RANK:10 )
10 楼
现在还看不懂...偶也要学了....
能力值:
( LV13,RANK:1050 )
11 楼
这么写不会有问题。
#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;
}
能力值:
( LV13,RANK:1050 )
12 楼
这样也可以。
#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;
}
能力值:
( LV12,RANK:1010 )
13 楼
感谢combojiang大叔。偶去试验下
能力值:
( LV2,RANK:10 )
14 楼
学习中……
能力值:
( LV2,RANK:10 )
15 楼
12楼的回答可以给我们菜鸟们当科普教材了,谢谢了
我在网吧测试成功,但我的特征码不一样,我的特征码是
char Findcode[] = { 0xE8, 0xB8, 0x29, 0x00, 0x00 };
能力值:
( LV2,RANK:10 )
16 楼
把工程发上来,让我好好看看
能力值:
( LV2,RANK:10 )
17 楼
combojiang 的教程非常好,
本来机器上没搜到原始KiInsertQueueApc入口
刚想到特征码会有不同,
尝试了各种不同inline hook方法,
经常BSOD,唉
多试试看~
能力值:
( LV13,RANK:330 )
18 楼
不错,下来研究下
能力值:
( LV2,RANK:10 )
19 楼
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)
哪位大虾解释一下 谢谢了