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