在Windows系統中用VC 實現鉤子機制

才智咖 人氣:9.83K

摘要:本文分析了在Windows環境下,什麼是鉤子程式以及怎樣用VC 實現一個鉤子機制的關鍵技術。最後,用一個可以截獲滑鼠資訊的完整程式說明了這些問題。

在Windows系統中用VC 實現鉤子機制

關鍵詞:鉤子程式,DLL,訊息截獲

一. 什麼是鉤子。
Windows系統是建立在事件驅動的機制上的,說穿了就是整個系統都是通過訊息的傳遞來實現的。鉤子(hook)是一種特殊的訊息處理機制,鉤子可以監視系統或程序中的各種事件訊息,截獲發往目標視窗的訊息並進行處理。這樣,我們就可以在系統中安裝自定義的鉤子,監視系統中特定事件的發生,完成特定的功能,比如截獲鍵盤、滑鼠的輸入,螢幕取詞,日誌監視等等。
鉤子的種類很多,每種鉤子可以截獲並處理相應的訊息,如鍵盤鉤子可以截獲鍵盤訊息,外殼鉤子可以擷取、啟動和關閉應用程式的訊息等。鉤子可以分為執行緒鉤子和系統鉤子, 執行緒鉤子監視指定執行緒的事件訊息, 系統鉤子監視系統中的所有執行緒的事件訊息。因為系統鉤子會影響系統中所有的應用程式,所以鉤子函式必須放在獨立的動態連結庫(DLL) 中。

二. 實現鉤子機制的幾個關鍵技術。
1. windows的鉤子程式,需要用到幾個sdk中的api函式。下面列出這幾個函式的原型及說明:
hhook setwindowshookex(int idhook,hook_proc lpfn,hinstance hmod,dword dwtHReadid);
引數說明如下:
  idhook:鉤子的型別
  lpfn:鉤子處理函式地址
  hmod:包含鉤子函式的模組控制代碼
  dwthreadid:鉤子的監控執行緒
函式說明:函式將在系統中掛上一個由idhook指定型別的鉤子,監控並處理相應的特定訊息。
bool unhookwindowshookex(hhook hhk);
函式說明:函式將撤銷由hhk指定的鉤子。
lresult callnexthookex( hhook hhk, int ncode,wparam wparam,lparam lparam );
函式說明:函式將訊息向下傳遞,下一個鉤子處理將截獲這一訊息。
2. 由於鉤子的處理涉及到模組及程序間的資料地址問題,一般情況是把鉤子整合到一個動態連結庫(dll)中,VC中有三種形式的MFC DLL可供選擇,即Regular statically linked to MFC DLL(標準靜態連結MFC DLL)、Regular using the shared MFC DLL(標準動態連結MFC DLL)以及Extension MFC DLL(擴充套件MFC DLL)。第一種DLL在編譯時把使用的MFC程式碼連結到DLL中,執行程式時不需要其他MFC動態連結類庫的支援,但體積較大;第二種DLL在執行時動態連結到MFC類庫,因而體積較小,但卻依賴於MFC動態連結類庫的支援;這兩種DLL均可被MFC程式和Win32程式使用。第三種DLL的也是動態連線,但做為MFC類庫的擴充套件,只能被MFC程式使用。
另外,要設立一個全域性資料共享資料段,以存貯一些全域性變數,保留上次鉤子訊息事件發生時的狀態。
3. Win32 DLL的入口和出口函式都是DLLMain。只要有程序或執行緒載入和解除安裝DLL時,都會呼叫該函式,其原型是:
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved); 其中,第一個引數表示DLL的例項控制代碼;第三個引數系統保留;第二個引數指明瞭當前呼叫該動態連線庫的'狀態,它有四個可能的值:DLL_PROCESS_ATTACH(程序載入)、DLL_THREAD_ATTACH(執行緒載入)、DLL_THREAD_DETACH(執行緒解除安裝)、DLL_PROCESS_DETACH(程序解除安裝)。在DLLMain函式中可以通過對傳遞進來的這個引數的值進行判別,根據不同的引數值對DLL進行必要的初始化或清理工作。由於在Win32環境下,所有程序的空間都是相互獨立的,這減少了應用程式間的相互影響,但大大增加了程式設計的難度。當程序在動態載入DLL時,系統自動把DLL地址對映到該程序的私有空間,而且也複製該DLL的全域性資料的一份拷貝到該程序空間,每個程序所擁有的相同的DLL的全域性資料其值卻並不一定是相同的。當DLL記憶體被對映到程序空間中,每個程序都有自己的全域性記憶體拷貝,載入DLL的每一個新的程序都重新初始化這一記憶體區域,也就是說程序不能再共享DLL。因此,在Win32環境下要想在多個程序中共享資料,就必須進行必要的設定。一種方法便是把這些需要共享的資料單獨分離出來,放置在一個獨立的資料段裡,並把該段的屬性設定為共享,建立一個記憶體共享的DLL。