Wednesday 26 February 2014

Xây dựng trình cắm cho IDA Pro (Phần 4)

Phần 1:
http://vcyberwarface.blogspot.com/2014/02/xay-dung-trinh-cam-cho-ida-pro-phan-1.html
Phần 2:
http://vcyberwarface.blogspot.com/2014/02/xay-dung-trinh-cam-cho-ida-pro-phan-2.html
Phần 3:
http://vcyberwarface.blogspot.com/2014/02/xay-dung-trinh-cam-cho-ida-pro-phan-3.html


4. Cơ bản

Có nhiều lớp, cấu trúc dữ liệu và kiểu khác nhau trong IDA SDK, một số được sử dụng nhiều hơn những thứ khác. Mục tiêu của phần này là sẽ giới thiệu bạn với những phần đó, vì chúng cung cấp một cái nhìn sâu hơn vào những gì mà IDA biết về tập tin disassemle, và có thể đưa ra những ý tưởng về những khả năng mà bạn có thể sử dụng với SDK.

Một vài lớp và cấu trúc có kích thước quá lớn, với nhiều biến thành viên và phương thức/hàm. Trong phần này, hầu hết các biến sẽ được mô tả, những phương thức sẽ được mô tả trong Chương 5 – Hàm. Một vài đoạn chú thích mã ở bên dưới được lấy trực tiếp từ IDA SDK, một vài là do tôi chú thích, và một số khác thì kết hợp cả hai. Những chỉ thị tiền xử lý #define, trong một vài trường hợp, được sử dụng bên cạnh nhiều biến thành viên, giống như cách mà nó được dùng trong SDK. Tôi đặt những phần đó ở đây, bởi vì nó mô tả một cách rõ ràng những giá trị hợp lệ mà những biến thành viên có thể có.

Chú ý quan trọng về mã ví dụ: Mã từ bất kỳ phần ví dụ nào của phần này nên được đặt trong hàm iDAP_run() ở khuôn mẫu 3.5, trừ khi nó có mục đích khác.

4.1 Những kiểu dữ liệu cơ sở
Những kiểu sau được sử dụng qua suốt SDK trong tài liệu này, bởi vậy, điều quan trọng là bạn phải nhận ra được nó khi nó được sử dụng.

Tất cả những kiểu bên dưới đều thuộc kiểu nguyên dài không dấu (unsigned long), và kiểu nguyên dài trong hệ thống 64bit. Chúng được định nghĩa trong pro.h.

Kiểu
Mô tả
ea_t
Viết tắt của ‘Effective Address’, và mô tả hầu như tất cả địa chỉ nào trong IDA (bộ nhớ, tập tin, limits, vvv)
sel_t
Chọn lọc phân đoạn, như trong mã, ngăn xếp và đoạn dữ liệu.
uval_t
Dùng để đại diện cho một giá trị không dấu.
asize_t
Hầu hết được dùng để đại diện cho kích cỡ một thứ gì đó, thường là một đoạn của bộ nhớ.

Những kiểu dữ liệu tiếp theo là những kiểu nguyên có dấu, và kiểu nguyên dài có dấu trong nền tảng 64bit. Chúng được định nghĩa trong tập tin pro.h

Kiểu
Mô tả
sval_t
Dùng để đại diện cho giá trị có dấu
adiff_t
Dùng để đại diện cho sự khác biệt giữa hai địa chỉ.

Cuối cùng, có một số hằng số cần phải được chú ý; một trong số đó là BADADDR, nó đại diện cho một địa chỉ không hợp lệ hoặc không tồn tại, bạn sẽ thấy nó được sử dụng trong vòng lặp để dò tìm phần kết của một khoảng địa chỉ đọc được hoặc một cấu trúc. Bạn cũng sẽ bắt gặp MAXSTR được sử dụng trong định nghĩa bộ đệm ký tự, có giá trị 1024.

4.2 Những cấu trúc và lớp cơ sở

4.2.1 Siêu thông tin

struct idainfo
{
  char          tag[3];                        // 'IDA'
  ushort        version;                    // Version of database
  char          procName[8];            // Name of current processor
  void set_proc_name(const char *name)
  {
    size_t len = strlen(name) + 1;
    memcpy(procName, name, qmin(len, sizeof(procName)));
  }
  char *get_proc_name(char *buf) const
  {
    buf[0] = procName[0];
    buf[1] = procName[1];
    buf[2] = procName[2];
    buf[3] = procName[3];
    buf[4] = procName[4];
    buf[5] = procName[5];
    buf[6] = procName[6];
    buf[7] = procName[7];
    buf[8] = '\0';
    return buf;
  }

  uchar         lflags;                 // Misc. flags
…………
};

Cấu trúc idainfo, được lưu trữ vật lý trong tập tin cơ sở dữ liệu của IDA (IDB), lưu giữ những gì mà tôi sẽ xem như là những ‘siêu thông tin’ về việc khởi tạo cho tập tin được nạp vào IDA. Nó không thay đổi nếu nhiều tập tin được nạp. Đây là một vài phần hấp dẫn của nó, như được định nghĩa trong ida.hpp:

inf là một thực thể có thể truy cập toàn cục của cấu trúc này. Bạn sẽ thường thấy những kiểm tra đối với inf.procName trong hàm khởi tạo của plugins, kiểm tra kiến trúc máy mà plugins được viết để làm việc.
Ví dụ, nếu bạn viết một plugins chỉ làm việc với loại tập tin nhị phân dạng PE và ELF cho kiến trúc x86, bạn có thể thêm vào những dòng sau vào phần khởi tạo của plugin (iDAP_init từ khuôn mẫu plugin của chúng ta ở mục 3.5).

// “metapc” đại diện cho kiến trúc x86
if (strncmp(inf.procName, "metapc", 8) != 0
            || inf.filetype != f_ELF && inf.filetype != f_PE))
{
            error("Only PE and ELF binary type compiled"
             "for the x86 platform is supported, sorry.");
            return PLUGIN SKIP;
            // Trả về PLUGIN_SKIP có nghĩa rằng plugin này
            // sẽ không được nạp
}
return PLUGIN KEEP; // Cho phép plugin tiếp tục nạp


F_ELF và f_PE là hai phần tử trong kiểu liệt kê filetype_t được định nghĩa trong tập tin tiêu đề ida.hpp.
4.2.2 Vùng

Trước khi đi vào chi tiết trong những cấu trúc lớp ở mức cao hơn để làm việc với đoạn, hàm và các chỉ thị, chúng ta hãy xem xét hai khái niệm nòng cốt; tên vùng và khối điều khiển vùng.

4.2.2.1 Cấu trúc area_t

Một vùng được đại diện bằng một cấu trúc area_t, được định nghĩa trong tập tin tiêu đề area.hpp. Dựa vào những ghi chú trong tập tin này, ta có thể nói một cách cụ thể:
“Vùng” bao gồm nhiều vùng con thuộc kiểu  area_t. Một vùng là một khoảng không rỗng bao gồm những địa chỉ tuyến tính (được xác định bởi địa chỉ bắt đầu và địa chỉ kết thúc, địa chỉ kết thúc không được chỉ rõ trong vùng) với những thuộc tính của nó.Ví dụ, một đoạn là một tập của các vùng.

Bạn có thể thấy phần khai báo bên dưới được lấy từ định nghĩa area_t, một vùng được định nghĩa bởi địa chỉ bắt đầu (startEA) và địa chỉ kết thúc (endEA) – địa chỉ này thường bị bỏ qua. Cùng một loạt các phương thức để kiểm tra nếu một vùng có chứa một địa chỉ cụ thể hay không, kiểm tra vùng rỗng, và cho biết kích thước của vùng. Một đoạn là một vùng, nhưng một  hàm cũng là một vùng, điều đó có nghĩa là nhiều vùng có thể lồng nhau.

struct area_t
{
            ............
  ea_t startEA;
  ea_t endEA;                  // endEA bị bỏ qua
  area_t(void) {}
  area_t(ea_t ea1, ea_t ea2) : startEA(ea1), endEA(ea2) {}
            ............
};


Theo cách nói kỹ thuật, nói rằng hàm và phân đoạn là vùng, là nói rằng lớp func_t và segment_t được mở rộng từ lớp area_t. Điều này có nghĩa rằng tất cả các biến và hàm trong cấu trúc area_t đều có thể được sử dụng bởi func_t và segment_t (ví dụ, segment_t.startEA và func_t.contains() đều hợp lệ). func_t và segment_t thêm vào area_t với những biến và hàm riêng biệt của chúng. Chúng sẽ được trình bày sau.
Một vài lớp được mở rộng từ lớp area_t như ở bên dưới:

Kiểu (tập tin)
Mô tả
hidden_area_t (bytes.hpp)
Vùng ẩn là nơi mà mã/dữ liệu được thay thế và tóm gọn bởi mô tả có thể được mở rộng để xem những thông tin ẩn.
regvar_t (frame.hpp)
Những tên thanh ghi được thay thế bởi những tên định nghĩa bởi người dùng (biến thanh ghi)
memory_info_t (idd.hpp)
Một khối bộ nhớ (khi sử dụng trình dò lỗi)
segreg_t (srarea.hpp)
Thông tin về thanh ghi đoạn (CS, SS, vv, trên nền x86)

4.2.2.2 Lớp areacb_t

Một khối điều khiển vùng (Area Control Block)  được đại diện bằng lớp areacb_t, và được định nghĩa trong tập tin area.h. Chú thích cho nó, như được trình bày bên dưới, có rất ít thông tin, nhưng không thật sự cần thiết:

“areacb_t” là một lớp cơ sở được sử dụng trong nhiều phần của IDA
Để mở rộng định nghĩa này; lớp này chỉ đơn giản là một tập hợp các phương thức được sử dụng để thao tác với vùng. Những phương thức này bao gồm get_area_qty(), get_next_area() và một số khác. Hầu như bạn sẽ không sử dụng những phương thức này một cách trực tiếp, khi bạn làm việc với những ví dụ, bạn sẽ sử dụng nhiều các phương thức của các lớp dẫn xuất như func_t và segment_t, và đây nguyên tắc chung được áp dụng cho những lớp được mở rộng từ area_t.

Có hai thực thể toàn cục của lớp areacb_t, tên là segs (được định nghĩa trong segment.hpp) và funcs (được định nghĩa trong funcs.hpp), mà nó đại diện cho tất cả các phân đoạn và hàm, tương ứng với tập tin bị đảo mã hiện tại. Bạn có thể thực thi đoạn mã sau để liệt kê số lượng phân đoạn và hàm trong tập tin đang bị đảo mã được mở bởi IDA (nhớ rằng đầy không phải là đoạn mã độc lập, nó phải được đặt trong iDAP_run):

#include <segment.hpp>
#include <funcs.hpp>
msg("Segments: %d, Functions: %d\n", segs.get_area_qty(),
            funcs.get_area_qty());



(Còn tiếp)

No comments: