FRIENDLYBOY
New member
- Xu
- 0
Hook là kỹ thuật điều khiển thông điệp (message-handling) giúp cho ứng dụng có thể cài đặt một thủ tục để điều khiển luồng thông điệp và tiến hành xử lý các thông điệp đó trước khi thông điệp đó đi tới cửa sổ đích.
Hook có thể xem là tính năng mạnh mẽ nhất của Windows, nó cho phép ta đặt bẫy đối với các sự kiện. Bằng cách sử dụng hook, ta có thể điều hướng ứng dụng tới một thủ tục mới bất kể khi nào mà sự kiện được quan tâm xuất hiện và bất kể sự kiện đó thuộc tiến trình của bạn hay thuộc tiến trình khác.
Các mô hình Hook:
- Local hook: là kỹ thuật Hook dùng để bẫy sự kiện ngay trong tiến trình cài đặt.
- Remote hook: là kỹ thuật Hook cho phép bẫy các sự kiện thuộc tiến trình của ứng dụng khác. Trong mô hình này lại tồn tại hai kiểu hook khác :
o Thread-specific : kiểu Hook này sẽ bẫy sự kiện của một luồng cụ thể.
o System-wide : bẫy sự kiện của tất cả các luồng trong tất cả các tiến trình đang thi hành trong hệ thống.
Thành phần của Hook:
- Chuỗi Hook
- Thủ tục Hook
- Các kiểu Hook
Hook là một kỹ thuật xử lý thông điệp rất mạnh cho phép chúng ta can thiệp sâu vào các tiến trình khác nhau, nhưng nó làm ảnh hưởng tới tốc độ của hệ thống, nhất là hook system-wide, vì tất cả các sự kiện của hệ thống sẽ được định hướng tới một hàm nào đó, rõ ràng điều này làm hệ thống chậm đi đáng kể. Vì thế ta chỉ hên hook những thông điệp thật cần thiết và kết thúc việc hook ngay khi không dùng đến nữa.
Chuỗi Hook
Hệ thống có khả năng hỗ trợ nhiều kiểu hook khác nhau, mỗi kiểu lại được quy định một cách thức truy nhập khác nhau trong kỹ thuật điều khiển thông điệp. Do vậy, hệ thống duy trì một chuỗi các hook cho mỗi một kiểu hook khác nhau.
Một chuỗi hook là một danh sách các con trỏ đặc biệt, nó được trỏ tới các hàm CallBack gọi là hook procedure (thủ tục hook). Như vậy khi một sự kiện xuất hiện, hệ thống sẽ chuyển sự kiện đó tới các thủ tục hook được tham chiếu bới chuỗi hook theo thứ tự lần lượt. Vì thế phải thực hiện xong thủ tục này mới được gọi thủ tục kế tiếp.
Thủ tục Hook
Thủ tục hook sẽ là nơi thực hiện các thao tác sau khi bắt được một sự kiện mong muốn. Các thủ tục hook phụ thuộc vào các kiểu hook khác nhau mà có cấu trúc, chức năng khác nhau. Có thủ tục chỉ có thể điều khiển thông điệp, một số khác có thể sửa đổi thông điệp, dừng tiến trình của thông điệp, ngăn cản thực hiện hook tiếp theo hoặc đưa tới cửa sổ cuối cùng …
Thủ tục hook có dạng chung như sau:
Code :
LRESULT CALLBACK HookProc( int nCode, WPARAM wParam, LPARAM lParam );
Trong đó:
- HookProc: là tên đại diện của thủ tục hook được cài đặt
- nCode : Đây là mã hook, nó quyết định toàn bộ hoạt động của thủ tục hook, mã hook phụ thuộc vào kiểu hook và mỗi kiểu hook được gán cho một ký tự để thiết lập mã hook.
- wParam, lParam: Hai tham số này chứa các thông tin về thông điệp được hook và nó phụ thuộc vào mã hook (nCode).
Để dễ dàng sử dụng hook, Windows cung cấp một giao diện API cho các lập trình viên với các hàm sau:
- SetWindowsHookEx để cài đặt thủ tục hook vào trong chuỗi hook.
- UnhookWindowsHookEx để gỡ bỏ hook khi không còn cần đến nó nữa.
- CallNextHookEx: Thủ tục hook sẽ quyết định có hay không đi tới các thủ tục tiếp theo trong chuỗi hook, để từ một thủ tục đưa tới các thủ tục tiếp theo, ta sử dụng hàm CallNextHookEx
Chú ý rằng, với thủ tục hook nếu chỉ xử lý các hook xảy ra trong tiến trình đơn thì không cần cài đặt thủ tục hook trong thư viện liên kết động (DLL). Tuy nhiên, với thủ tục hook xử lý sự kiện của tất cả các tiến trình thì bắt buộc phải cài đặt hook trong thư viện liên kết động (DLL) để tất cả các tiến trình có thể sử dụng thủ tục trong thư viện đó.
Các kiểu Hook
Mỗi một kiểu Hook cho phép ứng dụng điều khiển thông điệp theo những cách khác nhau trong kỹ thuật điều khiển thông điệp (message-handling mechanism). Dưới đây là những kiểu hook khác nhau :
Code :
a. WH_CALLWNDPROC và WH_CALLWNDPROCRET Hook
b. WH_CBT Hook
c. WH_DEBUG Hook
d. WH_FOREGROUNDIDLE Hook
e. WH_GETMESSAGE Hook
f. WH_JOURNALPLAYBACK Hook
g. WH_JOURNALRECORD Hook
h. WH_KEYBOARD_LL Hook
i. WH_KEYBOARD Hook
j. WH_MOUSE_LL Hook
k. WH_MOUSE Hook
l. WH_MSGFILTER và WH_SYSMSGFILTER Hook
m. WH_SHELL Hook
2. Sử dụng Hook
a) Cài đặt hook:
Ta có thể cài đặt thủ tục hook vào chuỗi hook bằng việc gọi hàm SetWindowsHookEx và chỉ ra kiểu hook đang gọi thủ tục, việc cài đặt hook có thể thực hiện trên mọi tiến trình trong hệ thống.
Nếu sử dụng hook toàn cục thì phải đặt trong thư viện liên kết động (DLL). Ứng dụng muốn sử dụng thư viện liên kết động phải lấy được handle của thư viện đó. Để nhận Handle của thư viện liên kết động ta có thể sử dụng hàm LoadLibrary với tham số là tên của thư viện. Sau khi có được Handle của DLL, ta sẽ lấy địa chỉ của thủ tục hook trong thư viện liên kết động thông qua hàm GetProcAddress. Sau khi đã có thủ tục hook, sử dụng hàm SetWindowsHookEx để cài đặt thủ tục hook vào trong chuỗi hook.
Ví dụ về sử dụng thư viện liên kết động :
Code :
HOOKPROC lpfSetAutoProtect;
static HINSTANCE hinstDLL;
static HHOOK hhookysMsg;
hinstDLL = LoadLibrary((LPCTSTR) "c:\\Windows\\ BrowserHook.dll");
lpfSetAutoProtect= (HOOKPROC)GetProcAddress(hinstDLL, "SetAutoProtect");
hhookysMsg= SetWindowsHookEx(WH_SYSMSGFILTER,
lpfSetAutoProtect,hinstDLL,0);
b) Giải phóng hook:
Như đã nói thì hook nên được bỏ đi nếu như không cần thiết nữa bằng cách sử dụng hàm UnhookWindowsHookEx.
Với thread-specific hook, việc sử dụng hàm UnhookWindowsHookEx sẽ giải phóng thủ tục hook. Tuy nhiên với hook toàn tục (system-wide hook) thì hàm này không thể trả tự do cho hàm DLL. Việc gọi hàm LoadLibrary sẽ gọi trong ngữ cảnh của tất cả các tiến trình, tuy nhiên hàm FreeLibrary thì không thể thực hiện với các tiến trình khác. Vì vậy, không có cách nào để giải phóng DLL. Hệ thống chỉ có thể giải phóng DLL khi tất cả các tiến trình liên kết tới DLL đó phải kết thúc hoặc gọi FreeLibrary.
Giải pháp đặt ra cho vấn đề này là xây dựng hàm cài đặt ngay trong thư viện DLL. Bằng việc liên kết tới DLL, ứng dụng có thể cài đặt hook. Và ngay trong DLL cũng phải có hàm giải phóng hook để giải phóng khi không cần đến nữa.
c) Các hàm thường được sử dụng:
- SetWindowsHookEx
- UnhookWindowsHookEx
- LoadLibrary
- FreeLibrary
- GetProcAddress
Hook có thể xem là tính năng mạnh mẽ nhất của Windows, nó cho phép ta đặt bẫy đối với các sự kiện. Bằng cách sử dụng hook, ta có thể điều hướng ứng dụng tới một thủ tục mới bất kể khi nào mà sự kiện được quan tâm xuất hiện và bất kể sự kiện đó thuộc tiến trình của bạn hay thuộc tiến trình khác.
Các mô hình Hook:
- Local hook: là kỹ thuật Hook dùng để bẫy sự kiện ngay trong tiến trình cài đặt.
- Remote hook: là kỹ thuật Hook cho phép bẫy các sự kiện thuộc tiến trình của ứng dụng khác. Trong mô hình này lại tồn tại hai kiểu hook khác :
o Thread-specific : kiểu Hook này sẽ bẫy sự kiện của một luồng cụ thể.
o System-wide : bẫy sự kiện của tất cả các luồng trong tất cả các tiến trình đang thi hành trong hệ thống.
Thành phần của Hook:
- Chuỗi Hook
- Thủ tục Hook
- Các kiểu Hook
Hook là một kỹ thuật xử lý thông điệp rất mạnh cho phép chúng ta can thiệp sâu vào các tiến trình khác nhau, nhưng nó làm ảnh hưởng tới tốc độ của hệ thống, nhất là hook system-wide, vì tất cả các sự kiện của hệ thống sẽ được định hướng tới một hàm nào đó, rõ ràng điều này làm hệ thống chậm đi đáng kể. Vì thế ta chỉ hên hook những thông điệp thật cần thiết và kết thúc việc hook ngay khi không dùng đến nữa.
Chuỗi Hook
Hệ thống có khả năng hỗ trợ nhiều kiểu hook khác nhau, mỗi kiểu lại được quy định một cách thức truy nhập khác nhau trong kỹ thuật điều khiển thông điệp. Do vậy, hệ thống duy trì một chuỗi các hook cho mỗi một kiểu hook khác nhau.
Một chuỗi hook là một danh sách các con trỏ đặc biệt, nó được trỏ tới các hàm CallBack gọi là hook procedure (thủ tục hook). Như vậy khi một sự kiện xuất hiện, hệ thống sẽ chuyển sự kiện đó tới các thủ tục hook được tham chiếu bới chuỗi hook theo thứ tự lần lượt. Vì thế phải thực hiện xong thủ tục này mới được gọi thủ tục kế tiếp.
Thủ tục Hook
Thủ tục hook sẽ là nơi thực hiện các thao tác sau khi bắt được một sự kiện mong muốn. Các thủ tục hook phụ thuộc vào các kiểu hook khác nhau mà có cấu trúc, chức năng khác nhau. Có thủ tục chỉ có thể điều khiển thông điệp, một số khác có thể sửa đổi thông điệp, dừng tiến trình của thông điệp, ngăn cản thực hiện hook tiếp theo hoặc đưa tới cửa sổ cuối cùng …
Thủ tục hook có dạng chung như sau:
Code :
LRESULT CALLBACK HookProc( int nCode, WPARAM wParam, LPARAM lParam );
Trong đó:
- HookProc: là tên đại diện của thủ tục hook được cài đặt
- nCode : Đây là mã hook, nó quyết định toàn bộ hoạt động của thủ tục hook, mã hook phụ thuộc vào kiểu hook và mỗi kiểu hook được gán cho một ký tự để thiết lập mã hook.
- wParam, lParam: Hai tham số này chứa các thông tin về thông điệp được hook và nó phụ thuộc vào mã hook (nCode).
Để dễ dàng sử dụng hook, Windows cung cấp một giao diện API cho các lập trình viên với các hàm sau:
- SetWindowsHookEx để cài đặt thủ tục hook vào trong chuỗi hook.
- UnhookWindowsHookEx để gỡ bỏ hook khi không còn cần đến nó nữa.
- CallNextHookEx: Thủ tục hook sẽ quyết định có hay không đi tới các thủ tục tiếp theo trong chuỗi hook, để từ một thủ tục đưa tới các thủ tục tiếp theo, ta sử dụng hàm CallNextHookEx
Chú ý rằng, với thủ tục hook nếu chỉ xử lý các hook xảy ra trong tiến trình đơn thì không cần cài đặt thủ tục hook trong thư viện liên kết động (DLL). Tuy nhiên, với thủ tục hook xử lý sự kiện của tất cả các tiến trình thì bắt buộc phải cài đặt hook trong thư viện liên kết động (DLL) để tất cả các tiến trình có thể sử dụng thủ tục trong thư viện đó.
Các kiểu Hook
Mỗi một kiểu Hook cho phép ứng dụng điều khiển thông điệp theo những cách khác nhau trong kỹ thuật điều khiển thông điệp (message-handling mechanism). Dưới đây là những kiểu hook khác nhau :
Code :
a. WH_CALLWNDPROC và WH_CALLWNDPROCRET Hook
b. WH_CBT Hook
c. WH_DEBUG Hook
d. WH_FOREGROUNDIDLE Hook
e. WH_GETMESSAGE Hook
f. WH_JOURNALPLAYBACK Hook
g. WH_JOURNALRECORD Hook
h. WH_KEYBOARD_LL Hook
i. WH_KEYBOARD Hook
j. WH_MOUSE_LL Hook
k. WH_MOUSE Hook
l. WH_MSGFILTER và WH_SYSMSGFILTER Hook
m. WH_SHELL Hook
2. Sử dụng Hook
a) Cài đặt hook:
Ta có thể cài đặt thủ tục hook vào chuỗi hook bằng việc gọi hàm SetWindowsHookEx và chỉ ra kiểu hook đang gọi thủ tục, việc cài đặt hook có thể thực hiện trên mọi tiến trình trong hệ thống.
Nếu sử dụng hook toàn cục thì phải đặt trong thư viện liên kết động (DLL). Ứng dụng muốn sử dụng thư viện liên kết động phải lấy được handle của thư viện đó. Để nhận Handle của thư viện liên kết động ta có thể sử dụng hàm LoadLibrary với tham số là tên của thư viện. Sau khi có được Handle của DLL, ta sẽ lấy địa chỉ của thủ tục hook trong thư viện liên kết động thông qua hàm GetProcAddress. Sau khi đã có thủ tục hook, sử dụng hàm SetWindowsHookEx để cài đặt thủ tục hook vào trong chuỗi hook.
Ví dụ về sử dụng thư viện liên kết động :
Code :
HOOKPROC lpfSetAutoProtect;
static HINSTANCE hinstDLL;
static HHOOK hhookysMsg;
hinstDLL = LoadLibrary((LPCTSTR) "c:\\Windows\\ BrowserHook.dll");
lpfSetAutoProtect= (HOOKPROC)GetProcAddress(hinstDLL, "SetAutoProtect");
hhookysMsg= SetWindowsHookEx(WH_SYSMSGFILTER,
lpfSetAutoProtect,hinstDLL,0);
b) Giải phóng hook:
Như đã nói thì hook nên được bỏ đi nếu như không cần thiết nữa bằng cách sử dụng hàm UnhookWindowsHookEx.
Với thread-specific hook, việc sử dụng hàm UnhookWindowsHookEx sẽ giải phóng thủ tục hook. Tuy nhiên với hook toàn tục (system-wide hook) thì hàm này không thể trả tự do cho hàm DLL. Việc gọi hàm LoadLibrary sẽ gọi trong ngữ cảnh của tất cả các tiến trình, tuy nhiên hàm FreeLibrary thì không thể thực hiện với các tiến trình khác. Vì vậy, không có cách nào để giải phóng DLL. Hệ thống chỉ có thể giải phóng DLL khi tất cả các tiến trình liên kết tới DLL đó phải kết thúc hoặc gọi FreeLibrary.
Giải pháp đặt ra cho vấn đề này là xây dựng hàm cài đặt ngay trong thư viện DLL. Bằng việc liên kết tới DLL, ứng dụng có thể cài đặt hook. Và ngay trong DLL cũng phải có hàm giải phóng hook để giải phóng khi không cần đến nữa.
c) Các hàm thường được sử dụng:
- SetWindowsHookEx
- UnhookWindowsHookEx
- LoadLibrary
- FreeLibrary
- GetProcAddress