http://blog.csdn.net/xugangjava/article/details/14001685
以前的文章(http://blog.csdn.net/xugangjava/article/details/7455851)中介绍了如何Hook 系统的MessageBox的函数不过只限于本进程,
本文主要介绍如何Hook其他进程的MessageBox函数。
这里我用SetWindowsHookEx 来实现,SetWindowsHookEx最后一个参数设置为0 ,表示拦截所有进程的相关消息。在回调函数中安装Hook就可以达到目的。
对原有代码稍作修改dllmain.cpp修改如下
// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "stdafx.h" #include "detours.h" #include <stdlib.h> #include <iostream> using namespace std; PVOID g_pOldMessageBoxW=NULL; PVOID g_pOldMessageBoxA=NULL; typedef int (WINAPI *PfuncMessageBoxA)(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType); typedef int (WINAPI *PfuncMessageBoxW)( HWND hWnd, LPCWSTR lpText,LPCWSTR lpCaption,UINT uType); int WINAPI ZwNewMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType) { return ((PfuncMessageBoxA)g_pOldMessageBoxA)(hWnd, "Hook This!","My hook",uType); } int WINAPI ZwNewMessageBoxW(HWND hWnd, LPCWSTR lpText,LPCWSTR lpCaption,UINT uType) { return ((PfuncMessageBoxW)g_pOldMessageBoxW)(hWnd,L"Hook This!",L"My hook",uType); } //共享代码段 #pragma data_seg("SHARED") HHOOK g_hMessageHook=NULL; BOOL g_bStopHook=FALSE; BOOL g_bHookInstalled=FALSE; #pragma data_seg() #pragma comment(linker, "/section:SHARED,RWS") BOOL APIENTRY SetHook() { //如果已经安装就return if(g_bHookInstalled)return TRUE; //输出到控制台 cout<<"let't us install hook of messagebox"<<endl; DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); g_pOldMessageBoxA=DetourFindFunction("User32.dll","MessageBoxA"); g_pOldMessageBoxW=DetourFindFunction("User32.dll","MessageBoxW"); DetourAttach(&g_pOldMessageBoxA,ZwNewMessageBoxA); DetourAttach(&g_pOldMessageBoxW,ZwNewMessageBoxW); LONG ret=DetourTransactionCommit(); g_bHookInstalled=TRUE; return g_bHookInstalled; } BOOL APIENTRY DropHook() { //如果已经卸载就return if(!g_bHookInstalled)return TRUE; //输出控制台 cout<<"let't us drop hook of messagebox"<<endl; DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&g_pOldMessageBoxA, ZwNewMessageBoxA); DetourDetach(&g_pOldMessageBoxW, ZwNewMessageBoxW); LONG ret=DetourTransactionCommit(); g_bHookInstalled=FALSE; return ret==NO_ERROR; } static HMODULE s_hDll; //查找函数地址 HMODULE WINAPI ModuleFromAddress(PVOID pv) { MEMORY_BASIC_INFORMATION mbi; if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0) { return (HMODULE)mbi.AllocationBase; } else { return NULL; } } static LRESULT CALLBACK MessageHookProc(int nCode,WPARAM wParam,LPARAM lParam) { wchar_t Dir[_MAX_DIR]; wchar_t FullPath[MAX_PATH]; // [sp+200h] [bp-614h]@1 wchar_t Ext[_MAX_EXT]; wchar_t Filename[_MAX_FNAME]; wchar_t Drive[_MAX_DRIVE]; GetModuleFileNameW(0, FullPath, MAX_PATH); _wsplitpath_s(FullPath, Drive, _MAX_DRIVE, Dir, _MAX_DIR, Filename, _MAX_FNAME, Ext, _MAX_EXT); //这里我只注入python进程 注入所有进程对系统影响很大 弄得我经常需要注销 if(!_wcsicmp(Filename, L"python")){ //安装钩子 if(!g_bStopHook){ SetHook(); } //卸载钩子 else{ DropHook(); } } return CallNextHookEx(g_hMessageHook,nCode,wParam,lParam); } //导出函数 加载全局钩子 extern "C" __declspec(dllexport) BOOL SetGoableHook() { g_bStopHook=FALSE; g_hMessageHook=SetWindowsHookEx(WH_GETMESSAGE, MessageHookProc, ModuleFromAddress(MessageHookProc),0); return TRUE; } //导出函数 卸载全局钩子 extern "C" __declspec(dllexport) BOOL DropGoableHook() { g_bStopHook=TRUE; return TRUE; } HMODULE WINAPI Detoured() { return s_hDll; } BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: s_hDll = hModule; DisableThreadLibraryCalls(hModule); break; case DLL_PROCESS_DETACH: UnhookWindowsHookEx(g_hMessageHook); break; } return TRUE; }好了我们下一步编写一个MFC程序来加载和卸载我们的钩子
在对话框上面添加两个按钮
按钮事件处理函数如下
typedef BOOL (WINAPIV *SetGoableHook)(); typedef VOID (WINAPIV *DropGoableHook)(); void CTestHookDlg::OnBnClickedSethook() { HINSTANCE hDLL=::LoadLibrary(L"Hook.dll"); SetGoableHook func=(SetGoableHook)GetProcAddress(hDLL,"SetGoableHook"); func(); } void CTestHookDlg::OnBnClickedDropHook() { HINSTANCE hDLL=::LoadLibrary(L"Hook.dll"); DropGoableHook func=(DropGoableHook)GetProcAddress(hDLL,"DropGoableHook"); func(); }
1.进入python交互界面后,点击SetDoableHook按钮,然后敲入如下命令,弹出MessageBox点确定这个进程就触发了WH_GETMESSAGE
进入我们的回调函数,我们的钩子已经加载成功了。
好的再次调用MessageBox
发现python 进程的MessageBox已经被我们替换掉了,因为这个是命令行程序,第一次调用弹出只是为了该进程进入我们的WH_GETMESSAGE 回调MessageHookProc。
对不同类型进程Hook的时候可以使用不同的参数 WH_CALLWNDPROCRET,WH_KEYBOARD_LL,WH_MOUSE_LL来进行Hook。
同理 卸载钩子
有不对的地方欢迎大家指正。
源码地址
http://download.csdn.net/detail/xugangjava/6488007