1.2.1 .Theo hình thức lây nhiễm
4.3 Phân tích giải nén các mẫu
4.3.1 Bảo vệ mã độc bằng phương pháp nén mẫu
Như đã trình bày về cấu trúc PE của các file trên Win, ta có thể mơ tả các file được pack như trong hình vẽ.
Hình 96 File PE khi bị pack
File được pack có cấu trúc như một búp bê ma ti ri u ska của Nga,với file chính chứa file packed data – là file gốc được nén, mã hóa.
Packed file vẫn là một file PE có cấu trúc bình thường. Thường hoạt động như sau:
Bước 1, Load thực thi từ Entry Point như bình thường với các section chứa code, import.
Bước 2,Trong unpacker code của trường trình thực hiện lưu các giá trị của các thanh ghi, cờ ... rồi thực hiện giải mã, giải nén, viết lại File như trước khi bị pack từ vùng nhớ chứa file đã được nén, mã hóa – Packed data.
Bước 3, Tiếp tục thực hiện việc lấy địa chỉ của các windows API, tự điền lại các địa chỉ này lại để hoàn chỉnh import table của file vừa được
152
gải mã tại vùng nhớ chứa Packed-data ( Ở các file thông thường việc này được windows thực hiện tự động khi file được load vào bộ nhớ. Quá trình này thường sử dụng các API như GetProcAddress, LoadLibraryA …).
Bước 4, Từ section code sẽ thực hiện phục hồi lại các thanh ghi rồi jump đến EntryPoint (OEP) của file mới được phục hồi từ packed-data.
Minh họa sau khi bước 2 thực hiện xong ta có:
Section chứa Packed-data với kích thước bành trướng. Khi được giải nén/mã
Hình 4-28: Khi được giải nén
Ngồi ra trong bước 2 unpacker code cịn có thể thực hiện nhiều thủ đoạn kiểm tra xem có bị debug không, kiểm tra xem đang chạy trong môi trường ảo hay thực, rồi thực hiện đánh lạc hướng, cản trở công việc unpack, điều tra. k
4.3.2 Giải nén mẫu mã độc
Có nhiều phương pháp để unpack một file như:
Cách1: Phân tích hàm giải mã/ giải nén sau đó tự giải mã các thơng tin về file trước khi bị pack trong packed-data. Khôi phục lại file gần như nguyên gốc.
Cách 2 tìm địa chỉ Entrypoint của file gốc (OEP) Break point hoặc trace dần để debuger dừng lại tại địa chỉ này Dump bộ nhớ của process này, rồi thực hiện việc tạo lại bảng IAT phù hợp với file mới.
153
Cách 3 xác định packer nếu là các packer phổ biến có thể tìm kiếm được các trường trình tự động unpack.
Ở đây ta sử dụng phương án 2 là chính do nó đơn giản hơn, an tồn hơn. Load chương trình vào trình Debug (ở đây ta dùng OllyDebug).
Bước 1: Tìm kiếm, Xác định OEP
Cách 1: OEP thường được nhảy đến bằng một lệnh Jump Far( đôi khi là một cặp lệnh push OEP address – ret ). Trước lệnh jump này thường là đoạn khôi phục lại các thanh ghi, xóa các thanh ghi của unpacker code, phía trên một chút nữa thường là đoạn code thực hiện tái tạo lại import table của file gốc. Ta có thể xác định các vị trí này bằng các cách như đặt break point tại các địa chỉ của các giá trị lưu trong các thanh ghi, Đặt break point tại các hàm loadlibrary, getprocaddress.
Ví dụ khi unpack UPX packer ta đặt hard ware tại địa chỉ chứa giá trị ở đỉnh stack, khi phục hồi lại các thanh ghi để chuẩn bị nhảy đến OEP chương trình sẽ pause lại, lúc này ta dễ dàng nhìn thấy lệnh jump đến OEP.
Cách 2: Dựa vào việc đặt các Break Point vào các hàm Virtual Alloc (phân quyền lại cho các vùng nhớ ). Để xác định các vùng nhớ được phân quyền từ đây có thể suy ra sau khi giải mã/ giải nén file được write lại vào đâu. Rồi sau đó ta có thể khơi phục lại từ các vùng nhớ này thành file gốc.Đặt memory break point tại section mà file được write vào. Dựa vào việc đến số lần bị pause cho đến khi file run hoàn toàn để xác định OEP.
Bước 2: Dump Execute Memory Image. Đặt break Point để chương trình dừng lại tại OEP. Dùng các tool như Plugin OllyDump của Ollydbg hoặc Lord PE, PE tool để dump, sửa lại EP của file sau khi dump thành OEP cho chính xác.
Bước 3: Xây dựng lại import table. Sử dụng ImportREC để xây dựng lại import table.
Các file pack thường có các chức năng tự kiểm tra xem nó có bị chạy trên trình debug nào khơng, có bị sửa đổi gì khơng ... Vấn đề này sẽ được trình bày ở các phần tiếp theo.
154