Phương pháp phân tích tĩnh
Hôm nay chúng ta sẽ tìm hiểu về phân tích mã độc với phương pháp phân tích tĩnh (static analysis), đây thường được xem làm bước làm đầu tiên trong việc nghiên cứu các phần mềm độc hại. Phân tích tĩnh mô tả quá trình phân tích mã hoặc cấu trúc của một chương trình để từ đó xác định chức năng của chương trình đó. Tại thời điểm phân tích tĩnh này, chương trình được xem là không hoạt động. Ngược lại, trong quá trình phân tích động mã độc, các nhà phân tích sẽ phải thực sự chạy các chương trình mã độc này trong môi trường thử nghiệm, vấn đề này chúng ta sẽ đề cập đến trong bài viết về phương pháp phân tích mã độc động (Dynamic analysis).
Trong bài viết này, chúng ta sẽ thảo luận cùng nhau về nhiều cách thức trích xuất thông tin hữu ích từ các tập tin thực thi (executables). Ngoài ra, chúng ta cũng sẽ tìm hiểu một số kỹ thuật như sau:
- Sử dụng các công cụ Antivirus để xác định các mã độc.
- Sử dụng hàm băm (hashes) để xác định các phần mềm độc hại.
- Thu thập thông tin từ một chuỗi (string), chức năng (functions), hoặc tiêu đề (headers) trong tập tin.
- Quét virus: Bước làm đầu tiên hữu ích
Khi lần đầu tiên tiến hành phân tích mã độc, một bước hữu ích đầu tiên là chạy nó thông qua nhiều chương trình phòng chống virus, điều này cho thể giúp ta có thể xác định các mã độc ngay tại thời điểm này. Tuy nhiên, các công cụ chống virus thường không đặt hiệu quả cao và hoàn hảo đến như thế. Các phần mềm Antivirus thường chủ yếu dựa vào một cơ sở dữ liệu chứa phần nhận dạng các mã đáng ngờ (file signatures), cũng như phân tích hành vi và mô hình hoạt động để xác định các tập tin đáng ngờ. Có một vấn đề là người tạo ra mã độc có thể dễ dàng chỉnh sửa mã nguồn của họ, do đó họ có thể thay đổi chữ ký của chương trình mã độc và qua mặt các trình antivirus. Ngoài ra, các loại mã độc mới thường không bị phát hiện bởi các trình antivirus vì đơn giản là chúng không tồn tại trong cơ sở dữ liệu của trình antivirus. Cuối cùng, các phương pháp Heuristic, thường thành công trong việc xác định mã độc, cũng có thể bị qua mặt bởi các loại mã độc mới và hiếm gặp.
Bởi vì các chương trình Antivirus hiện nay sử dụng các chữ ký và phương pháp Heuristic khác nhau, điều này thật hữu ích khi chạy các chương trình Antivirus trên cùng một mẫu mã độc. Các Website như trang VirusTotal (http://www.virustotal.com) cho phép bạn tải lên một tập tin và sẽ được quét bởi nhiều chương trình Antivirus khách nhau. Virus Total sau đó sẽ cung cấp một báo cáo cung cấp tổng số các công cụ Antivirus đánh dấu tập tin này là phần mềm độc hại, tên của mã độc này, và nếu có thể sẽ cung cấp cho bạn nhiều thông tin hơn về tập tin mã độc trên.
2. Hashing: Kiểm tra tính toàn vẹn
Băm (Hashing) là một phương pháp phổ biến được sử dụng để nhận dạng mã độc. Các phần mềm độc hại được chạy thông qua một chương trình băm để tạo ra một số băm duy nhất để xác định rằng đây là phần mềm độc hại. Thuật toán The Message-Digest Algorithm 5 (MD5) là một trong những thuật toán phổ biến nhất để phân tích phần mềm độc hại, ngoài ra thuật toán Secure Hash Algorithm 1 (SHA-1) cũng được sử dụng rất phổ biến.
Ví dụ: sử dụng chương trình miễn phí md5deep để tính toán số băm của chương trình Solitaire có sẵn trong HĐH Windows cho ra kết quả như sau:
C:\>md5deep c:\WINDOWS\system32\sol.exe
373e7a863a1a345c60edb9e20ec3231 c:\WINDOWS\system32\sol.exe
Giá trị băm là 373e7a863a1a345c60edb9e20ec3231
Công cụ băm MD5 giao diện đồ họa có thể tính toán và hiển thị cho nhiều tập tin cùng lúc.
Một khi bạn đã có chuỗi băm duy nhất của mã độc này, bạn có thể sử dụng nó trong những việc sau:
- Sử dụng chuỗi băm (hash) như là một nhãn (label).
- Chia sẻ chuỗi băm này với các nhà phân tích khác để giúp họ xác định phần mềm độc hại.
- Tìm kiếm chuỗi băm trực tuyến trên mạng internet nếu như các tập tin đã được xác định.
3. Tìm các chuỗi (Finding Strings)
Một chuỗi (String) trong một chương trình (Program) là một chuỗi các ký tự. Một chương trình có chứa các chuỗi nếu như nó xuất ra một thông điệp (message), kết nối tới một URL, hoặc sao chép một tập tin tới một vị trí cụ thể nào đó.
Tìm kiếm thông qua các chuỗi có thể là cách đơn giản nhất để có được các gợi ý về các chức năng của một chương trình. Ví dụ, nếu một chương trình truy cập đến một URL, thì bạn sẽ thấy được các URL đã truy cập được lưu trữ như là một chuỗi trong chương trình. Bạn có thể sử dụng chương trình như Strings Program (http://bit.ly/ic4plL) để tìm kiếm tập tin thực thi cho các chuỗi, đó là các tập tin thường được lưu trữ với định dạng ASCII hoặc Unicode.
Cả 2 định dạng ASCII và Unicode đều lưu trữ các ký tự trong một dãy mà kết thúc bằng một giá trị NULL để chỉ ra rằng chuỗi đã được hoàn tất. Các chuỗi định dạng ASCII sử dụng 1 byte/1 ký tự, và chuỗi định dạng kiểu Unicode sử dụng 2 byte/1 ký tự.
Hình trên cho thấy chuỗi BAD được lưu trữ dưới dạng mã ASCII. Chuỗi dạng ASCII được lưu trữ như là byte 0x42, 0x41, 0x44, và 0x00, với 0x42 là mã ASCII đại diện cho chữ cái B hoa, 0x41 là mã ASCII đại diện cho chữ cái A hoa, 0x44 là mã ASCII đại diện cho chữ cái D hoa. Giá trị 0x00 ở cuối là giá trị NULL
Hình trên cho thấy chuỗi BAD được lưu trữ dưới dạng mã Unicode. Chuỗi dạng Unicode được lưu trữ như là byte 0x42, 0x00, 0x41, và tương tự. Chữ các B được trình diễn bởi 2 byte là 0x42 và 0x00, và giá trị kết thúc NULL là 2 byte 0x00.
Khi chương trình Strings tìm kiếm một tập tin thực thi cho các chuỗi định dạng ASCII và Unicode, nó bỏ qua phạm vi và định dạng, do đó nó có thể phân tích bất kỳ loại tập tin nào và phát hiện các chuỗi trong toàn bộ tập tin (mặc dù điều này cũng có nghĩa là nó có thể xác định các byte của các ký tự như là các chuỗi khi chúng thực sự không phải vậy). String tìm kiếm một chuỗi gồm 3 ký tự hoặc một dãy nhiều hơn của các ký tự ASCII và Unicode, theo sau là một ký tự kết thúc chuỗi.
Đôi khi các chuỗi được phát hiện với chương trình Strings là các chuỗi không có thật. Ví dụ, nếu chương trình Strings tìm ra một dãy các byte 0x56, 0x50, 0x33, 0x00, nó sẽ cho rằng đây là chuỗi VP3. Nhưng những byte đó có thể không thực sự đại diện cho chuỗi, chúng có thể là một địa chỉ của bộ nhớ, các chỉ thị của CPU, hoặc là dữ liệu được sử dụng bởi một chương trình nào đó. Chương trình Strings cho phép nó cập nhật lên người dùng để lọc ra các chuỗi không hợp lệ.
May mắn thay, hầu hết các chuỗi không hợp lệ là điều hiển nhiên, bởi vì chúng không đại diện cho văn bản hợp pháp nào. Ví dụ, các đoạn trích sau đây cho thấy kết quả của việc chạy chương trình Strings trên tập tin bp6.ex:
C:>strings bp6.ex_
VP3
VW3
t$@
D$4
99.124.22.1 (4)
e-@
GetLayout (1)
GDI32.DLL (3)
SetLayout (2)
M}C
Mail system DLL is invalid.!Send Mail failed to send message. (5)
Trong ví dụ trên, các chữ in đậm có thể được bỏ qua. Thông thường, nếu một chuỗi là ngắn và không tương ứng với từng từ, nó có thể là vô nghĩa.
Mặt khác, các chuỗi GetLayout ở mục (1) và SetLayout ở mục (2) là các hàm chức năng của Windows được sử dụng bởi các thư viện đồ họa của Windows. Chúng ta có thể dễ dàng xác định như ý nghĩa trên bởi vì tên hàm chức năng của Windows thường bắt đầu bằng một ký tự in hoa và ký tự đầu của từ tiếp theo (Subsequent word) cũng bắt đầu bằng một ký tự in hoa.
GDI32.DLL tại mục (3) là có ý nghĩa bởi vì nó là tên của một thư viên liên kết động (DLL) phổ biến của Windows được sử dụng bởi các chương trình đồ họa. (Các tập tin DLL chứa các mã thực thi được chia sẻ giữa nhiều ứng dụng.)
Như bạn có thể hình dung, con số 99.124.22.1 tại mục (4) là một địa chỉ IP thông dụng thường được các mã độc sử dụng.
Cuối cùng, tại mục (5), Mail system DLL is invalid.!Send Mail failed to send message là một câu thông báo lỗi. Thông thường, những thông tin hữu ích nhất được thu thập bằng cách chạy chương trình Strings là tìm thấy trong các thông báo lỗi. Thông điệp này cho ta thấy 2 điều như sau: mã độc bên dưới gửi các thông điệp (có thể là thông qua email), và nó phụ thuộc vào một DLL Mail system. Thông tin này cho thấy rằng ta có thể muốn kiểm tra bản ghi nhật ký email cho các luồng dữ liệu đáng ngờ, và một DLL khác (DLL Mail system) có thể được kết hợp với phần mềm độc hại đặc biệt này. Lưu ý rằng các DLL bị mất tự nó không nhất thiết phải là phần mềm độc hại, phần mềm độc hại thường sử dụng các thư viện chính thống và các DLLs để đạt được mục đích của chúng.
4. Đóng gói và làm khó hiểu cho mã độc (Packed and Obfuscated Malware)
Những người viết mã độc thường sử dụng kỹ thuật đóng gói hoặc làm cho tối nghĩa giúp cho các tập tin của họ khó bị phát hiện cũng như là phân tích. Các chương trình tối nghĩa là một mã độc thực thi mà tác giả cố tình che giấu bản chất thực của nó. Các chương trình được đóng gói là một tập hợp con của các chương trình tối nghĩa trong đó các chương trình độc hại đã được nén và không thể phân tích. Hai kỹ thuật trên làm hạn chế rất nhiều đến nỗ lực phân tích tĩnh các phần mềm mã độc.
Các chương trình hợp pháp gần như luôn luôn bao gồm nhiều chuỗi (string). Mã độc thì được đóng gói hoặc làm cho tối nghĩa thì chứa ít các chuỗi hơn. Nếu khi tìm kiếm một chương trình với phần mềm Strings, bạn thấy rằng chương trình này chỉ có vài chuỗi, nó có lẽ đã bị đóng gói hoặc bị làm cho tối nghĩa, chính vì điều đó có thể cho thấy rằng nó có thể chính là một phần mềm độc hại. Bạn có thể sẽ cần đưa nó vào môi trường phân tích tĩnh để điều tra kỹ hơn.
Lưu ý, mã đóng gói và làm cho tối nghĩa thường sẽ bao gồm ít nhất các chức năng như LoadLibrary và GetProAddress, đây là những chức năng dùng để đọc (load) và truy cập (gain access) tới các chức năng bổ sung.
5. Định dạng tập tin thực thi Portable (Portable Executable File Format)
Cho đến lúc này, chúng ta đã thảo luận về các công cụ quét các tập tin thực thi, mã đối tượng (object code), và các DLLs. Các định dạng tập tin PE là một cấu trúc dữ liệu chứa các thông tin cần thiết cho việc nạp hệ điều hành Windows để quản lý các mã thực thi đã được đóng gói. Gần như mọi tập tin với mã thực thi được nạp bởi Windows là có trong định dạng tập tin PE, mặc dù vẫn còn một số định dạng tập tin cũ xuất hiện trong mã độc.
Các tập tin PE bắt đầu với một đầu đề (Header) mà bao gồm các thông tin về mã (code), kiểu của ứng dụng, các thư viện chức năng cần thiết, và các không gian trống như yêu cầu. Các thông tin trong Header của PE có giá trị rất lớn đối với các nhà phân tích mã độc.
6. Các thư viện liên kết và chức năng (Linked Libraries and Functions)
Một trong những thành phần hữu ích của thông tin mà chúng ta có thể thu thập về một tập tin thực thi là danh sách các chức năng mà nó sở hữu. Những chức năng mà tập tin thực thi sở hữu (Imports) là các chức năng được sử dụng bởi một chương trình đang thực sự được lưu trữ trong một chương trình khác, chẳng hạn như các thư viện mã (code libraries) có chứa các chức năng phổ biến cho nhiều chương trình khác nhau. Thư viện mã có thể được kết nối tới các tập tin thực thi chính bằng cách liên kết.
Các lập trình viên liên kết các Imports này tới các chương trình của họ sao cho họ không cần phải tái thực hiện các chức năng thông dụng đó trong nhiều chương trình khác nhau. Các thư viện mã có thể được liên kết tĩnh lúc chạy hoặc tự động. Hiểu rõ việc các thư viện mã code liên kết với nhau như thế nào là rất quan trọng cho sự hiểu biết về Malware bởi vì các thông tin mà chúng ta có thể tìm thấy trong Header của các tập tin PE phụ thuộc vào việc thư viện mã code được liên kết như thế nào. Chúng ta sẽ thảo luận về một vài công cụ để xem các chức năng được đưa vào trong một tập tin thực thi trong bài viết này.
Bigguy
(Tham khảo: Practical Malware Analysis)