C++钩子技术,拦截带有某些关键字的窗体

这次想写一篇,自己曾经做过的一个Hook程序,温故而知新。

作为一个C++程序员,肯定对钩子(Hook)技术有所了解:消息钩子,API钩子。

基本概念:

    钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。

    钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。

对于标题所描述的拦截带有某些关键字窗体,基本思路是:我们需要创建一个全局钩子,然后捕获到窗体显示消息,捕获到后利用Windows消息机制,抛出去到外层获取窗口标题,当匹配关键字时,给对应窗口发送关闭消息。

对于创建全局钩子,我们需要采用DLL注入的方式,Hook的DLL工程主代码如下:

#include <Windows.h>

#pragma data_seg("HookWnd")
HHOOK	  g_HookWnd		 = NULL;	//钩子句柄
HWND      g_DestWnd		 = NULL;	//目的窗口句柄,就是截获的消息要发往什么窗口
HINSTANCE g_hInst		 = NULL;
#pragma data_seg()

#pragma comment( linker, "/section:HookWnd,RWS" )

__declspec(dllexport) BOOL SetHook(HWND hWnd);
__declspec(dllexport) void DestroyHook();

#define WM_MYMESSAGE (WM_USER + 1)

BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
{
	g_hInst = hinstDll;//保存应用程序实例
	return TRUE;
}


LRESULT CALLBACK MyWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	CWPSTRUCT *pCwp = reinterpret_cast<CWPSTRUCT*>(lParam);
	if (pCwp->message == WM_SHOWWINDOW)
	{
		::SendMessage(g_DestWnd, WM_MYMESSAGE, wParam, reinterpret_cast<LPARAM>(pCwp->hwnd));
		return 0;
	}
	else
		return CallNextHookEx(g_HookWnd, nCode, wParam, lParam);
}

BOOL SetHook(HWND hWnd)
{
	if (NULL == hWnd)
		return FALSE;
	
	g_DestWnd = hWnd;

	//第三个参数还可通过些方法获得:GetModuleHandle("HookTest.dll")
	return (NULL != (g_HookWnd = ::SetWindowsHookEx(WH_CALLWNDPROC, MyWndProc, g_hInst, 0)));
}

void DestroyHook()
{
	if (NULL != g_HookWnd) 
	{
		UnhookWindowsHookEx(g_HookWnd);
		g_DestWnd = NULL;
	}
}

SetWindowsHookEx(WH_CALLWNDPROC, MyWndProc, g_hInst, 0));最后一个参数0,代表创建的是全局钩子。

 

 

 

WH_CALLWNDPROC装载的是:窗口钩子,当系统向目标窗口发送消息时将触发此钩子 进入到MyWndProc回调函数处理;

 当回调函数里面捕获到:WM_SHOWWINDOW消息,发送消息到外层处理;

外层消息处理函数为:

LRESULT CHookTestDlg::OnMyMessage( WPARAM wParam, LPARAM lParam )
{
	HWND hwnd = reinterpret_cast<HWND>(lParam);
	UINT nTitleLen = ::GetWindowTextLength(hwnd);
	TCHAR *pStr = new TCHAR[nTitleLen + 1]();
	ZeroMemory(pStr, nTitleLen + 1);
	::GetWindowText(hwnd, pStr, nTitleLen + 1);
	CString str(pStr);
	delete []pStr;

	if (str.Find(m_str) != -1)	//CString查找字符串未找到返回-1
	{
		::SendMessage(hwnd, WM_CLOSE, NULL, NULL);
		return 1;
	}

	return 0;
}

获取对应窗口句柄的窗口标题,和设置的关键字匹配,当满足条件则发送关闭消息;

 

 

 

外层调用Hook的DLL函数实例:

HINSTANCE hIst = NULL;
// 创建全局钩子,监控所有进程
void CHookTestDlg::OnCreateDllHook() 
{
	m_edit.GetWindowText(m_str);
	m_edit.EnableWindow(FALSE);
	hIst = ::LoadLibrary("..\\HookTest\\HookDll.dll"); // 加载dll
	if (NULL != hIst)
	{
		typedef BOOL (*pFunSetHook)(HWND);
		pFunSetHook pSetHook = (pFunSetHook)GetProcAddress(hIst, "SetHook");
		if (NULL != pSetHook)
		{
			if(pSetHook(m_hWnd))
				AfxMessageBox("创建全局钩子成功...");
		}
	}
}

//卸载全局钩子
void CHookTestDlg::OnDestroyDllHook() 
{
	if (NULL != hIst)
	{
		typedef void (*pFunDestroyHook)();
		pFunDestroyHook pDestryHook = (pFunDestroyHook)GetProcAddress(hIst, "DestroyHook");
		if (NULL != pDestryHook)
		{
			pDestryHook();
			::FreeLibrary(hIst);
			hIst = NULL;
			AfxMessageBox("销毁全局钩子成功!");
		}
	}
	m_edit.EnableWindow(TRUE);
}

 

 

 

 

 

.........

至此,一个简单的拦截窗口程序,已经实现。

 

 

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值