前段時間學習了HOOK,但沒有做筆記,今天稍微整理下。
一 HOOK的功能
在訊息體傳遞給應用程式的訊息佇列前對訊息進行處理,也就是說如果在鉤子過程中對訊息進行了屏蔽,是不會進入應用程式的訊息佇列的。(我實驗過,我們自己使用SendMessage和PostMessage的訊息是沒辦法被鉤住的,說明鉤子過程的調用應該比較靠近訊息傳遞過程的前面,很有可能位於事件觸發,形成訊息之後的環節)
二 HOOK的分類
1 進程內HOOK:只能截獲自己進程的訊息。
2 全域HOOK(系統鉤子):能夠截獲所有進程的訊息。
三 Hook函數
1 設定鉤子的函數
HHOOK WINAPI SetWindowsHookEx(int idHook,HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId);
WINAPI不用說 大家知道是__stdcall,windows api的標準調用方式,由api函數中自行清理堆棧。
參數1 idHook,截獲的鉤子類型,首碼WH,可以在MSDN中輸入“WH_”來查看可截獲的各種類型的訊息
參數2 lpfn是HOOKPROC類型的,HOOKPROC是使用typedef定義的一個函數指標的別名:
typedef LRESULT (CALLBACK *)(int nCode, WPARAM wParam, LPARAM lParam) HOOKPROC;
參數3 在進程內鉤子時為NULL,在系統鉤子時指定鉤子過程所在的DLL,是HINSTANCE類型的,可以通過GetModule來擷取。
參數4 在進程內鉤子時是GetCurrentThreadId(),在系統鉤子時設0。
傳回值:鉤子的控制代碼,可根據該控制代碼卸載鉤子。
2 調用下一個鉤子的函數
LRESULT WINAPI CallNextHookEx(HHOOK hhk,int nCode, WPARAM wParam, LPARAM lParam);
在HookProc中判斷該訊息是否是自己要處理的,如果是的話處理完返回一個1,則不會調用別人設定的鉤子了,否則要調用下一個鉤子。
3 卸載鉤子
BOOL WINAPI UnhookWindowsHookEx(HHOOK hhk);
卸載掉一個鉤子。
四 設定系統鉤子的方法
系統鉤子的設定需要將鉤子過程函數放到動態連結程式庫中,原因很簡單,因為動態連結程式庫在記憶體中是共用的,所以系統才能訪問到這個鉤子過程函數。
在原鉤子過程的基礎上加入 __declspec(dllexport) 即可實現,然後其他進程匯入該鉤子過程函數,調用SetWindowHookEx的時候第三個參數設定GetModule擷取的dll模組,第四個參數設定0即可。