複製鏈接
請複製以下鏈接發送給好友

消息鈎子

鎖定
鈎子是WINDOWS中消息處理機制的一個要點,通過安裝各種鈎子,應用程序能夠設置相應的子例程來監視系統裏的消息傳遞以及在這些消息到達目標窗口程序之前處理它們。 鈎子的種類很多,每種鈎子可以截獲並處理相應的消息,如鍵盤鈎子可以截獲鍵盤消息,鼠標鈎子可以截獲鼠標消息,外殼鈎子可以截獲啓動和關閉應用程序的消息,日誌鈎子可以監視和記錄輸入事件。
中文名
消息鈎子
種    類
鍵盤鈎子、鼠標鈎子、外殼鈎子等

消息鈎子簡介

若在dll中使用SetWindowsHookEx設置一全局鈎子,系統會將其加載入使用user32的進程中,因而它也可被利用為無進程木馬的進程注入手段。</CA>
Hook解釋
Hook是Windows中提供的一種用以替換DOS下“中斷”的系統機制,中文譯為“掛鈎”或“鈎子”。在對特定的系統事件進行hook後,一旦發生已hook事件,對該事件進行hook的程序就會受到系統的通知,這時程序就能在第一時間對該事件做出響應。
另一解釋
鈎子(Hook),是Windows消息處理機制的一個平台,應用程序可以在上面設置子程以監視指定窗口的某種消息,而且所監視的窗口可以是其他進程所創建的。當消息到達後,在目標窗口處理函數之前處理它。鈎子機制允許應用程序截獲處理window消息或特定事件。
鈎子實際上是一個處理消息的程序段,通過系統調用,把它掛入系統。每當特定的消息發出,在沒有到達目的窗口前,鈎子程序就先捕獲該消息,亦即鈎子函數先得到控制權。這時鈎子函數即可以加工處理(改變)該消息,也可以不作處理而繼續傳遞該消息,還可以強制結束消息的傳遞。
Hook原理
每一個Hook都有一個與之相關聯的指針列表,稱之為鈎子鏈表,由系統來維護。這個列表的指針指向指定的,應用程序定義的,被Hook子程調用的回調函數,也就是該鈎子的各個處理子程。當與指定的Hook類型關聯的消息發生時,系統就把這個消息傳遞到Hook子程。一些Hook子程可以只監視消息,或者修改消息,或者停止消息的前進,避免這些消息傳遞到下一個Hook子程或者目的窗口。最近安裝的鈎子放在鏈的開始,而最早安裝的鈎子放在最後,也就是後加入的先獲得控制權。
Windows 並不要求鈎子子程的卸載順序一定得和安裝順序相反。每當有一個鈎子被卸載,Windows 便釋放其佔用的內存,並更新整個Hook鏈表。如果程序安裝了鈎子,但是在尚未卸載鈎子之前就結束了,那麼系統會自動為它做卸載鈎子的操作。
鈎子子程是一個應用程序定義的回調函數(CALLBACK Function),不能定義成某個類的成員函數,只能定義為普通的C函數。用以監視系統或某一特定類型的事件,這些事件可以是與某一特定線程關聯的,也可以是系統中所有線程的事件。
系統鈎子與線程鈎子
SetWindowsHookEx函數的最後一個參數決定了此鈎子是系統鈎子還是線程鈎子。
線程鈎子用於監視指定線程的事件消息。線程鈎子一般在當前線程或者當前線程派生的線程內。
系統鈎子監視系統中的所有線程的事件消息。因為系統鈎子會影響系統中所有的應用程序,所以鈎子函數必須放在獨立的動態鏈接庫(DLL) 中。系統自動將包含“鈎子回調函數”的DLL映射到受鈎子函數影響的所有進程的地址空間中,即將這個DLL注入了那些進程。
幾點説明
(1)如果對於同一事件(如鼠標消息)既安裝了線程鈎子又安裝了系統鈎子,那麼系統會自動先調用線程鈎子,然後調用系統鈎子。
(2)對同一事件消息可安裝多個鈎子處理過程,這些鈎子處理過程形成了鈎子鏈。當前鈎子處理結束後應把鈎子信息傳遞給下一個鈎子函數
(3)鈎子特別是系統鈎子會消耗消息處理時間,降低系統性能。只有在必要的時候才安裝鈎子,在使用完畢後要及時卸載

消息鈎子應用模式

消息鈎子觀察模式

最為常用,像Windows提供的SetWindowHook就是典型地為這類應用準備的。而且這也是最普遍的用法。
這個模式的特點是,在事情發生的時候,發出一個通知信息。觀察者只可以查看過程中的信息,根據自己關心的內容處理自己的業務,但是不可以更改原來的流程。
全局鈎子中,經常使用的鼠標消息、鍵盤消息的監視等應用。金山詞霸屏幕取詞的功能是一個典型的應用(具體技術可以參考此類文章)。

消息鈎子注入模式

這個模式和觀察模式最大的不一樣的地方在於,注入的代碼是為了擴展原始代碼的功能業務。插件模式是此類模式的典型案例。
不管瘦核心的插件系統(如Eclipse)還是胖核心的插件系統(如Delphi、Visual Studio等IDE環境),其對外提供的插件接口都是為了擴展本身系統的功能的。
這種擴展的應用方式的典型特點,就是新的擴展代碼和原來的代碼會協調處理同類業務。

消息鈎子替換模式

如果針對應用目的不同,可以叫修復模式或破解模式。前者是為了修改系統中的BUG,後者是為了破解原有系統的限制。
很多黑客使用此種模式,將訪問加密鎖的DLL中的導出表,替換成自己的函數,這樣跳過對軟件的控制代碼。這類應用的難點是,找出函數的參數。
這類模式的特點是,原有的代碼會被新的代碼所替換。
前面三個是基本模式,還有很多和實際應用相關的模式。

消息鈎子集權模式

此類模式的出現,大都是為了在全部系統中,統一處理某類事情。它的特點不在於注入的方式,而在於處理的模式。
這個模式,大都應用到某類服務上,比如鍵盤服務,鼠標服務,打印機服務等等特定服務上。通過統一接管此類服務的訪問,限制或者協調對服務的訪問。
比如鍵盤鎖功能的實現,就是暫時關閉鍵盤的所有應用。
這類模式的特點主要會和特點服務有關聯。

消息鈎子修復模式

替換模式的一種,這裏強調的是其應用的目的是為了修復或擴展原有系統的功能。

消息鈎子破解模式

替換模式的一種,這裏強調的是其應用的目的是為了跳過原有系統的一部分代碼。如加密檢測代碼,網絡檢測代碼等等。

消息鈎子插件模式

注入模式的一種,在系統的內部直接依靠HOOK機制進行擴展業務功能。

消息鈎子共享模式

這類應用中,經常是為了獲取對方的數據。必然我希望獲取對方系統中,所有字符串的值。可以通過替換對方的內存管理器,導出所有字符串。
這個應用比較特殊。不過其特點在於,目的是達到系統之間的數據共享。
其實現,可能是觀察模式,也可能是替換模式。

消息鈎子技術應用

Hook簡介
Hook這個東西有時令人又愛又怕,Hook是用來攔截系統某些訊息之用,例如説,我們想
讓系統不管在什麼地方只要按個Ctl-B便執行NotePad,或許您會使用Form的KeyPreview
,設定為True,但在其他Process中按Ctl-B呢?那就沒有用,這是就得設一個Keyboard
Hook來攔截所有Key in的鍵;再如:MouseMove的Event只在該Form或Control上有效,如果希望在Form的外面也能得知Mouse Move的訊息,那隻好使用Mouse Hook來欄截Mouse
的訊息。再如:您想記錄方才使用者的所有鍵盤動作或Mosue動作,以便錄巨集,那就
使用JournalRecordHook,如果想停止所有Mosue鍵盤的動作,而放(執行)巨集,那就
使用JournalPlayBack Hook;Hook呢,可以是整個系統為範圍(Remote Hook),即其他
Process的動作您也可以攔截,也可以是LocalHook,它的攔截範圍只有Process本身。
Remote Hook的Hook Function要在.Dll之中,Local Hook則在.Bas中。
在VB如何設定Hook呢?使用SetWindowsHookEx
Declare Function SetWindowsHookEx Lib 'user32' Alias 'SetWindowsHookExA' _
ByVal idHook As Long, _
ByVal lpfn As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long As Long
idHook代表是何種Hook,有以下幾種
Public Const WH_CALLWNDPROC = 4
Public Const WH_CALLWNDPROCRET = 12
Public Const WH_CBT = 5
Public Const WH_DEBUG = 9
Public Const WH_FOREGROUNDIDLE = 11
Public Const WH_GETMESSAGE = 3
Public Const WH_HARDWARE = 8
Public Const WH_JOURNALPLAYBACK = 1
Public Const WH_JOURNALRECORD = 0
Public Const WH_KEYBOARD = 2
Public Const WH_MOUSE = 7
Public Const WH_MSGFILTER = (-1)
Public Const WH_SHELL = 10
Public Const WH_SYSMSGFILTER = 6
WH_CALLWNDPROC 當調用SendMessage時
WH_CALLWNDPROCRET 當SendMessage的調用返回時
WH_GETMESSAGE 當調用GetMessage 或 PeekMessage時
WH_KEYBOARD 當調用GetMessage 或 PeekMessage 來從消息隊列中查詢WM_KEYUP 或 WM_KEYDOWN 消息時
WH_MOUSE 當調用GetMessage 或 PeekMessage 來從消息隊列中查詢鼠標事件消息時
WH_HARDWARE 當調用GetMessage 或 PeekMessage 來從消息隊列種查詢非鼠標、鍵盤消息時
WH_MSGFILTER 當對話框、菜單或滾動條要處理一個消息時。該鈎子是局部的。它時為那些有自己的消息處理過程的控件對象設計的。
WH_SYSMSGFILTER 和WH_MSGFILTER一樣,只不過是系統範圍的
WH_JOURNALRECORD 當WINDOWS從硬件隊列中獲得消息時
WH_JOURNALPLAYBACK 當一個事件從系統的硬件輸入隊列中被請求時
WH_SHELL 當關於WINDOWS外殼事件發生時,譬如任務條需要重畫它的按鈕.
WH_CBT 當基於計算機的訓練(CBT)事件發生時
WH_FOREGROUNDIDLE 由WINDOWS自己使用,一般的應用程序很少使用
WH_DEBUG 用來給鈎子函數除錯
lpfn代表Hook Function所在的Address,這是一個CallBack Fucnction,當掛上某個
Hook時,我們便得定義一個Function來當作某個訊息產生時,來處理它的Function
,這個Hook Function有一定的叁數格式
Private Function HookFunc ByVal ncode As Long, _
ByVal wParam As Long, _
ByVal lParam As Long As Long
nCode 代表是什麼請況之下所產生的Hook,隨Hook的不同而有不同組的可能值
wParam lParam 傳回值則隨Hook的種類和nCode的值之不同而不同。
因這個叁數是一個 Function的Address所以我們固定將Hook Function放在.Bas中,
並以AddressOf HookFunc傳入。至於Hook Function的名稱我們可以任意給定,不一
定叫 HookFunc
hmod 代表.DLL的hInstance,如果是Local Hook,該值可以是Null(VB中可傳0進去),
而如果是Remote Hook,則可以使用GetModuleHandle('.dll名稱')來傳入。
dwThreadId 代表執行這個Hook的ThreadId,如果不設定是那個Thread來做,則傳0所以
一般來説,Remote Hook傳0進去,而VB的Local Hook一般可傳App.ThreadId進去
值回值如果SetWindowsHookEx成功,它會傳回一個值,代表目前的Hook的Handle,
這個值要記錄下來。
因為A程式可以有一個System Hook(Remote Hook),如KeyBoard Hook,而B程式也來設一
個Remote的KeyBoard Hook,那麼到底KeyBoard的訊息誰所攔截?答案是,最後的那一個
所攔截,也就是説A先做keyboard Hook,而後B才做,那訊息被B攔截,那A呢?就看B的
Hook Function如何做。如果B想讓A的Hook Function也得這個訊息,那B就得呼叫
CallNextHookEx將這訊息Pass給A,於是產生Hook的一個連線。如果B中不想Pass這訊息
給A,那就不要呼叫CallNextHookEx。
Declare Function CallNextHookEx Lib 'user32' _
ByVal hHook As Long, _
ByVal ncode As Long, _
ByVal wParam As Long, _
lParam As Any As Long
hHook值是SetWindowsHookEx的傳回值,nCode, wParam, lParam則是Hook Procedure
中的三個叁數。
最後是將這Hook去除掉,請呼叫UnHookWindowHookEx
Declare FunctionUnhookWindowsHookExLib 'user32' (ByVal hHook As Long) As Long
hHook便是SetWindowsHookEx的傳回值。此時,以上例來説,B程式結束Hook,則換A可
以直接攔截訊息。
KeyBoard Hook的範例
Hook Function的三個叁數
nCode wParam lParam 傳回值
HC_ACTION 表按鍵Virtual Key 與WM_KEYDOWN同 若訊息要被處理傳0
或 反之傳1
HC_NOREMOVE
Public hHook As Long
Public Sub UnHookKBD
If hnexthookproc 0 Then
hHook = 0
End If
End Sub
Public Function EnableKBDHook
If hHook 0 Then
Exit Function
End If
hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf MyKBHFunc, App.hInstance, App.ThreadID)
End Function
Public Function MyKBHFunc(ByVal iCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
MyKBHFunc = 0 '表示要處理這個訊息
If wParam = vbKeySnapshot Then '偵測 有沒有按到PrintScreen鍵
MyKBHFunc = 1 '在這個Hook便吃掉這個訊息
End If
Call CallNextHookEx(hHook, iCode, wParam, lParam) '傳給下一個Hook
End Function
只要將上面代碼放在VB的模塊中,用標準VB程序就可以了,當運行該程序後,就能攔截所有鍵盤操作。