Hook MessageBox 进阶 跨过程Hook

Hook MessageBox 进阶 跨进程Hook

转载注明出处

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程序来加载和卸载我们的钩子

在对话框上面添加两个按钮

Hook MessageBox 进阶  跨过程Hook

按钮事件处理函数如下

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 

进入我们的回调函数,我们的钩子已经加载成功了。

Hook MessageBox 进阶  跨过程Hook

好的再次调用MessageBox

Hook MessageBox 进阶  跨过程Hook

发现python 进程的MessageBox已经被我们替换掉了,因为这个是命令行程序,第一次调用弹出只是为了该进程进入我们的WH_GETMESSAGE 回调MessageHookProc。

对不同类型进程Hook的时候可以使用不同的参数 WH_CALLWNDPROCRET,WH_KEYBOARD_LL,WH_MOUSE_LL来进行Hook。

同理 卸载钩子

Hook MessageBox 进阶  跨过程Hook

有不对的地方欢迎大家指正。