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.
- Static, Runtime, and Dynamic Linking
Liên kết tĩnh là một phương pháp phổ biến nhất của các thư viện liên kết, mặc dù nó rất phổ biến trong các chương trình Unix và Linux. Khi một thư viện được liên kết tĩnh để thực thi, tất cả các mã code từ thư viện đó được sao chép vào trong tập tin thực thi, điều này làm cho tiến trình thực thi gia tăng kích thước. Khi phân tích mã code, rất khó để phân biệt giữa các mã liên kết tĩnh và các mã của riêng tiến trình thực thi, bởi vì không có gì trong phần Header của tập tin PE chỉ ra rằng tập tin có chứa mã liên kết.
Trong khi không được phổ biến trong các chương trình thân thiện, liên kết Runtime thường được sử dụng trong các phần mềm độc hại, đặc biệt là khi nó đã được đóng gói hoặc làm mờ đi. Các tiến trình thực thi sử dụng liên kết Runtime kết nối tới các thư viện chỉ khi chức năng đó là cần thiết, không phải lúc chương trình khởi động như các chương trình liên kết động.
Một số chức năng của hệ điều hành Windows cho phép các lập trình viên thêm vào các chức năng liên kết mà không có trong phần đầu (header) tập tin của chương trình. Trong số này, hai chức năng thông dụng nhất được sử dụng là LoadLibrary và GetProcAddress. Hàm chức năng LdrGetProcAddress và LdrLoadDll cũng được sử dụng. Hàm chức năng LoadLibrary và GetProcAddress cho phép một chương trình truy cập các chức năng trong mọi thư viện trong hệ thống, điều này có nghĩa là khi các chức năng này được sử dụng, bạn không thể gọi tĩnh các chức năng được liên kết bởi các chương trình đáng ngờ.
Trong tất cả các phương pháp liên kết, liên kết động là phổ biến nhất và là mối quan tâm hàng đầu của các nhà phân tích mã độc. Khi các thư viện được liên kết động, hệ điều hành máy chủ tìm kiếm các thư viện cần thiết khi chương trình được nạp lên. Khi chương trình gọi hàm thư viện liên kết, thì các hàm thực thi trong thư viện.
Header của tập tin PE lưu trữ thông tin về tất cả các thư viện mà sẽ được nạp và các hàm chức năng sẽ được sử dụng bởi chương trình. Các thư viện được sử dụng và các hàm chức năng thường là các phần quan trọng nhất của một chương trình, bởi vì chúng cho phép chúng ta đoán được chương trình làm cái gì. Ví dụ, nếu một chương trình thêm vào hàm chức năng URLDownloadToFile, bạn có thể đoán là nó kết nối tới Internet để tải về một vài nội dung nào đó và lưu trữ trong một tập tin nội bộ.
2. Phát hiện các hàm chức năng liên kết động với Dependency Walker (Exploring Dynamically Linked Functions with Dependency Walker)
Chương trình Dependency Walker (http://www.dependencywalker.com/), được phân phối với một số phiên bản của Microsoft Visual Studio và các gói phát triển Microsoft khác, liệt kê chỉ các hàm chức năng liên kết động trong một thực thi. Hình minh họa bên dưới cho thấy các phân tích của Dependency Walker trên tiến trình SERVICES.EX_ (1)
Cửa sổ bên trái tại mục (2) cho thấy chương trình cũng như các tập tin DLLs được thêm vào, cụ thể ở đây là KERNEL32.DLL và WS2_32.DLL.
Chọn vào KERNEL32.DLL cho thấy các hàm chức năng đã được thêm vào trong khung bên phải tại mục (3). Chúng ta nhìn thấy một vài hàm chức năng, tuy nhiên điều quan tâm nhất chính là hàm chức năng có tên CreateProcessA, điều này cho chúng ta biết rằng chương trình này có thể sẽ tạo ra một tiến trình khác, và cho thấy rằng khi chạy chương trình này, chúng ta sẽ nhìn thấy sự xuất hiện hoạt động của các chương trình bổ sung kèm theo.
Khung cửa sổ ở giữa bên phải tại mục (4) liệt kê tất cả các hàm chức năng có trong KERNEL32.DLL có thể là các thông tin không hữu dụng lắm cho chúng ta. Lưu ý cột có tên là Ordinal trong mục (3) và (4). Các thực thi có thể thêm vào các hàm chức năng dựa vào thứ tự trong cột Ordinal này thay vì dựa vào thứ tự tên. Khi thêm vào một hàm chức năng bởi thứ tự trong cột Ordinal, tên của hàm chức năng không bao giờ xuất hiện trong thực thi ban đầu, và nó có thể gây khó khăn cho nhà phân tích để tìm ra các chức năng đang được sử dụng. Khi phần mềm độc hại thêm vào một hàm chức năng theo thứ tự Ordinal, bạn có thể tìm ra hàm chức năng nào đang được thêm vào bằng cách nhìn vào giá trị Ordinal trong cửa sổ ở mục (4).
Ở 2 khung cửa sổ (5) và (6) bên dưới liệt kê các thông tin bổ sung về phiên bản của các DLLs mà sẽ được nạp nếu bạn chạy chương trình và báo cáo một vài lỗi xảy ra tương ứng. Các DLLs của một chương trình có thể cho bạn biết khá nhiều thông tin về chức năng của nó. Ví dụ, hình bên dưới liệt kê các DLLs thông dụng và cho bạn biết những gì về một ứng dụng.
DLL | Diễn giải |
Kernel32.dll | Đây là một DLL rất phổ biến và có chức năng cốt lõi quan trọng, cho phép truy cập thao tác trên bộ nhớ, tập tin, và hệ thống phần cứng. |
Advapi32.dll | Đây là DLL cung cấp việc truy cập tới các thành phần cốt lõi cao cấp của Windows như là Service Manager và Registry. |
User32.dll | Đây là DLL chứa tất cả các thành phần giao diện người dùng, như là các nút (buttons), các thanh cuộn (scroll bars), và các thành phần cho việc kiểm soát và hồi đáp các hành động tác vụ của người dùng. |
Gdi32.dll | Đây là DLL chứa các chức năng hiển thị và các thao tác đồ họa. |
Ntdll.dll | DLL này là giao diện tương tác với nhân của Windows (Windows Kernel). Các tác vụ thực thi thường không thêm trực tiếp tập tin này khi chạy, mà nó luôn được thêm gián tiếp thông qua tập tin Kernel32.dll. Nếu một tiến trình thực thi thêm tập tin này vào, nó có nghĩa là tác giả có ý định sử dụng chức năng ẩn đối với các chương trình Windows. Một vài nhiệm vụ như ẩn các chức năng hay các tiến trình hoạt động sẽ sử dụng giao diện tương tác này. |
WSock32.dll và Ws2_32.dll |
Đây là các DLLs về hệ thống mạng. Một chương trình có thể truy cập một là bằng các kiểu kết nối thông dụng nhất tới hệ thống mạng hoặc thực hiện các tác vụ liên quan tới hệ thống mạng. |
Wininet.dll | Đây là DLL chứa các chức năng mạng cao cấp hơn như triển khai thực hiện các giao thức như FTP, HTTP, và NTP. |
3. Các hàm chức năng Imported Functions
Header của tập tin PE cũng chứa thông tin về các chức năng cụ thể được sử dụng bởi một tiến trình thực thi. Những các tên của các hàm chức năng Windows có thể cho bạn một gợi ý các tiến trình thực thi các gì. Microsoft đã cung cấp một tài liệu rất hay về các API của Windows thông qua thư viện Microsoft Developer Network (MSDN). Bạn có thể tham khảo các hàm chức năng quan trọng của Windows được các mã độc hay sử dụng trong các bài viết sau.
4. Các hàm chức năng Exported Functions
Giống như chức năng Import, các DLLs và EXEs xuất (export) các chức năng để tương tác với các chương trình và mã chương trình (code). Thông thường, một DLL thực hiện ra một hoặc nhiều chức năng và xuất chúng ra để chúng được sử dụng bởi một tiến trình thực thi mà tiến trình thực thi này sẽ đưa (import) các chức năng này vào trong nó và sử dụng chúng.
Các tập tin PE chứa các thông tin về các chức năng mà một tập tin xuất ra (export). Bởi vì các DLLs này thực hiện công việc đặc biệt để cung cấp các chức năng mà được sử dụng bởi các tập tin EXEs, các chức năng được export này được xem là phổ biến nhất trong các tập tin DLLs. Các tập tin EXEs không được thiết kế để cung cấp các chức năng cho các tập tin EXEs khác, và các chức năng được xuất ra (exported functions) là rất hiếm. Nếu bạn phát hiện các thành phần được xuất ra (export) trong một tiến trình thực thi, điều này thường cung cấp cho bạn những thông tin rất hữu ích.
Trong nhiều trường hợp, tác giả phần mềm đặt tên cho các chức năng export function của họ cũng là cách để bạn thu thập các thông tin hữu ích. Một quy ước chung là sử dụng những cái tên mà được quy định trong tài liệu của Microsoft. Ví dụ, để chạy một chương trình hoạt động như là một dịch vụ, trước tiên bạn phải định nghĩa một chức năng có tên là ServiceMain. Sự hiện diện của chức năng export function được gọi là ServiceMain này mách cho bạn biết rằng các mã độc vận hành như là một phần của một dịch vụ.
Thật không may, trong các tài liệu của Microsoft gọi hàm chức năng này là ServiceMain, nó thì phổ biến cho các lập trình viên trong việc đặt tên, hàm chức năng có thể có những tên khác. Chính vì vậy, những các tên của các hàm chức năng export functions đang thực sự được sử dụng để chống lại các phần mềm độc hại tinh vi. Nếu các mã độc sử dụng các exports này, nó thường sẽ hoặc bỏ qua hoàn toàn cái tên này hoặc sử dụng tên không rõ ràng hoặc gây hiểu nhầm.
Bạn có thể xem thông tin export function này bằng cách sử dụng phần mềm Dependency Walker
Bigguy
(Tham khảo: Practical Malware Analysis)