學習Hook

基本概念 


鉤子(Hook),是Windows消息處理機制的一個平臺,應用程序可以在上面設置子程以監視指定窗口的某種消息,而且所監視的窗口可以是其他進程所創建的。當消息到達後,在目標窗口處理函數之前處理它。鉤子機制允許應用程序截獲處理window消息或特定事件。

鉤子實際上是一個處理消息的程序段,通過系統調用,把它掛入系統。每當特定的消息發出,在沒有到達目的窗口前,鉤子程序就先捕獲該消息,亦即鉤子函數先得到控

制權。這時鉤子函數即可以加工處理(改變)該消息,也可以不作處理而繼續傳遞該消息,還可以強制結束消息的傳遞。

理論
WINDOWS的鉤子函數可以認爲是WINDOWS的主要特性之一。利用它們,您可以捕捉您自己進程或其它進程發生的事件。通過“鉤掛”,您可以給WINDOWS一個處理或過濾事件的回調函數,該函數也叫做“鉤子函數”,當每次發生您感興趣的事件時,WINDOWS都將調用該函數。一共有兩種類型的鉤子:局部的和遠程的。

鉤子的類型

1、按事件分類

有如下的幾種常用類型

(1) 鍵盤鉤子和低級鍵盤鉤子可以監視各種鍵盤消息。

(2) 鼠標鉤子和低級鼠標鉤子可以監視各種鼠標消息。

(3) 外殼鉤子可以監視各種Shell事件消息。比如啓動和關閉應用程序。

(4) 日誌鉤子可以記錄從系統消息隊列中取出的各種事件消息。

(5) 窗口過程鉤子監視所有從系統消息隊列發往目標窗口的消息。

此外,還有一些特定事件的鉤子提供給我們使用,不一一列舉。

2、按使用範圍分類

主要有線程鉤子和系統鉤子:

(1) 線程鉤子監視指定線程的事件消息。

(2) 系統鉤子監視系統中的所有線程的事件消息。因爲系統鉤子會影響系統中所有的應用程序,所以鉤子函數必須放在獨立的動態鏈接庫(DLL)中。這是系統鉤子和線程鉤子很大的不同之處。

鉤子實例

編寫鉤子程序的三個步驟是:

定義鉤子函數:

LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam)

安裝鉤子:

HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId )

卸載鉤子:

BOOL UnhookWindowsHookEx( HHOOK hhk)

函數

  • SetWindowsHookEx用來安裝一個鉤子過程。
HHOOK WINAPI SetWindowsHookEx(
  _In_  int idHook,
  _In_  HOOKPROC lpfn,
  _In_  HINSTANCE hMod,
  _In_  DWORD dwThreadId
);

返回:

成功:返回SetWindowsHookEx返回所安裝的鉤子句柄;
失敗:NULL;

  • 參數:idHook:設置鉤子過程的類型:

WH_CALLWNDPROC:安裝一個掛鉤處理過程,在系統將消息發送至目標窗口處理過程之前,對該消息進行監視,詳情參見CallWndProc鉤子過程.

WH_MOUSE:安裝一個掛鉤處理過程,對鼠標消息進行監視. 詳情參見MouseProc鉤子過程.


WH_KEYBOARD:安裝一個掛鉤處理過程對擊鍵消息進行監視. 詳情參見KeyboardProc鉤子過程.

WH_MSGFILTER:安裝一個掛鉤處理過程,以監視由對話框、消息框、菜單條、或滾動條中的輸入事件引發的消息.詳情參見MessagePorc鉤子過程.

WH_CALLWNDPROCRET:安裝一個掛鉤處理過程,它對已被目標窗口處理過程處理過了的消息進行監視,詳情參見CallWndRetProc 掛鉤處理過程.

WH_CBT:安裝一個掛鉤處理過程,接受對CBT應用程序有用的消息,詳情參見CBTProc 掛鉤處理過程.

WH_DEBUG:安裝一個掛鉤處理過程以便對其他掛鉤處理過程進行調試, 詳情參見DebugProc掛鉤處理過程.

WH_FOREGROUNDIDLE:安裝一個掛鉤處理過程,該掛鉤處理過程當應用程序的前臺線程即將進入空閒狀態時被調用,它有助於在空閒時間內執行低優先級的任務.

WH_GETMESSAGE:安裝一個掛鉤處理過程對寄送至消息隊列的消息進行監視,詳情參見GetMsgProc 掛鉤處理過程.

WH_JOURNALPLAYBACK:安裝一個掛鉤處理過程,對此前由WH_JOURNALRECORD 掛鉤處理過程紀錄的消息進行寄送.詳情參見JournalPlaybackProc掛鉤處理過程.

WH_JOURNALRECORD:安裝一個掛鉤處理過程,對寄送至系統消息隊列的輸入消息進行紀錄.詳情參見JournalRecordProc掛鉤處理過程.

WH_KEYBOARD_LL:此掛鉤只能在Windows NT中被安裝,用來對底層的鍵盤輸入事件進行監視.詳情參見LowLevelKeyboardProc掛鉤處理過程.

WH_MOUSE_LL:此掛鉤只能在Windows NT中被安裝,用來對底層的鼠標輸入事件進行監視.詳情參見LowLevelMouseProc掛鉤處理過程.

WH_MSGFILTER:安裝一個掛鉤處理過程,以監視由對話框、消息框、菜單條、或滾動條中的輸入事件引發的消息.詳情參見MessageProc掛鉤處理過程.

WH_SHELL:安裝一個掛鉤處理過程以接受對外殼應用程序有用的通知, 詳情參見ShellProc掛鉤處理過程.

WH_SYSMSGFILTER:安裝一個掛鉤處理過程,以監視由對話框、消息框、菜單條、或滾動條中的輸入事件引發的消息.這個掛鉤處理過程對系統中所有應用程序的這類消息都進行監視.詳情參見SysMsgProc掛鉤處理過程.

  • 參數:lpfn:函數指針,指向鉤子過程,如MouseProc、CallWndProc等
  • 參數:hMod:鉤子過程所在的DLL的句柄。如果第四個參數dwThreadId指定的線程由當前進程創建,且鉤子過程定義在當前進程相關的代碼中則hMod必須爲NULL。
  • 參數:dwThreadId:與鉤子過程相關的線程ID。爲0即爲安裝的鉤子過程與桌面上運行的所有線程相關。

注意:

dwThreadId爲0 ,則是表示安裝的鉤子過程與桌面上運行的所有線程相關(全局鉤子),並且全局鉤子要設置再DLL中才會其效果。所以dwThreadId設置0,設置爲所在DLL句柄。局部鉤子則是設置hMod設置NULL,dwThreadId設置當前線程的ID

總結:

  • 局部鉤子:

HHOOK g_hKeyBoard=SetWindowsHookEx(WH_KEYBOARD,KeyBoardProc,NULL,GetCurrentThreadId());

設置hMod爲NULL,dwThreadId設置當前線程的ID,GetCurrentThreadId()即是當前線程ID

  • 全局鉤子:

HHOOK g_hKeyBoard=SetWindowsHookEx(WH_KEYBOARD,KeyBoardProc,GetModuleHandle("Hook"),0);

設置hMod爲所在DLL句柄,GetModuleHandle("Hook") 爲獲取Hook.dll的句柄,dwThreadId設置0

  • 鉤子過程的聲明形式如下:
LRESULT CALLBACK HookProc
(
   int nCode,
   WPARAM wParam,
   LPARAM lParam
);

int  nCode:   消息代碼

WPARAM  wParam:  附加參數1

LPARAM  lParam:  附加參數2

注意:

如果鉤子過程返回非0值,表示已經對當前消息進行了處理,這樣,這個消息就不會再傳遞給目標窗口了。因此,如果鉤子過程中對消息進行了處理,就應返回一個非0值,否則建議調用CallNextHookEx()並返回該函數的返回值。

LRESULT CALLBACK KeyboardProc(
   int code,       // hook code
   WPARAM wParam, // virtual-key code
   LPARAM lParam   // keystroke-message information
)
{

  //if(VK_SPACE==wParam || VK_RETURN==wParam)如果是空格鍵

  /*if(VK_F4==wParam && (1==(lParam>>29 & 1)))攔截ALT+F4按鍵!
      return 1;
    else
      return CallNextHookEx(g_hKeyboard,code,wParam,lParam);*/

    if(VK_F2==wParam)按F2時程序可以退出,這是留的後門。否則程序無法關閉,只能用任務管理器來關閉它
    {
      ::SendMessage(g_hWnd,WM_CLOSE,0,0);
      UnhookWindowsHookEx(g_hKeyboard);當程序退出時最好將鉤子移除。
      UnhookWindowsHookEx(g_hMouse);
     }
     return 1;
}

如上代碼,如果return 1則是屏蔽了對應的邏輯,如果不屏蔽則是調用CallNextHookEx(g_hKeyboard,code,wParam,lParam),接下來說下CallNextHookEx(g_hKeyboard,code,wParam,lParam)的函數原型:

  • CallNextHookEx-調用下一個鉤子
LRESULT CallNextHookEx(
         HHOOK   hhk,      // 是自己的鉤子函數的句柄。用該句柄可以遍歷鉤子鏈
         int     nCode,    // 把傳入的參數簡單傳給CallNextHookEx即可
         WPARAM  wParam,   // 把傳入的參數簡單傳給CallNextHookEx即可
         LPARAM  lParam    // 把傳入的參數簡單傳給CallNextHookEx即可
        )
  • 釋放鉤子
BOOL WINAPI UnhookWindowsHookEx( __in HHOOK hhk);
參數介紹:
__in HHOOK hhk:要刪除的hook鉤子句柄
返回值:成功true否則false

即使是在UnhookWindowsHookEx返回之後,鉤子程序還可以被其他線程調用。如果鉤子程序沒有同時被調用,鉤子程序將會在UnhookWindowsHookEx返回之前刪除。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章