[轉載]Windows HOOK(鉤子)機制
阿新 • • 發佈:2019-02-17
Windows HOOK(鉤子)機制與例項
1.WINDOWS的訊息機制
Windows系統是以訊息處理為其控制機制,系統通過訊息為視窗過程(windows procedure)傳遞輸入。系統和應用兩者都可以產生訊息。對於每個輸入事件,例如使用者按下了鍵盤上的某個鍵、移動了滑鼠、單擊了一個控制元件上的滾動條,等等,系統都將產生一系列訊息。此外,對於應用帶給系統的變化,如字型資源的改變、應用本身視窗的改變,系統都將通過訊息以響應這種變化。應用通過產生訊息指示應用的視窗完成特定的任務,或與其他應用的視窗進行通訊。
每個視窗都有一個處理Windows系統傳送訊息的處理程式,稱為視窗程式。它是隱含在視窗背後的一段程式指令碼,其中包含對事件進行處理的程式碼。
Windows系統為每條訊息指定了一個訊息編號,例如當一個視窗變為活動視窗時,它事實上是收到一條來自Windows系統的WM_ACTIVATE訊息,該訊息的編號為6,它對應於VB視窗的Activate事件。對於視窗來說,諸如Open、Activate、MouseDown、Resize等事件,實際上對應的是視窗內部的訊息處理程式,這些程式對於使用者來講是不可見的。類似地,命令按鈕也有訊息處理程式,它的處理程式響應諸如WM_LBUTTONDOWN和WM_RBUTTONDOWN之類的訊息,即啟用命令按鈕的MouseDown事件。
Windows的訊息處理機制為了能在應用程式中監控系統的各種事件訊息,提供了掛接各種回撥函式(HOOK)的功能。這種掛鉤函式(HOOK)類似擴充中斷驅動程式,掛鉤上可以掛接多個回撥函式構成一個掛接函式鏈。系統產生的各種訊息首先被送到各種掛接函式,掛接函式根據各自的功能對訊息進行監視、修改和控制等,然後交還控制權或將訊息傳遞給下一個掛接函式以致最終達到視窗函式。Windows系統的這種回撥函式掛接方法雖然會略加影響到系統的執行效率,但在很多場合下是非常有用的,通過合理有效地利用鍵盤事件的掛鉤函式監控機制可以達到預想不到的良好效果。
2.HOOK介紹
HOOK(鉤子)是Windows提供的一種訊息處理機制平臺,是指在程式正常執行中接受資訊之前預先啟動的函式,用來檢查和修改傳給該程式的資訊,(鉤子)實際上是一個處理訊息的程式段,通過系統呼叫,把它掛入系統。每當特定的訊息發出,在沒有到達目的視窗前,鉤子程式就先捕獲該訊息,亦即鉤子函式先得到控制權。這時鉤子函式即可以加工處理(改變)該訊息,也可以不作處理而繼續傳遞該訊息,還可以強制結束訊息的傳遞。
注意:安裝鉤子函式將會影響系統的效能。監測“系統範圍事件”的系統鉤子特別明顯。因為系統在處理所有的相關事件時都將呼叫您的鉤子函式,這樣您的系統將會明顯的減慢。所以應謹慎使用,用完後立即解除安裝。還有,由於您可以預先截獲其它程序的訊息,所以一旦您的鉤子函數出了問題的話必將影響其它的程序。
記住:功能強大也意味著使用時要負責任。
3.HOOK鏈
Windows提供了14種不同型別的HOOKS;不同的HOOK可以處理不同的訊息。例如,WH_MOUSE HOOK用來監視滑鼠訊息。
Windows為這幾種HOOKS維護著各自的HOOK連結串列。HOOK連結串列是一串由應用程式定義的回撥函式(CALLBACK Function)佇列,當某種型別的訊息發生時,Windows向此種類型的HOOK鏈的第一個函式(HOOK鏈的頂部)傳送該訊息,在第一函式處理完該訊息後由該函式向連結串列中的下一個函式傳遞訊息,依次向下。如果鏈中某個函式沒有向下傳送該訊息,那麼連結串列中後面的函式將得不到此訊息。(對於某些型別的HOOK,不管HOOK鏈中的函式是否向下傳遞訊息,與此型別HOOK聯絡的所有HOOK函式都會收到系統傳送的訊息)一些HOOK子過程可以只監視訊息,或者修改訊息,或者停止訊息的前進,避免這些訊息傳遞到下一個HOOK子過程或者目的視窗。最近安裝的鉤子放在鏈的開始,而最早安裝的鉤子放在最後,也就是後加入的先獲得控制權。
4.HOOK的作用範圍
一共有兩種範圍(型別)的鉤子:區域性的和遠端的
1. 區域性鉤子僅鉤掛您自己程序的事件。
2. 遠端的鉤子還可以將鉤掛其它程序發生的事件。
遠端的鉤子又有兩種:
1. 基於執行緒的 它將捕獲其它程序中某一特定執行緒的事件。簡言之,就是可以用來觀察其它程序中的某一特定執行緒將發生的事件。
2. 系統範圍的 將捕捉系統中所有程序將發生的事件訊息。
5.HOOK型別
Windows共有14種HOOKS,每一種型別的Hook可以使應用程式能夠監視不同型別的系統訊息處理機制。下面描述所有可以利用的Hook型別的發生時機。(這些常數值均可以API瀏覽器裡查到)
1.WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks
WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使你可以監視傳送到視窗過程的訊息。系統在訊息傳送到接收視窗過程之前呼叫WH_CALLWNDPROC Hook子過程,並且在視窗過程處理完訊息之後呼叫WH_CALLWNDPROCRET Hook子過程。
WH_CALLWNDPROCRET Hook傳遞指標到CWPRETSTRUCT結構,再傳遞到Hook子過程。CWPRETSTRUCT結構包含了來自處理訊息的視窗過程的返回值,同樣也包括了與這個訊息關聯的訊息引數。
2.WH_CBT Hook
在以下事件之前,系統都會呼叫WH_CBT Hook子過程,這些事件包括:
- 啟用,建立,銷燬,最小化,最大化,移動,改變尺寸等視窗事件;
- 完成系統指令;
- 來自系統訊息佇列中的移動滑鼠,鍵盤事件;
- 設定輸入焦點事件;
- 同步系統訊息佇列事件。
Hook子過程的返回值確定系統是否允許或者防止這些操作中的一個。
3.WH_DEBUG Hook
在系統呼叫系統中與其它Hook關聯的Hook子過程之前,系統會呼叫WH_DEBUG Hook子過程。你可以使用這個Hook來決定是否允許系統呼叫與其它Hook關聯的Hook子過程。
4.WH_FOREGROUNDIDLE Hook
當應用程式的前臺執行緒處於空閒狀態時,可以使用WH_FOREGROUNDIDLEHook執行低優先順序的任務。當應用程式的前臺執行緒大概要變成空閒狀態時,系統就會呼叫WH_FOREGROUNDIDLE Hook子過程。
5.WH_GETMESSAGE Hook
應用程式使用WH_GETMESSAGE Hook來監視從GetMessage or PeekMessage函式返回的訊息。你可以使用WH_GETMESSAGE Hook去監視滑鼠和鍵盤輸入,以及其它傳送到訊息佇列中的訊息。
6.WH_JOURNALPLAYBACK Hook
WH_JOURNALPLAYBACK Hook使應用程式可以插入訊息到系統訊息佇列。可以使用這個Hook回放通過使用WH_JOURNALRECORD Hook記錄下來的連續的滑鼠和鍵盤事件。只要WH_JOURNALPLAYBACK Hook已經安裝,正常的滑鼠和鍵盤事件就是無效的。WH_JOURNALPLAYBACK Hook是全域性Hook,它不能象執行緒特定Hook一樣使用。WH_JOURNALPLAYBACK Hook返回超時值,這個值告訴系統在處理來自回放Hook當前訊息之前需要等待多長時間(毫秒)。這就使Hook可以控制實時事件的回放。WH_JOURNALPLAYBACK是system-wide local hooks,它們不會被注射到任何行程地址空間。
7.WH_JOURNALRECORD Hook
WH_JOURNALRECORD Hook用來監視和記錄輸入事件。典型的,可以使用這個Hook記錄連續的滑鼠和鍵盤事件,然後通過使用WH_JOURNALPLAYBACK Hook來回放。WH_JOURNALRECORD Hook是全域性Hook,它不能象執行緒特定Hook一樣使用。WH_JOURNALRECORD是system-wide local hooks,它們不會被注射到任何行程地址空間。
8.WH_KEYBOARD Hook
在應用程式中,WH_KEYBOARD Hook用來監視WM_KEYDOWN and WM_KEYUP訊息,這些訊息通過GetMessage or PeekMessage function返回。可以使用這個Hook來監視輸入到訊息佇列中的鍵盤訊息。
9.WH_KEYBOARD_LL Hook
WH_KEYBOARD_LL Hook監視輸入到執行緒訊息佇列中的鍵盤訊息。
10.WH_MOUSE Hook
WH_MOUSE Hook監視從GetMessage 或者 PeekMessage 函式返回的滑鼠訊息。使用這個Hook監視輸入到訊息佇列中的滑鼠訊息。
11.WH_MOUSE_LL Hook
WH_MOUSE_LL Hook監視輸入到執行緒訊息佇列中的滑鼠訊息。
12.WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks
WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我們可以監視選單,滾動條,訊息框,對話方塊訊息並且發現使用者使用ALT+TAB or ALT+ESC 組合鍵切換視窗。
WH_MSGFILTER Hook只能監視傳遞到選單,滾動條,訊息框的訊息,以及傳遞到通過安裝了Hook子過程的應用程式建立的對話方塊的訊息。WH_SYSMSGFILTER Hook監視所有應用程式訊息。
WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我們可以在模式迴圈期間過濾訊息,這等價於在主訊息迴圈中過濾訊息。
通過呼叫CallMsgFilter function可以直接的呼叫WH_MSGFILTER Hook。通過使用這個函式,應用程式能夠在模式迴圈期間使用相同的程式碼去過濾訊息,如同在主訊息迴圈裡一樣。
13.WH_SHELL Hook
外殼應用程式可以使用WH_SHELL Hook去接收重要的通知。當外殼應用程式是啟用的並且當頂層視窗建立或者銷燬時,系統呼叫WH_SHELL Hook子過程。
WH_SHELL 共有5鍾情況:
- 只要有個top-level、unowned 視窗被產生、起作用、或是被摧毀;
- 當Taskbar需要重畫某個按鈕;
- 當系統需要顯示關於Taskbar的一個程式的最小化形式;
- 當目前的鍵盤佈局狀態改變;
- 當使用者按Ctrl+Esc去執行Task Manager(或相同級別的程式)。
按照慣例,外殼應用程式都不接收WH_SHELL訊息。所以,在應用程式能夠接收WH_SHELL訊息之前,應用程式必須呼叫SystemParametersInfo function註冊它自己。