MỤC LỤC
T ỔNG QUAN VỀ ĐỀ TÀI. 5
Chương 1. CƠ SỞ LÝ THUYẾT. 6
I. Giới thiệu. 6
II. Thông Điệp và HÀNG ĐỢI THÔNG ĐIỆP CỦA WINDOWS . 6
II.1. Giới thiệu. 6
II.1.1. Thông đi ệp windo ws . 6
II.1.2. Lo ại Thông điệp . 7
II.1.3. Lộ trình thông đi ệp . 10
II.1.4. Xử lý thông điệp . 12
II.1.5. Lọc thông điệp . 16
II.1.6. Đăng và chuyển thông điệp . 16
II.1.7. Bế tắc thông điệp . 18
II.1.8. Thông đi ệp quảng bá . 19
II.1.9. Truy vấn thông điệp . 20
II.2. Sử dụng thông điệp và hàng đợi thông điệp . 21
II.2.1. T ạo vòng lặp thông điệp . 21
II.2.2. Kiểm tra một hàng đ ợi thông điệp . 24
II.2.3. Đăng thông đi ệp . 25
II.2.4. Gửi một thông đi ệp . 26
III. k ỹ thu ật hook . 28
III.1. Giới thiệu . 28
III.2. Chuỗi Hook . 29
III.2.1. Thủ tục Hook. 29
III.2.2. Các kiểu Hook . 29
III.3. Cách s ử dụng . 31
III.3.1. Cài đ ặt Hook . 31
III.3.2. Giải phóng Hook . 31
IV. win 32 api . 32
IV.1. Giới thiệu . 32
IV.2. Các hàm thườ ng dùng . 32
IV.2.1. SetWindowsHookEx . 32
IV.2.2. UnhookWindowsHookEx . 33
IV.2.3. CallNextHookEx. 33
IV.2.4. LowLevelKeyboardProc . 34
IV.2.5. GetKeyState . 35
IV.2.6. GetKeyboardState . 35
IV.2.7. To Ascii . 35
IV.2.8. LoadLibrary. 36
IV.2.9. GetProcAddress . 36
IV.2.10. OpenProcess . 36
IV.2.11. EnumProcessModules . 37
IV.2.12. GetModuleBaseName. 37
IV.2.13. GetForegroundWindow. 38
IV.2.14. GetWindowThreadProcessId . 38
IV.2.15. GetLocalTime . 39
IV.3. Mã bàn phím ảo . 39
Chương 2. PHÂN TÍCH VÀ XÂY DỰNG CHƯƠNG TRÌNH. 47
I. PHân tích yêu c ầu . 47
I.1. Yêu c ầu v ề chức năng . 47
I.2. Yêu c ầu v ề giao diện người dùng . 47
I.3. Yêu c ầu v ề tương thích . 47
II. phân tích chức năng. 47
III. xây dựng chức năng . 47
III.1. T ập tin thi hành Jaam.exe . 47
III.2. Thư viện Hooker.dll . 49
III.2.1. Phiên bản 1 . 49
III.2.2. Phiên bản 2 . 51
III.2.3. Phiên bản 3 . 53
Chương 3. TRIỂN KHAI VÀ ĐÁNH GIÁ KẾT QUẢ. 57
I. Môi trường triển khai. 57
II. Kết qu ả chức nĂng chương trình . 57
III. Đánh giá và nh ận xét . 58
60 trang |
Chia sẻ: maiphuongdc | Lượt xem: 6019 | Lượt tải: 2
Bạn đang xem trước 20 trang tài liệu Đồ án Phần mềm keyloger sử dụng Hook Windows, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
kiểm soát bằng cách gửi một thông điệp tới nó. Việc kiểm soát có thể thông
báo cho cửa sổ cha mẹ thay đổi văn bản được thực hiện bởi người sử dụng bằng
cách gửi tin nhắn lại cho phụ huynh.
18 Bộ môn Mạng và Truyền Thông
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
Chức năng SendMessageCallback cũng sẽ gửi một thông điệp tới các thủ tục
cửa sổ tương ứng với cửa sổ nhất định. Tuy nhiên, chức năng này trả về ngay lập
tức. Sau khi các thủ tục cửa sổ xử lý tin nhắn, hệ thống các cuộc gọi chức năng gọi
lại quy định. Để biết thêm thông tin về chức năng gọi lại, thấy chức năng
SendAsyncProc.
Chức năng SendMessageCallback cũng sẽ gửi một thông điệp tới các thủ tục
cửa sổ tương ứng với cửa sổ nhất định. Tuy nhiên, chức năng này trả về ngay lập
tức. Sau khi các thủ tục cửa sổ xử lý tin nhắn, hệ thống các cuộc gọi chức năng gọi
lại quy định. Để biết thêm thông tin về chức năng gọi lại, thấy chức năng
SendAsyncProc.
Bằng cách sử dụng chức năng InSendMessage hoặc InSendMessageEx, một
thủ tục cửa sổ có thể xác định cho dù đó là chế biến một thông báo được gửi bởi
thread khác. Khả năng này rất hữu ích khi xử lý thông báo phụ thuộc vào nguồn gốc
của tin nhắn.
II.1.7. Bế tắc thông điệp
Một chủ đề đó gọi hàm SendMessage để gửi tin nhắn đến chủ đề khác không
thể tiếp tục thực hiện cho đến khi các thủ tục cửa sổ nhận được tin nhắn trả về. Nếu
sản lượng chủ đề được kiểm soát trong khi xử lý tin nhắn, các chủ đề gửi không có
thể tiếp tục thực hiện, bởi vì nó là chờ đợi cho SendMessage trở lại. Nếu các chủ đề
nhận được được gắn vào hàng đợi tương tự như người gửi, nó có thể gây ra một bế
tắc ứng dụng để xảy ra. (Lưu ý rằng tạp chí móc đính kèm các chủ đề cùng một
hàng đợi.)
Lưu ý rằng các chủ đề nhận được cần không mang lại kiểm soát một cách rõ
ràng, gọi điện thoại bất kỳ của các chức năng sau có thể gây ra một thread để năng
suất kiểm soát ngầm.
- DialogBox
- DialogBoxIndirect
- DialogBoxIndirectParam
- DialogBoxParam
KeyLogger-Sử dụng Hook Windows 19
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
- GetMessage
- MessageBox
- PeekMessage
- SendMessage
Để tránh bế tắc tiềm năng trong ứng dụng của bạn, hãy xem xét sử dụng
SendNotifyMessage hoặc các chức năng SendMessageTimeout. Nếu không, một thủ
tục cửa sổ có thể xác định xem một tin nhắn đã nhận được đã được gửi chủ đề khác
bằng cách gọi InSendMessage hoặc InSendMessageEx chức năng. Trước khi gọi bất
kỳ các chức năng trong danh sách trước khi thực hiện một tin nhắn, các thủ tục cửa
sổ đầu tiên nên gọi InSendMessage hoặc InSendMessageEx. Nếu chức năng này trả
về TRUE, các thủ tục cửa sổ phải gọi hàm ReplyMessage trước khi bất kỳ chức
năng gây ra các chủ đề để sản lượng kiểm soát.
II.1.8. Thông điệp quảng bá
Mỗi thông điệp bao gồm một định danh thông điệp và hai tham số wParam
và lParam. Từ định danh tin nhắn là một giá trị duy nhất quy định cụ thể mục đích
thông báo. Các thông số cung cấp thông tin bổ sung đó là thông điệp cụ thể, nhưng
các tham số wParam nói chung là một giá trị kiểu cung cấp thông tin về tin nhắn.
Chương trình phát sóng tin nhắn chỉ đơn giản là gửi một tin nhắn tới nhiều
người trong hệ thống. Để phát sóng một thông điệp từ một ứng dụng, sử dụng chức
năng BroadcastSystemMessage, quy định cụ thể người nhận của tin nhắn. Thay vì
chỉ định người nhận cá nhân, bạn phải chỉ định một hoặc nhiều loại người nhận.
Những loại ứng dụng, trình điều khiển cài đặt, trình điều khiển mạng, và các trình
điều khiển thiết bị hệ thống. Hệ thống sẽ gửi tin nhắn quảng bá cho tất cả các thành
viên của từng loại quy định.
Hệ thống này thường chương trình phát sóng thông điệp phản ứng với những
thay đổi diễn ra trong các trình điều khiển thiết bị hệ thống hoặc các thành phần liên
quan. Người lái xe hoặc thành phần liên quan đến chương trình phát sóng thông
điệp đến các ứng dụng và các thành phần khác để thông báo cho họ về sự thay đổi.
20 Bộ môn Mạng và Truyền Thông
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
Ví dụ, thành phần chịu trách nhiệm cho các ổ đĩa chương trình phát sóng một thông
báo bất cứ khi nào điều khiển thiết bị cho các ổ đĩa mềm phát hiện một sự thay đổi
của các phương tiện truyền thông chẳng hạn như khi người sử dụng chèn một đĩa
vào ổ đĩa.
Hệ thống chương trình phát sóng tin nhắn đến người nhận theo thứ tự này: hệ
thống cấp trình điều khiển thiết bị, trình điều khiển mạng, cài đặt trình điều khiển,
và các ứng dụng. Điều này có nghĩa là hệ thống cấp trình điều khiển thiết bị, nếu
được lựa chọn như người nhận, luôn luôn có được cơ hội đầu tiên để đối phó với
một tin nhắn. Trong thời hạn một loại người nhận nhất định, lái xe không được đảm
bảo để nhận được thông báo đưa ra trước khi bất kỳ trình điều khiển khác. Điều này
có nghĩa rằng một thông điệp dành cho một trình điều khiển cụ thể phải có một định
danh tin nhắn trên toàn cầu duy nhất để không có trình điều khiển khác vô ý quá
trình đó.
Bạn cũng có thể phát sóng các tin nhắn cho tất cả các cửa sổ cấp cao nhất
bằng cách xác định HWND_BROADCAST trong SendMessage,
SendMessageCallback, SendMessageTimeout, hoặc SendNotifyMessage chức năng.
Các ứng dụng nhận tin nhắn thông qua các thủ tục cửa sổ của cửa sổ cấp cao
nhất của họ. Tin nhắn không được gửi đến các cửa sổ con. Dịch vụ có thể nhận tin
nhắn thông qua một thủ tục xử lý cửa sổ hoặc dịch vụ kiểm soá
Lưu ý hệ thống cấp trình điều khiển thiết bị sử dụng một chức năng, hệ thống
cấp liên quan để phát sóng các thông báo hệ thống.
II.1.9. Truy vấn thông điệp
Bạn có thể tạo ra các tin nhắn tùy chỉnh của bạn và sử dụng chúng để phối
hợp hoạt động giữa các ứng dụng của bạn và các thành phần khác trong hệ thống.
Điều này đặc biệt hữu ích nếu bạn đã tạo ra trình điều khiển cài đặt riêng của bạn
hoặc trình điều khiển thiết bị hệ thống cấp. Tin nhắn tuỳ chỉnh của bạn có thể mang
thông tin đến và từ trình điều khiển của bạn và các ứng dụng sử dụng các trình điều
khiển.
KeyLogger-Sử dụng Hook Windows 21
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
Bạn có thể tạo ra các tin nhắn tùy chỉnh của bạn và sử dụng chúng để phối
hợp hoạt động giữa các ứng dụng của bạn và các thành phần khác trong hệ thống.
Điều này đặc biệt hữu ích nếu bạn đã tạo ra trình điều khiển cài đặt riêng của bạn
hoặc trình điều khiển thiết bị hệ thống cấp. Tin nhắn tuỳ chỉnh của bạn có thể mang
thông tin đến và từ trình điều khiển của bạn và các ứng dụng sử dụng các trình điều
khiển.
II.2. Sử dụng thông điệp và hàng đợi thông điệp
II.2.1. Tạo vòng lặp thông điệp
Các hệ thống không tự động tạo một hàng đợi tin nhắn cho mỗi thread. Thay
vào đó, hệ thống sẽ tạo ra một hàng đợi tin nhắn chỉ dành cho các chủ đề thực hiện
các hoạt động mà yêu cầu một hàng đợi thông điệp. Nếu chủ đề tạo ra một hoặc
nhiều cửa sổ, một vòng lặp tin nhắn phải được cung cấp, vòng lặp thông điệp này
lấy thông điệp từ hàng đợi thông điệp của thread và công văn cho họ các thủ tục cửa
sổ thích hợp.
Bởi vì hệ thống chỉ đạo thông báo cho các cửa sổ trong một ứng dụng cá
nhân, một sợi phải tạo ra ít nhất một cửa sổ trước khi bắt đầu vòng lặp thông điệp
của mình. Hầu hết các ứng dụng có chứa một chủ đề duy nhất mà tạo ra cửa sổ. Một
ứng dụng điển hình đăng ký lớp cửa sổ cho cửa sổ chính của nó, tạo ra và hiển thị
cửa sổ chính, và sau đó bắt đầu vòng lặp thông điệp của nó - tất cả trong hàm
WinMain.
Bạn tạo ra một vòng lặp tin nhắn bằng cách sử dụng chức năng GetMessage
và DispatchMessage. Nếu ứng dụng của bạn phải có đầu vào nhân vật từ người sử
dụng, bao gồm các chức năng TranslateMessage trong vòng lặp. TranslateMessage
dịch ảo-key tin nhắn vào tin nhắn ký tự. Ví dụ sau đây cho thấy các vòng lặp tin
nhắn trong các chức năng winmain của một ứng dụng đơn giản dựa trên Windows.
HINSTANCE hinst;
HWND hwndMain;
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
22 Bộ môn Mạng và Truyền Thông
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
MSG msg;
BOOL bRet;
WNDCLASS wc;
UNREFERENCED_PARAMETER(lpszCmdLine);
// Register the window class for the main window.
if (!hPrevInstance)
{
wc.style = 0;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon((HINSTANCE) NULL,
IDI_APPLICATION);
wc.hCursor = LoadCursor((HINSTANCE) NULL,
IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "MainMenu";
wc.lpszClassName = "MainWndClass";
if (!RegisterClass(&wc))
return FALSE;
}
hinst = hInstance; // save instance handle
// Create the main window.
hwndMain = CreateWindow("MainWndClass", "Sample",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, (HWND) NULL,
(HMENU) NULL, hinst, (LPVOID) NULL);
// If the main window cannot be created, terminate
// the application.
if (!hwndMain)
return FALSE;
KeyLogger-Sử dụng Hook Windows 23
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
// Show the window and paint its contents.
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
// Start the message loop.
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// Return the exit code to the system.
return msg.wParam;
}
Ví dụ sau đây cho thấy một vòng lặp tin nhắn cho một chủ đề đó sử dụng
máy gia tốc và hiển thị một hộp thoại modeless. Khi TranslateAccelerator hoặc
IsDialogMessage trả về TRUE (chỉ ra rằng thông điệp đã được xử lý),
TranslateMessage và DispatchMessage không được gọi. Lý do cho việc này là
TranslateAccelerator và IsDialogMessage thực hiện tất cả các dịch cần thiết và cử
các tin nhắn.
HWND hwndMain;
HWND hwndDlgModeless = NULL;
MSG msg;
BOOL bRet;
HACCEL haccel;
//
// Perform initialization and create a main window.
//
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
24 Bộ môn Mạng và Truyền Thông
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
// handle the error and possibly exit
}
else
{
if (hwndDlgModeless == (HWND) NULL ||
!IsDialogMessage(hwndDlgModeless, &msg) &&
!TranslateAccelerator(hwndMain, haccel,
&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
II.2.2. Kiểm tra một hàng đợi thông điệp
Đôi khi, một ứng dụng cần kiểm tra các nội dung của hàng đợi thông điệp
của một chủ đề từ bên ngoài vòng lặp thông điệp của chủ đề. Ví dụ, nếu thủ tục cửa
sổ của một ứng dụng thực hiện một hoạt động bản vẽ dài, bạn có thể muốn người sử
dụng có thể làm gián đoạn hoạt động. Trừ khi ứng dụng của bạn định kỳ kiểm tra
hàng đợi thông điệp trong quá trình hoạt động cho chuột và tin nhắn bàn phím, nó
sẽ không đáp ứng với người sử dụng đầu vào cho đến khi sau khi hoạt động đã hoàn
thành. Lý do cho điều này là rằng các chức năng DispatchMessage trong vòng lặp
thông điệp của chủ đề không trả lại cho đến khi các thủ tục cửa sổ kết thúc xử lý tin
nhắn.
Bạn có thể sử dụng chức năng PeekMessage để kiểm tra một hàng đợi thông
điệp trong một hoạt động dài. PeekMessage tương tự như chức năng GetMessage,
cả hai kiểm tra một hàng đợi tin nhắn cho một tin nhắn phù hợp với tiêu chuẩn bộ
lọc và sau đó sao chép tin nhắn tới một cấu trúc MSG. Sự khác biệt chính giữa hai
chức năng là GetMessage không trở lại cho đến khi một tin nhắn phù hợp với tiêu
chuẩn lọc được đặt trong hàng đợi, trong khi PeekMessage trả về ngay lập tức bất
kể cho dù một thông báo là trong hàng đợi.
Ví dụ sau đây cho thấy làm thế nào để sử dụng PeekMessage để kiểm tra một
hàng đợi tin nhắn cho số lần nhấp chuột và đầu vào bàn phím trong một hoạt động
dài.
HWND hwnd;
BOOL fDone;
MSG msg;
// Begin the operation and continue until it is complete
KeyLogger-Sử dụng Hook Windows 25
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
// or until the user clicks the mouse or presses a key.
fDone = FALSE;
while (!fDone)
{
fDone = DoLengthyOperation(); // application-defined function
// Remove any messages that may be in the queue. If the
// queue contains any mouse or keyboard
// messages, end the operation.
while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE))
{
switch(msg.message)
{
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_KEYDOWN:
//
// Perform any required cleanup.
//
fDone = TRUE;
}
}
}
Các chức năng khác, bao gồm cả GetQueueStatus và GetInputState, cũng cho
phép bạn kiểm tra các nội dung của hàng đợi thông điệp của một chủ đề.
GetQueueStatus trả về một mảng của lá cờ cho biết các loại tin nhắn trong hàng đợi,
sử dụng nó là cách nhanh nhất để xác định xem liệu hàng đợi có chứa bất kỳ tin
nhắn. GetInputState trả về TRUE nếu hàng đợi có chứa tin nhắn chuột hoặc bàn
phím. Cả hai của các chức năng này có thể được sử dụng để xác định xem hàng đợi
có chứa tin nhắn cần được xử lý.
II.2.3. Đăng thông điệp
Bạn có thể gửi một thông điệp tới một hàng đợi thông điệp bằng cách sử
dụng chức năng PostMessage. PostMessage một tin nhắn vào cuối hàng đợi thông
điệp của một chủ đề và trả về ngay lập tức, mà không cần chờ đợi cho thread để xử
lý các tin nhắn. Các thông số của chức năng bao gồm một cửa sổ xử lý, nhận dạng
một tin nhắn, và hai tham số tin nhắn. Hệ thống bản sao các thông số này một cấu
trúc MSG, lấp đầy thời gian và các thành viên pt của cấu trúc, và cấu trúc trong các
hàng đợi thông điệp.
Hệ thống sử dụng cửa sổ xử lý được thông qua với chức năng PostMessage
để xác định mà chủ đề hàng đợi tin nhắn sẽ nhận được thông báo. Nếu xử lý là
26 Bộ môn Mạng và Truyền Thông
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
HWND_TOPMOST, các bài viết hệ thống tin nhắn tới hàng đợi tin nhắn của tất cả
các cửa sổ cấp cao nhất trong chủ đề.
Hệ thống sử dụng cửa sổ xử lý được thông qua với chức năng PostMessage
để xác định mà chủ đề hàng đợi tin nhắn sẽ nhận được thông báo. Nếu xử lý là
HWND_TOPMOST, các bài viết hệ thống tin nhắn tới hàng đợi tin nhắn của tất cả
các cửa sổ cấp cao nhất trong chủ đề.
Sử dụng chức năng PostQuitMessage để thoát khỏi vòng lặp thông điệp.
PostQuitMessage thông điệp WM_QUIT các chủ đề hiện đang thực hiện. Vòng lặp
thông điệp của chủ đề kết thúc và trả về kiểm soát hệ thống khi gặp phải thông điệp
WM_QUIT. Một ứng dụng thường gọi PostQuitMessage trong phản ứng với thông
điệp WM_DESTROY, như trong ví dụ sau đây.
case WM_DESTROY:
// Perform cleanup tasks.
PostQuitMessage(0);
break;
II.2.4. Gửi một thông điệp
Chức năng SendMessage được sử dụng để gửi tin nhắn trực tiếp đến một thủ
tục cửa sổ. SendMessage gọi một thủ tục cửa sổ và chờ đợi cho rằng thủ tục để xử
lý tin nhắn và trả lại kết quả.
Một thông báo có thể được gửi đến bất kỳ cửa sổ trong hệ thống, tất cả
những gì cần thiết là một cửa sổ xử lý. Hệ thống sử dụng xử lý để xác định thủ tục
cửa sổ sẽ nhận được tin nhắn.
Trước khi chế biến một thông điệp có thể được gửi từ chủ đề khác, một thủ
tục cửa sổ đầu tiên nên gọi chức năng InSendMessage. Nếu chức năng này trả về
TRUE, các thủ tục cửa sổ nên gọi ReplyMessage trước khi bất kỳ chức năng gây ra
các chủ đề năng suất kiểm soát, như trong ví dụ sau đây.
case WM_USER + 5:
if (InSendMessage())
ReplyMessage(TRUE);
DialogBox(hInst, "MyDialogBox", hwndMain, (DLGPROC) MyDlgProc);
break;
KeyLogger-Sử dụng Hook Windows 27
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
Một số tin nhắn có thể được gửi đến các điều khiển trong một hộp thoại.
Những thông điệp điều khiển thiết lập sự xuất hiện, hành vi, và nội dung của các
điều khiển hoặc lấy thông tin về điều khiển. Ví dụ, thông điệp CB_ADDSTRING có
thể thêm một chuỗi một hộp kết hợp, và tin nhắn BM_SETCHECK có thể thiết lập
nhà nước kiểm tra một hộp kiểm tra hoặc nút.
Sử dụng chức năng SendDlgItemMessage để gửi một tin nhắn để kiểm soát,
xác định định danh của kiểm soát và xử lý của cửa sổ hộp thoại có chứa kiểm soát.
Ví dụ sau đây, được lấy từ một thủ tục hộp thoại, bản sao một chuỗi từ kiểm soát
chỉnh sửa một hộp kết hợp vào hộp danh sách. Ví dụ sử dụng SendDlgItemMessage
để gửi một tin nhắn CB_ADDSTRING vào hộp kết hợp.
HWND hwndCombo;
int cTxtLen;
PSTR pszMem;
switch (uMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDD_ADDCBITEM:
// Get the handle of the combo box and the
// length of the string in the edit control
// of the combo box.
hwndCombo = GetDlgItem(hwndDlg, IDD_COMBO);
cTxtLen = GetWindowTextLength(hwndCombo);
// Allocate memory for the string and copy
// the string into the memory.
pszMem = (PSTR) VirtualAlloc((LPVOID) NULL,
(DWORD) (cTxtLen + 1), MEM_COMMIT,
PAGE_READWRITE);
GetWindowText(hwndCombo, pszMem,
cTxtLen + 1);
// Add the string to the list box of the
// combo box and remove the string from the
// edit control of the combo box.
if (pszMem != NULL)
{
SendDlgItemMessage(hwndDlg, IDD_COMBO,
CB_ADDSTRING, 0,
(DWORD) ((LPSTR) pszMem));
SetWindowText(hwndCombo, (LPSTR) NULL);
}
// Free the memory and return.
28 Bộ môn Mạng và Truyền Thông
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
VirtualFree(pszMem, 0, MEM_RELEASE);
return TRUE;
//
// Process other dialog box commands.
//
}
//
// Process other dialog box messages.
//
}
III. KỸ THUẬT HOOK
III.1. Giới thiệu
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 :
+ Thread-specific : kiểu Hook này sẽ bẫy sự kiện của một luồng cụ
thể.
+ 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.
KeyLogger-Sử dụng Hook Windows 29
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
III.2. 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.
III.2.1. 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:
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).
III.2.2. 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 :
30 Bộ môn Mạng và Truyền Thông
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
- WH_CALLWNDPROC: Cài đặt một thủ tục hook theo dõi message trước
khi hệ thống sẽ gửi chúng đến các thủ tục cửa sổ đích.
- WH_CALLWNDPROCRET: Cài đặt một thủ tục hook theo dõi message
sau khi đã được xử lý bởi các thủ tục cửa sổ đích.
- WH_CBT: Cài đặt một thủ tục hook tiếp nhận thông báo hữu ích để một
ứng dụng CBT.
- WH_DEBUG: Cài đặt một thủ tục hook hữu ích để gỡ lỗi thủ tục hook
khác.
- WH_FOREGROUNDIDLE: Cài đặt một thủ tục hook sẽ được gọi khi
luồng của ứng dụng là trở thành nhàn rỗi. Hook này rất hữu dụng cho thực hiện
nhiệm vụ ưu tiên thấp trong thời gian nhàn rỗi.
- WH_GETMESSAGE: Cài đặt một thủ tục hook theo dõi các message
được đưa lên một hàng đợi message.
- WH_JOURNALPLAYBACK: Cài đặt một thủ tục hook gởi message
trước đây được ghi lại bằng một thủ tục hook WH_JOURNALRECORD.
- WH_JOURNALRECORD: Cài đặt một thủ tục hook ghi lại các message
đầu vào được đưa lên hàng đợi thông điệp hệ thống. Hook này rất hữu ích cho các
macro ghi.
- WH_KEYBOARD: Cài đặt một thủ tục móc theo dõi tin nhắn tổ hợp
phím.
- WH_KEYBOARD_LL: Cài đặt một thủ tục móc theo dõi các sự kiện bàn
phím đầu vào ở mức độ thấp.
- WH_MOUSE: Cài đặt một thủ tục móc theo dõi tin nhắn chuột.
- WH_MOUSE_LL: Cài đặt một thủ tục móc theo dõi các sự kiện chuột đầu
vào ở mức độ thấp.
- WH_MSGFILTER: Cài đặt một thủ tục móc theo dõi tin nhắn được tạo ra
như là kết quả của một sự kiện đầu vào trong hộp thoại, hộp thông báo, menu, hoặc
di chuyển một thanh.
KeyLogger-Sử dụng Hook Windows 31
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
- WH_SHELL: Cài đặt một thủ tục hook tiếp nhận thông báo hữu ích cho
các ứng dụng shell.
- WH_SYSMSGFILTER: Cài đặt một thủ tục móc theo dõi tin nhắn được
tạo ra như là kết quả của một sự kiện đầu vào trong hộp thoại, hộp thông báo, menu,
hoặc di chuyển một thanh.
III.3. Cách sử dụng
III.3.1. 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 :
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);
III.3.2. 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
32 Bộ môn Mạng và Truyền Thông
Nguyễn Quang Nhật – Nguyễn Quốc Mỹ
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.
IV. WIN 32 API
IV.1. Giới thiệu
Windows API, gọi tắ là WINAPI, được gọi là giao diện lập trình ứng dụng
(API) có sẵn trong các hệ thống điều hành Microsoft Windows của Microsoft. Nó
cũng được gọi là Win32 API, tuy nhiên, tên "Windows API" phản ánh chính xác
hơn nguồn gốc của nó trong Windows 16-bit và hỗ trợ trên Windows 64-bit. Hầu
như tất cả các chương trình Windows tương tác với các API của Windows trên các
dòng Windows NT của hệ điều hành.
Công cụ hỗ trợ phát triển có sẵn trong các phiên bản của Microsoft Windows
SDK, cung cấp tài liệu và các công cụ cần thiết để xây dựng phần mềm dựa trên các
giao diện API Windows và các Windows.
Windows API chủ yếu quan tâm đến sự tương tác giữa các hệ thống điều
hành và ứng dụng. Đối với truyền thông giữa các ứng dụng Windows khác nhau với
nhau, Microsoft
Các file đính kèm theo tài liệu này:
- keylog_3468.pdf