Windows下32位程序的Inline Hook
Posted 念秋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Windows下32位程序的Inline Hook相关的知识,希望对你有一定的参考价值。
话不多说,首先贴代码,代码主体参考自一本关于黑客技术的书,书名给忘了。
当时只是敲出来跟着用,也没有深入理解,最近再看,才发现一些原理。
Inline Hook的好处就是可以获取被Hook函数的参数,我们可以自行处理这些数据,再调用本来的Hook函数。
#include <stdio.h> #include <windows.h> #include<iostream> using namespace std; class MyHook public: MyHook() funcAddr = NULL; ZeroMemory(oldBytes,5); ZeroMemory(newBytes,5); ~MyHook() UnHook(); funcAddr = NULL; ZeroMemory(oldBytes,5); ZeroMemory(newBytes,5); /* *Hook的模块名称,Hook的API函数名称,钩子函数地址 */ WINBOOL Hook(LPSTR ModuleName, LPSTR FuncName, PROC HookFunc) BOOL bRet = FALSE; funcAddr = (PROC)GetProcAddress(GetModuleHandleA(ModuleName),FuncName); cout<<funcAddr<<endl; if(funcAddr!=NULL) DWORD num = 0; ReadProcessMemory(GetCurrentProcess(),(void*)funcAddr,oldBytes,5,&num); newBytes[0] = 0xe9; *(DWORD *)(newBytes + 1) = (DWORD)HookFunc - (DWORD)funcAddr - 5; WriteProcessMemory(GetCurrentProcess(),(void*)funcAddr,newBytes,5,&num); bRet = TRUE; return bRet; void UnHook() if(funcAddr!=0) DWORD num = 0; WriteProcessMemory(GetCurrentProcess(),(void*)funcAddr,oldBytes,5,&num); WINBOOL ReHook() BOOL ret = FALSE; if(funcAddr!=0) DWORD num; WriteProcessMemory(GetCurrentProcess(),(void*)funcAddr,newBytes,5,&num); ret = TRUE; return ret; private: PROC funcAddr; BYTE oldBytes[5]; BYTE newBytes[5]; ; MyHook hook; int WINAPI MyMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT type) hook.UnHook(); MessageBox(hWnd,"Hook流程",lpCaption,type); MessageBox(hWnd,lpText,lpCaption,type); hook.ReHook(); return 0; int main() MessageBox(NULL,"正常流程1","test",MB_OK); hook.Hook((LPSTR)"User32.dll",(LPSTR)"MessageBoxA",(PROC)&MyMessageBoxA); MessageBox(NULL,"被Hook了1","test",MB_OK); // MessageBox(NULL,"被Hook了2","test",MB_OK); hook.UnHook(); // MessageBox(NULL,"正常流程2","test",MB_OK);
既不解释代码含义,也不解释Win32 API。需要注意的就是以下两点。
首先来看图
为什么是0xe9?
0xe9代表jmp指令。
但是图上不是EB吗?
因为平时使用OD这样的调试工具,大多数情况下修改跳转,把jne之类的修改成jmp,
都是修改成了EB,久而久之,就忘了,jmp有好几种跳转方式,这种修改应该是属于直接跳转。
Jmp short.(说是short,实际上是一个带符号的字节范围 -128~127)。
如图所示,地址0x00401200 和0x00401216,有着0x14个字节的指令,这就是直接跳转。
1个字节,肯定不够我们跳转的,所以这里要用的是第2种跳转方式。再看另一副图
从地址0x0041c3c1跳转到0x41c2ae,用的是E9 e8feffff
因为32位下jmp远跳一共用了5字节的内存。
E9 是jmp ,对应代码中的第一处
剩下4字节保存的是 目的地址-起始地址-指令长度,对应代码中的第二处
所以才有 0x41c2ae-0x41c3c1-5 = FFFFFEE8 。因为内存里面是小端,所以显示出来就是E8FEFFFF。
一种比较好的测试方案,就是使用OD调试以上代码,ctrl+g跳转到MessageBoxA的地址处,看看随着代码的运行,该地址处的指令如何变化。
以上是关于Windows下32位程序的Inline Hook的主要内容,如果未能解决你的问题,请参考以下文章