VB編程中鉤子的實現及應用

來源:互聯網
上載者:User
編程  前言

  Windows系統中鉤子具有相當強大的功能,通過這種技術可以對幾乎所有的Windows 系統中的訊息進行攔截、監視、處理。這種技術可以廣泛應用於各種軟體,尤其是需要有監控、自動記錄等對系統進行監測功能的軟體。本文針對這個專題進行了探討,希望可以為讀者朋友們起到拋磚引玉的作用。

  一、鉤子的機制及類型

  Windows的應用程式都是基於訊息驅動的,應用程式的操作都依賴於它所得到的訊息的類型及內容。鉤子與Dos中斷截獲處理機制有類似之處。鉤子(Hook)是Windows訊息處理機制的一個平台,通過安裝各種鉤子,應用程式可以在上面設定子程式以監視指定視窗的某種訊息,並且當訊息到達目標視窗之前處理它。

  在Windows中,鉤子有兩種,一種是系統鉤子(RemoteHook),它對訊息的監視是整個系統範圍,另一種是線程鉤子(LocalHook),它的攔截範圍只有進程內部的訊息。對於系統鉤子,其鉤子函數(HookFunction)應在Windows系統的動態連結程式庫(DLL)中實現,而對於線程鉤子來說,鉤子函數可以在DLL之中實現,也可以在相應的應用程式之中實現。這是因為當開發人員建立一個鉤子時,Windows先在系統記憶體中建立一個資料結構,該資料結構包含了鉤子的相關資訊,然後把該結構體加到已經存在的鉤子鏈表中去,並且新的鉤子將排在老的鉤子的前面。當一個事件發生時,如果安裝的是一個局部鉤子,當前進程中的鉤子函數將被調用。如果是一個遠程鉤子,系統就必須把鉤子函數插入到其它進程的地址空間,要做到這一點就要求鉤子函數必須在一個動態連結程式庫中,所以如果想要使用遠程鉤子,就必須把該鉤子函數放到動態連結程式庫中去。對於鉤子所監視的訊息類型來說,Windws一共提供了如下幾種類型:如表1所示:

表一、Windows訊息類型







訊息類型常量標識

訊息類型
適用範圍

WH_CALLWNDPROC
4
發給視窗的訊息
線程或系統

WH_CALLWNDPROCRET
12
視窗返回的訊息
線程或系統

WH_CBT
5
視窗變化、焦點設定等訊息
線程或系統

WH_DEBUG
9
是否執行其它Hook的Hook
線程或系統

WH_FOREGROUNDIDLE
11
前景程式空閑
線程或系統

WH_GETMESSAGE
3
投放至訊息佇列中的訊息
線程或系統

WH_JOURNALPLAYBACK
1
將所記載的訊息進行回放
系統

WH_JOURNALRECORD
0
監視並記錄輸入訊息
系統

WH_KEYBOARD
2
鍵盤訊息
線程或系統

WH_MOUSE
7
滑鼠訊息
線程或系統

WH_MSGFILTER
-1
菜單捲軸、對話方塊訊息
線程或系統

WH_SHELL
10
外殼程式的訊息
線程或系統

WH_SYSMSGFILTER
6
所有線程的菜單捲軸、對話方塊訊息
系統



  二、VB編程中鉤子的實現

  (一)鉤子函數(HOOK Function)的格式。Hook Function實際上是一個函數,如果是系統鉤子,該函數必須放在動態連結程式庫中。該函數有一定的參數格式,在VB中如下:

Private Function HookFunc(ByVal nCode As Long,ByVal wParam As Long,ByVal lParam As Long)As Long



  其中,nCode代表是什麼情況之下所產生的鉤子,隨鉤子的不同而有不同組的可能值;參數wParam,lParam傳回值包括了所監視到的訊息內容,它隨Hook所監視訊息的種類和nCode的值不同而不同。對於用VB所設定的鉤子函數,一般的架構形式如下:

Private Function HookFunc(ByVal nCode As Long,ByVal wParam As Long,ByVal lParam As Long)As Long
 Select case of nCode
  case ncode<0:hookfunc=callnexthookex(hHookFunc,nCode,wParam,lParam)
  case值1:處理過程1:HookFunc=X1
  case2:處理過程2:HookFunc=X1
  ……
 end select
end Function



  函數的傳回值,如果訊息要被處理,則傳0,否則傳1,吃掉訊息。

  (二)鉤子的安裝及執行。鉤子的安裝要用到幾個API函數:可以使用API函數SetWindowsHookEx()把一個應用程式定義的鉤子子程安裝到鉤子鏈表中。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值為它處理的訊息類型;lpfn值為鉤子子程式的地址指標。如果dwThreadId參數為0或是一個由別的進程建立的線程的標識,lpfn必須指向DLL中的鉤子子程。除此以外,lpfn可以指向當前進程的一段鉤子子程代碼。hMod值為應用程式的控制代碼,標識包含lpfn所指的子程的DLL。如果dwThreadId標識當前進程建立的一個線程,而且子程代碼位於當前進程,hMod必須為0。dwThreadId值為與安裝的鉤子子程相關聯的線程的標識符,如果為0,鉤子子程與所有的線程關聯。鉤子安裝成功則返回鉤子子程的控制代碼,失敗返回0。

  另外,一般應在鉤子子程中調用CallNextHookEx()函數以執行鉤子鏈表所指的下一個鉤子子程,否則安裝了別的鉤子的應用程式就會收不到鉤子通知,從而產生錯誤的結果。CallNextHookEx()函數的聲明如下:

Declare Function CallNextHookEx Lib"user32" Alias "CallNextHookEx"(ByVal hHook As Long,ByVal ncode As Lonog, ByVal wParam As Long,lParam As Any)As Long



  hHook值是SetWindowsHookEx()的傳回值,nCode、wParam、lParam則是Hook函數中的三個參數。在程式終止之前,必須調用UnhookWindowsHookEx()函數釋放與鉤子關聯的系統資源。UnhookWindowsEx()函式宣告如下:

Declare Function Unhook WindowsHookEx Lib "user32" Alias "Unhook WindowsHookEx(ByVal hHook As Long)As Long



  hHook為安裝鉤子時的傳回值,即鉤子子程的控制代碼。

  (三)VB中鉤子安裝應注意的問題。lpfn參數是一個HookFunc的地址,VB規定必須將HookFunc代碼放到標準的.BAS模組中,並以"Address Of HookFunc"傳入,而不可以將其放到類別模組中,也不能將其附加到表單上。而對於RemoteHook來說,HookFunc應包含在動態連結程式庫中,因此如果在VB中使用RemoteHook,則還要用到GetModuleHandle()、GetProcAddress()兩個API函數,它們的聲明如下:

Declare Function GetModuleHandle Lib"kernel32" Alias "GetModuleHandleA"(ByVal lpModuleName As String)As Long
Declare Function GetProcAddress Lib "kernel32" Alias "GetProcAddress"(ByVal hModule As Long,ByVal lpProcName As String)As Long



  hmod值是含鉤子過程的模組名柄,如果是LocalHook,該值可以是Null(VB中傳0),而如果是RemoteHook,則可以使用GetModuleHandle("名稱.dll")來傳入。
三、執行個體--鍵盤訊息的攔截

  在程式開發時常用的有對輸入訊息進行監視的鍵盤鉤子,對於所監視到的訊息應進行處理,下面對鍵盤鉤子參數的具體內容組成進行說明:

  如果有鍵盤訊息(WM_KEYUP或WM_KEYDOWN)將被處理時,則系統調用鍵盤鉤子。

  nCode為HC_ACTION或HC_NOREMOVE,若小於0,則要求處理函數向下傳遞該訊息。

  wParam表示按鍵鍵碼常數,A鍵到Z鍵與其ASCII碼的相應值'A'到'Z'是一致的,例如按C鍵,則wParam值為67。

  lParam與WM_KEYDOWN同,佔四個位元組,其包括的內容較多,其二進位結構如下:

0
1
……
15
16
………
23
24
25
……
28
29
30
31



  0-15位(Key repeat count),鍵碼重複次數。16-23位(Scan code),按鍵的掃描碼。24位(Extended_Key flag),擴充鍵(功能鍵、數字小鍵盤上的鍵)標誌,為1則是擴充鍵,否則為0。25-28位被保留。29位(Context Code),狀態原因碼,ALT鍵被按下則為1,否則為0。30位(Previouskey_stateflag)指定先前的鍵狀態,如果訊息被發出之前鍵處於按下狀態,則為1;鍵處於釋放狀態則為0。31位(Transiton_stateflag)狀態轉換標誌,如果鍵是被按下值為1,如果鍵被放開值為0。

  本例中的鉤子用來監視並記錄應用程式中的按鍵資訊。在程式中,ALT+F4按鍵組合被屏蔽。下面是部分代碼:

Public hHook as Long
Private Sub Form_Load()′程式啟動時安裝鉤子
hHook=SetWindowsHookEx(2,Address of MyKBHook,0,App.ThreadID)
End Sub
′具體的鉤子程式,本例中該過程被包含在Module1中
Public Function MyKBHook(ByVal nCode As Long,ByVal wParam As Long,ByVal lParam As Long)As Long
If nCode>=0 then
Open "C:\Keyfile.txt" For Append As #1 '將鍵盤的操作記錄在Keyfile.txt檔案之中
'記錄所操作的鍵、操作時間、日期操作時的按鍵狀態,用16進位記錄
Write #1,wParam,Hex(lParam),Date,time
Close #1
MyKBHook=0 '表示要處理這個訊息
'屏蔽ALT+F4按鍵組合
if wParam=115 And(lParam And&H20000000)<>0 Then
if(lParam And &HC000000)=0 Then  '是否進行ALT+F4操作
MyHBHook=1 '鉤子吃掉這個訊息
End if
End if
End if
Call CallNextHookEx(hHook,nCode,wParam,lParam)'將訊息傳給下一個鉤子
End Function
'程式退出時卸載鉤子
Private Sub Form_Unload(Cancel As Interger)
Call Unhook WindowsHookEx(hHook)
End Sub



  四、總結

  鉤子處理常式是Windows進階編程技術,一般程式員都使用VC++等程式設計工具實現,本文表明,對於VB來說,雖然很多人認為是非專業的設計工具,但實現鉤子這樣的進階技術也是非常方便的。另外在使用鉤子時應注意到,鉤子雖然功能比較強,但如果使用不當將會嚴重影響系統的效率,所以要盡量避免使用系統鉤子,並且在不用鉤子時,應將鉤子及時卸載。



相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。