18/09/2018, 15:09

PHÁT HIỆN CẤU TRÚC CODE C TRONG HỢP NGỮ PHẦN 3

Kết thúc chuỗi chủ đề về Phát hiện cấu trúc Code C trong hợp ngữ chuyên gia an ninh mạng Nguyễn Việt Anh sẽ gửi đến bạn đọc những phân tích: Các quy ước gọi hàm, cdecl, stdcall, fastcall, Phân tích code hướng đối tượng trong hợp ngữ, Các phương thức, Các hàm mã hóa, giải mã trong hợp ngữ… ...

Kết thúc chuỗi chủ đề về Phát hiện cấu trúc Code C trong hợp ngữ chuyên gia an ninh mạng Nguyễn Việt Anh sẽ gửi đến bạn đọc những phân tích: Các quy ước gọi hàm, cdecl, stdcall, fastcall, Phân tích code hướng đối tượng trong hợp ngữ, Các phương thức, Các hàm mã hóa, giải mã trong hợp ngữ…

Các lời gọi hàm có thể xuất hiện theo những cách khác nhau trong hợp ngữ, quy ước gọi hàm quản lý cách thức lời gọi hàm xảy ra. Các quy ước này bao gồm thứ tự sắp xếp các tham số trong stack hoặc các thanh ghi, và liệu hàm gọi đến hàm được gọi có trách nhiệm dọn dẹp stack khi hàm được gọi hoàn tất thực thi hay không.

Sử dụng giả mã trong Code 10 để mô tả từng quy ước gọi hàm.

Code 10: Giả mã cho một lời gọi hàm

Code 10: Giả mã cho một lời gọi hàm

Ba quy ước gọi hàm phổ biến nhất ta có thể bắt gặp là cdecl, stdcall fastcall. Một quy ước cũng có thể được triển khai theo các cách khác nhau theo từng trình biên dịch.

XEM PHẦN 1 CỦA CHỦ ĐỀ PHÁT HIỆN CẤU TRÚC CODE C TRONG HỢP NGỮ TẠI ĐÂY

cdecl

cdecl là một trong các quy ước phổ biến nhất. Trong cdecl, các tham số được push vào stack từ phải sang trái, hàm gọi đến chịu trách nhiệm dọn dẹp stack khi hàm được gọi hoàn tất thực thi, và giá trị trả về được lưu trong EAX.

Code 11 thể hiện hợp ngữ được biên dịch từ Code 10 sử dụng cdecl.

Code 11: Lời gọi hàm cdecl

Code 11: Lời gọi hàm cdecl

Chú ý đến dòng 0x4015B5, stack được dọn dẹp bởi hàm gọi đến, tương đương với lệnh pop lần lượt 3 biến a, b, c khỏi stack. Trong ví dụ này, các tham số được push vào stack từ phải sang trái, bắt đầu bằng c (ecx).

stdcall

Quy ước phổ biến stdcall cũng tương tự cdecl, ngoại trừ việc stdcall không yêu cầu hàm gọi dọn dẹp stack khi hàm thực hiện xong. Vì thế, lệnh add bôi đậm trong Code 11 sẽ không cần thiết nếu ta sử dụng quy ước stdcall, hàm được gọi sẽ đảm nhiệm dọn dẹp stack.

Hàm test trong Code 10 sẽ được biên dịch theo cách khác với stdcall vì nó phải quan tâm đến việc dọn dẹp stack. Kết thúc hàm (epilogue) sẽ là cần thiết để thực hiện dọn dẹp.

stdcall là quy ước gọi hàm chuẩn đối với Windows API. Bất kì code nào gọi đến các hàm API sẽ không cần phải dọn dẹp stack vì đó là nhiệm vụ của các DLL triển khai code cho hàm API.

fastcall

Trong fastcall, một số đối số đầu tiên (thường là 2) được truyền vào các thanh ghi, với các thanh ghi được dùng phổ biến nhất là EDX và ECX (theo quy ước fastcall của Microsoft). Các đối số khác được tải từ phải sang trái, và hàm gọi thường đảm nhiệm dọn dẹp stack nếu cần. Dùng fastcall thường hiệu quả hơn là dùng các quy ước khác vì code không cần liên quan nhiều đến stack.

https://en.wikibooks.org/wiki/X86_Disassembly/Calling_Conventions

Phân tích code hướng đối tượng trong hợp ngữ

Các lớp (Class)

Một lớp cơ bản không có kế thừa có thể chia thành 2 thành phần – các biến và các phương thức. Các biến không phải là biến tĩnh có thể coi như một cấu trúc dữ liệu và các phương thức thì có thể xem như các hàm  bình thường. Khi xuất hiện kế thừa và đa hình, mọi thứ nhìn sẽ phức tạp hơn một chút.

Các biến

Mọi biến tĩnh được định nghĩa trong lớp sẽ nằm trên các vùng nhớ không đổi trên bộ nhớ xuyên suốt toàn bộ chương trình. Tất cả các biến khác loại này được đặt trong một cấu trúc dữ liệu gọi là đối tượng (object). Thường thì khi hàm khởi tạo (constructor) được gọi, các biến sẽ được đặt trong đối tượng một cách tuần tự (dòng 0x402DE8 – 0x402E01).

code

Code 12: Các biến của một đối tượng trong C++ và hợp ngữ tương ứng

Code 12: Các biến của một đối tượng trong C++ và hợp ngữ tương ứng

Để có thể truy cập bởi chương trình chính, các biến cần có một con trỏ đối tượng để trỏ tới vị trí của chúng. Trong ví dụ này, arg_0 được dùng để trỏ tới địa chỉ offset của các biến đối tượng.

Các phương thức

Ở ngôn ngữ bậc thấp, hầu như không có khác biệt giữa hàm và phương thức nên khi dịch ngược, chúng ta thường khó có thể phân biệt chúng. Cả hai đều nằm trong không gian nhớ của phần text và đều được gọi bởi cùng một cách thức.

13.1

Code 13: Các phương thức của lớp Rectangle và cách chúng được gọi bởi hàm main trong C++ và hợp ngữ tương ứng.

Code 13: Các phương thức của lớp Rectangle và cách chúng được gọi bởi hàm main trong C++ và hợp ngữ tương ứng.

Các hàm mã hóa, giải mã trong hợp ngữ

Xor

Lệnh xor trong hợp ngữ thực hiện phép tính XOR mức vật lý, tương đương với toán tử “^” trong C và Python. Cú pháp lệnh như sau:

xor destination, value

Giá trị các cờ OF và CF bị xóa sau mỗi lệnh xor, giá trị các cờ SF, ZF và PF được set tùy theo kết quả phép XOR.

Để giải mã XOR, ta cần có giá trị phép XOR và một trong hai toán hạng XOR ban đầu. Code 14 mô tả một phép mã hóa XOR và một phép giải mã XOR ngay sau đó.

code 14

Code 14: Mã hóa và giải mã XOR trong C và hợp ngữ tương ứng

Code 14: Mã hóa và giải mã XOR trong C và hợp ngữ tương ứng

Các hàm mã hóa khác: Base64, MD5, SHA-1, SHA-256…

Sử dụng plugin FindCrypt cho IDA Pro. Hầu hết các thuật toán mã hóa đều sử dụng một hằng số đặc trưng (magic constant, magic number), FindCrypt dựa vào các số đặc trưng đó để tìm kiếm những đoạn code nghi ngờ là hàm mã hóa hoặc hàm băm. FindCrypt có thể hỗ trợ tìm kiếm dấu hiệu của các hàm mã hóa sau:

Blowfish

Camellia

CAST

CAST256

CRC32

DES

GOST

HAVAL

MARS

MD2

MD4

MD5

PKCS_MD2 (byte sequence used in PKCS envelope)

PKCS_MD5 (byte sequence used in PKCS envelope)

PKCS_RIPEMD160 (byte sequence used in PKCS envelope)

PKCS_SHA256 (byte sequence used in PKCS envelope)

PKCS_SHA384 (byte sequence used in PKCS envelope)

PKCS_SHA512 (byte sequence used in PKCS envelope)

PKCS_Tiger (byte sequence used in PKCS envelope)

RawDES

RC2

RC5

RC6

Rijndael

SAFER

SHA-1

SHA-256

SHA-512

SHARK

SKIPJACK

Square

Tiger

Twofish

WAKE

Whirlpool

zlib

Kết quả tìm kiếm được thể hiện qua cửa sổ thông báo của IDA Pro,

code 15

Từ vị trí của số đặc trưng, ta có thể sử dụng tham chiếu chéo của IDA Pro để tìm ra hàm nào đã gọi đến hàm mã hóa và có thể khóa giải mã sẽ nằm gần đó.

Theo chuyên gia Nguyễn Việt Anh.

0