鉤子(hook),是windows訊息處理機制的乙個平台,應用程式可以在上面設定子程以監視指定視窗的某種訊息,而且所監視的視窗可以是其他程序所建立的。當訊息到達後,在目標視窗處理函式之前處理它。鉤子機制允許應用程式截獲處理window訊息或特定事件。
鉤子實際上是乙個處理訊息的程式段,通過系統呼叫,把它掛入系統。每當特定的訊息發出,在沒有到達目的視窗前,鉤子程式就先捕獲該訊息,亦即鉤子函式先得到控制權。這時鉤子函式即可以加工處理(改變)該訊息,也可以不作處理而繼續傳遞該訊息,還可以強制結束訊息的傳遞。這和前面我部落格的視窗子類化都異曲同工,但是hook可強大多了,我是這兩天才開始看的,所以略知皮毛。
我聽完孫鑫老師c++教程裡的解釋,覺得還是把hook講得比較形象,加上我自己的一些理解就覺得hook原理不是很難。windows一直都是有自己處理各種訊息的函式,hook其實就能夠做到程式設計師自己處理自己感興趣的事情。這樣說,假設windows的訊息就是馬路上的車輛,一般情況下是windows自己派人在檢查,然後呢,hook是擁有這個能力能在windows自己安排的檢查站之前也進行抽查,hook根據程式設計師的需求可以變化,比如我就感興趣100萬以上的車(可能是走私的(*^__^*)),hook就能在檢查的時候專門找100萬以上的車,至於其他不上檔次的車hook就放行,交還給windows自己的檢查站。同樣hook可以「為所欲為」,可以擅自設立乙個檢查站,也可以兩個,三個···換成程式來說,鉤子函式的工作原理是:當我們建立乙個鉤子時,windows會先在記憶體中建立乙個資料結構,該資料結構包含了鉤子的相關資訊,然後把該結構體加到已經存在的鉤子鍊錶中去。新的鉤子將加到老的前面。當乙個事件發生時,如果我們安裝的是乙個區域性鉤子(下面有解釋,暫時理解為你程式本身中的),我們程序中的鉤子函式將被呼叫。
每乙個hook都有乙個與之相關聯的指標列表,稱之為鉤子鍊錶,由系統來維護。被hook子程呼叫的**函式,也就是該鉤子的各個處理子程。當與指定的hook型別關聯的訊息發生時,系統就把這個訊息傳遞到hook子程。一些hook子程可以只監視訊息,或者修改訊息,或者停止訊息的前進,避免這些訊息傳遞到下乙個hook子程或者目的視窗。最近安裝的鉤子放在鏈的開始,而最早安裝的鉤子放在最後,也就是後加入的先獲得控制權。鉤子子程是乙個應用程式定義的**函式(callbackfunction),不能定義成某個類的成員函式,只能定義為普通的c函式。用以監視系統或某一特定型別的事件,這些事件可以是與某一特定執行緒關聯的,也可以是系統中所有執行緒的事件。
鉤子子程必須按照以下的語法:
lresult callback hookproc
(int ncode, //指定是否需要處理該訊息
wparam wparam,
lparam lparam //包含該訊息的附加訊息 ,
);這個**函式的名字可以隨你取,但形式可一定要滿足以上要求,其實鉤子的**函式和windows的差不多乙個德行。看看鉤子函式的返回值,若是返回非0值,表示我們已經自己處理了該訊息,則訊息就不被傳遞到目標視窗過程。
看看lresult callnexthookex
( hhook hhk;
int ncode;
wparam wparam;
lparam lparam;)這個函式把鉤子資訊傳遞給下乙個鉤子函式,也就是可以理解成把車輛放行到下乙個檢查站,這個可以根據自己的需要進行呼叫。若是我們只設定了乙個鉤子函式,那麼我們假設把鉤子訊息用callnexthookex傳給下個鉤子函式,因為不存在所以就傳遞歸了目標視窗函式。
呼叫setwindowhookex函式,該函式的原型如下:
hhook setwindowshookex( int idhook,
hookproc lpfn,
hinstance hmod,
dword dwthreadid );返回值是乙個hook的控制代碼。
idhook是我們感興趣的訊息型別,比如我們對滑鼠訊息感興趣就是wh_mouse,再者比如鍵盤訊息wh_keyboard,我們可以通過查詢win32 api使用手冊來找到自己感興趣的訊息。
第二個引數是鉤子函式的位址,這裡就有兩種情況:其實鉤子有兩種,一種是區域性鉤子,這種鉤子只能關注自己所在的程序的事件,另一種鉤子叫做遠端鉤子,這裡又有兩種:1.基於執行緒的它將捕獲其它程序中某一特定執行緒的事件。簡言之,就是可以用來觀察其它程序中的某一特定執行緒將發生的事件。2.系統範圍的 將捕捉系統中所有程序將發生的事件訊息。 看上去區域性鉤子的功能沒有遠端鉤子的給力,但是凡事都是要付出代價的,遠端鉤子會影響系統的效能,特別是監視系統範圍的鉤子,因為要監視系統範圍的訊息,明顯就會影響系統的速度。
第三個引數和第四個引數相關,所以一起解釋。
如果第四個引數是null,則說明是全域性鉤子,那麼就是鉤子子程與所有的執行緒關聯,此時第三個引數是程式例項控制代碼;
如果第三個引數是null,則說明鉤子是區域性鉤子,說明子程**位於當前程序,這時候第四個引數就是當前程序的id,可以用getcurrentthreadid()填充,或者可以儲存例項來填充,再做介紹···
再看看鉤子函式的解除安裝,用unhookwindowshookex(hhook hhk);引數就是setwindowshookex返回的控制代碼。
下面是是乙個小程式,大概的功能就是實現在所在程序內的滑鼠訊息和鍵盤訊息的截獲,一旦點選了「lockmouse」那麼就在目標視窗截獲了所以滑鼠的訊息,這裡實現的是遮蔽滑鼠訊息,只能通過按回車鍵恢復滑鼠功能。若是點選了「lockkeyboard」按鈕,那麼只能在編輯框輸入0或者1,但是在沒有點選的情況下是正常的編輯框。這點可是比視窗子類化更加簡單。
[cpp]view plain
copy
?#include "windows.h"
#include "tchar.h"
#include "resource.h"
hinstance g_hinstance ;
static hhook hhook = null;
int_ptr callback procwinmain(hwnd hwnd, uint msg, wparam wparam ,lparam lparam);
lresult callback mouseproc(int ncode, wparam wparam,lparam lparam);
lresult callback boardproc(int ncode, wparam wparam,lparam lparam);
int winapi winmain( hinstance hinstance,
hinstance hprevinstance,
lpstr lpcmdline,
int ncmdshow
)
int_ptr callback procwinmain( hwnd hwnd,
uint msg,
wparam wparam,
lparam lparam
)
break;
case wm_close:
enddialog(hwnd,null);
break;
case wm_command:
else
} break;
case id_btnhookmouse :
else
} break;
} }
break;
default:
return false;
} return true;
} lresult callback mouseproc(int ncode, wparam wparam,lparam lparam)
lresult callback boardproc(int ncode, wparam wparam,lparam lparam)
else
return 1; //表示已經處理了該訊息
} 參考資料
《windows+sdk系列文章》
Hook技術 1 Hook技術簡介
hook技術又被稱為鉤子技術。在系統沒有呼叫該函式之前,鉤子程式就先捕獲該訊息,鉤子函式先得到控制權,這時鉤子函式既可以加工處理 改變 該函式的執行行為,還可以強制結束訊息的傳遞。簡單來說,hook是一種擷取資訊 更改程式執行流向 新增新功能的技術。通俗來說,就是一條高速公路,我們去追擊乙個罪犯 要...
仿照SDK程式設計寫的視窗
option explicit public declare function createwindowex lib user32 alias createwindowexa byval dwexstyle as long,byval lpclassname as string,byval lpwi...
vb6中的hook技術
public declare function setwindowshookex lib user32 alias setwindowshookexa byval idhook as long,byval lpfn as long,byval hmod as long,byval dwthreadi...