标签:
参考 http://9200cs.blog.163.com/blog/static/134577369201041111656659/
环境:VS2008
一、新建一个dll程序add,程序非常简单,其功能就是实现简单的a+b。
1、新建一个项目名为add
选择dll
然后打开dllmain.cpp,代码:
// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "stdafx.h" int WINAPI add(int a, int b) { return a + b; } BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; }
右键项目添加一个新建项名为add.def的文件
打开编写代码:
LIBRARY Add DESCRIPTION "ADD LA" EXPORTS add @1;
编译后我们就能在Debug目录下获取add.dll了。
二、编写主程序,新建一个基于对话框的MFC应用程序One
在向导中选择基于对话框
双击确定进入,代码为
HINSTANCE hAddDll = NULL; void COneDlg::OnBnClickedOk() { typedef int (WINAPI*AddProc)(int a, int b);//函数原型定义 AddProc add; if (hAddDll == NULL) { hAddDll = ::LoadLibrary(_T("add.dll"));//加载dll } add = (AddProc)::GetProcAddress(hAddDll, "add");//获取函数add地址 int a = 1; int b = 2; int c = add(a, b); CString tem; tem.Format(_T("%d+%d=%d"), a, b, c); AfxMessageBox(tem); }
编译一下再将之前获取到的add.dll拷贝到项目One下有exe文件的Debug目录下
运行结果出现
就说明我们的One已经成功调用了add.dll里的add()方法了。
三、至此,我们的小程序已经完成了,接下来该到我们的主角HOOK登场了!
新建一个MFC DLL项目
Hook.cpp里的代码
// Hook.cpp : Defines the initialization routines for the DLL. #include "stdafx.h" #include "Hook.h" #ifdef _DEBUG #define new DEBUG_NEW #endif //变量定义 #pragma data_seg("SHARED") //不同Instance共享的该变量 static HHOOK hhk = NULL; //鼠标钩子句柄 static HINSTANCE hinst = NULL; //本dll的实例句柄 (hook.dll) #pragma data_seg() #pragma comment(linker, "/section:SHARED,rws") //以上的变量为共享 CString temp; //用于显示错误的临时变量 bool bHook = false; //是否Hook了函数 bool m_bInjected = false; //是否对API进行了Hook BYTE OldCode[5]; //原程序API入口代码 BYTE NewCode[5]; //新跳转的API代码 (jmp xxxx) typedef int (WINAPI*AddProc)(int a, int b);//add.dll中的add函数定义 AddProc add; //add.dll中的add函数 HANDLE hProcess = NULL; //所处进程的句柄 FARPROC pfadd; //指向add函数的远指针 DWORD dwPid; //所处进程ID //end of 变量定义 // CHookApp BEGIN_MESSAGE_MAP(CHookApp, CWinApp) END_MESSAGE_MAP() //鼠标钩子过程,什么事情也不做,目的是注入dll到程序中 LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) { return CallNextHookEx(hhk, nCode, wParam, lParam); } //开启钩子的函数 void HookOn() { ASSERT(hProcess != NULL); DWORD dwTemp = 0; DWORD dwOldProtect; //将内存保护模式改为可写,老模式保存入dwOldProtect VirtualProtectEx(hProcess, pfadd, 5, PAGE_READWRITE, &dwOldProtect); //将所属进程中add()的前5个字节改为Jmp Myadd WriteProcessMemory(hProcess, pfadd, NewCode, 5, 0); //将内存保护模式改回为dwOldProtect VirtualProtectEx(hProcess, pfadd, 5, dwOldProtect, &dwTemp); bHook = true; } //关闭钩子的函数 void HookOff()//将所属进程中add()的入口代码恢复 { ASSERT(hProcess != NULL); DWORD dwTemp = 0; DWORD dwOldProtect; VirtualProtectEx(hProcess, pfadd, 5, PAGE_READWRITE, &dwOldProtect); WriteProcessMemory(hProcess, pfadd, OldCode, 5, 0); VirtualProtectEx(hProcess, pfadd, 5, dwOldProtect, &dwTemp); bHook = false; } //然后,写我们自己的Myadd()函数 int WINAPI Myadd(int a, int b) { //截获了对add()的调用,我们给a,b都加上一定的数 a = a + 1; b = b + 1; HookOff();//关掉Myadd()钩子防止死循环 int ret; ret = add(a, b); HookOn();//开启Myadd()钩子 return ret; } //好,最重要的HOOK函数: void Inject() { if (m_bInjected == false) { //保证只调用1次 m_bInjected = true; //获取add.dll中的add()函数 HMODULE hmod = ::LoadLibrary(_T("add.dll")); add = (AddProc)::GetProcAddress(hmod, "add"); pfadd = (FARPROC)add; if (pfadd == NULL) { AfxMessageBox(L"cannot locate add()"); } // 将add()中的入口代码保存入OldCode[] _asm { lea edi, OldCode mov esi, pfadd cld movsd movsb } NewCode[0] = 0xe9;//实际上0xe9就相当于jmp指令 //获取Myadd()的相对地址 _asm { lea eax, Myadd mov ebx, pfadd sub eax, ebx sub eax, 5 mov dword ptr[NewCode + 1], eax } //填充完毕,现在NewCode[]里的指令相当于Jmp Myadd HookOn(); //可以开启钩子了 } } CHookApp::CHookApp() { } CHookApp theapp; //鼠标钩子安装函数: BOOL InstallHook() { hhk = ::SetWindowsHookEx(WH_MOUSE, MouseProc, hinst, 0); return true; } //卸载鼠标钩子函数 void UninstallHook() { ::UnhookWindowsHookEx(hhk); } //在dll实例化中获得一些参数 BOOL CHookApp::InitInstance() { CWinApp::InitInstance(); //获得dll 实例,进程句柄 hinst = ::AfxGetInstanceHandle(); DWORD dwPid = ::GetCurrentProcessId(); hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid); //调用注射函数 Inject(); return TRUE; }
接着别忘了Hook.def下的配置
LIBRARY "Hook" DESCRIPTION ‘Hook Windows Dynamic Link Library‘ EXPORTS ; Explicit exports can go here InstallHook MouseProc Myadd UninstallHook
编译一下,再将之前获得的add.dll丢一份到Hook的Debug目录下
这样,我们的Hook完成了
四、接下来我们就可以修改前面的One的测试程序了
添加一个按钮,双击进入相应事件 代码:
HINSTANCE hinst; void COneDlg::OnBnClickedButton1() { hinst=LoadLibrary(_T("hook.dll")); if(hinst==NULL) { AfxMessageBox(_T("no hook.dll!")); return; } typedef BOOL (CALLBACK *inshook)(); inshook insthook; insthook=::GetProcAddress(hinst,"InstallHook"); if(insthook==NULL) { AfxMessageBox(_T("func not found!")); return; } DWORD pid=::GetCurrentProcessId(); BOOL ret=insthook(); }
别忘了退出时卸掉钩子
再加个按钮
void COneDlg::OnBnClickedButton2() { // TODO: 在此添加控件通知处理程序代码s typedef BOOL (CALLBACK *UnhookProc)(); UnhookProc UninstallHook; UninstallHook=::GetProcAddress(hinst,"UninstallHook"); if(UninstallHook==NULL) UninstallHook(); if (hinst!=NULL) { ::FreeLibrary(hinst); } if (hAddDll!=NULL) { ::FreeLibrary(hAddDll); } CDialog::OnCancel(); }
再将Hook目录下的Hook.dll也丢到One的Debug目录下
至此,整个HOOK的例子就结束了。
最后的效果:正常为1+2=3,点击button1后再点击确定,就变成1+1=5了
最后需要注意的是项目里面有2个Debug目录,要放在这个
里面有
不要 放错了哦,这个Debug目录是需要编译过后才生成的~~!
标签:
原文地址:http://www.cnblogs.com/muchme/p/4388885.html