转载注明出处
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;
- }
在对话框上面添加两个按钮
按钮事件处理函数如下
- 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();
- }
Ok 了 下面我们来测试我们的钩子,依然使用python命令行来进行演示
1.进入python交互界面后,点击SetDoableHook按钮,然后敲入如下命令,弹出MessageBox点确定这个进程就触发了WH_GETMESSAGE
进入我们的回调函数,我们的钩子已经加载成功了。
好的再次调用MessageBox
发现python 进程的MessageBox已经被我们替换掉了,因为这个是命令行程序,第一次调用弹出只是为了该进程进入我们的WH_GETMESSAGE 回调MessageHookProc。
对不同类型进程Hook的时候可以使用不同的参数 WH_CALLWNDPROCRET,WH_KEYBOARD_LL,WH_MOUSE_LL来进行Hook。
同理 卸载钩子
有不对的地方欢迎大家指正。
源码地址