Anti-Debugging
Một số cách chống debug:
- Kiểm tra sự hiện diện của debugger: malware tìm kiếm các tiến trình hoặc file liên quan đến debugger chẳng hạn như dùng hàm
IsDebuggerPresent
của Window API. - Malware có thể chỉnh sửa hoặc làm hư hỏng debug log để debugger không thể điều khiển được quá trình thực thi của code.
- Sử dụng code tự chỉnh sửa: malware tự động thay đổi chính nó trong khi chạy để debugger khó theo kịp luồng thực thi.
Anti-Debugging Using Suspend Thread
Mã nguồn của một malware sử dụng hàm SuspendThread thuộc Window API để treo luồng khi phát hiện ra debugger:
Giải thích cách hoạt động:
- Malware lặp qua tất cả các luồng trong hệ thống thông qua hàm
CreateToolhelp32Snapshot
, hàmThread32First
và hàmThread32Next
. - Với mỗi thread, malware dùng hàm
EnumWindows
để lặp qua các cửa sổ được hiển thị trong hệ thống. - Nếu tên của cửa sổ hiển thị có chứa chuỗi
debugger
,dbg
hoặcdebug
thì malware biết được có debugger đang chạy. - Nếu có sự hiện diện của debugger, malware treo luồng của debugger và khiến nó bị crash.
- Malware tiếp tục thực hiện hành vi độc hại.
Để giải quyết điều này thì cần sử dụng patching1. Cụ thể, sau khi sử dụng x32dbg để debug malware, ta cần tìm kiếm lời gọi hàm SuspendThread
thông qua context menu: “Search for > Current Module > Intermodular calls”.
Kết quả tìm kiếm có thể có dạng như sau:
Double-click để đi đến chỗ gọi hàm. Sau đó, thay instruction này thành các nop
instruction:
Tip
Có thể xuất bản vá ra để áp dụng cho những lần debug sau thông qua option “View > Patch file > Export”.
Cuối cùng, nhấn F9 lần nữa để chạy malware thì ta thấy malware không còn khiến debugger bị treo nữa.
VM Detection
Malware sẽ kiểm tra các mục tiêu sau để phát hiện máy ảo:
- Các tiến trình đang chạy: các máy ảo thường có các tiến trình dễ nhận diện. Ví dụ, VMWare có tiến trình của
vmtools
còn VirtualBox có tiến trình củavboxservice
. Malware sẽ sử dụng hàmEnumProcess
của Window API để lặp qua các tiến trình nhằm tìm kiếm sự hiện diện của những công cụ này. - Các phần mềm phân tích được cài đặt chẳng hạn như debugger, decompiler, … Malware sẽ tìm kiếm các phần mềm này trong registry key
SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall
. - Các địa chỉ MAC tương ứng với các máy ảo. Ví dụ, một số máy ảo sẽ tự sinh ra địa chỉ MAC có các số sau:
00-05-69
,00-0c-29
,00-1c-14
hoặc00-50-56
(VMWare). - Tài nguyên của máy chẳng hạn như CPU và RAM. Ví dụ, một máy mà có RAM ít hơn 8GB thì rất có thể là máy ảo.
- Kết nối của các thiết bị ngoại vi chẳng hạn như máy in bởi vì máy ảo thường không cấu hình các thiết bị này.
- Active Directory domain thông qua các biến môi trường chẳng hạn như
LoggonServer
vàComputerName
. - Thời gian thực hiện một chỉ thị hoặc truy cập vào một tài nguyên cụ thể. Thông thường, thời gian để thực hiện những hành động này trong máy ảo sẽ chậm hơn thông thường.
Khi malware phát hiện ra nó đang được thực thi trong máy ảo, nó sẽ thay đổi hành vi theo những cách sau:
- Chỉ thực thi một số ít các tính năng.
- Tự hủy hoặc tự xóa chính nó bằng cách tự ghi đè một phần mã nguồn.
- Gây thiệt hại cho hệ thống chẳng hạn như xóa hoặc mã hóa tập tin.
- Không chạy gì cả.
Để ngăn cản việc phát hiện của malware, ta có thể làm cho máy ảo giống một máy vật lý thông thường chẳng hạn như giấu registry của các phần mềm phân tích, đổi địa chỉ MAC hoặc cấu hình để máy ảo trông có vẻ như là đang kết nối đến máy in. Có thể sử dụng các script có sẵn để tự động hóa việc này chẳng hạn như VMwareCloak hoặc VBoxCloak.
VM Detection by Checking the Temperature
Giá trị Win32_TemperatureProbe
thuộc lớp Windows Management Instrumentation (WMI) chứa dữ liệu thời gian thực về nhiệt độ của phần cứng được cung cấp bởi cấu trúc dữ liệu SMBIOS (System Management BIOS). Trong môi trường máy ảo, giá trị trả về sẽ là Not Supported
. Malware có thể lợi dụng điều này để kiểm tra xem nó có đang được chạy trong máy ảo hay không.
Note
Trong máy vật lý thì giá trị này vẫn có thể là
Not Supported
nếu phần cứng không hỗ trợ tính năng SMBIOS.
Mã nguồn mà malware sử dụng:
Để ngăn cản malware phát hiện ra máy ảo thì có thể sử dụng patching. Cụ thể, sau khi mở malware bằng x32dbg thì nhấn CTRL + G để đi đến địa chỉ 0x004010E0
ở trong code.
Từ địa chỉ 0x004010E0
đến 0x004010F8
tương đương với dòng code hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
.
Tại địa chỉ 004010FD
là một phép so sánh [ebp-18]
(uReturn
) với số 0 và nó tương đương với dòng code if (uReturn == 0)
.
Nếu giá trị của uReturn
là 0 thì hàm hasThermalZoneTemp
sẽ có giá trị là false
, đồng nghĩa với việc máy đang chạy malware không có thông tin về nhiệt độ.
Sau khi chọn “Follow in dump > Address: EBP-18” thì debugger chuyển dump view đến vị trí vùng nhớ 0019FF08
:
Double-click vào byte 00
cuối cùng rồi chọn “Modify Value” để sửa thành 01
nhằm bypass được điều kiện so sánh uReturn == 0
:
Nhấn F8 để step into và ta thấy debugger nhảy từ địa chỉ 00401101
đến 0040110A
. Việc này sẽ gây ra exception bởi vì đáng lẽ chương trình phải thoát sau khi gọi hàm hasThermalZoneTemp
.
Thay vì chạy tiếp, ta có thể nhảy đến một vùng code nào đó chẳng hạn như dòng code printf("Thermal Zone Temperature: %d\n", vtProp.intVal);
có địa chỉ từ 00401130
đến 00401139
:
Để nhảy đến địa chỉ 00401134
, ta có thể chỉnh sửa giá trị của thanh ghi eip
(instruction pointer) bằng cách chuột phải vào EIP rồi chọn “Modify value”.
Cuối cùng, nhấn F9 để chương trình tiếp tục chạy.
Packers
Một số kỹ thuật làm rối mà malware sử dụng:
- Encode dữ liệu chẳng hạn như các chuỗi CLI, tên miền, … sử dụng các kỹ thuật encode chẳng hạn như XOR hoặc Base64.
- Sử dụng các kỹ thuật mã hóa để mã hóa các giao tiếp đến C2, định dạng file hoặc là network traffic.
- Làm rối code bằng cách đổi cú pháp, tên hàm, tên biến hoặc chia code ra nhiều file.
Packer là công cụ giúp nén và mã hóa file thực thi. File thực thi gốc sẽ được nén lại và nhúng vào một file thực thi khác mà đóng vai trò như là wrapper hay container. Việc nén file làm giảm kích thước của file gốc, giúp cho việc phân phối và cài đặt nó dễ dàng hơn. Một số packer có một số tính năng chẳng hạn như làm rối code, runtime packing hoặc anti-debugging.
Một số packer phổ biến:
- Alternate EXE Packer
- ASPack
- ExeStealth
- hXOR-Packer
- Milfuscator
- MPress
- PELock
- Themida
- UPX: the Ultimate Packer for eXecutables
- VMProtect
Không phải chương trình nào sử dụng packer cũng là mã độc bởi vì một số nhà phân phối phần mềm cần nó để bảo vệ khỏi việc ăn cắp chất xám.
Identifying Packer
Bước đầu tiên để đối phó với malware có sử dụng packer là xác định xem loại packer mà nó sử dụng. Có thể sử dụng công cụ DetectItEasy hoặc PEStudio để làm việc này.
DetectItEasy có một danh sách các signature của các packer phổ biến giúp phát hiện ra packer mà file sử dụng. Nếu nó có thể nhận diện được packer thì nó sẽ hiện như sau:
Có thể click vào “Entropy” để xem section nào bị pack.
Nếu sử dụng PEStudio, ta có thể vào phần “sections (self-modifying)” để xem các section trong file:
Thông thường thì một file thực thi sẽ có section .text
, .data
và .rsrc
. Tuy nhiên, trong hình minh họa trên, tên của các section đã bị thay đổi thành UPX0
, UPX1
, và UPX2
. Đây có thể là dấu hiệu của packer UPX.
Important
Mỗi packer sẽ sử dụng một kỹ thuật riêng biệt để pack file nên những cách làm trên không phải lúc nào cũng có thể áp dụng được.
Automated Unpacking
Sau khi nhận diện được loại packer thì ta cần dùng unpacker tương ứng. Một số packer chẳng hạn như UPX sử dụng cùng một công cụ cho việc packing và unpacking. Một số tool thương mại chẳng hạn như Themida thì ta cần sử dụng các unpacker script từ bên thứ 3.
Một số script:
Cũng có thể sử dụng trang web unpac.me để unpack tự động.
Manual Unpacking and Dumping
Tuy nhiên, cách tốt nhất để unpack là thực thi nó. Khi một file bị pack được thực thi, wrapper hoặc container code sẽ giải mã và gỡ rối file thực thi gốc. Khi đó, chúng ta có thể truy xuất malware đã được unpack ra để tiện phân tích về sau.
Giả sử địa chỉ 004172D4
trong malware là nơi gọi đến entry point của file thực thi gốc, ta có thể đặt breakpoint của x32dbg ở đây:
Nhấn F7 để thực thi chỉ thị jmp
. Chỉ thị này sẽ nhảy đến địa chỉ 00401262
và đây chính là entry point của file thực thi gốc:
Giải thích hai bước trên: khi chương trình chạy đến 004172D4
thì có nghĩa là file đã được unpack thành công và nó sẽ sao chép code của file thực thi gốc vào địa chỉ 00401262
.
Để trích xuất file thực thi gốc sau khi unpack, chọn “Plugins > Scylla > Dump” và lưu cùng vị trí với file chưa được unpack.
Scylla là một công cụ giúp dump bộ nhớ của tiến trình và xây dựng lại Import Address Table (IAT)2.
Sau khi trích xuất file thì nhấn “IAT Autosearch” để nó quét qua bộ nhớ của tiến trình nhằm tìm import address table. Sau đó, nhấn “Get Imports” để cập nhật import list section:
Có thể xóa dòng cuối cùng vì nó không hợp lệ.
Nhấn vào nút “Fix Dump” rồi chọn file dump đã xuất để sửa IAT.
Kiểm tra lại bằng cách dùng DetectItEasy:
Có thể thấy, nó không tìm thấy packer có trong file nữa.
Related
Resources
Footnotes
-
xem thêm Bypassing Unwanted Execution Path ↩
-
xem thêm TryHackMe - Dissecting PE Headers ↩