Spy++是如何獲取發往窗口的消息的?

就是我用了spy++抓了一個窗口,然後在spy++的窗口列表中右鍵選中的窗口,查看消息,可以看到一堆的消息。包括在窗口上的滑鼠事件等等,請問是如何實現的,原理是什麼?

======================================================================

感謝@蔣晟 @姚冬 ,分別從不同方面解決了問題。


本來想昨天寫的,發現已經有答案了,稍微補充一下細節。

IDA 粗看了一下 VS2015 社區版帶的 spyxx_amd64,用的是 SetWindowHookEx 設置了全局鉤子。實現代碼在 .text:140037A64 __int64 __fastcall SetMsgHook(int),一共設置了三個 hook: WH_GETMESSAGE, WH_CALLWNDPROC, WH_CALLWNDPROCRET。

三者都可以監視窗口消息,它們的區別是:

  • WH_GETMESSAGE:監視由 GetMessage 或 PeekMessage 獲取的消息,但不能攔截或者修改消息參數;

  • WH_CALLWNDPROC 可以在窗口接收到消息之前進行處理,修改參數,甚至丟棄消息;
  • WH_CALLWNDPROCRET 在窗口已經處理完了消息的時候觸發。

詳見:Hooks Overview (Windows)

這三個 hook 對應的回調函數在 spyxxhk_amd64.dll 中實現,分別對應 SpyxxGetMsgProc, SpyxxCallWndProc 和 SpyxxCallWndRetProc。

這三個函數的具體實現非常相似,都是根據窗口的句柄獲取一些額外的信息,如 ClassName / WindowLong / ProcessId / ThreadId 等,投遞消息到日誌處理常式中。例如 SpyxxCallWndRetProc:

LRESULT __fastcall SpyxxCallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
{
LPARAM v3; // rbx@1
int v4; // esi@1
LRESULT v5; // rdi@1
HWND v6; // rcx@5
DWORD v7; // eax@6
DWORD dwProcessId; // [sp+70h] [bp+18h]@6
__int64 v10; // [sp+78h] [bp+20h]@1

v3 = lParam;
v4 = nCode;
v5 = CallNextHookEx(ghhkRetHook, nCode, wParam, lParam);
v10 = v5;
if ( gfHookEnabled )
{
if ( !gfHookDisabled !v4 )
{
if ( v3 )
{
v6 = *(HWND *)(v3 + 32);
if ( v6 )
{
v7 = GetWindowThreadProcessId(v6, dwProcessId);
if ( dwProcessId != gpidSpyxx v7 != gtidSpyxx GetCurrentThreadId() != gtidSpyxx )
PostToSpyxxApp(
2,
*(void **)v3,
*(HWND *)(v3 + 32),
*(_DWORD *)(v3 + 24),
*(void **)(v3 + 16),
*(void **)(v3 + 8),
0,
0,
0);
}
}
}
}
return v5;
}

SpyXX 通過設置鉤子來全局捕獲消息。如果已經知道目標窗口的句柄,可以簡單地替換 WNDPROC 來接管消息,根據需要選擇是否丟棄消息或者放行。具體實現是 GetWindowLong(hWnd, GWL_WNDPROC 獲取原始的回調函數地址,接著 SetWindowLong 替換其為自定義的回調函數,在回調中使用 CallWindowProc 調用原始函數即可實現放行或修改 wParam / lParam。


這個Windows SDK里有源代碼的

Spy: Monitoring Messages with SPY


Windows高級編程指南 (豆瓣)

你應該去讀這本書,書的作者 Jeffrey Richter 就是Spy++的作者

書里詳細描述了Spy++技術的實現。


setwindowlong 好像是 反正有winAPI的


推薦閱讀:

很多人說MFC落伍了,那有什麼可以代替MFC?
對於一個初學者,MFC和Qt哪個好下手?
MFC為什麼難用,框架的敗筆是?
DirectUI與GUI框架有什麼區別,如MFC,QT,wxWidgets的區別是什麼?
電腦桌面背景可以總是前置嗎?

TAG:MicrosoftVisualStudio | MFC | Windows開發 | VisualC | Net開發 |