Archive for the ‘Unprotecting-the-crypter’ Category


1. Target

Link download Ntpacker: http://tuts4you.com/download.php?view.980

2. Thực hành unpack

2.1. Cách dùng vòng lặp vô tận

Đầu tiên scan target bằng các trình PE detector. Thử với PEiD trước xem thế nào:

null

Tiếp theo dùng RDG để scan:

Với việc scan bằng PeiD và RDG như trên và với kết quả mà RDG đưa ra ta thấy có vẻ như đây là một dạng Crypter. Nếu đúng là Crypter thì theo phương pháp đã mô tả ở phần trước nó phải tạo ra một tiến trình mới. Do vậy, ta sẽ thử đặt BP tại hàm API là CreateProcessA, nếu khi run trong OllyDBG và break tại hàm, quan sát xem tham số truyền vào của hàm có phải là SUSPENDED MODE hay không (tương ứng với dwCreationFlags = CREATE_SUSPENDED). Nếu đúng thì có thể nói nó là Crypter.

Load target vào OllyDBG, ta dừng tại đây:

 photo 1-4-20141-40-09PM.png

Đặt BP tại hàm CreateProcessA, sau đó nhấn F9:

 photo 1-4-20141-42-25PM.png

OllyDBG break tại hàm CreateProcessA, quan sát tại cửa sổ Stack ta thấy :

0012FE2C   00000004  |CreationFlags = CREATE_SUSPENDED

Như vậy, phán đoán của ta đã đúng, với việc dwCreationFlags có giá trị CREATE_SUSPENDED thì nó sẽ tạo process nhưng không được start. Process sẽ không thực thi cho đến chừng nào tiến trình chính (main process) được start thông qua hàm API ResumeThread.

Theo phần trước, do bước cuối cùng nó sẽ gọi tới hàm ResumeThread, vậy đặt một BP tại hàm này và nhấn F9 tại OllyDBG:

 photo 1-4-20141-51-54PM.png

Olly dừng lại tại hàm ResumeThread, nhấn F7 để trace vào trong hàm:

 photo 1-4-20141-53-34PM.png

Bên trong hàm ResumeThread lại gọi tới native API là được export bởi ntdll.dll là NtResumeThread. Tiếp tục trace tiếp và trace vào trong hàm NtResumeThread cho tới khi dừng lại tại lệnh Sysenter:

 photo 1-4-20141-58-44PM.png

Giờ mở Process Explorer lên và tiến hành dump tiến trình con (child process). Lựa chọn tiến trình con và chọn full dump:

 photo 1-4-20142-01-22PM.png

Save file dump lại dưới tên là UnPackMe_NtPacker1_dump.exe. Scan thử bằng PEID xem thế nào:

 photo 1-4-20142-06-24PM.png

Tiến hành fix lại file dump bằng cách dùng Winhex để mởi file. Tại màn hình Winhex, nhấn tổ hợp phím tắt là Ctrl+Alt+X(Find Hex Values), trong ô text box nhập thông tin cần tìm là 4D 5A (tương ứng với “MZ”):

 photo 1-4-20142-10-43PM.png

Nhấn OK để thực hiện tìm kiếm, kết quả sẽ dừng lại tại đây:

 photo 1-4-20142-11-36PM.png

Tiến hành xóa toàn bộ các giá trị trước đó đi và lưu lại:

 photo 1-4-20142-13-46PM.png

 photo 1-4-20142-14-17PM.png

Đóng Winhex, dùng PEiD để scan lại xem kết quả thế nào:

 photo 1-4-20142-16-15PM.png

Có vẻ OK, tuy nhiên để ý vùng khoanh đỏ sẽ thấy giá trị First Bytes tại EP có vẻ hơi lạ, không giống bình thường đối với một target được code bằng VC++ (bình thường đối với những Target code bằng VC++ 6 trở về trước thường có bytes đầu tiên là 55 8B). Đương nhiên nếu ta run thử file dump sẽ lỗi ngay:

 photo 1-4-20142-22-24PM.png

Với thông tin First bytes như trên, có vẻ nhưng việc Patch vòng lặp vô tận không khả thi vì ta không biết rõ 2 bytes gốc là thế nào để mà khôi phục lại. Tuy nhiên, như đã nói dựa vào kinh nghiệm thì 2 bytes đầu sẽ là 55 8B và ta cứ thử xem thế nào. Giờ restart lại OllyDBG (nhớ kill cái child process bằng Process Explorer), thực hiện các bước như đã làm cho tới khi dừng lại tại địa chỉ lệnh SYSENTER.Chuyển qua Process Explorer để tìm thông tin của child process:

 photo 1-4-20142-53-48PM.png

Chuyển Process ID của child process là 768 về dạng HEX, ta có được giá trị là 0x300. Giờ ta chạy PUPE và tìm đến child process để tiến hành patch:

 photo 1-4-20142-58-02PM.png

Tại màn hình Patch, điền thông tin về EP mà ta có được ở trên vào ô Direction và nhấn Search (PUPE sẽ hiện thị kết quả tìm kiếm là 55 8B J). Tiếp theo điền EB FE vào To change by (EB FE là lệnh nhảy tới cùng một lệnh do vậy tạo ra một vòng lặp vô tận) và nhấn Patching. Lúc này, các bytes gốc đã được thay bằng EB FE.

 photo 1-4-20143-02-09PM.png

Thoát PUPE, quay trở lại Olly và nhấn F9 để run. Sau khi nhấn F9, quan sát sẽ thấy tiến trình của chúng ta đã bị terminated trong OllyDBG.

 photo 1-4-20143-03-12PM.png

Đừng lo lắng, điều này không ảnh hưởng gì cả. Lúc này chỉ có tiến trình còn là đang chạy (bởi nó đang rời vào vòng lặp vô tận). Giờ ta sẽ tiến hành dump nó, để dump tôi sử dụng công cụ SirPE (của tác giả Guan de Dio). Chạy SirPE và chọn child process, sau đó chọn Dump All:

 photo 1-4-20143-06-45PM.png

 photo 1-4-20143-09-56PM.png

Save với bất kỳ tên nào bạn muốn, ở đây tôi đặt là final_dump.exe. Sau khi dump xong cũng kill luôn process đi. Kết quả file dump ta có được như sau:

 photo 1-4-20143-11-54PM.png

Mở file final_dump.exe trong OllyDBG:

 photo 1-4-20143-12-41PM.png

Như trong hình, hai bytes đầu tiên đang là EB FE, chúng ta sẽ thay lại bằng 2 bytes gốc là 55 8B tương tự như hình:

 photo 1-4-20143-14-37PM.png

Sau khi patch xong thì save file lại, kiểm tra bằng cách run thử file:

 photo 1-4-20143-16-33PM.png

2.2. Cách dump trực tiếp từ OllyDBG

Cách này khả đơn giản, đầu tiên ta load file vào trong OllyDBG. Đi vào lệnh call tại địa chỉ : 10001E13   .  E8 70FCFFFF   call    10001A88 ta sẽ thấy được đoạn code bên dưới như sau:

 photo 1-4-20144-27-38PM.png

Như vậy, theo lý thuyết mô tả ở phần trước thì hàm API VirtualAllocEx dùng để cấp pháp đủ bộ nhớ cho file EXE thứ hai bên trong không gian bộ nhớ của suspended process. Tiếp theo, sau khi bộ nhớ đã được cấp phát sẽ thực hiện gọi hàm API WriteProcessMemory ghi dữ liệu từ điểm bắt đầu của PE file (file EXE thứ hai) vào trong vùng nhớ vừa được cấp phát.

Với cách phân tích này, ta sẽ tìm tới vùng buffer chứa thông tin về file thứ hai rồi dump ra ngay trong OllyDBG. Tiến hành đặt BP tại hàm API WriteProcessMemory, nhấn F9 ta dừng lại tại đây:

 photo 1-4-20144-35-32PM.png

Chú ý vùng buffer, đây là nơi chứa thông tin về PE file. Follow in dump tại địa chỉ này ta có được như sau:

 photo 1-4-20144-37-36PM.png

Ok tại cửa số dump, chuột phải chọn Backup > Save data to file:

 photo 1-4-20144-43-56PM.png

Lưu lại dưới tên là dumped.exe. File này sẽ chứa toàn bộ dữ liệu bắt đầu từ 00160000. Do vậy để biến nó thành một valid PE file thì phải tìm đến đoạn chứa “MZ” và xóa dữ liệu trước “MZ” đi và lưu lại. Dùng winhex để xóa, kết quả sau khi xóa như sau:

 photo 1-4-20144-51-23PM.png

Scan file dumped.exe bằng PEiD:

 photo 1-4-20144-53-49PM.png

Có thể thấy là mặc dù đã được fix thành valid PE file tuy nhiên thì file dumped.exe không có đầy đủ icon như file final_dump.exe, và chắc chắn một điều là file dumped.exe khi run sẽ bị crash. Vậy ta làm thế nào tiếp theo? Tôi mở đại LordPE để rebuild thử xem có được không. Kết quả rebuild bằng LordPE như sau:

 photo 1-4-20144-57-04PM.png

Sau khi rebuild xong thì kết quả đã có icon. Chạy thử OK:

 photo 1-4-20144-57-53PM.png

Regards,

m4n0w4r


I. Cơ bản về Crypter

Link gốc của bài viết: https://reverse2learn.wordpress.com/2011/09/01/unprotecting-the-crypter/

Ai có kinh nghiệm hoặc đã nghiên cứu trong lĩnh vực malware hẳn sẽ biết về các công cụ được gọi là “Crypter” hoặc đã từng sử dụng các công cụ đó vào mục đích riêng. Mục đích của Crypter nói chung là nhằm bảo vệ các file thực thi (executable), làm khó khăn trong việc phân tích hoặc RE. Trong ngữ cảnh malware thì mục đích chính của các trình crypter là làm cho các malware trở nên không thể bị phát hiện bởi các trình AV hay còn gọi với thuật ngữ là Fully Undetectable (FUD).

Nguyên tắc để tạo ra một Crypter rất đơn giản. Crypter bao gồm hai phần:

  1. Builder
  2. Stub

crypter

Cách thức thực hiện của chúng như sau:

  1. Cung cấp file đầu vào cho trình crypter, nó sẽ được mã hóa bằng một thuật toán mã hóa (thông thường là RC4, AES). Bằng việc mã hóa file như vậy sẽ vượt qua được cơ chế phân tích tĩnh của các trình AV, bởi vì trong quá trình phân tích tĩnh các trình AV sẽ tìm kiếm các mẫu (pattern) trong file thực thi xem có khớp với các signatures không. Khi file đã bị mã hóa thì các trình AV sẽ không thể tìm kiếm / so mẫu được.
  2. Chèn stub trước đoạn code thực thi. Khi người dùng thực thi chương trình thì stub sẽ chạy và giải mã file đã được mã hóa. Chú ý rằng lúc đó file được giải mã vẫn nằm trong bộ nhớ.
  3. Thực thi file đã giải mã từ bộ nhớ. Đây được coi là điểm cốt lõi của trình crypter. Còn được gọi là “Run PE”, có nhiều cách thức khác nhau để cho thực thi PE. Tuy nhiên hầu hết các trình crypter đều sử dụng cùng một phương pháp để thực thi file từ bộ nhớ, phương pháp đó sẽ được trình bày dưới đây (nếu anh em nào đã nghiên cứu về malware chắc sẽ chẳng lạ gì phương pháp của tác giả Tan Chew Keong)

Phương pháp:

  1. Sử dụng hàm API là CreateProcess với tham số là CREATE_SUSPENDED để tạo ra một suspended process từ bất kỳ file EXE nào. (Ta gọi đây là file EXE thứ nhất).
  2. Gọi hàm API là GetThreadContext để lấy thông tin về giá trị thanh ghi (thread context) của suspended process. Thanh ghi EBX của suspended process sẽ trỏ tới process’s PEB. Thanh ghi EAX chứa entry point của process (file EXE thứ nhất)
  3. Lấy địa chỉ base-address của suspended process từ thông tin PEB có được, ví dụ tại [EBX+8]
  4. Tải file EXE thứ hai vào trong memory (sử dụng API ReadFile) và cần thực hiện việc alignment bằng tay.
  5. Nếu như file EXE thứ hai có cùng địa chỉ base-address như the suspended process và kích thước image-size của nó <= image-size của suspended process, việc thực hiện rất đơn già là sử dụng hàm API WriteProcessMemory để ghi ảnh (image) của file EXE thứ hai vào trong không gian bộ nhớ của suspended process, nơi ghi bắt đầu từ địa chỉ base-address.
  6. Cách khác, unmap image của file EXE đầu tiên bằng việc sử dụng hàm API ZwUnmapViewOfSection (exported by ntdll.dll) và sử dụng hàm API VirtualAllocEx để cấp pháp đủ bộ nhớ cho file EXE thứ hai bên trong không gian bộ nhớ của suspended process. Hàm API VirtualAllocEx phải được cấp địa chỉ base-address của file EXE thứ hai để đảm bảo rằng Windows sẽ cung cấp memory theo vùng yêu cầu. Tiếp theo, sap chép image của file EXE thứ hai vào trong không gian bộ nhớ của suspended process bắt đầu tại địa chỉ đã được cấp phát (allocated address) (thực hiện bằng cách sử dụng hàm WriteProcessMemory).
  7. Tiếp theo tiến hành Patch địa chỉ base-address của file EXE thứ hai trong PEB của suspended process tại [EBX+8]
  8. Thiết lập thanh ghi EAX của thread context thành entry point của file EXE thứ hai
  9. Sử dụng hàm API SetThreadContext để chỉnh sửa thread context của suspended process
  10. Cuối cùng sử dụng hàm API ResumeThread khôi phục lại thực thi của (resume execute) của suspended process.

Thông thường khi các bạn load một file bị packed (packed executable) vào trong Ollydbg thì OllyDBG sẽ bật các cảnh báo tương tự như sau: “The code section is compressed” hay “The entrypoint is outside the code section“, điều này có nghĩa là OllyDBG thông báo cho ta biết file đó đã bị packed. Tuy nhiên, đối với những file đã bị crypted bởi trình crypter (thông qua việc áp dụng phương pháp trên) thì OllyDBG sẽ không đưa ra bất kỳ cảnh báo nào và vẫn load file một cách bình thường.

II. Phân tích

Đầu tiên dùng PeiD để scan file:
PeID scan

Với thông tin của PEiD cung cấp thì mọi thứ hoàn toàn bình thường. Tiến hành load file vào trong Olly, không nhận được bất kỳ cảnh báo nào:

Giờ sẽ tiến hành kiểm tra chương trình xem nó là bình thường hay là file độc hại. Theo phương pháp đã mô tả ở trên nó phải tạo ra một tiến trình mới. Do vậy, đặt BP tại các hàm API là CreateProcessACreateProcessW. Nếu khi run trong Olly và break tại hàm thì quan sát xem tham số truyền vào của hàm có phải là SUSPENDED MODE hay không (tương ứng với dwCreationFlags = CREATE_SUSPENDED). Thực hiện đặt BP và run trong Olly sẽ break tại hàm CreateProcessA, quan sát các tham số truyền vào cho hàm tại màn hình Stack sẽ thấy được giá trị CREATE_SUSPENDED:

Như vậy, nó gọi hàm CreateProcess ở chế độ suspended mode (suspend its main thread) và sau đó giải mã encrypted malware vào không gian địa chỉ của tiến trình mới đã được tạo, sau khi xong việc nó sẽ gọi tới hàm API ResumeThread.

Do bước cuối cùng nó sẽ gọi tới hàm ResumeThread, vậy đặt một BP tại hàm này và nhấn F9 tại Olly:

Olly dừng lại tại hàm ResumeThread, nhấn F7 để trace vào trong hàm.

Có thể thấy rằng bên trong hàm ResumeThread lại gọi tới native API là NtResumeThread

Chú ý: NtResumeThread là một Undocumneted API. Hầu hết các hàm API của Windows đều hoat động theo cơ chế này. Chúng cung cấp một hàm chính với các thông tin cụ thể về hàm nhưng sau đó trong nội bộ của hàm lại gọi tới các hàm APIs được liệt vào dạng undocumented. Khái niệm này rất quan trọng bởi đôi lúc các tác giả của các trình Crypter sẽ sử dụng undocumented APIs thay vì các Documented APIs. Lấy ví dụ, họ có thể gọi trực tiếp luôn hàm NtResumeThread thay vì gọi đến hàm ResumeThread. Trong trường hợp này nếu như ta đặt BP tại hàm ResumeThread thì OllyDBG sẽ không thể break. Do vậy, khuyến nghị nên đặt BP tại undocumented APIs. Nếu như trên ta đặt BP tại NtResumeThread thì sẽ break tại địa chỉ 75A0C3D5 chứ không phải 75A0C3C9.

Hiện tại, ta đang dừng tại NtResumeThread, nhần F7 để trace vào trong hàm và tiếp tục nhấn cho tới khi dừng lại tại 778764F2:

Đây là nơi mà hàm ResumeThread thực sự được thực thi và suspended process cũng sẽ bắt đầu thực thi, tuy nhiên để tránh bị lây nhiễm (infected) thì ta không muốn điều này xảy ra. Do đó, chúng ta dừng lại tại đây. Giờ mở Process Explorer lên và tiến hành dump tiến trình (ở đây chính là child process). Lựa chọn tiến trình con và chọn full dump:

File sau khi dump sẽ được lưu dưới dạng .dmp, đổi tên file thành dump.exe và scan thử bằng PEiD:

Trắng trơn chả có gì và nhận được thông tin là “Not a valid PE file”. Tiến hành fix lại file, PE file thường bắt đầu với dấu hiệu “MZ”, do vậy các trình detect như PeiD đầu tiên sẽ kiểm tra xem file có chứa MZ ở đầu hay không … nếu không thì có nghĩa đây không phải là một PE file hợp lệ. Để fix ta sử dụng Hex Workshop để mở file dump.exe, tìm kiếm chuỗi “MZ”, sau đó xóa toàn bộ những gì phỉa trên “MZ”. Sau khi xóa xong thì lưu lại:

Giờ scan lại bằng PeiD, kết quả có được như sau:

Có vẻ OK rồi, thử chạy file thì nhận được thông báo:

File không chạy được, có vẻ ta đang mất quá nhiều thời gian vào việc fix nó thì phải? Việc fix ở trên mới chỉ là biến file dump trở thành một PE file hợp lệ, tiếp theo ta cần phải tìm OEP cho nó bằng cách load vào OllyDBG hoặc sử dụng các trình PE tools. OEP là Original Entry Point, nó là địa chỉ mà từ đó chương trình bắt đầu thực thi.

III. Tại sao cần OEP

Như đã thấy qua các bước ở trên, chúng ta dump chương trình trước khi hàm ResumeThread thực thi nhưng file dump lại không hoạt động. Giả sử rằng các crypted program là malware vì vậy ta không muốn chúng chạy, vậy thì sau đó làm cách nào để ta có thể khiến nó hoạt động. Ý tưởng ở đây là thay đổi hai bytes đầu tiên tại Program entry point để nó bị bẫy trong một vòng lặp vô tận (infinite loop), với cách này nó sẽ không thể được thực thi và tất cả mọi thứ sẽ được đặt một cách chính xác, do vậy lúc đó là cơ hội tốt để tiến hành dump file. (Cách patch vòng lặp vô tận này anh em nào unpack Armadillo nhiều sẽ biết).

Đầu tiên tìm OEP của file mà ta đã dump bằng cách load file vào OllyDBG. Lưu ý, nên ghi lại các bytes bắt đầu tại entry point.

Ta có: 0048847F <ModuleEntryPoint>    6A 60   PUSH 60

EntryPoint là: 0048847F. Hai bytes đầu tiên là:  6A 60

Giờ tiến hành fix, ta load file Crypted.exe trong Olly, thực hiện các bước như đã làm cho tới khi dừng lại tại địa chỉ 7C90EB8D  0F34   SYSENTER sau khi đã trace vào trong hàm ResumeThread. Đó là điểm mà tại đây quá trình thực thi thực sự sẽ diễn ra. Bây giờ, ta phải thay đổi hay bytes đầu tiên tại Entry Point để bẫy chương trình vào vòng lặp vô tận. Sử dụng công cụ PUPE để thực hiện:

Quan sát trên hình, trong Process Explorer có thể thấy tiến trình con Crypted.exe, tiến trình này có process id là 544. Chuyển qua dạng HEX sẽ có giá trị là 0x220. Dùng PUPE để tìm:

Lựa chọn file có Process ID tương ứng và chọn Patch. Tại màn hình Patch, tiến hành Patch như sau:

Nhập thông tin OEP vào Direction và nhấn Search sẽ có được các bytes là 6A 60 (hãy nhỡ những bytes này để sau này còn khôi phục lại). Tiếp theo điền EB FE vào To change by (EB FE là lệnh nhảy tới cùng một lệnh do vậy tạo ra một vòng lặp vô tận) và nhấn Patching. Lúc này, các bytes gốc đã được thay bằng EB FE. Quay trở lại Olly và nhấn F9 để run. Sau khi nhấn F9, quan sát sẽ thấy tiến trình của chúng ta đã bị terminated trong OllyDBG.

Đừng lo lắng, điều này không ảnh hưởng gì cả. Lúc này chỉ có tiến trình còn là đang chạy (bởi nó đang rơi vào vòng lặp vô tận). Giờ ta sẽ tiến hành dump nó, để dump ta sử dụng công cụ PE Tools:

Lựa chọn Dump Full và save với bất kỳ tên nào bạn muốn, ở đây đặt là final_dump.exe. Sau khi dump xong cũng kill luôn process đi. Mở file final_dump.exe trong OllyDBG:

Như trong hình, hai bytes đầu tiên đang là EB FE, chúng ta sẽ thay lại bằng 2 bytes gốc là 6A 60 tương tự như hình:

Sau khi patch xong thì save file lại, như vậy ta đã thành công trong việc unpack crypted file. Có thể kiểm tra bằng cách run thử file.

PS: Bài tiếp theo sẽ thực hành trên target là ntpacker.

Regards,

m4n0w4r