核心函数
SetWindowsHookExA
API文档:https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa
https://docs.microsoft.com/zh-cn/previous-versions/windows/desktop/legacy/ms644981(v=vs.85)
核心代码:
1、写一个dll。
HWND g_MainWnd = NULL; HHOOK g_hook = NULL; #ifdef __cplusplus extern "C" { //only need to export C interface if // used by C++ source code #endif __declspec(dllexport) void SetHHook(HHOOK hook) //此函数废弃 { g_hook = hook; } __declspec(dllexport) LRESULT GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode == HC_ACTION && wParam == PM_REMOVE) { //must process and lParam is MSG struct MSG* msg = (MSG*)lParam; if (g_MainWnd) { PostMessage(g_MainWnd, WM_USER + 100 + msg->message, msg->wParam, msg->lParam); } } //晕,第一个参数被忽略的,可以直接传NULL return CallNextHookEx(g_hook, nCode, wParam, lParam); } #ifdef __cplusplus } #endif BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: //try to get the windows g_MainWnd = FindWindow(NULL, L"EasySpy"); case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
2、 调用函数
//查看捕获的窗口句柄 HWND hCaptured = ::WindowFromPoint(point); DWORD dwThreadId; HOOKPROC hkprcSysMsg=NULL; dwThreadId = GetWindowThreadProcessId(hCaptured, NULL); if (g_lastHook) { UnhookWindowsHookEx(g_lastHook); } //尝试去loaddll if (!g_module) { g_module = LoadLibrary(TEXT("E:\代码\开源代码\hookdemo\trunk\EasySpy\Debug\DllInject.dll")); } if (g_module) { hkprcSysMsg = (HOOKPROC)GetProcAddress(g_module, "GetMsgProc"); } if (hkprcSysMsg) { //这里去拦截消息 g_lastHook = SetWindowsHookEx(WH_GETMESSAGE, hkprcSysMsg, g_module, dwThreadId); }
完整代码Demo见github:https://github.com/xuhuajie-NetEase/EasySpy
有兴趣的同学可以优化下代码,做成跟spy++更像的。我只是研究下Hook技术,就不再优化了了。