Hiện nay có vô vàn các ứng dụng Windows đang tồn tại và xu hướng phân tích các ứng dụng này đang được đông đảo các bạn đọc công nghệ quan tâm. Ở chuỗi bài viết về những lưu ý khi phân tích ứng dụng Windows chuyên gia an ninh mạng Bùi Đình Cường sẽ chia sẻ cho bạn đọc một số khái niệm thông dụng cần lưu ý và nắm rõ khi tiến hành phân tích, dịch ngược các ứng dụng Windows.
Windows API
Các kiểu và Ký hiệu Hungarian
Đa số các Windows API sử dụng tên kiểu riêng của mình để biểu diễn các kiểu dữ liệu của C. Ví dụ: DWORD và WORD lần lượt biểu diễn kiểu unsigned int 32-bit và 16-bit. Các kiểu dữ liệu chuẩn của C như int, short, unsigned int thường không được sử dụng.
Windows cũng thường sử dụng Ký hiệu Hungarian (Hungarian notation) để định danh hàm API. Kiểu sử dụng kí hiệu này giúp dễ dàng xác định kiểu dữ liệu của các biến hơn. Một biến có kiểu dữ liệu 32-bit unsigned int (hay DWORD) sẽ được đặt tên bắt đầu bằng dw. Ví dụ, đối số thứ ba của hàm VirtualAllocEx là dwSize, ta có thể thấy ngay nó là một biến DWORD. Dưới đây là ví dụ một số kiểu dữ liệu thường gặp trong Windows API.
XEM THÊM: PHÁT HIỆN CẤU TRÚC CODE C TRONG HỢP NGỮ PHẦN 1
Các Handle
Handle là tên gọi chung cho các đối tượng được mở (truy cập) hoặc được tạo bởi OS, chẳng hạn như một cửa sổ, một tiến trình, một module, menu, file,… Các handle giống như các con trỏ khi trỏ tới một đối tượng hoặc địa chỉ ô nhớ. Nhưng khác với con trỏ, handle không thể được sử dụng trong các phép tính số học và không phải lúc nào chúng cũng biểu diễn địa chỉ của đối tượng. Điều duy nhất ta có thể làm với handle là lưu trữ và sử dụng trong các lời gọi hàm để tham chiếu tới cùng một đối tượng.
Hàm CreateWindowEx có một ví dụ về handle. Nó trả về một HWND, là handle của một cửa sổ. Bất cứ khi nào ta muốn thực hiện một thao tác trên cửa sổ đó, ví dụ gọi hàm DestroyWindow, ta sẽ cần sử dụng handle HWND.
Ta không thể sử dụng HWND như một pointer hoặc một giá trị số học. Tuy nhiên, một số hàm trả về các handle biểu diễn giá trị có thể được sử dụng như các pointer.
Các hàm thao tác trên hệ thống file
Một trong các cách phổ biến để mã độc giao tiếp với hệ thống là tạo mới hoặc sửa đổi các file. Sự thay đổi các file (thêm mới, sửa đổi nội dung hoặc tên file) có thể là những dấu hiệu host hữu ích.
Hoạt động trên file có thể gợi ý hành vi của mã độc. Ví dụ, nếu mã độc tạo một file và lưu trữ hành vi duyệt web vào file vừa tạo, đó có thể là một dạng spyware.
Microsoft cung cấp một số hàm hỗ trợ truy cập hệ thống file:
CreateFile
Hàm này được sử dụng để tạo và mở các file. Nó có thể mở các file, pipe,
stream hoặc các thiết bị I/O có sẵn, và tạo file mới. Tham số dwCreationDisposition dùng để kiểm soát khi nào thì CreateFile tạo một file mới và khi nào thì mở một file có sẵn.
ReadFile và WriteFile
Các hàm này được dùng để đọc và ghi file. Cả hai đều thao tác trên file như một dòng (stream). Hai hàm này sẽ thao tác dựa vào vị trí hiện tại của con trỏ file. Để thay đổi vị trí tác động, chúng ta cần thay đổi vị trí con trỏ file qua các hàm sẽ giới thiệu tiếp theo.
CreateFileMapping và MapViewOfFile
Các ánh xạ file thường được mã độc sử dụng vì chúng giúp nạp vào bộ nhớ và sử dụng các file một cách dễ dàng. Hàm CreateFileMapping thực hiện nạp một file từ ổ đĩa lưu trữ vào bộ nhớ. Hàm MapViewOfFile trả về một pointer trỏ tới địa chỉ cơ sở của ánh xạ, pointer này có thể được dùng để truy cập file trong bộ nhớ, nhờ đó mà ta có thể đọc và ghi tại bất kì vị trí nào trong file.
Ánh xạ file thường được dùng để thực hiện theo chức năng của Windows loader. Sau khi có được một ánh xạ file, mã độc có thể phân tích PE header và thực hiện sửa đổi file trong bộ nhớ, do đó có thể khiến một PE file được thực thi như là nó được nạp bởi OS loader.
Các file đặc biệt
Windows có một số dạng file không thể truy cập bằng ký tự ổ đĩa và thư mục (ví dụ: C:\docs) như các file bình thường. Các chương trình độc hại thường sử dụng những file đặc biệt như vậy.
Một số file đặc biệt có thể được ẩn đi (tàng hình hoặc khó truy cập theo cách thông thường) trong thư mục. Một số file đặc biệt có thể cấp quyền truy cập cao tới phần cứng và dữ liệu hệ thống.
Các shared file, các file có thể truy cập bằng không gian tên hoặc các dòng dữ liệu xen kẽ (ADS) có thể được truyền vào bất kì một hàm quản lý file nào như các chuỗi string và các thao tác quản lý file được thực hiện trên chúng như các file bình thường.
Shared File
Shared files là các file đặc biệt với tên bắt đầu bằng \\serverName\share hoặc \\?\serverName\share.
Tiền tố \\?\ thông báo OS vô hiệu hóa mọi chức năng phân tích string (string parsing) và cho phép truy cập tới các tên file dài hơn bình thường.
Các file truy cập thông qua không gian tên
Không gian tên (namespace) là tập hợp phân cấp các lớp đối tượng khác nhau, có thể được dùng để quản lý nhiều thành phần khác nhau của máy tính Windows. Không gian tên mức thấp nhất là không gian tên NT với tiền tố \. Không gian tên này cung cấp quyền truy cập tới mọi thiết bị và mọi không gian tên tồn tại bên trong nó.
Để duyệt không gian tên NT trên hệ thống, ta sử dụng WinObj Object Manager trong bộ SysInternal Suite (https://docs.microsoft.com/en-us/sysinternals/downloads/winobj).
Không gian tên của các thiết bị Win32 với tiền tố \\.\ thường được mã độc sử dụng để truy cập trực tiếp tới các thiết bị vật lý và đọc/ghi lên chúng như một file. Ví dụ, một chương trình có thể dùng \\.\PhysicalDisk1 để truy cập trực tiếp tới PhysicalDisk1 trong khi không cần quan tâm tới hệ thống file của thiết bị này, do đó mã độc có thể sửa đổi ổ đĩa bằng cách mà các API bình thường không thể thực hiện. Sử dụng phương pháp truy cập theo không gian tên, mã độc có thể đọc và ghi dữ liệu trên các sector chưa được phân vùng mà không cần phải tạo mới hoặc truy cập tới bất kì file nào, nhớ đó thoát khỏi cơ chế phát hiện của các Antivirus.
Ví dụ, sâu Witty (https://en.wikipedia.org/wiki/Witty_(computer_worm)) truy cập \Device\PhysicalDisk1 thông qua không gian tên NT để làm hỏng hệ thống file của nạn nhân. Nó có thể mở \Device\PhysicalDisk1 và ghi lên một không gian lưu trữ ngẫu nhiên trên ổ đĩa gây hư hại OS của nạn nhân và khiến máy tính không thể boot. Sâu Witty không gây ảnh hưởng được lâu vì hệ thống của nạn nhân thường hư hại trước khi nó có thể lây lan sang máy tính khác.
Một ví dụ khác khi mã độc sử dụng \Device\PhysicalMemory để truy cập trực tiếp vào bộ nhớ vật lý, dẫn đến việc một chương trình từ user-space có thể ghi lên không gian kernel. Kỹ thuật này được mã độc sử dụng để sửa đổi kernel và che giấu chương trình trong user-space.
Bắt đầu từ Windows 2003 SP1, \Device\PhysicalMemory không còn được truy cập từ user space mà chỉ có thể truy cập từ kernel.
Các dòng dữ liệu xen kẽ
Dòng dữ liệu xen kẽ (Alternate Data Stream – ADS) cho phép thêm dữ liệu vào một file đã tồn tại trong NTFS, bản chất là thêm một file vào một file khác. Dữ liệu thêm vào không được hiển thị trong danh sách file của thư mục cũng như khi hiển thị nội dung của file ban đầu; nó chỉ được nhìn thấy khi ta truy cập dòng dữ liệu.
Dữ liệu ADS được đặt tên theo quy ước normalFile.txt:Stream:$DATA. Mã độc rất khoái dùng ADS vì nó có thể che giấu dữ liệu.
Windows Registry
Windows registry được dùng để lưu trữ thông tin cấu hình OS và các chương trình. Đây là nguồn dấu hiệu host-based tốt để tìm kiếm thông tin hữu ích về hành vi của mã độc.
Các phiên bản đầu của Windows sử dụng các file .ini để lưu thông tin cấu hình. Ý tưởng Registry xuất phát từ một cơ sở dữ liệu có thứ bậc để lưu các thông tin cấu hình thay thế các file .ini nhằm cải thiện hiệu năng và giúp nhiều ứng dụng có thể cùng lưu trữ thông tin trong nó. Gần như mọi thông tin cấu hình Windows đều được lưu trong registry, bao gồm cả cấu hình mạng, driver, startup, tài khoản người dùng,…
Mã độc thường sử dụng registry để lưu trú hoặc lưu cấu hình. Một mã độc có thể thêm các entry vào registry cho phép nó tự động chạy mỗi khi hệ thống boot. Registry rất rộng nên mã độc có rất nhiều cách sử dụng nó để lưu trú.
Một vài khái niệm registry cần nắm rõ để hiểu các tài liệu của Microsoft:
Root key Registry được chia thành 5 thành phần mức đỉnh gọi là root keys. Đôi khi
khái niệm HKEY hoặc hive cũng được dùng để gọi các root key. Mỗi root key có một mục đích riêng.
Subkey Khái niệm subkey tương tự một thư mục con (subfolder) bên trong một thư mục mẹ (folder).
Key Một key là một thư mục trong registry, nó chứa các giá trị hoặc các folder khác. Cả root key và subkey đều là các key.
Value entry Một value entry là một cặp gồm tên và giá trị (value) tương ứng.
Value (hoặc data) Value hoặc data là giá trị được lưu trong một registry entry.
Các Registry Root Key
Registry được chia thành năm root key sau:
HKEY_LOCAL_MACHINE (HKLM) Lưu trữ các cài đặt toàn cục trên máy local
HKEY_CURRENT_USER (HKCU) Lưu trữ các cài đặt riêng cho user hiện thời
HKEY_CLASSES_ROOT Lưu thông tin định nghĩa kiểu (type)
HKEY_CURRENT_CONFIG Lưu các cài đặt cấu hình phần cứng hiện thời, đặc
biệt là sự khác nhau giữa cấu hình hiện thời và cấu hình chuẩn.
HKEY_USERS Định nghĩa các cài đặt cho user mặc định, user mới và user hiện thời
Hai root key thường được sử dụng nhất là HKLM và HKCU.
Một số key thực chất là các key ảo để tham chiếu tới thông tin registry khác. Ví dụ, HKEY_CURRENT_USER thực sự được lưu trữ trong HKEY_USERS\SID, với SID là định danh bảo mật cho user đang trong phiên đăng nhập. Một ví dụ khác, một subkey phổ biến, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run, chứa một chuỗi các giá trị các file tự động thực thi khi user đăng nhập hệ thống. Root key là HKEY_LOCAL_MACHINE, lưu trữ các subkey SOFTWARE, Microsoft, Windows, CurrentVersion và Run.
Regedit
Registry Editor (Regedit) là công cụ tích hợp sẵn trong Windows để duyệt và sửa registry. Phần bên trái cửa sổ hiển thị các subkey đang được mở, phần bên phải hiển thị các value entry trong subkey. Mỗi value entry được thể hiện với tên, kiểu và giá trị. Đường dẫn đầy đủ của subkey đang duyệt được hiển thị phía dưới cửa sổ (Windows 7 trở về trước) hoặc phía trên khung hiển thị chính (từ Windows 8).
Các chương trình tự động chạy
Ghi thêm các entry vào subkey Run (trong ảnh trên) là một cách phổ biến để cài đặt một chương trình tự động thực thi. Dù không được che giấu tốt, kỹ thuật này vẫn thường được mã độc sử dụng để tự cấu hình thực thi tự động.
Công cụ Autoruns trong bộ công cụ SysInteral Suite (https://docs.microsoft.com/en-us/sysinternals/downloads/autoruns) thực hiện kiểm tra khoảng 30 vùng trong registry để tìm ra các mã được thiết kế để thực thi tự động khi khởi động OS. Nó cho phép tìm các file nhị phân tự động chạy, các DLL được nạp vào một chương trình, các driver được nạp vào kernel.
Các hàm Windows API phổ biến thao tác trên Registry
Mã độc thường sử dụng các hàm registry trong Windows API để sửa đổi registry nhằm tự cài đặt thực thi tự động. Các hàm registry phổ biến là:
RegOpenKeyEx Mở một registry key để truy vấn và sửa đổi giá trị. Có nhiều hàm
khác cho phép truy vấn và sửa đổi giá trị registry key mà không cần phải mở chúng, nhưng đa số các chương trình vẫn sử dụng RegOpenKeyEx.
RegCreateKeyEx Tạo một registry key mới. Nếu key đó đã tồn tại, hàm
RegCreateKeyEx sẽ mở nó. Tên key không phân biệt viết hoa-thường.
RegSetValueEx Set dữ liệu và kiểu dữ liệu cho một value của một registry key.
RegGetValue Trả về dữ liệu của một value entry. Ngoài các registry key phục vụ việc thiết lập tự động thực thi, nhiều registry value giữ thông tin quan trọng về cài đặt và bảo mật hệ thống.
Phân tích mã độc truy cập Registry trong thực tế
Hình bên dưới minh họa đoạn code của một mã độc trong thực tế có chức năng mở một subkey trong registry và thêm một value mới khiến mã độc có thể tự động thực thi khi Windows khởi động.
Hình trên bao gồm phần comment sau mỗi dấu ;. Trong hầu hết trường hợp, comment là tên tham số sẽ được push vào stack, các tên này dựa trên quy ước đặt trên của Microsoft. Ví dụ, các dòng code từ 0x401190 tới 0x40119C gồm các comment samDesired, ulOptions, “Software\\Microsoft\\Windows\\CurrentVersion\\Run” và hKey. Các comment này cung cấp thông tin ý nghĩa về các giá trị sẽ được push vào stack. Giá trị samDesired mô tả quyền truy cập tới key, ulOption là một trường usigned long interger biểu diễn các tùy chọn cho lời gọi đến registry key và hKey là handle của root key được truy cập tới. 80000002h là giá trị HKEY Equate của HKEY_LOCAL_MACHINE (http://www.masmforum.com/board/index.php?PHPSESSID=8d46cd4ecb1688be429ab49694ec53e6&topic=15715.0;wap2, https://www.serverwatch.com/tutorials/article.php/1476831/Managing-Windows-Registry-with-Scripting-Part-1.htm ).
Đoạn code gọi hàm RegOpenKeyEx tại 0x4011A1 với các tham số cần thiết để mở handle tới registry key HKLM\Software\Microsoft\Windows\CurrentVersion\Run. Tên value (0x4011B2) và data (0x4011A9) được push vào stack làm tham số cho hàm RegSetValueEx được gọi tại (0x4011BB).
Trong thực tế, các hàm API thường được gọi với tên kèm đuôi W hoặc A, ví dụ RegOpenKeyExA, RegSetValueExW. Khi phân tích mã độc, ta không cần quan tâm tới các đuôi đó.
Registry Scripting với các file .reg
Các file định dạng .reg chứa dữ liệu registry ở dạng dễ đọc. Khi ta click đúp vào một file .reg, các thông tin chứa trong file đó sẽ được tự động gộp vào registry. Đôi khi mã độc sử dụng các file .reg để sửa đổi registry, nhưng hầu hết trường hợp chúng vẫn trực tiếp sửa đổi registry bằng mã lập trình như trình bày ở phần trên.
Hình trên minh họa một file .reg đơn giản. Dòng đầu tiên là phiên bản của Regedit, 5.00 tương ứng với Regedit trên Windows XP. Key cần sửa đổi được đặt trong cặp dấu ngoặc vuông [HKLM\SOFWARE\Microsoft\Windows\CurrentVersion\Run] và dòng bên dưới là tên và dữ liệu của value cho key đó. Khi click đúp vào file .reg này, một key mới được tạo với tên value là MaliciousValue, nó cho phép thực thi file nhị phân tại C:\Windows\evil.exe mỗi khi khởi động Windows.