发一个支持任意地点hook的类(包含驱动hook和应用层hook)
2014-02-07 11:36
369 查看
这是以前练习写驱动类的一个产物, 有点早了,很简单.
写这个类也是方便自己绕过某些驱动的保护钩子. 当然这个也只支持x86, 没有做x64的拓展. 因为只是方便自己不需要每次都copy一大堆代码;
如果需要x64的拓展的,可以参考detours 或者是 EasyHook. 比较好的是EasyHook提供了驱动的hook;
貌似关于驱动写类论坛上比较少, 对于驱动,大家更倾向于直接用c写, 而不喜欢用c++写; 其实遇到大的工程,用c++有很多好处,而且微软也是有c++写驱动类的例子的.
废话不多说:
关于驱动的,啰嗦一句, 不能定义全局的驱动对象, 具体为什么不能大家就自己baidu或者google;
直接上代码,代码里提供了例子;hook NtOpenProcess 和 NtReadVirtualMemory
驱动部分Hook.zip.
应用层的:
应用层hook.zip.
比较简单, 高手飘过. 这里只是给一个例子
代码:
至于用法就比较简单了;
CKernelDetours *g_p= NULL; //hook NtOpenProcess 定义一个全局的指针,是为了方便还原, 不需要还原hook的可以直接在函数内部定义对象
代码:
这里就是演示其用法. 作用就是可以在任意函数内部进行Hook, 专心写中继函数,也不需要你人为的去调用被覆盖的代码. 你只需要在中继函数的最后面调用一下 g_p->CallJmpBack();就是实现跳转的功能,即可跳转会原函数执行; 这个功能对绕过某些驱动保护应该足够了.而且用法也很简单.
鱼台论坛http://bbs.370827.org/forum-75-1.html
写这个类也是方便自己绕过某些驱动的保护钩子. 当然这个也只支持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 }*/ }
至于用法就比较简单了;
CKernelDetours *g_p= NULL; //hook NtOpenProcess 定义一个全局的指针,是为了方便还原, 不需要还原hook的可以直接在函数内部定义对象
代码:
//NtOpenProcess的中继函数 __declspec(naked) void MyOpenProcess() { __asm { pushad pushfd } ANSI_STRING p_str1; RtlInitAnsiString(&p_str1,(PSTR)((ULONG)IoGetCurrentProcess()+0x174)); //将我们要比对的进程名放入str2 KdPrint(("访问OPenProcess的进程名为 %s\n", p_str1.Buffer)); __asm { popfd popad } // call detours g_p->CallJmpBack(); } CKernelDetours* Hook_NtOpenProcess() { CKernelDetours *p = new(NonPagedPool, 'RysI') CKernelDetours; ULONG addr= GetSsdtFuncAddr(0x7A) ; KdPrint(("NtOpenProcess Addr 0x%x\n",addr)); p->Hook(addr,(PULONG)MyOpenProcess);//这里只需要填入要hook的地址,和中继函数的地址即可.很简单; 在函数头,函数尾都行;有了这个功能,大家就可以专心写中继函数了.不必考虑其他的事情; return p; } void UnHookNtOpenProcess(CKernelDetours* p) { CKernelDetours *pthis = p; if (pthis != NULL) { pthis->UnHook(); delete pthis; } }
这里就是演示其用法. 作用就是可以在任意函数内部进行Hook, 专心写中继函数,也不需要你人为的去调用被覆盖的代码. 你只需要在中继函数的最后面调用一下 g_p->CallJmpBack();就是实现跳转的功能,即可跳转会原函数执行; 这个功能对绕过某些驱动保护应该足够了.而且用法也很简单.
鱼台论坛http://bbs.370827.org/forum-75-1.html
相关文章推荐
- 每一天都有更多的数据、用户和应用在加入Apache Hadoop这个日益壮大的集群中来。虽然对于整个数据驱动的组织来说这是一个好消息,但对于安全管理员和监察人员来说,如何让终端用户在现存的Hadoop
- 内核驱动编程------一个模块包含多个中断线资源
- 应用层(用户模式)I2C驱动支持
- 请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字
- 谷歌笔试题--给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), 指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。
- 一个完整的linux驱动 + 应用测试demo
- 构造一个单词查找树,支持以下两个操作的数据结构: 添加和搜索,只包含字母a-z或.。
- 也Show一个Silverlight打印应用吧,包含报表设计器,预览,打印。
- 请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字
- 请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
- JSPatch库, 一个Apple官方支持的实现在线更新iOS应用的库
- 的VARCHART JGantt让你设计一个甘特图包含精确规划需求所需的功能,无论是项目计划,人员配置,生产控制或其他应用领域。
- .分析以下需求,并用代码实现 1.定义List集合,存入多个字符串 2.删除集合元素字符串中包含0-9数字的字符串 只要字符串中包含0-9中的任意一个数字就需
- MM应用引擎——一个支持HTML5的互联网应用开发运行托管平台
- 关于hook设置函数如何支持多核CPU的一个说明
- 如何用Google APIs和Google的应用系统进行集成(7)----在把JSON转换成XML数据过程中,JSON数据中包含违背XML数据规范:XML节点名不支持数字的Java解决方案
- 王爽《汇编语言》实验十一:编写一个子程序:将包含任意字符,以0结尾的字符串中的小写字母转变成大写字母
- JSPatch库, 一个Apple官方支持的实现在线更新iOS应用的库
- JSPatch库, 一个Apple官方支持的实现在线更新iOS应用的库
- JSPatch库, 一个Apple官方支持的实现在线更新iOS应用的库