Trao đổi với tôi

http://www.buidao.com

7/6/09

[Virus] Anti-keylogger

Source: http://blog.360.yahoo.com/blog-Dy.ZrLwlbqcdH0eCG28z_0660tw-?cq=1&tag=hook

Giới thiệu


Loạt các blog entry sau được rút ra từ 1 bản phân tích đề án dang dở của P cách đây khá lâu. Không đi sâu về mặt cài đặt, đơn giản nhằm giới thiệu 1 hướng đi khác cho các chương trình anti-keylogger dựa trên phương pháp kiểm tra hành vi (heuristics), không dựa vào dấu hiện nhận dạng (signature) như phần lớn các chương trình tương tự hiện có tại Việt Nam!

Về đề án


Xây dựng 1 chương trình chống key logger với các tính năng:

· Phát hiện các key logger đang hoạt động trên hệ thống bằng phương pháp kiểm tra hành vi (heuristics), không dựa trên dấu hiện nhận dạng (signature).

· Có khả năng ngăn chặn/ngăn chặn tạm thời các tiến trình nghi ngờ là key logger.

· Ghi nhận các tiến trình hợp pháp từ người dùng (white list).

Các dạng logger cần chặn


1. Password Reader
Log nội dung trong các điều khiển Edit dạng ES_PASSWORD kèm các thông tin liên quan (tên ứng dụng, thời điểm, điều khiển Edit nhập user name…).

Chủ yếu dùng các API:

· SendMessage (A/W)


2. Keyboard Reader
Log các phím được gõ từ keyboard.

Chủ yếu dùng các API:

· GetAsyncKeyState: thường dùng

· GetKeyState: hiếm dùng vì khó cài đặt và không hiệu quả

· GetKeyboardState: hiếm dùng vì khó cài đặt và không hiệu quả

Dạng logger này bắt buột phải gọi các API trên liên tục để kiểm tra phím, thường cài đặt theo 2 cách sau:

· Tạo 1 timer với interval nhỏ, xấp xỉ nhỏ hơn 1000/số phím người dùng có thể gõ được trong 1 giây , kiểm tra phím khi nhận thông điệp WM_TIMER hoặc dùng hàm callback (TimerProc).

· Gọi trong vòng lặp vô tận, sử dụng các hàm delay (như sleep) hoặc thiết lập độ ưu tiên của tiến trình logger xuống mức thấp (chẳng hạn IDLE_PRIORITY_CLASS) để tránh tình trạng sử dụng CPU 100%.

Lưu ý: dạng logger này không sử dụng Hook.


3. Keyboard Hooker
Thiết lập 1 global (system-wide) windows hook, thông thường là:

· WH_KEYBOARD: rất thường

· WH_KEYBOARD_LL: rất thường

· WH_CBT: thường

Một số dạng hook khác cũng có thể sử dụng như WH_GETMESSAGE, WH_CALLWNDPROC, WH_CALLWNDPROCRET để bắt phím.


4. Các dạng khác

· Web logger
Bằng cách hook các API Winsock hoặc thiết lập 1 proxy, dạng này có thể thu thập các thông tin trao đổi qua mạng, nhất là các thông tin đăng nhập, đăng ký từ web.

· Screen capturer

· Keyboard filter drive

Chiến lược ngăn chặn


Sử dụng phương pháp hook API.

1. Mô tả
Việc hook các API thích hợp có thể ngăn chặn được các dạng phần lớn các dạng logger. Ở đây chia làm 2 kịch bản ngăn chặn, 1 cho dạng Password Reader, Keyboard Reader và 1 cho Keyboard Hooker.

a) Chặn Password Reader và Keyboard Reader
Bước 1:
Hook các API thích hợp:

· SendMessageA/W

· GetAsyncKeyState, GetKeyState, GetKeyboardState

·

Bước 2:
Trong các hàm CustomAPIProc, xử lý theo kịch bản sau:



Kịch bản xác định tiến trình có hành vi của 1 key logger như sau:

Trường hợp SendMessageA/W
Kiểm tra có phải đang lấy thông tin từ các điều khiển Edit có style ES_PASSWORD hay không?
Tuy nhiên, nhận dạng kiểu này là khá mạo hiểm vì dễ trùng với hành vi xử lý bình thường khi lấy text từ 1 Edit style ES_PASSWORD.

Trường hợp là GetAsyncKeyState, GetKeyState, GetKeyboardState
Các hàm GetAsyncKeyState, GetKeyState thường dùng để kiểm tra tình trạng các phím chức năng (Ctrl, Alt, Shift, Windows…) cho nên 1 tiến trình bị nghi ngờ là key logger chỉ khi:

· Triệu gọi các hàm này quá nhiều lần trong 1 thời gian ngắn

· Kiểm tra các phím trong khoảng [0..9], [A..Z]

b) Chặn Keyboard Hooker
Hook API SetWindowsHookExA/W

Quá trình xử lý tương tự trường hợp a, tuy nhiên ở đây không block hoàn toàn quá trình xử lý của tiến trình dùng Hook, nghĩa là vẫn cho phép SetWindowsHookExA/W thi hành bình thường, mục đích để đáp ứng cho yêu cầu enable/disable tiến trình bị nhận dạng là key logger của đề án.

Theo dõi mẫu hàm của API SetWindowsHookExA/W:
HHOOK SetWindowsHookEx(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId
);

Ở đây cần hook thêm lpfn (lấy từ tham số thứ 2), trong trường hợp người dùng enable tiến trình này thì cho thi hành bình thường, ngược lại sẽ gọi hàm custom của anti-keylogger có dạng như sau:
LRESULT CALLBACK CustomHookProc(
int code, WPARAM wParam, LPARAM lParam
)
{
return CallNextHookEx(NULL, code, wParam, lParam);
}
Điều này có thể disable tạm thời quá trình xử lý hook của tiến trình nghi ngờ (hoặc chắc chắn) là key logger.

Mã giả như sau:
HHOOK CustomSetWindowsHookEx(
int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId
)
{
if (!IsBadCodePtr(lpfn))
HookAPI(lpfn, CustomHookProc);

return OriginalSetWindowsHookEx(idHook, lpfn, hMod, dwThreadId);
}
LRESULT CALLBACK CustomHookProc(
int code, WPARAM wParam, LPARAM lParam
)
{
if (PleaseReleaseMe(...)) // Quá vần :D
return OriginalHookProc(code, wParam, lParam);
else
return CallNextHookEx(NULL, code, wParam, lParam);
}

Lưu ý:

· Mã giả chỉ có tính chất minh họa.

· Chưa kiểm tra thực tế phương pháp trên, chỉ phân tích theo suy đoán.


2. Nhược điểm
Trong trường hợp các keyboard hooker (dùng system-wide windows hook) được thi hành trước anti-keylogger thì phương pháp hook API hoàn toàn không ngăn chặn được, đây là nhược điểm lớn.

Các chiến lược bổ sung


1. Cài đặt hook WH_DEBUG
Hệ thống sẽ gọi hook procedure của tiến trình hook WH_DEBUG trước khi gọi các hook procedure của các dạng hook khác. Cấu trúc DEBUGHOOKINFO lấy từ tham số lParam có thể cung cấp 1 số thông tin (trừ trường idThreadInstaller), thậm chí có thể phủ quyết các hook procedure khác bằng cách không gọi API CallNextHookEx và trả về giá trị khác 0.
Cách này có thể ngăn chặn được các keyboard hooker thi hành trước anti-keylogger.

Nhược điểm:

· Trong trường hợp keyboard hooker cũng cài đặt hook này và thi hành trước anti-keylogger nó có thể phủ quyết hook procedure của anti-keylogger bằng cách không gọi API CallNextHookEx.

· Không theo dõi được dạng hook WH_KEYBOARD_LL và WH_MOUSE_LL, trong đó quan trọng nhất là WH_KEYBOARD_LL.


2. Kiểm tra IAT (Import Address Table) của các tiến trình

Đối với các keyboard hooker thi hành trước anti-keylogger có thể dùng cách này để kiểm tra hợp lệ bằng cách duyệt qua các tiến trình + module, tìm trong IAT để kiểm tra có sử dụng API SetWindowsHookExA/W.

Nhược điểm:

· Không thể áp dụng cơ chế enable/disable tiến trình phát hiện có sử dụng, ngoại trừ xuất cảnh báo đề nghị đóng tiến trình.

· Có thể qua mặt bằng cách không import API SetWindowsHookExA/W mà sử dụng API GetProcAddress để lấy entry point của SetWindowsHookExA/W rồi gọi.


3. Kiểm tra mã thi hành bằng phương pháp so sánh mẫu (pattern)


Pattern gọi API SetWindowsHookExA/W thông thường có dạng:
push x ; dwThreadId
push x ; hMod
push x ; lpfn
push x ; idHook
call SetWindowsHookExA/W

Nhược điểm:

· Chậm và quá khó cài đặt.

· Đặc trưng của phương pháp này là kết quả nhận được không đảm bảo chính xác, chỉ có giá trị tham khảo.

· Dễ dàng qua mặt bằng cơ chế đa hình (kéo giãn hoặc thay thế mã tương đương), Dynamic En/Decrypt.

· Dễ dàng bị đánh lừa.


4. Truy cập “Hook table”
Đây là chiến lược hiệu quả nhất vì cung cấp khá nhiều thông tin về các tiến trình đang sử dụng global windows hook. Thử tham khảo chức năng Message Hooks từ tiệc ích hệ thống nổi tiếng IceSword.

Lưu ý:
Chiến lược này chỉ có giá trị tham khảo vì hiện giờ không tìm thấy bất cứ thông tin gì về việc lấy “hook table” (tạm gọi như thế), có thể vì việc truy cập các thông tin này là không hợp pháp, ít nhất đối với Microsoft , và phải sử dụng các API (+ Native API) không công bố.

Các từ khóa tìm kiếm:
SYSCALL, 2E, 1212, 1225, win32k.sys, NtSetWindowsHookEx, GetHmodTableIndex, AddHmodDependancy, FreeHook, UnlinkHook, RemoveHmodDependancy, catomSysTableEntries, catomSysDepends


5. Kiểm tra các hành vi khác


Thông thường 1 logger sẽ có 1 trong các hành vi (hoặc tất cả) sau:

· Thi hành lúc Windows khởi động.

· Tập trung dữ liệu: tạo đồng loạt các file với tên theo 1 pattern nhất định, nội dung chứa các thông tin đã thu thập (dạng text hoặc đã mã hóa).

· Chuyển dữ liệu: qua HTTP (POST), FTP hoặc SMTP.

·

Lưu ý: không quá khó để có thể che dấu các hành vi này.

Việc xác định 1 tiến trình trong danh sách nghi ngờ có các module thực hiện các hành vi này (ghi file, mở Socket…) có thể cho biết nó có phải là key logger hay không. Dĩ nhiên chỉ kiểm tra tổng quát, vì nếu kiểm tra chính xác (process gì? tên file thực thi gì? dữ liệu thu thập lưu ở đâu? theo cách nào? gởi dùng giao thức gì? gởi lên đâu?...) thì đây chính là cơ chế xác định key logger dựa trên dấu hiệu nhận dạng.