Author:skymelai
It is unoccupied to work recently,has read things to not touched on work,That include inLine Hook,Next is understand of me,I wonder whether it is correct or no or not.
Usual step:Function Address is finded in memory and save first a few bytes of original function(The code was getted by kernel's debugging). Write to jump to our function address on original function startting(Calculate to get addrees).Regain first some bytes of original function on oneself function and jump to original function.
Usual step:Function Address is finded in memory and save first a few bytes of original function(The code was getted by kernel's debugging). Write to jump to our function address on original function startting(Calculate to get addrees).Regain first some bytes of original function on oneself function and jump to original function.
I believe stack' change that is important,Have two kinds of cases,Watch
The image show be hook of function passed parameter with stack,So We can't change value of EBP or value of ESP.
The image show be hook of function passed parameter with register(FASTCALL),So we can free use on our function, That don't change aprropriate register while entry be hook of function
next code will show two kinds of cases
code 1:
#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;
}
Code 2:
//===================inline hook KiInsertQueueApc====================
//KiInsertQueueApc为内核未导出函数,可以从导出函数KeInsertQueueApc定位
//修改KiInsertQueueApc开头5字节
//处理函数思路:apc-->kthread---apc_state--eprocess--进程名字
//HookKiInsertQueueApc---DetourMyKiInsertQueueApc---UnHookKiInsertQueueApc
#include "ntddk.h"
ULONG CR0VALUE;
ULONG g_KiInsertQueueApc;
unsigned char JmpAddress[5]={0xE9,0,0,0,0}; //跳转到HOOK函数的地址
unsigned char OriginalBytes[5]={0}; //保存原始函数前五个字
VOID FASTCALL DetourMyKiInsertQueueApc(IN PKAPC Apc,IN KPRIORITY Increment);
VOID WPOFF()
{
_asm
{
push eax
mov eax, cr0
mov CR0VALUE, eax
and eax, 0fffeffffh
mov cr0, eax
pop eax
cli
};
}
VOID WPON()
{
__asm
{
sti
push eax
mov eax, CR0VALUE
mov cr0, eax
pop eax
};
}
//1、获取KiInsertQueueApc地址
ULONG GetFunctionAddr( IN PCWSTR FunctionName) //PCWSTR常量指针,指向16位UNICODE
{
UNICODE_STRING UniCodeFunctionName;
RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );
}
ULONG GetKiInsertQueueApcAddr()
{
ULONG sp_code1=0x28,sp_code2=0xe8,sp_code3=0xd88a; //特征码,sp_code3 windbg显示错误,应该为d88a
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))
{
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));
// 保存原函数的前字节内容
RtlCopyMemory (OriginalBytes, (unsigned char*)g_KiInsertQueueApc, 5);
//新函数对原函数的偏移地址
*( (ULONG*)(JmpAddress + 1) ) = (ULONG)DetourMyKiInsertQueueApc - (ULONG)g_KiInsertQueueApc - 5;
// 禁止系统写保护,提升IRQL到DPC
WPOFF();
Irql = KeRaiseIrqlToDpcLevel();
//inline hook函数
RtlCopyMemory ( (unsigned char*)g_KiInsertQueueApc, JmpAddress, 5 );
// 恢复写保护,降低IRQL
KeLowerIrql(Irql);
WPON();
}
//原函数
_declspec (naked) VOID 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;
/*OriginalKiInsertQueueApc(Apc,Increment);*/
if(MmIsAddressValid((PULONG)((ULONG)Apc+0x008))) //地址验证 KAPC结构+008--->kthread
thread=*((PULONG)((ULONG)Apc+0x008));
else
return ;
if(MmIsAddressValid((PULONG)((ULONG)thread+0x044))) //kthread+30-->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;
}
//卸载函数
VOID UnHookKiInsertQueueApc()
{
KIRQL Irql;
WPOFF();
Irql = KeRaiseIrqlToDpcLevel();
//inline hook函数
RtlCopyMemory ( (unsigned char*)g_KiInsertQueueApc, OriginalBytes, 5);
// 恢复写保护,降低IRQL
KeLowerIrql(Irql);
WPON();
}
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!");
// TODO!!
theDriverObject->DriverUnload = OnUnload;
HookKiInsertQueueApc();
return STATUS_SUCCESS;
}
#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;
}
Code 2:
//===================inline hook KiInsertQueueApc====================
//KiInsertQueueApc为内核未导出函数,可以从导出函数KeInsertQueueApc定位
//修改KiInsertQueueApc开头5字节
//处理函数思路:apc-->kthread---apc_state--eprocess--进程名字
//HookKiInsertQueueApc---DetourMyKiInsertQueueApc---UnHookKiInsertQueueApc
#include "ntddk.h"
ULONG CR0VALUE;
ULONG g_KiInsertQueueApc;
unsigned char JmpAddress[5]={0xE9,0,0,0,0}; //跳转到HOOK函数的地址
unsigned char OriginalBytes[5]={0}; //保存原始函数前五个字
VOID FASTCALL DetourMyKiInsertQueueApc(IN PKAPC Apc,IN KPRIORITY Increment);
VOID WPOFF()
{
_asm
{
push eax
mov eax, cr0
mov CR0VALUE, eax
and eax, 0fffeffffh
mov cr0, eax
pop eax
cli
};
}
VOID WPON()
{
__asm
{
sti
push eax
mov eax, CR0VALUE
mov cr0, eax
pop eax
};
}
//1、获取KiInsertQueueApc地址
ULONG GetFunctionAddr( IN PCWSTR FunctionName) //PCWSTR常量指针,指向16位UNICODE
{
UNICODE_STRING UniCodeFunctionName;
RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );
}
ULONG GetKiInsertQueueApcAddr()
{
ULONG sp_code1=0x28,sp_code2=0xe8,sp_code3=0xd88a; //特征码,sp_code3 windbg显示错误,应该为d88a
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))
{
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));
// 保存原函数的前字节内容
RtlCopyMemory (OriginalBytes, (unsigned char*)g_KiInsertQueueApc, 5);
//新函数对原函数的偏移地址
*( (ULONG*)(JmpAddress + 1) ) = (ULONG)DetourMyKiInsertQueueApc - (ULONG)g_KiInsertQueueApc - 5;
// 禁止系统写保护,提升IRQL到DPC
WPOFF();
Irql = KeRaiseIrqlToDpcLevel();
//inline hook函数
RtlCopyMemory ( (unsigned char*)g_KiInsertQueueApc, JmpAddress, 5 );
// 恢复写保护,降低IRQL
KeLowerIrql(Irql);
WPON();
}
//原函数
_declspec (naked) VOID 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;
/*OriginalKiInsertQueueApc(Apc,Increment);*/
if(MmIsAddressValid((PULONG)((ULONG)Apc+0x008))) //地址验证 KAPC结构+008--->kthread
thread=*((PULONG)((ULONG)Apc+0x008));
else
return ;
if(MmIsAddressValid((PULONG)((ULONG)thread+0x044))) //kthread+30-->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;
}
//卸载函数
VOID UnHookKiInsertQueueApc()
{
KIRQL Irql;
WPOFF();
Irql = KeRaiseIrqlToDpcLevel();
//inline hook函数
RtlCopyMemory ( (unsigned char*)g_KiInsertQueueApc, OriginalBytes, 5);
// 恢复写保护,降低IRQL
KeLowerIrql(Irql);
WPON();
}
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!");
// TODO!!
theDriverObject->DriverUnload = OnUnload;
HookKiInsertQueueApc();
return STATUS_SUCCESS;
}
No comments:
Post a Comment