这是以前练习写驱动类的一个产物, 有点早了,很简单.
写这个类也是方便自己绕过某些驱动的保护钩子. 当然这个也只支持x86, 没有做x64的拓展. 因为只是方便自己不需要每次都copy一大堆代码;
如果需要x64的拓展的,可以参考detours 或者是 EasyHook. 比较好的是EasyHook提供了驱动的hook;
貌似关于驱动写类论坛上比较少, 对于驱动,大家更倾向于直接用c写, 而不喜欢用c++写; 其实遇到大的工程,用c++有很多好处,而且微软也是有c++写驱动类的例子的. 废话不多说: 关于驱动的 ,啰嗦一句, 不能定义全局的驱动对象, 具体为什么不能大家就自己baidu或者google; 直接上代码,代码里提供了例子;hook NtOpenProcess 和 NtReadVirtualMemory 驱动部分Hook.zip 应用层的: 应用层hook.zip
比较简单, 高手飘过. 这里只是给一个例子
//KernelDetours.h
#pragma once
#include <ntddk.h>
#include "ldasm.h"
//保存5字节代码的结构
#pragma pack(1)
typedef struct _TOP5CODE
{
UCHAR instruction; //指令
ULONG address; //地址
}TOP5CODE,*PTOP5CODE;
#pragma pack()
#ifdef __cplusplus
extern "C" {
#endif
class CKernelDetours
{
public:
CKernelDetours();
~CKernelDetours();
BOOLEAN Hook(ULONG HookAddr,PULONG NakedFunc);
void UnHook();
void __stdcall CallJmpBack();
protected:
VOID WPOFF();
VOID WPON();
private:
UCHAR m_Bak[5];
ULONG m_hookAddr;
ULONG m_HookCodeLen;//被hook指令的长度
ULONG m_OldProtect;
BOOLEAN m_bHookSuccess;
KIRQL Irql;
PVOID m_detoursFunc;//这个地方呢,是动态生成的. 他是保存hook前的指令, 可以执行到这里然后跳转到原函数下面继续执行
public:
static void __cdecl operator delete(void* pointer) { ASSERT(NULL != pointer); if (NULL != pointer) ExFreePool(pointer); }
static void * __cdecl operator new(size_t iSize,POOL_TYPE PoolType,unsigned int tag) {
KdPrint(("global operator new -- Allocate size :%d \n",iSize));
PVOID result; // [sp+0h] [bp-4h]@1
result = ExAllocatePoolWithTag(PoolType, iSize, tag);
if ( result )
memset(result, 0, iSize);
return result;
}
};
#ifdef __cplusplus
}; // extern "C"
#endif
//KernelDetours.cpp
#include "KernelDetours.h"
#define TAG 'liuq'
CKernelDetours::CKernelDetours(void)
{
RtlZeroMemory(m_Bak,0,6);
m_hookAddr =0;
m_OldProtect = 0;
m_bHookSuccess = FALSE;
m_HookCodeLen = 0;
m_detoursFunc = NULL;
m_detoursFunc = ExAllocatePoolWithQuotaTag(NonPagedPool,0x50,TAG);
memset(m_detoursFunc,0x90,0x50);
KdPrint(("Enter CKernelDetours::CKernelDetours(void) m_detoursFunc: %x",(ULONG)m_detoursFunc));
}
CKernelDetours::~CKernelDetours(void)
{
// if (m_bHookSuccess)
// {
// UnHook();
// }
KdPrint(("Enter CKernelDetours::~CKernelDetours(void)"));
}
void CKernelDetours::WPOFF()
{ //清除页面保护
__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
}
void CKernelDetours::WPON()
{ //恢复页面保护
__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}
void CKernelDetours::UnHook()
{
if (m_bHookSuccess)
{
ULONG a = m_hookAddr;
WPOFF();
Irql = KeRaiseIrqlToDpcLevel();
RtlCopyMemory((void*)a,m_Bak,5);
KeLowerIrql(Irql);
WPON();
m_bHookSuccess =FALSE;
}
if (m_detoursFunc != NULL)
{
KdPrint(("ExFreePoolWithTag(m_detoursFunc,TAG);"));
ExFreePoolWithTag(m_detoursFunc,TAG);
m_detoursFunc = NULL;
}
}
BOOLEAN CKernelDetours::Hook(ULONG HookAddr,PULONG NakedFunc)
{
if(m_bHookSuccess || NakedFunc==NULL || HookAddr == NULL)
{
return FALSE;
}
m_hookAddr = HookAddr; //保存被hook的地址
unsigned char jmp[6] ={0xe9};
jmp[5] = 0x90;
PUCHAR pcode = NULL;
ULONG codelen =0;
ULONG uSumCodeLen = 0;
BOOLEAN bFind = FALSE;
for (int j =0; j<0x30; j+=codelen)
{
codelen = SizeOfCode((void*)(HookAddr+j),&pcode);
uSumCodeLen+=codelen;//计算总长度
if (uSumCodeLen>=5)
{
bFind =TRUE;
break;
}
}
if (!bFind)
{
KdPrint((" I'm sorry, Can Not Find Right Place to Hook\n"));
return FALSE;
}
m_HookCodeLen = uSumCodeLen; //保存这个长度
ULONG JmpBack= HookAddr + uSumCodeLen;
ULONG jmpDetoursAddr = ((ULONG)m_detoursFunc + uSumCodeLen);//在detours函数跳转到hook的地方
ULONG b = JmpBack - jmpDetoursAddr - 5;
*(ULONG *)(jmp+1) = b;
WPOFF();
Irql = KeRaiseIrqlToDpcLevel();
RtlCopyMemory((void*)m_detoursFunc,(void*)HookAddr,uSumCodeLen); //把这些数据保存到detours 函数里面,//然后在后面写上 jmp (HookAddr+uSumCodeLen)
RtlCopyMemory((void*)jmpDetoursAddr,jmp,5);
KeLowerIrql(Irql);
WPON();
ULONG a = HookAddr; //hook的地址
b = (ULONG)NakedFunc - a - 5;
*(ULONG *)(jmp+1) = b;
RtlCopyMemory((void*)m_Bak,(void*)a,5);//保存hook的地方
WPOFF();
Irql = KeRaiseIrqlToDpcLevel();
RtlCopyMemory((void*)a,jmp,5);
KeLowerIrql(Irql);
WPON();
m_bHookSuccess = TRUE;
return TRUE;
}
void CKernelDetours::CallJmpBack()
{
/*
__asm
{
push ebp
mov ebp,esp
sub,esp,8
}*/
ULONG ebp1 = (ULONG)m_detoursFunc;
__asm
{
mov eax,ebp1
mov esp,ebp
pop ebp
add esp,8 ;//这里会有一个变量的堆栈空间 + 一个this指针的参数
jmp eax
}
/*
__asm
{
mov esp,ebp
pop ebp
retn 4
}*/
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
上传的附件: