安裝鉤子
使用SetWindowsHookEx函數(API函數),指定一個Hook類型、自己的Hook過程是全局還是局部Hook,同時給出Hook過程的進入點,就可以輕松的安裝自己的Hook過程。SetWindowsHookEx總是將你的Hook函數放置在Hook鏈的頂端。你可以使用CallNextHookEx函數將系統消息傳遞給Hook鏈中的下一個函數。
對於某些類型的Hook,系統將向該類的所有Hook函數發送消息,這時,Hook函數中的CallNextHookEx語句將被忽略。全局(遠程鉤子)Hook函數可以攔截系統中所有線程的某個特定的消息,為了安裝一個全局Hook過程,必須在應用程序外建立一個DLL並將該Hook函數封裝到其中, 應用程序在安裝全局Hook過程時必須先得到該DLL模塊的句柄。將Dll名傳遞給LoadLibrary 函數,就會得到該DLL模塊的句柄;得到該句柄 後,使用GetProcAddress函數可以得到Hook過程的地址。最後,使用SetWindowsHookEx將 Hook過程的首址嵌入相應的Hook鏈中,SetWindowsHookEx傳遞一個模塊句柄,它為Hook過程的進入點,線程標識符置為0,該Hook過程同系統中的所有線程關聯。如果是安裝局部Hook此時該Hook函數可以放置在DLL中,也可以放置在應用程序的模塊段。在C#中通過平台調用(前文已經介紹過)來調用API函數。
1 public void Start(bool installMouseHook, bool installKeyboardHook) {
2 if (hMouseHook == IntPtr.Zero && installMouseHook) {
3 MouseHookProcedure = new HookProc(MouseHookProc);
4 hMouseHook = SetWindowsHookEx(
5 WH_MOUSE_LL,
6 MouseHookProcedure,
7 Marshal.GetHINSTANCE(
8 Assembly.GetExecutingAssembly().GetModules()[0]),
9 0
10 );
11
12 if (hMouseHook == IntPtr.Zero) {
13 int errorCode = Marshal.GetLastWin32Error();
14 Stop(true, false, false);
15
16 throw new Win32Exception(errorCode);
17 }
18 }
19
20 if (hKeyboardHook == IntPtr.Zero && installKeyboardHook) {
21 KeyboardHookProcedure = new HookProc(KeyboardHookProc);
22 //install hook
23 hKeyboardHook = SetWindowsHookEx(
24 WH_KEYBOARD_LL,
25 KeyboardHookProcedure,
26 Marshal.GetHINSTANCE(
27 Assembly.GetExecutingAssembly().GetModules()[0]),
28 0);
29 // If SetWindowsHookEx fails.
30 if (hKeyboardHook == IntPtr.Zero) {
31 // Returns the error code returned by the last
32 // unmanaged function called using platform invoke
33 // that has the DllImportAttribute.SetLastError flag set.
34 int errorCode = Marshal.GetLastWin32Error();
35 //do cleanup
36 Stop(false, true, false);
37 //Initializes and throws a new instance of the
38 // Win32Exception class with the specifIEd error.
39 throw new Win32Exception(errorCode);
40 }
41 }
42 }