Hệ điều hành Windows xử lý thông điệp qua hàng đợi thông điệp. Nó sẽ lấy tuần tự các thông điệp trong hàng đợi thông điệp ra xử lý.
Một cửa sổ window được tạo ra từ 1 chương trình gởi đến HĐH Windows 1 thông điệp qua hàng đợi thông điệp, Khi Windows xử lý đến thông điệp này, Windows sẽ gọi “thủ tục window”(hàm xử lý chính của 1 chương trình chạy trong Windows) của chương trình yêu cầu xử lý. Đó là mối quan hệ làm việc giữa Windows và chương trình. Ví dụ khi bạn click chuột trái vào nút button “OK” thì chương trình sẽ gởi đến Windows 1 thông điệp MSG có giá trị là 202, rồi Windows sẽ gọi “thủ tục window” của chương trình xử lý “biến cố” khi người dùng click nút OK , chẳng hạn như kiểm tra serial nhập vào có hợp lệ ko.
Trong lập trình ASM, ta sẽ thấy đọan code sau:
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
Trong VC++ ko dùng MFC, đọan code đó là :
While (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg) ;
}
Đọan code này có ý nghĩa như sau : Kiểm tra thông điệp MSG , nếu có bất kỳ thông điệp nào thì thực hiện lần lượt 2 hàm TranslateMessage và DispatchMessage. Hai hàm này có ý nghĩa sau:
TranslateMessage là một hàm tiện ích bắt lấy input từ keyboard “thô” và sinh ra 1 thông điệp mới (WM_CHAR) được đặt trong dãy thông điệp tiếp nối nhau chờ Windows xử lý. Thông điệp WM_CHAR chứa giá trị ASCII từ key nhấn vào, chúng dễ dàng được “xử lý” đến hơn là với scan code của keyboard “thô”. Bạn có thể quên hàm này nếu chương trình của bạn ko tiến hành keystrokes (nhấn key bàn phím).
DispatchMessage gởi dữ liệu thông điệp đến thủ tục window đảm trách cho cửa sổ window mà thông điệp đó cần xử lý.
Cụ thể ta quan tâm đến hàm TranslateMessage. Tra cứu APIs ta có :
The TranslateMessage function translates virtual-key messages into character messages. The character messages are posted to the calling thread's message queue, to be read the next time the thread calls the GetMessage or PeekMessage function.
BOOL TranslateMessage(
CONST MSG *lpMsg // address of structure with message
);
Parameters
lpMsg
Points to an MSG structure that contains message information retrieved from the calling thread's message queue by using the GetMessage or PeekMessage function.
Return Values
If the message is translated (that is, a character message is posted to the thread's message queue), the return value is nonzero.
If the message is not translated (that is, a character message is not posted to the thread's message queue), the return value is zero.
Để dễ dàng hơn về cách lý luận, ta lấy crackme trong bài Moon làm dẫn chứng:
Khi chúng ta nhập vào FakePassword (FPass) : 1234567890 (chưa nhấn OK) như hình sau
Chúng ta chắc chắn rằng chuổi FPassword sẽ nằm đâu đó trong memory . Ta suy nghĩ tiếp: nếu chúng ta nhấn OK thì chương trình sẽ đến vùng nhớ memory chứa FPass để “truy xuất” (access) nó rồi xử lý mã hóa chuổi này.
Để access chuổi FPass trong memory , đầu tiên chương trình phải translate mã scan code của key ta nhấn (press) thành character thông qua hàm TranslateMessage như chúng ta biết ở trên.
Vậy tại sao ta ko đặt bp (F2 ) tại hàm TranslateMessage mà lại phải đặt bp CONDITIONAL LOG BREAKPOINT ON IMPORT như tut của Moon? .
Theo đọan code lập trình trong ASM và VC++ tui dẫn chứng trên, nếu ta đặt bp tại hàm này thì bất cứ thông điệp nào xảy ra hàm TranslateMessage và DispatchMessage cũng xử lý. Vì vậy ta đặt bp hàm này thì olly luôn bị pause do phải xử lý thông điệp WM_PAINT. Do đó ko thể đặt bp F2 cho hàm này được.
Ta phải đặt bp sau cho : bp xảy ra trên hàm TranslateMessage với điều kiện sau khi ta click trái vào nút OK.
Tra tập tin Windows.inc ta biết các thông điệp sau có thông số:
WM_LBUTTONDOWN equ 201h
WM_LBUTTONUP equ 202h
Vì vậy ta mới đặt bp như Moon :
Tiếp tục, sau khi chuyển đổi thành character chuổi FPass , Windows sẽ lưu nó vào 1 vùng nhớ memory nào đó . Chương trình chắc chắn sẽ access vùng nhớ này. Vì vậy , để tìm vùng nhớ này ta search nó trong memory map:
và ta tìm được nó nằm tại addr này trong memory:
Và để chương trình ngừng lại khi access vùng nhớ này ta set bp như hình trên (Breakpoint/Memory, on access).Từ đó ta tìm ra Point-H
Chương trình sẽ dùng 1 hàm Import nào đó để access . Và như Moon đã nói, nó là 1 hàm trong user32.dll để làm chuyện này. Và điểm Point-H sẽ nằm trong hàm này.
Đây là ý kiến riêng của BE, Moon check lại giùm: Vì ASM và VC++ khi compile sử dụng hàm APIs, nên có điểm Point-H giống nhau. Nhưng Delphi và VB có thể dùng dll khác để access . Do đó Point-H của delphi và VB khác với Point-H mà Moon đề cập. Vì vậy, để nghiên cứu vấn đề này. Chúng ta cần nghiên cứu dll của Delphi như thế nào.
Benina (7/6/2005)