同樣的鍵盤鉤子,只有KeyboardProc不一樣
程序1 是
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
int i = CallNextHookEx(g_hhook, nCode, wParam ,lParam);
CString str;
str.Format("i's value !!! %d",i);
AfxMessageBox(str);
return 0;
}
程序2 是
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
int i = CallNextHookEx(g_hhook, nCode, wParam ,lParam);
CString str;
str.Format("i's value %d",i);
AfxMessageBox(str);
return 1;
}
1、如果只啓動程序1
鍵入字母m效果是:
i's value !!! 0;
i's value !!! 0;
在記事本顯示:m
2、如果只啓動程序2
鍵入字母m效果是:
i's value 0;
i's value 0;
1、如果先啓動程序1,再啓動程序2。
鍵入字母m效果是:
i's value !!! 0;
i's value 0;
i's value !!! 0;
i's value 0;
2、如果先啓動程序2,再啓動程序1。
鍵入字母m效果是:
i's value 0;
i's value !!! 1;
i's value 0;
i's value !!! 1;
在記事本顯示:m
解釋:
1、消息成對出現是因爲:按一次鍵,將產生KEY_UP 和KEY_DOWN的兩個鍵盤消息,兩者都將被視爲:WH_KEYBOARD消息。
2、後掛的鉤子在鉤子鏈的最頂端(後加入的鉤子加在原來存在的鉤子的前面。後加入的鉤子先獲得消息)。
3、當CallNextHookEx的時候會執行鉤子鏈的下一個hook函數,CallNextHookEx將返回一個值,如果是0表示成功,如果是1表示失敗。
4、消息並不是從 頂端hook函數 --> 底端hook 函數 --> 系統 傳遞的。一般情況下(鉤子函數的形式如下,通常的鉤子函數形式也是這樣的)
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx(g_hhook, nCode, wParam ,lParam);
}
執行hook函數是一個遞歸的過程:
頂端(n)hook函數 --> (n-1)hook函數 -> (n-2)hook函數 -> (n-i)hook函數 -> (1) hook函數
|------<----| |------<----| |------<----| |------<----|
5、如果在一個鉤子函數中使用return 1,或者 return 0 ,那麼這個返回值將是上層鉤子函數調用CallNextHookEx的返回值。
6、現在關注頂端hook函數:
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// doing something
return CallNextHookEx(g_hhook, nCode, wParam ,lParam);
}
如果CallNextHookEx(g_hhook, nCode, wParam ,lParam);的返回值是1,那麼消息不會被傳遞給系統來處理。(返回值爲1的出現的情況:a,在鉤子鏈中使用過return1, b,系統傳遞鉤子消息失敗)如果CallNextHookEx(g_hhook, nCode, wParam ,lParam);的返回值是0,那麼消息將經過鉤子鏈以後再傳遞給系統來處理。
7、做一個擴展假設,如果使用下面的鉤子函數,並且該鉤子函數在鉤子鏈的頂端
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return 0;
}
那麼鍵盤消息將不會傳遞給鉤子鏈上的其他鉤子函數,而直接傳遞給系統。那麼如果這個鉤子函數在hook chain的最頂端,那麼它就可以屏蔽掉有鍵盤記錄功能的木馬或者外掛。