利用钩子进行进程通信,在网上搜了许多帖子还是不明所以。
没办法自己摸索了4,5天终于测试好了代码。写下来,希望不要有人像我这样云里雾里的在这上面浪费时间。
钩子的加载
使用函数SetWindowsHookEx加载钩子
HHOOK SetWindowsHookExA(
int idHook, //钩子的类型
HOOKPROC lpfn, //钩子的系统回调函数
HINSTANCE hmod, // 模块的句柄
DWORD dwThreadId //线程ID 为0时,钩子是全局钩子
);
参数说明: 如果需要设置局部钩子(作用范围:单一的进程),那么hmod参数为0,dwThreadId设置为需要钩住的线程的ID。
如果需要设置全局钩子(作用范围:所有有效进程),那么hmod参数为模块句柄(钩子的回调函数需要在DLL中),dwThreadId设置为0。
实例:
程序目标: 进程A 向进程B(欲控制的程序) 发送一个自定义消息,进程B 根据消息做出不同的处理。
进程B中肯定没有自定义消息的处理过程,需要通过钩子向进程B 注入该消息的处理过程。
第1步:
在DLL中写钩子加载函数
#pragma comment(linker,"/SECTION:.share,RWS")
#pragma data_seg(".share")
HHOOK g_Hook=0; //这几句代码申明g_Hook为所有DLL共享的变量 有关于DLL共享节自行baidu
#pragma data_seg()
HMODULE g_Hmodule = 0;
BOOL WINAPI SetWndHook()
{
if (g_Hook) //如果钩子句柄有值,说明已经加载过钩子。
{
MessageBox(0, TEXT("钩子已经被加载"), TEXT("success"), 0);
return true;
}
MessageBox(0, TEXT("运行钩子加载函数"), TEXT("success"), 0);
g_Hook = SetWindowsHookEx(WH_CALLWNDPROC, //hook类型为窗口消息
WndProc, //钩子回调函数
g_Hmodule, //该DLL在进程中的句柄
0 //为0 表明钩子为全局的钩子
);
if (!g_Hook)
return FALSE;
else
return TRUE;
}
第2步:钩子的回调函数
LRESULT CALLBACK WndProc(
_In_ int code,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
if (code== HC_ACTION)
{
TCHAR szWindowText[] = TEXT("MFCHookTest"); //我测试的程序标题 一定要是有消息循环的程序
PCWPSTRUCT pcw = (PCWPSTRUCT)lParam; //文档说明 lParam参数为CWPSTRUCT结构的指针 这里转换使用
if (pcw->message == WM_USER + 100 && pcw->lParam == 100 )
{
// 自定义消息为WM_USER+100 lParam 值是100
//MessageBox(0, TEXT("接受到自定义消息"), TEXT("success"), 0);
SetWindowText(FindWindow(NULL, szWindowText),TEXT("接受成功")); //接收自定义消息成功,修改其窗口标题
}
}ram, lParam); //文档说明返回时要这样做
}
SetWndHook通过def文件导出 方便查找函数名
第三步:在任意exe中调用钩子加载函数即可 ,然后发送自定义消息,观察目标程序的窗口标题。
//导入dll 通过函数指针得到函数SetWndHook的地址
if (SetWndHook())
{
AfxMessageBox(TEXT("Hook成功"));
}
HWND hWnd = ::FindWindow(NULL, TEXT("MFCHookTest")); //查找窗口句柄
if (!hWnd)
{
AfxMessageBox(TEXT("窗口句柄查找失败"));
}
::SendMessage(hWnd,WM_USER+100,0,100); //发送自定义消息