Hướng dẫn deobfuscate DotnetPatcher 3.1 - Bài dịch
1. Trang 1
Hướng dẫn Deobfusacte DotnetPatcher 3.1 một cách thủ công
(viết bởi ubbelol cho http://rtn-team.cc)
Người dịch : Levis Nickaster (http://ltops9.wordpress.com)
Đây là tài liệu MIỄN PHÍ, nhằm phục vụ mục đích nghiên cứu và chia sẻ kiến thức. Khi copy và đăng tải ở bất kì đâu cần
ghi rõ nguồn để tôn trọng tác giả cũng như tôn trọng người dịch, cảm ơn. Đề xuất, đóng góp để bản dịch tốt hơn, hãy
gửi email cho tôi: levintaeyeon[at]live[dot]com.
Công cụ sử dụng:
- DnSpy (http://ubbecode.wordpress.com/2014/05/03/dnspy-more-powerful-net-decompiler/)
- Windbg
- De4dot
File thực hành trong bài viết này: http://www.multiupload.nl/6GJ3UQX71Y (hiện tại link đã bị die, tác giả
chưa update, cho nên bài viết này chỉ mang tính chất tham khảo, cách thực hiện đối với các file khác cũng
tương tự).
Lời giới thiệu
Tôi đã thấy rất nhiều người gặp vấn đề khi cố gắng thực hiện deobfuscate loại protector này, lí do là dạng bảo
vệ này không thể bị loại bỏ một cách tự động chỉ bằng việc kéo và thả file vào de4dot. Vì vậy trong bài viết
này tôi sẽ hướng dẫn cách làm thủ công sử dụng Windbg và de4dot.
Nếu bạn thấy thích những bài viết như thế này, hãy ghé thăm blog của tôi, nơi mà tôi sẽ cố gắng đăng thêm
nhiều bài viết mới : http://ubbecode.wordpress.com
2. Trang 2
Chúng ta có 1 file được bảo vệ bằng DotnetPatcher 3.1 packer + obfuscation. Dạng này không phải là một
dạng bảo vệ quá phức tạp, nhưng de4dot không thể deobfuscate nó tự động nếu chương trình đó có sử dụng
packer và có 1 dạng mã hóa string chưa được nhận diện. Chúng ta sẽ bắt đầu bằng việc xem xét code của
entrypoint của chương trình trong DnSpy (hoặc .NET Reflector):
Nhìn giống như 1 loader cơ bản sử dụng Assembly.EntryPoint.Invoke(..), để load file nguyên thủy. Có nghĩa
là, chương trình sẽ phải load file nguyên thủy từ đâu đó. Hãy xem xét hàm call đầu tiên được sử dụng để load
Assembly vào và lăn xuống dưới 1 chút cho đến khi ta nhìn thấy Assembly.Load:
Phải rồi, vậy là chương trình sử dụng Assembly.Load(byte[]). Tiến hành load file vào trong WinDbg.
Chúng ta sẽ đặt 1 breakpoint ở clrjit và chạy chương trình:
0: 000> sxe ld:clrjit
0: 000> g
Breakpoint sẽ hoạt động ngay lập tức:
ModLoad: 64da0000 64e1d000 C:WindowsMicrosoft.NETFrameworkv4.0.30319clrjit
.dll
Bây giờ chúng ta sẽ load SOS extension:
0: 000> .loadby SOS clr
Chúng ta cần phải đặt 1 breakpoint ở Assembly.Load, hãy tìm địa chỉ của MethodDesc của method đó. Dùng
lệnh sau:
0: 000> !name2ee mscorlib.dll System.Reflection.Assembly.Load
3. Trang 3
Kết quả:
Token: 0600265c
MethodDesc: 55727db0
Name: System.Reflection.Assembly.Load(Byte[])
JITTED Code Address: 56080714
Đặt 1 breakpoint tại đó và chạy chương trình:
0: 000> !bpmd -md 55727db0
0: 000> g
Khi breakpoint có tác dụng có nghĩa là loader vừa mới gọi Assembly.Load, và chúng ta có 1 assembly buffer ở
trong memory. Dùng lệnh:
0: 000> !clrstack -a
Ở trên đỉnh (top) của clrstack chúng ta thấy có:
Child SP IP Call Site
0039f0f0 56080714 System.Reflection.Assembly.Load(Byte[])
PARAMETERS:
rawAssembly (<CLR reg>) = 0x024b5290
LOCALS:
<no data>
Dump thử:
0:000> !do 0x024b5290
Trong phần Content chúng ta có thể nhìn thấy rõ rang đây là 1 file exe với MZ signature:
Name: System.Byte[]
MethodTable: 55a74588
EEClass: 5570229c
Size: 12812(0x320c) bytes
Array: Rank 1, Number of elements 12800, Type Byte
Content: MZ......................@...
4. Trang 4
Tiến hành dump vùng nhớ xuống và lưu lại thành file:
0: 000> .writemem C:Dumpsdumped.exe 0x024b5290+8 L?0x320c
Bây giờ ta đã có được file gốc (không bị pack), tuy nhiên vẫn còn bị obfuscate. Đưa file này vào de4dot để
“làm sạch sẽ”, dễ đọc hơn 1 chút. Sau đó mở file mới tạo bằng de4dot trong DnSpy:
Phần code ghi là Class2.smethod_2() thực ra là 1 string, vì vậy chúng ta cần phải deobfuscate để lấy lại string
gốc. Để làm điều này, chúng ta sẽ sử dụng một tính năng rất hữu ích của de4dot, mà rất nhiều người không
biết sử dụng nó, thậm chí còn không biết đến sự tồn tại của tính năng này. Có một vài dạng string decrypter
bạn có thể lựa chọn trong de4dot:
Trong trường hợp này chugns ta sẽ sử dụng ‘emulate’. Nhưng để sử dụng được string decrypter chúng ta cần
phải có token (nôm na là địa chỉ các thành phần của chương trình lưu trong metadata của .NET file). Trong
trường hợp của smethod_2(), ta sẽ xem trong DnSpy:
Thật không may, DotNetPatcher sử dụng các hàm decrypt string riêng biệt cho mỗi 1 string. Nhìn vào class
chứa smethod_2():
5. Trang 5
Tất cả các method ở dưới smethod_1(byte*+) đều là các method dùng dể decrypt string. Cho nên chúng ta cần
phải lấy token của tất cả các method này, sau đó chạy de4dot với tham số như sau:
de4dot.exe "C:Dumpsdumped-cleaned.exe" --strtyp emulate --strtok 0600001b --str
tok
0600001c --strtok 0600001d …
(dấu “…” ở cuối có nghĩa là ghi lần lượt các token của method decrypt string cho đến khi hết, theo cùng 1
dạng “—strtok <token_value>”).
Sau khi de4dot hoạt động xong, mở file mới tạo ra bởi de4dot trong DnSpy:
Vậy là chúng ta đã thành công. File đã được unpack, các string được decrypt và có thể đọc được dễ dang, file
mới này cũng hoạt động ổn định.
Cảm ơn vì đã đọc
This article is originally created by ubbelol, and has been translated into Vietnamese by me (Levis), so I’m not
the author of it. All credits go to him. Any suggests for better translation in future, feel free to contact me:
levintaeyeon[at]live[dot]com or my personal blog: http://ltops9.wordpress.com
Enjoy and Best Regards
Levis
Created Aug 3 2014