Saturday 8 November 2014

Xây dựng trình cắm cho IDA Pro - Phần 8

4.4.3 Điểm dừng
Một trong những chức năng cơ bản của trình gỡ rối là cho phép tạo ra các điểm dừng (breakpoint), IDA sử dụng điểm dừng cứng (hardware breakpoint) và điểm dừng mềm (software breakpoint) một cách khác nhau sử dụng cấu trúc bpt_t, được trình bày bên dưới và được định nghĩa trong tập tin dbg.hpp. Điểm dừng cứng được tạo ra bởi việc sử dụng những thanh ghi dò lỗi đặc biệt có sẵn trên Vi Sử Lý (DR0 – DR3 trên dòng X86), trong khi điểm dừng mềm dược tạo ra bởi việc chèn vào chỉ thị INT3 ở một địa chỉ ngắt cụ thể - mặc dù điều này được đảm nhiệm bởi IDA, cũng sẽ rất hữu ích khi bạn biết sự khác biệt. Trên vi sử lý x86, số lượng điểm dừng cứng bạn có thể sử dụng là 4.
struct bpt_t
{
// read only characteristics:
ea_t ea; //starting address of the breakpoint
asize_t size; // size of the breakpoint
// (undefined if software breakpoint)
bpttype_t type; // type of the breakpoint:
// Taken from the bpttype_t const definition in idd.hpp:
// BPT_EXEC = 0, // Execute instruction
// BPT_WRITE = 1, // Write access
// BPT_RDWR = 3, // Read/write access
// BPT_SOFT = 4; // Software breakpoint
// modifiable characteristics (use update_bpt() to modify):
int pass_count; // how many times does the execution reach
// this breakpoints? (-1 if undefined)
int flags;
#define BPT_BRK 0x01 // does the debuger stop on this breakpoint?
#define BPT_TRACE 0x02 // does the debugger add trace informaton
// when this breakpoint is reached?
char condition[MAXSTR]; // an IDC expression which will be used as
// a breakpoint condition or run when the
// breakpoint is hit

};
Bởi vậy, nếu kiểu thành viên của bpt_t được đặt là 0, 1, hoặc 3, thì nó là điểm dừng cứng, khi mà 4 sẽ xác định nó là điểm dừng mềm.
Có rất nhiều hàm để tạo ra, thao tác và đọc những chỉ thị, nhưng hiện tại, Tôi sẽ chỉ cung cấp một ví dụ đơn giản mà sẽ duyệt qua tất cả các định nghĩa điểm dừng, và hiển thị chúng là điểm dừng mềm hoặc điểm dừng cứng trên cửa sổ Log của IDA. Những hàm được dùng sẽ được trình bày chi tiết sau:
#include <dbg.hpp>
// get_bpt_qty() gets the number of breakpoints defined
for (int i = 0; i < get_bpt_qty(); i++) {
bpt_t brkpnt;
// getn_bpt fills bpt_t struct with breakpoint information based
// on the breakpoint number supplied.
getn_bpt(i, &brkpnt);
// BPT SOFT is a software breakpoint
if (brkpnt.type == BPT_SOFT)
msg("Software breakpoint found at %a\n", brkpnt.ea);
else
msg("Hardware breakpoint found at %a\n", brkpnt.ea);
}



4.4.4 Dò lỗi
Trong IDA, có ba kiểu dò lỗi mà bạn có thể kích hoạt; Dò lỗi theo hàm; dò lỗi theo chỉ thị và dò lỗi theo điểm dừng (được biết đến như là read/write/execute). Khi viết plugin, một cửa sổ phụ để dò lỗi được hiển thị.; Dò theo bước. Dò theo bước là một hình thức thấp của dò lỗi cho phép bạn xây dựng cơ chế dò lỗi dựa trên nó, sử dụng cảnh báo sự kiện (xem phần 4.5) để thông bao cho plugin mỗi chỉ thị được thực thi. Điều này dựa trên chức năng dò của CPU, không phải điểm dừng.
Một “sự kiện dò” được tạo ra và lưu trữ trong bộ đệm khi một việc dò xảy ra, và những sự kiện dò được tạo ra và kích hoạt dựa vào kiểu dò bạn đã kích hoạt, tuy nhiên, chú ý rằng dò theo bước sẽ không tạo ra sự kiện dò, nhưng thay vào đó là tạo ra sự kiện cảnh báo. Bảng bên dưới liệt kê tất cả những kiểu sự kiện dò cùng với giá trị tev_type_t tương ứng, được định nghĩa trong tập tin dbg.hpp.
Kiểu dò
Kiểu sự kiện (tev_type_t)
Mô tả
Function call and return
tev_call và tev_ret
A function has been called or returned from.
Instruction
tev_insn
An instruction has been executed (this is built on top of step tracing in the IDA kernel).
Breakpoint
tev_bpt
A breakpoint with tracing enabled has been hit. Also known as a Read/Write/Execute trace.


Tất cả các sự kiện dò được lưu trữ trong một bộ đệm vòng, bởi vậy nó không bao giờ bị đầy, những những sự kiện dò cũ sẽ bị ghi đề nếu bộ đệm quá nhỏ. Mỗi sự kiện dò được thể hiện bởi cấu trúc tev_info_t, được định nghĩa trong tập tin dbg.hpp.
struct tev_info_t
{
tev_type_t type; // trace event type (one of the above or tev_none)
thid_t tid; // thread where the event was recorded
ea_t ea; // address where the event occurred
};


Dựa vào cấu strúc bpt_t được trình bày trong phần 4.4.3, một điểm dừng dò lỗi sẽ giống như một điểm dừng thông thường, nhưng có cờ BPT_TRACE được đặt trong biến thành viên flags. Bộ đệm theo điều kiện có thể chứa các lệnh IDC để chạy tại mỗi điểm dừng.
Thông tin dò được lấy trong suốt quá trình thực thi tiến trình, nhưng chỉ có thể được truy cập khi tiến trình đã kết thúc và bạn trở về chế độ đảo mã tĩnh (trừ khi một trình cắm mà bạn sử dụng xóa bộ đệm khi kết thúc một cách tường min). Bạn có thể dùng đoạn mã sau để liệt kê tất cả các sự kiện dò, dù bạn có kích hoạt nó trong khi thực thi hay không.
#include <dbg.hpp>
// Loop through all trace events
For (int I = 0; I < get_tev_qty(); i++) {
Regval_t esp;
Tev_info_t tev;
// Get the trace event information
Get_tev_info(I, &tev);
Switch (tev.type) {
Case tev_ret:
Msg(“Function return at %a\n”, tev.ea);
Break;
Case tev_call:
Msg(“Function called at %a\n”, tev,ea);
Break;
Case tev_insn:
Msg(“Instruction executed at %a\n”, tev.ea);
Break;
Case tev_bpt:
Msg(“Breakpoint with tracing hit at %a\n”, tev.ea);
Break;
Default:
Msg(“Unknown trace type..\n”);
}
}
Chú ý rằng tại thời điểm này thì một plugin không thể nào thêm, hoặc thậm chí thay đổi giá trị trong nhật ký dò sự kiện.
Tất cả các hàm được sử dụng ở trên sẽ được trình bày trong Chương 5 – Hàm.
4.4.5 Tiến trình và Tiểu trình
IDA quản lý những thông tin về tiến trình và tiểu trình hiện tại đang chạy trong trình gỡ rối. Số định danh của tiến trình và tiểu trình được đại diện bằng kiểu pid_t và thid_t, cả hai đều là kiểu nguyên có dấu. Tất cả các kiểu được định nghĩa trong tập tin idd.hpp. Kiểu duy nhất còn lại liên hệ với tiến trình là process_into_t, như được trình bày bên dưới:
struct process_info_t {
pid_t pid; // Process ID
char name[MAXSTR]; // Process Name (executable file name)
};
Chúng chỉ có thể được sử dụng khi tập tin nhị phân được thực thi với IDA (bạn không thể sử dụng chúng trong chế độ tĩnh). Ví dụ tiếp theo sẽ trình bày việc sử dụng của cấu trúc info_t.
#include <dbg.hpp>

// Get the number of processes available for debugging.
// get_process_qty() also initilises IDA's "process snapshot"
if (get_process_qty() > 0) {
process_info_t pif;
get_process_info(0, &pif);
msg("ID: %d, Name: %s\n", pif.pid, pif.name);
} else {
msg("No process running!\n");
}

Những hàm được sử dụng với cấu trúc này sẽ được trình bày trong Chương 5 – Hàm.
4.5 Cảnh báo sự kiện
Hầu hết, những plugin được chạy đồng bộ, trong trường hợp đó, chúng được thực thi bởi người dùng, thông qua việc nhấn phím tắt hoặc qua thực đơn Edit->Plugins. Một plugin có thể, tuy nhiên, chạy trong chê độ bất đồng bộ, khi nó được gọi bởi IDA để phản hồi một vài sự kiện được gây ra bởi người dùng hoặc chính bản thân IDA.
Trong suốt khóa học làm việc với IDA, hầu hết bạn sẽ nhấn những nút lệnh, tìm kiếm, và những thứ khác. Tất cả những hành động đó là các “sự kiện”, và những gì IDA phải làm là tạo ra các “cảnh báo sự kiện” mỗi khi những hành động đó xảy ra. Nếu plugin của bạn được cài đặt để nhận những cảnh báo đó (được trình bày bên dưới), nó có thể hành động bất cứ gì như bạn muốn nó làm. Một ứng dụng cho loại hình này là bạn có thể ghi lại những macro. Một plugin có thể tạo ra những sự kiện, khiến IDA thực hiện một loạt các chức năng, có thể những sự kiện gây ra một loạt các tương tác giữa các plugin.
4.5.1 Nhận cảnh báo
Để nhận một cảnh báo sự kiện từ IDA, tất cả các plugin phải được đăng ký vào một hàm call-back sử dụng hàm hook_to_notification_point(). Để tạo ra sự kiện cảnh báo, hàm callui() được sử dụng, nó sẽ đực trình bày chi tiết trong Chương 5 – Hàm.
Khi đăng ký một hàm call-back với hook_to_notification_point(), bạn có thể xác định sử dụng một trong ba kiểu sự kiện, tùy thuộc vào loại cảnh báo nào bạn muốn nhận. Chúng được định nghĩa trong kiểu liệt kê type_t khai báo trong loader.hpp.
Kiểu
Nhận sự kiện cảnh báo từ
Liệt kê tất cả các sự kiện cảnh báo
HT_IDP
Processor module
idp_notify (không được đề cập ở đây)
HT_IDB
Database
idp_event_t (không được đề cập ở đây)
HT_UI
IDA user interface
ui_notification_t
HT_DBG
Currently running IDA debugger
dbg_notification_t


Bởi vậy, để nhận tất cả các cảnh báo được phát sinh bởi trình gỡ rối và chuyển chúng vào hàm dbg_callback(ví dụ), bạn có thể đặt nó vào trong hàm IDAP_init():
Tham số thứ ba thường có giá trị NULL, trừ khi bạn muốn truyền dữ liệu cùng với hàm call-back khi snó nhận một sự kiện (bất cứ cấu trúc nào mà bạn chọn).
Hàm call-back được truyền vào hook_to_notification_point() sẽ có hình thức giống như này:
int idaapi dbg_callback (void *user_data, int notif_code, va_list va)
{
…….
return 0;
}



Trong khi dbg_callback() thậm chí được gọi bởi IDA để đảm nhiệm những cảnh báo sự kiện, user_data có thể trỏ đến bất cứ dữ liệu nào bạn xác định để truyền qua hàm call-back (được định nghĩa khi gọi hàm hook_to_notification_point()), notif_code sẽ là sự kiện thực được xác định (được liệt kê trong phần sau) và là bất cứ dữ liệu nào được cung cấp bởi IDA cùng với sự kiện, có thể cung cấp những thông tin thêm.
Hàm call-back sẽ trả về 0 nếu nó cho phép cảnh báo sự kiện được thực hiện tởi những hàm con tuần tự (trong hầu hết trường hợp), hoặc bất cứ giá trị nào khác nếu nó là hàm duy nhất/cuối cùng đảm nhiệm.
Một vài điều cần chú ý là nếu bạn sử dụng hàm hook_to_notification_point() trong plugin của mình, bạn cũng sẽ phải sử dụng unhook_from_notification_point(), khi mà bạn không cần nhận cảnh báo nữa, hoặc trong hàm IDAP_term(). Điều này sẽ tránh xảy ra trường hợp lỗi khi kết thúc IDA. Tiếp tục theo ví dụ ở trên, để tháo kết nối điểm kết nối, chúng ta sẽ làm như sau:
unhook_from_notification_point(ht_dbg, dbg_callback, null);
4.5.2 Cảnh báo sự kiện UI
ui_notification_t là một kiểu liệt kê được định nghĩa trong kernwin.hpp, và bao gồm tất cả các sự kiện cảnh báo về giao diện có thể được tạo ra bởi IDA hoặc một plugin. Để đăng ký những cảnh báo sự kiện này, bạn phải sử dụng hằng số HT_UI như là tham số đầu tiên của hook_to_notification_point().
Hai danh sách sau sẽ cho thấy một vài cảnh báo sự kiện có thể được nhận và tạo ra bởi plugin. Đó chỉ là những tập con của một tập các cảnh báo sự kiện; danh sách bên dưới có một ý nghĩa tổng quát hơn.
Mặc dù những thông tin bên dưới có thể được tạo ra bởi plugin sử dụng hàm callui(), hầu hết có những hàm trợ giúp, điều đó có nghĩa là bạn sẽ không phải sử dụng callui() và có thể chỉ cần gọi những hàm trợ giúp.
Sự kiện cảnh báo bên dưới được nhận bởi plugin, và sẽ được thực hiện bởi hàm call-bak của bạn.
Event
Description
Helper Function
Ui_jumpto
Moves the cursor to an address
Jumpto
Ui_screenea
Return the address where the cursor is currently positioned
Get_screen_ea
ui_refresh
Refresh all disassembly views
Refresh_idaview_anyway
ui_mbox
Display a message box to the user
vwarning, vinfo and more.
Ui_msg
Print some text in IDA's Log window
deb, vmsg
Ui_askyn
Dislpay a message box with Yes and No as options
Askbuttons_cv
Ui_askfile
Prompt the user for a filename
askfile_cv
Ui_askstr
Prompt the user for a single line string
vaskstr
Ui_asktext
Prompt the user for some text
vasktext
ui_form
Display a form (very flexible - look at the comments in the header!)
AskUsingForm_cv
ui_open_url
Open a web browser at a particular URL
Open_url
Ui_get_hwnd
Get the hwnd (Window Handle) for the IDA window
none
Ui_get_curline
Get the colour-coded disassembled line
Get_curline
Ui_get_cursor
Get the X and Y coordinates of the current cursor position
Get_cursor


Những cảnh báo sự kiện tiếp theo được nhận bởi plugin, và nên được đảm nhiệm bởi hàm callback của bạn.
Event Notification
Description
ui saving & ui saved
IDA is currently saving and has saved the database, respectively
ui term
IDA has closed the database


Ví dụ, đoạn mã phía dưới sẽ tạo ra một cảnh báo sự kiện ui_screenea và hiển thị kết quả trong hộp thoại của IDA sử dụng một sự kiện cảnh báo ui_mbox.
void IDAP_run(int arg)
{
ea_t addr;
va_list va;
char buf[MAXSTR];
// Get the current cursor position, store it in addr
callui(ui_screenea, &addr);
qsnprintf(buf, sizeof(buf)-1, "Currently at: %a\n", addr);
// Display an info message box
callui(ui_mbox, mbox_info, buf, va);
return;
}




Trong trường hợp trên, bạn sử dụng hầu hết các hàm trợ giúp, tuy nhiên callui() sẽ được dùng với mục đích miêu tả. Phần tiếp theo mô tả làm thế nào để phản hồi những sự kiện với plugin của bạn.

No comments: