Saturday 8 November 2014

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

5.16 Dò lỗi
Ba phần sau sẽ làm việc với giá trị nhị phân trong suốt quá trình thực thi. Phần này sẽ tập trung vào những thao tác bậc cao (như là điều khiển tiến trình và tiểu trình) trong một tập tin nhị phân/tiến trình. Dò lỗi và duyệt được trình bày trong hai phần tiếp theo. Tất cả những hàm bên dưới được định nghĩa trong tập tin dbg.hpp với 2 ngoại lệ là invalidate_dbg_contents() và invalidate_dbg_config(), được định nghĩa trong bytes.hpp. Để hiểu rõ hơn về chúng, bạn cần phải chạy chúng (gọi plugin của bạn) trong một tập tin đang được dò lỗi bởi IDA.
Bạn sẽ nhận thấy rằng tất cả những hàm này không được đặt tiền tố bởi ida_export. Chúng không cần thiết bởi vì tất cả chúng là những hàm bao của callui(), và sử dụng những cảnh báo sự kiện tương ứng với chức năng của mình.
5.16.0 Chú ý về loại hàm Request
Không giống như hầu hết các hàm trong SDK, hầu hết các hàm của trình gỡ rối (và một vài hàm duyệt) được chia làm hai hình thức; hình thức bất đối xứng thông thường, ví dụ run_to(), và hình thức đồng bộ, hoặc hình thức request, như request_run_to(). Cả hai hình thức của hàm đều nhận cùng một dạng tham số, nhưng nó khác nhau ở những tác vụ tương ứng tạo cho nó sự khác biệt.
Hình thức hàm đồng bộ (request_) sẽ được nhập vào một hàng đợi hàm, và cuối cùng được thực thi bởi IDA khi bạn gọi hàm run_requests(). Hình thức còn lại, những hàm không đồng bộ, sẽ chạy một mạch, giống như những hàm thôn thường.
Hình thức hàm đồng bộ có thể rất hữu dụng khi bạn muốn thực thi một loạt các thao tác trong IDA khi được kích hoạt. Ví dụ 5.17.5 là một ví dụ tốt cho điều này, khi xóa một loạt các điểm dừng sử dụng hàm del_bpt() sẽ thất bại trừ khi nó được làm trong chế độ đồng bộ, bởi vì số định danh của điểm dừng sẽ được tổ chức lại bởi lần mà bạn lấy giá trị kế tiếp bằng việc sử dụng hàm getn_bpt(). Một điều quan trọng cần chú ý là bạn phải sử dụng hình thức đồng bộ của hàm khi bạn ở trong một cảnh báo sự kiện của trình gỡ rối (xem phần 4.5, đặc biệt là 4.5.3 đễ biết rõ thêm).
Tất cả các hàm trong phần 5.16, 5.17 và 5.18 mà có thể được dùng dưới hai dạng sẽ được thêm dấu sao (*) ngay sau tên hàm.
5.16.1 run_requests
Định nghĩa
bool idaapi
run requests(void)
Chú giải
Chạy bất cứ yêu cầu nào (các hàm đồng bộ) đã được đặt trong hàng đợi.
Ví dụ
#include <dbg.hpp>
// Run to the entry point of the binary request run to(inf.startlP);
// Enable function tracing request enable func trace();
// Run the above requests run requests();


5.16.2 get_proces_state
Định nghĩa
int idaapi
get process state(void)
Chú giải
Trả về trạng thái của tiến trình dang được dò lỗi. Nếu tiến trình đã bị đóng băng, -1 sẽ được trả về, trả về 1 nếu tiến trình đang chạy hoặc 0 nếu không có tiến trình nào đang chạy trong trình gỡ rối.
Ví dụ
#include <dbg.hpp>
switch (get process state()) { case DSTATE SUSP FOR EVENT:
msg("Suspended to react to debug event.\n"); break; case DSTATE NOTASK:
msg("No process running.\n"); break; case DSTATE SUSP:
msg("Process is suspended.\n"); break; case DSTATE RUN:
msg("Process is running.\n"); break;
case DSTATE RUN WAIT ATTACH
msg("Process is running, waiting for attach.\n"); break;
case DSTATE RUN WAIT END
msg("Running, user requested kill/detach.\n"); break; default:
msg("Unknown status.\n");


5.16.3 get_process_qty
Định nghĩa
int idaapi
get process qty(void)
Chú giải
Trả về số lượng tiến trình tướng ứng với ảnh của tập tin đang được thực thi trong IDA. Hàm này cũng cần được gọi để khởi tạo ảnh tiến trình, mà sẽ được sử dụng bởi IDA để thao tác với những cấu trúc dữ liệu được dùng bởi những hàm khác liên quan đến tiến trình.
Ví dụ
#include <dbg.hpp>
msg("There are %d processes running.\n", get process qty());


5.16.4 get_process_info
Định nghĩa
pid t idaapi
get process info(int n, process info t *process info);
Chú giải
Gán vào *process_info với thông tin về tiến trình có số thứ tự n (đây không phải là định danh tiến trình PID). Định dạng của tiến trình thứ n sẽ được trả về. nếu *process_info là null, thì chỉ có PID của tiến trình được trả về.
Ví dụ
#include <dbg.hpp>
// Only get the info if a process is actually running. if (get process qty() > 0) { process info t pif;
// Populate pif
get process info(0, &pif);
msg("ID: %d, Name: %s\n", pif.pid, pif.name);
} else {
msg("No process running!\n");
}


5.16.5 start_proces *
Định nghĩa
int idaapi
start process(const char *path = NULL, const char *args = NULL, const char *sdir = NULL);
Chú giải
Bắt đầu quá trình dò lỗi của tiến trình *path với tham số truyền vào *args, trong thư mục *sdir. Nếu bất cứ tham số nào là null, chúng sẽ được lấy trong tùy chọn tiến trình được xác định trong Debugger->Process Options … Điều này giống như là khi bạn nhấn F9 trong IDA.
Ví dụ
#include <kernwin.hpp> // For askstr()
#include <dbg.hpp>
// Ask the user for arguments to supply.
char *args = askstr(HIST IDENT, "", "Arguments");
// Run the process with those arguments start process(NULL, args, NULL);


5.16.6 continue_process *
Định nghĩa
bool idaapi continue process(void)
Chú giải
Tiếp tục thực thi tiến trìh. Trả về false nếu việc tiếp tục tiến trình thất bại. Điều này tương tự như khi bạn nhấn F9 trong IDA khi một tiến trình ở trong trạng thái tạm dừng (điểm dừng được kích hoạt hoặc tạm dừng).
Ví dụ
#include <dbg.hpp>
// Continue running the process when the user // involkes this plug-in. if (continue process())
msg("Continuing process..\n");
else
msg("Failed to continue process execution.\n");


5.16.7 suspend_process *
Định nghĩa
bool idaapi suspend process(void)
Chú giải
Tạm dừng tiến trình đang được dò lỗi. Trả về false nếu quá trình tạm dừng tiến trình lỗi. Điều này giống như là khi bạn nhấn phím Pause Process trong IDA.
Ví dụ
#include <dbg.hpp>
// Suspend the process being debugged. if (suspend process())
msg("Suspended process.\n");
else
msg("Failed to suspend process.\n");


5.16.8 attach_process *
Định nghĩa
int idaapi
attach process(pid t pid=NO PROCESS, int event id=-1)
Chú giải
Attach vào tiến trình có PID là pid. Tiến trình đang được attach phải có ảnh thực thi giống như là đang được đảo mã trong IDA. Nếu tham số pid là NO_PROCCESS, người dùng sẽ được hỏi một danh sách các tiến trình có thể được attach. Mã trả về có thể là những giá trị sau, mà được lấy từ tập tin dbg.hpp
-2 không thể tìm thấy tiến trình tương ứng
-1 không thể attach vào tiến trình được chỉ định (tiến trình bị chết, quyền hạn cần không được cung cấp bởi trình gỡ rối …)
0 người dùng hủy thao tác attach vào tiến trình
1 trình gỡ rối attach vào tiến trình bình thường.
Ví dụ
#include <dbg.hpp>
// Present the user with a list of processes to // attach to. If there is no executable running that // matches what's open in IDA, no dialog box will // be presented. int err;
if ((err = attach process(NO PROCESS)) == 1)
msg("Successfully attached to process.\n");
else
msg("Unable to attach, error: %d\n", err);


5.16.9 detach_process *
Định nghĩa
bool idaapi detach process(void)
Chú giải
Detach tiến trình đang được dò lỗi. Đây có thể là tiến trình được attach hoặc chạy thông qua IDA. Trả về alse nếu nó không thể detach. Detach từ một tiến trình chỉ được hỗ trợ trong các phiên bản Windowss XP SP2 trở lên.
Ví dụ
#include <dbg.hpp>
// Detach from the debugged process. if (detach process())
msg("Successfully detached from process.\n");
else
msg("Failed to detach.\n");


5.16.10 exit_process *
Định nghĩa
bool idaapi exit process(void)
Chú giải
Kết thúc một tiến trình đang được dò lỗi. Trả về false nếu nó không thể kết thúc tiến trình.
Ví dụ
#include <dbg.hpp>
// Terminate the debugged process. if (exit process())
msg("Successfully terminated the process.\n");
else
msg("Failed to terminate the proces.\n");


5.16.11 get_thread_qty
Định nghĩa
int idaapi
get thread qty(void)
Chú giải
Trả về số lượng tiểu trình tồn tại trong tiến trình đang được dò lỗi.
Ví dụ
#include <dbg.hpp>
// Only display if there is a process being debugged. if (get process qty() > 0)


5.16.12 get_current_thread
Định nghĩa
thid t idaapi
get current thread(void)
Chú giải
Returns the ID of the currently active thread in the debugged process.
Trả về số định danh ID của tiểu trình hiện tại đang được kích hoạt bởi tiến trình được dò lỗi.
Ví dụ
#include <dbg.hpp>
// Only display if there is a process being debugged. if (get process qty() > 0)
msg("Thread ID running: %d\n", get current thread());


5.16.13 getn_thread
Định nghĩa
thid t idaapi getn thread(int n)
Chú giải
Trả về số định danh của tiểu trình ở vị trí thứ n. N nằm trong khoảng từ 0 đến số lượng tiểu trình được trả về bởi hàm get_thead_qty() - 1
Ví dụ
#include <dbg.hpp>
// Only display if there is a process being debugged. for (int i = 0; i < get thread qty(); i++) {
msg("Thread %d ID: %d \n", i, getn thread(i));
}


5.16.14 get_reg_val
Định nghĩa
bool idaapi
get reg val(const char *regname, regval t *regval)
Chú giải
Lấy giá trị chứa trong thanh ghi *regname và lưu nó trong *regval. Trả về false nếu nó không thể lấy giá trị từ thanh ghi. Tên thanh ghi phân biệt hoa thường.
Ví dụ
#include <dbg.hpp>


5.16.15 thread_get_sreg_base(member of dbg)
Định nghĩa
int idaapi
thread get sreg base(thid t tid, int sreg value, ea t *answer)
Chú giải
Với tiểu trình tid, đặt vào *answer địa chỉ cơ sở tuyến tính được trỏ bởi thanh ghi đoạn sreg. Trong một vài trường hợp, bạn sẽ cần phải sử dụng địa chỉ đoạn khi đọc thông tin về bộ nớ đang được dò lỗi (FS:0 trong Windows), mà hàm này được sử dụng
Ví dụ
#include <idd.hpp>
#include <dbg.hpp>
// x86 segment registers
char *srs[] = { "CS", "DS", "ES", "FS", "GS", "SS", 0 };
for (int i = 0; srs[i] != 0; i++) { ea t addr; regval t sreg val;
// Because it's done on a thread-by-thread basis, we // need to get the thread ID. thid t tid = get current thread();
// Fetch the segment register's value get reg val(srs[i], &sreg val);
// Get the base address
dbg->thread get sreg base(tid, sreg val.ival, &addr); msg("%s base is %a\n", srs[i], addr);
}


5.16.16 read_memory(member of dbg)
Định nghĩa
ssize t idaapi
read memory(ea t ea, void *buffer, size t size)
Chú giải
Đọc size byte từ bộ nhớ tại địa chỉ ea và đưa vào *buffer. Trả về -1 nếu lỗi.
Ví dụ
#include <dbg.hpp>
#include <idd.hpp>
ea t saddr; char chunk[1024]; int i = 0;
// Ask the user what address to dump a string from askaddr(&saddr, "Address to dump a string from");
// Read 1KB of data from that address dbg->read memory(saddr, (void *)&chunk, 1024); while (i < 1024 && chunk[i] != '\0') { msg("%c", chunk[i++]);
}
msg("\n");


5.16.17 write_memory(member of dbg)
Định nghĩa
ssize t idaapi
write memory(ea t ea, const void *buffer, size t size);
Chú giải
Ghi size byte từ buffer vào vùng nhớ tại địa chỉ ea. Trả về -1 nếu lỗi.
Ví dụ
#include <dbg.hpp>
#include <idd.hpp>
ea t saddr; char chunk[1024];
// Fill up the buffer with As memset(chunk, 'A', 1024); askaddr(&saddr, "Address to fill");
// Overwrite 1KB of memory with our 'A' buffer
int res = dbg->write memory(saddr, (void *)&chunk, 1024);
if (res <= 0) {
msg("There was an error writing to memory.");
}


5.16.18 set_reg_val*
Định nghĩa
bool idaapi
set reg val(const char *regname, const regval t *regval)
Chú giải
Đặt giá trị của thanh ghi *regname với giá trị được cho bởi *regval trong tiểu trình hiện tại. Nếu việc đọc thất bại, giá trị false được trả về. Giống như get_reg_val(), *regname có phân biệt hoa thường. Không giống như những hàm không đồng bộ, hàm này an toàn để được gọi từ cảnh báo sự kiện dò lỗi.
Ví dụ
#include <kernwin.hpp> // For get screen ea() definition #include <dbg.hpp>
// Suspend the currently executing process. suspend process();
// Continue execution from the user's cursor position. ea t addr = get screen ea(); char *regname = "EIP";
if (set reg val(regname, addr)) {
msg("Continuing execution from %a\n", addr); continue process();
}


5.16.19 invalidate_dbgmem_contents
Định nghĩa
idaman void ida export
invalidate dbgmem contents(ea t ea, asize t size)
Chú giải
Làm mất hiệu lực size byte của bộ nhớ, bắt đầu từ địa chỉ ea. Nếu bạn muốn làm mất hiệu lực toàn bộ vùng nhớ của tiến trình, đặt giá trị ea thành BADADDR và size thành 0.
Làm mất hiệu lực nội dung bộ nhớ là thiết yếu để làm tươi lại bộ đệm bộ nhớ của IDA cho tiến trình, việc làm này sẽ đảm bảo rằng bạn đang truy cập vào nội dung bộ nhớ mới nhất từ bộ nhớ của tiến trình. Bạn nên gọi hàm này sau khi một tiến trình được tạm dừng, hoặc nếu bạn xác định rằng nội dung bộ nhớ đã được thay đổi.
Ví dụ
#include <dbg.hpp>


5.16.20 invalidate_dbgmem_config
Định nghĩa
idaman void ida export invalidate dbgmem config(void)
Chú giải
Giống như hàm invalidate_dbgmem_contents(), bạn sử dụng hàm này để chắc chắn rằng IDA đang làm việc với cấu hình bộ nhớ mới nhất. Bạn cần chạy hàm này nếu tiến trình được dò lỗi đã được cấp phát hoặc cấp phát lại bộ nhớ kể từ khi nó được tạm dừng lần cuối cùng. Hàm này cũng làm tươi lại bộ đệm bộ nhớ của IDA, tuy nhiên nó chậm hơn hàm invalidate_dbgmem_contents().
Ví dụ
#include <dbg.hpp>
#include <bytes.hpp>
regval t esp;
// Get ESP before invalidate config
get reg val("ESP", &esp);
uchar before = get byte(esp.ival);
// Invalidate memory config invalidate dbgmem config();
// After invalidate uchar after = get byte(esp.ival); msg("%08a Before: %a, After: %a\n", esp.ival, before, after);


5.16.21 run_to *
Định nghĩa
bool idaapi run to(ea t ea)
Chú giải
Chạy tiến trình đến khi thực thi đến địa chỉ ea. Nếu không có tiến trình nào đang chạy, tập tin bị đảo mã hiện tại sẽ được thực thi. Trả về alse nếu nó không thể thực thi tiến trình.
Ví dụ
#include <kernwin.hpp> // For get screen ea() definition #include <dbg.hpp>
// Replicate F4 functionality if (!run to(get screen ea()))
msg("Failed to run to %a\n", get screen ea());


5.16.22 step_into *
Định nghĩa
bool idaapi step into(void)
Chú giải
Chạy một chỉ thị trong tiểu trình hiện tại của tiến trình được dò lỗi. Giống như là khi bạn nhấn F7 trong IDA. Trả về false nếu nó không thể nhảy vào chỉ thị.
Ví dụ
#include <dbg.hpp>
// Go to the entry point (queued) request run to(inf.startlP);
// Run 20 instructions (queued) for (int i = 0; i < 20; i ++) request step into();
// Run through the queue run requests();


5.168.23 step_over *
Định nghĩa
bool idaapi step over(void)
Chú giải
Chạy một chỉ thị trong tiểu trình của tiến trình đang được dò lỗi, nhưng không nảy vào hàm, xem hàm đó như là một chỉ thị. Giống như chức năng F8 trong IDA. Trả về false nếu nó không thể nhảy qua chỉ thị.
Ví dụ
#include <dbg.hpp>
// This can only run when the process is suspended
// Step over 5 instructions. This needs to be done as // a request, otherwise only one step will execute. for (int i = 0; i < 5; i ++) request step over(); run requests();


5.16.24 step_until_ret *
Định nghĩa
bool idaapi
step until ret(void)
Chú giải
Thực thi mỗi chỉ thị trong tiểu trình hiện tại của tiến trình đang được dò lỗi cho đến khi hàm hiện tại được trả về. Hàm này giống chức năng của CTRL + F7 trong IDA
Ví dụ
#include <dbg.hpp>

No comments: