REVERSING WITH IDA FROM SCRATCH (P2)

Lời tựa

Như tôi đã đề cập ở phần 1, mục tiêu của bộ tutorial này là dành cho những người mới bắt đầu, do vậy có những kiến thức mà có thể nhiều bạn đã biết rồi. Bạn có thể bỏ qua nếu muốn, nhưng đối với đa số những người chưa biết, những kiến thức này sẽ rất quan trọng và đó là lý do tại sao tôi vẫn dành thời gian để hệ thống hóa lại những kiến thức cơ bản này.

Hệ thống số

Ba hệ thống số học được sử dụng nhiều nhất là số nhị phân, thập phân và thập lục phân.

Các khái niệm cơ bản của từng hệ thống số học này như sau:

BINARY (Số nhị phân): các số được biểu diễn bằng hai chữ số là 0 và 1, đó là lý do tại sao nó được gọi là nhị phân. Máy tính chỉ hiểu được số nhị phân.

DECIMAL (Số thập phân): các số được biểu diễn bằng 10 chữ số (từ 0 đến 9), đó là lý do tại sao nó được gọi là số thập phân. Con người chúng ta từ lúc sinh ra mặc định sẽ được làm quen với hệ thống số này.

HEXADECIMAL (Số thập lục phân): Tất cả các số được biểu diễn với các kí tự từ 0 đến F (từ 0 đến 9, cộng với A, B, C, D, E và F (không phân biệt chữ hoa và chữ thường), có nghĩa là sẽ có tổng cộng 16 kí tự). Trong đó: A = 10, B = 11, C = 12, D = 13, E = 14, F = 15.

Bên lề: Hệ nhị phân là cách mà một máy tính “hiểu” và “hành xử”, nhưng với con người thì nó thực sự rất bất tiện. Nó tốn quá nhiều chữ số để biểu diễn cho một số, dẫn đến khó viết và khó ghi nhớ. Chính vì lý do này, chúng ta mới cần đến hệ thập lục phân để khắc phục những vấn đề đó. Khi tìm hiểu về reversing/cracking và kể cả khi xây dựng mã khai thác (exploits), các bạn sẽ liên tục phải làm việc với các giá trị hexa, chính vì thế các bạn cần phải nắm vững nó.

Quan sát tại giao diện của IDA, nếu như bạn đã cài đặt chuẩn thì ở dưới cùng sẽ thấy có một thanh dùng để thực hiện các câu lệnh Python. Điều này sẽ hỗ trợ chúng ta chuyển đổi giữa các hệ số một cách rất dễ dàng:

Nếu tôi gõ, ví dụ 0x45, giá trị này được diễn giải như là một số thập lục phân bởi vì có tiền tố 0x ở phía trước. Chúng ta có thể chuyển đổi từ thập lục phân sang thập phân chỉ bằng cách nhấn Enter.

Kết quả có được là:

Ta nhận được số 69, đó chính là 0x45 ở hệ thập lục phân chuyển đổi sang hệ thập phân. Nếu muốn chuyển đổi ngược lại, chúng ta phải sử dụng hàm hex():

Để chuyển đổi sang hệ nhị phân ta sử dụng bin():


Kết quả có được là 1000101, tiền tố 0b ở đằng trước có nghĩa đây là số nhị phân. Chúng ta cũng có thể chuyển đổi từ hệ nhị phân sang thập phân hoặc thập lục phân.

Qua đây có thể thấy, bất kỳ số nào ta nhập trực tiếp vào thanh Python, sau khi nhấn Enter sẽ hiển thị kết quả ở hệ thập phân, để chuyển nó sang hệ Hexa hoặc Binary tương ứng, chúng ta phải sử dụng các hàm hex() hoặc bin() của Python.

Số âm trong hệ thập lục phân

Hầu như chúng ta sẽ làm việc nhiều ở hệ thập lục phân, nhưng câu hỏi đặt ra là làm thế nào để biểu diễn một số âm (32 bit) ở hệ thập lục phân? Khi các bạn học về lập trình, các bạn được học về số nguyên (integer). Để thông báo cho máy tính biết các bạn sử dụng số âm thì các bạn sẽ khai báo kiểu biến là signed integer. Lúc này, phía máy tính, nó cần phải có một phương thức để biểu diễn cho các số âm. Nếu máy tính được yêu cầu biểu diễn số âm thì sẽ nó bỏ qua bit có trọng số cao nhất (MSB) – tức là bit đầu tiên và xem bit này như là bit dấu. Nếu bit dấu là 0 đó là số dương, ngược lại nếu là 1 thì đó là số âm.

Tóm lại, với một số nhị phân 32 bit, người ta quy định sử dụng bit đầu tiên để biểu diễn dấu của số, là 0 thì đó là số dương và ngược lại, là 1 thì đó là số âm. Ví dụ:

Chúng ta thấy rằng giá trị -0x45 ở hệ thập lục phân có thể được biểu diễn là 0xffffffbb và bit đầu tiên của nó ở hệ nhị phân là 1. Bằng cách này, số dương nhỏ nhất rõ ràng là 0 nhưng số dương lớn nhất mà chúng ta có thể biểu diễn là bao nhiêu?

Chúng ta thấy rằng 0x7fffffff sẽ là số dương lớn nhất nếu ta quan tâm tới bit dấu. Nếu cộng thêm 1 vào giá trị này:

Khi đó, bit đầu tiên thay đổi thành 1 và tất cả các bit còn lại là 0. Vấn đề là trình Calculator của IDA xem xét tất cả các số đều là số dương trừ khi chúng ta thêm dấu ““ vào trước số, ví dụ:

Như vậy, giá trị âm lớn nhất là -1 tương ứng với 0xFFFFFFFF và giá trị âm nhỏ nhất sẽ là 0x80000000. Trường hợp, ta không quan tâm đến dấu, thì tất cả các giá trị sẽ là số dương nằm trong khoảng từ 0 đến 0xFFFFFFFF.

Còn nếu xem xét đến sử dụng bit dấu, chúng ta sẽ có các số dương nằm trong khoảng từ 0x0 đến 0x7FFFFFFF và các số âm nằm trong khoảng từ 0xFFFFFFFF đến 0x80000000.

Số dương

000000000 bằng 0

000000001 bằng 1

…………………………

…………………………

7FFFFFFF bằng 2147483647 thập phân (sẽ là số dương lớn nhất)

Số âm

FFFFFFFF bằng -1

FFFFFFFE bằng -2

…………………………

…………………………

80000000 bằng -2147483648 (sẽ là số âm nhỏ nhất)

Bảng mã ASCII

Một trong những vấn đề nữa mà chúng ta cần phải biết là cách mà hệ thống in/hiển thị dữ liệu trên màn hình, mỗi kí tự được gán tương ứng với một giá trị thập lục phân để biểu diễn chúng là các chữ cái, chữ số, hay biểu tượng, v.v …

Quan sát bảng ở bên dưới, chúng ta có cột đầu tiên là các giá trị thập phân, cột thứ hai là các giá trị thập lục phân và cột thứ ba biểu diễn các kí tự tương ứng. Lấy ví dụ, nếu tôi muốn viết một khoảng trống, tôi phải sử dụng 0x20 hoặc 32 ở hệ thập phân. Do đó, để biểu diễn bất kỳ kí tự nào mà chúng ta cần là số hay chữ cái, ta có thể sử dụng bảng mã này, và nó được gọi là bảng mã ASCII (American Standard Code for Information Interchange). Bảng mã ASCII được đùng để hiển thị văn bản trong máy tính và các thiết bị thông tin khác, nó cũng được dùng bởi các thiết bị điều khiển làm việc với văn bản.

Tại IDA calculator, nó sẽ xem xét các biểu thức và hiển thị các kí tự tương ứng như chúng ta đã thấy trong trường hợp 0x45 là kí tự E.

Một cách khác để chuyển đổi là sử dụng hàm chr() của Python:

Trong cửa sổ Hex Dump của IDA chúng ta cũng có một cột để hiển thị các kí tự tương ứng:

Như trên hình, chúng ta thấy 45 được biểu diễn là chữ E.

Chức năng tìm kiếm trong IDA

Các bạn để ý sẽ thấy có tùy chọn Search trên menu của IDA và nếu ở màn hình disassembly hoặc tab IDA – View, IDA sẽ cung cấp cho chúng ta nhiều lựa chọn tìm kiếm rất dễ hiểu. Khi chuyển sang các tab khác (trừ tab Hex-View) thì các tùy chọn của Search sẽ được lược bớt.

Các tùy chọn được hiển thị trong hình dưới đây có thể sẽ khác trên máy của các bạn, bởi bản IDA của tôi có bổ sung thêm một số plugin.

Next Code

Tùy chọn này sẽ tìm kiếm lệnh kế tiếp đã được hiểu là Code. Nếu như không được nhận diện là Code, nó sẽ bỏ qua.

Next Data

Tùy chọn này sẽ tìm kiếm các địa chỉ tiếp theo, nơi được IDA hiểu là Data (đã được định nghĩa) hoặc là xử lý dữ liệu tại bất kỳ section nào.

Như trong trường hợp trên, IDA phát hiện một dword (dd) tại địa chỉ không tương ứng với bất kỳ lệnh nào, rõ ràng là, nếu chúng ta tiếp tục tìm kiếm, nó sẽ tìm kiếm dữ liệu tiếp theo. Ví dụ, quan sát phần dữ liệu bên dưới khi tôi thực hiện tìm kiếm một lần nữa:

IDA dừng ở địa chỉ 00402004, tại đó thông tin ở bên phải hàm ý rằng đó là nơi mà bạn sẽ làm việc với dữ liệu, thuộc section DATA. IDA sẽ bỏ qua các địa chỉ chỉ chứa số 0, không có bất kỳ tham chiếu nào. Tóm lại, IDA chỉ tìm kiếm những dữ liệu mà chương trình có thể sử dụng tới.

Search completed. Found at 00402004.

Search completed. Found at 00402048.

Search Explored và Unexplored

Tính năng đầu tiên sẽ tìm code hoặc data đã được định nghĩa (lệnh hoặc dữ liệu) và tính năng thứ hai áp dụng với các vùng không được phát hiện là lệnh hoặc dữ liệu hợp lệ:

Khu vực với các giá trị 0 tại 0x402000 được tìm thấy với tính năng Search Unexplored.

Search completed. Found at 00402000.

Search completed. Found at 00402000.

Search completed. Found at 00402001.

Search completed. Found at 00402001.

Search completed. Found at 00402002.

Search completed. Found at 00402003.

Search completed. Found at 00402008.

Lặp lại việc tìm kiếm này, chúng ta thấy rằng nó bỏ qua dữ liệu tại 0x402004 vì dữ liệu đó được coi là Explored.

Search Immediate Value – Search Next Immediate Value

Lệnh này tìm kiếm lệnh đầu tiên hoặc byte dữ liệu có chứa giá trị hằng số được chỉ định. Quá trình tìm kiếm tương đối chậm (nhưng nhanh hơn nhiều so với tìm kiếm text):

Nếu chọn Find all occurrences, IDA sẽ tìm tất cả. Còn nếu không chọn, IDA sẽ tìm kiếm từng lần một, với trường hợp này, để lặp lại việc tìm kiếm, ta sẽ sử dụng Search next immediate value.

Search Text – Search Next Text

Tìm kiếm các chuỗi mà chúng ta nhập vào, bao gồm cả biểu thức chính quy nếu chúng ta muốn.

Nếu chúng ta chỉ tìm kiếm một lần, để tìm tiếp thì sử dụng Search Next Text.

Search Sequence Of Bytes

Tùy chọn này cho phép ta tìm kiếm các chuỗi các bytes ở hệ thập lục phân:

Nếu nhấp đúp vào kết quả đầu tiên và tại tùy chọn của IDA, ta thiết lập giá trị 6 tại Number of opcode bytes để hiển thị tối đa 6 bytes tương ứng với mỗi lệnh.

Kết quả IDA sẽ hiển thị opcode 90 90 mà ta đã yêu cầu tìm kiếm:

Search Not Function

Chức năng này cho phép tìm kiếm byte đầu tiên không thuộc về bất kỳ hàm nào:

Search completed. Found at 004013D7.

Trên hình, ta thấy có một lệnh RET đứng độc lập, như vậy nó không thuộc bất kỳ một hàm nào. Đôi khi có những hàm mà IDA không thể xác định đó là hàm nhưng chúng lại có các lệnh hợp lệ.

Trên đây, các bạn đã tìm hiểu những chức năng tìm kiếm quan trọng nhất mà IDA cung cấp thông qua Search menu, tất nhiên, bên cạnh đó IDA còn hỗ trợ khả năng xử lý các Python script, từ đó bạn có thể thực hiện nhiều tác vụ hơn.

Tôi sẽ cố gắng đi thật chậm, từng bước một, không vội vã để các đều có thể dễ dàng hiểu và nắm bắt được.

Phần 2 đến đây kết thúc. Hẹn các bạn trong phần 3!

m4n0w4r

Xin gửi lời cảm ơn chân thành tới thầy Ricardo Narvaja!

Ủng hộ tác giả

Nếu bạn cảm thấy những gì tôi chia sẻ trong bài viết là hữu ích, bạn có thể ủng hộ bằng “bỉm sữa” hoặc “quân huy” qua địa chỉ:

Tên tài khoản: TRAN TRUNG KIEN
Số tài khoản: 0021001560963
Ngân hàng: Vietcombank

6 thoughts on “REVERSING WITH IDA FROM SCRATCH (P2)

  1. Cái chỗ biểu diễn số âm, mình nghĩ là nên giải thích ký pháp bù 2, thì mới rõ việc convert số âm qua biểu diễn nhị phân hoặc ngược lại.

      1. Chào a! e mới bắt đầu nhập môn, a có thể chỉ cho e nên bắt đầu học từ đâu ko ạ? và a cho e xin link tải của các bộ tài liệu a đã viết.E cảm ơn a!

  2. a ơi, a có thể giải thích cho e hiểu rõ hơn chỗ này được không?
    a có nói là “số dương nhỏ nhất rõ ràng là 0”.
    e tưởng số dương nhỏ nhất là 1 chứ???????

  3. a giải thích giùm e chỗ này với:
    “Như vậy, giá trị âm nhỏ nhất là -1 tương ứng với 0xFFFFFFFF và giá trị âm lớn nhất sẽ là 0x80000000”.
    Giá trị âm lớn nhất là trừ 1 chứ?????????????????

    1. @Khánh: OK em, anh đã điều chỉnh lại phần số âm lớn nhất và nhỏ nhất trong bài viết.
      Còn về phần số dương liên quan đến cách biểu diễn số nguyên trong máy tính. Do phần cứng máy tính cần giới hạn kích thước của các số để có thể lưu nó trong các thanh ghi hay trong ô nhớ. Như anh đề cập, số nguyên có dấu thì có thể là số dương hoặc âm. Bit MSB sẽ quyết định điều này, MSB =1 biểu diễn số âm; MSB = 0 biểu diễn số dương. Các số âm được lưu trữ trong máy tính dưới dạng số bủ 2 (đảo bit và + 1).

      Ví dụ với số 8bit cho dễ hình dung: biểu diễn số -5.
      Ta có 5 ở dạng nhị phân: 0000 0101
      Đảo bit : 1111 1010
      + 1 : 1111 1011 (Bù hai)

      Khi ta cộng 5 với số bù 2 của nó:
      0000 0101
      + 1111 1011
      ————-
      ‭1 0000 0000‬

      Ta nhận được số có độ lớn 9 bit nhưng ta đang làm việc ở chế độ chỉ lưu được 8 bit, nên bit có giá trị 1 ở vị trí cao nhất sẽ bị cắt bỏ, ta chỉ còn lại 8 bit bằng 0. Như vậy, tổng của 5 và số bù hai của nó cho ta kết quả bằng 0. Từ đó suy ra, số bù 2 của 5 rõ ràng bieur diễn giá trị của -5.

      Vậy với 8 bit để biểu diễn số ta có:
      0000 0000 số hệ 10: 0 số hệ mười theo mã hệ hai có dấu: +0 số hệ mười theo bù 2: +0

      0111 1111 số hệ 10: 127 số hệ mười theo mã hệ hai có dấu: +127 số hệ mười theo bù 2: -127

      1000 0000 số hệ 10: 128 số hệ mười theo mã hệ hai có dấu: -0 số hệ mười theo bù 2= -128

Leave a Reply