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.
Ba quy ước gọi hàm phổ biến nhất ta có thể bắt gặp là cdecl, stdcall và 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.
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).
Để 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.
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 đó.
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,
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.