SlideShare a Scribd company logo
1 of 6
Download to read offline
Trang 1
Phân tích confuser 1.9.0.0
Constant Protection
Tác giả: ubbelol (http://ubbecode.wordpress.com)
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.
Constant Protection là gì?
Khi một chương trình .NET được biên dịch mà không có bất kì biện pháp bảo vệ nào, thì mọi người đều có thể sử dụng một
trình decompiler để dịch ngược và xem IL code. Tôi biết, bạn đã hiểu điều này trước khi đọc bài viết này của tôi. Một khi đã
có thể xem được IL code, cũng đồng nghĩa với việc người ta có thể xem được tất cả các giá trị bất biến (hay còn gọi là hằng,
“constant values”) trong chương trình của bạn. Dưới đây là một ví dụ:
Bạn có thể nhìn thấy 2 giá trị bất biến (trong trường hợp này là 2 string), được sử dụng trong code. Trong ví dụ trên, 2 tring
đó không mang ý nghĩa gì quá đặc biệ cả, nhưng trong một vài trường hợp đặc biệt, có một vài dữ liệu quan trọng mà bạn
cần phải giữ kín, và tìm cách giấu càng kĩ càng tốt. Việc này không chỉ giới hạn ở các string, mà còn có thể áp dụng cả với các
dữ liệu là các số.
Bây giờ, nếu chúng ta sử dụng “constant confusion của Confuser, thì code của ví dụ phía trên nhìn sẽ như thế này:
Hãy để ý vào cái cách mà 2 string ban đầu đã bị thay đổi bởi 2 lệnh call đến method với chúng 1 kiểu tham số, trong trường
hợp này là 2 string sẽ được đưa vào. Việc xác định kiểu tham số đưa vào rất quan trọng, tôi sẽ nói đến điều này sau. Nhưng
mục đích chính ở đây chính là việc giấu đi các giá trị bất biến để không bị nhìn thấy. Nhưng để chương trình vẫn có thể hoạt
động được bình thường, thì các giá trị bất biến này vẫn phải tồn tại. Có nghĩa là giá trị gốc được ẩn giấu đâu đó trong file, và
đó chính là những gì chúng ta cần phải tìm.
Trang 2
Cách hoạt động như thế nào?
Chúng ta sẽ bắt đầu bằng việc xem thử những method mà Confuser thêm vào trong file của chúng ta khi thực hiện việc
obfuscate. Nếu chúng ta mò theo lệnh call thực hiện việc thay đổi các string gốc trong hàm Main(), chúng ta sẽ thấy như
sau:
Method được đánh dấu bằng màu xám là 1 trong 2 lệnh call đầu tiên. Nhưng hãy chú ý thêm rằng: ở đây có 3 method với
kiểu của các tham số truyền vào giốn y hệt nhau (tất nhiên là các method này có tên khác nhau). Tại sao lại như vậy? Thực
sự thì tôi cũng không dám chắc chắn. Trong chương trình chỉ có 2 string cần phải decrypt, nhưng tại sao ở đây lại có đến 3
method? Không chỉ như thế, những phần code bên trên, khi mở ra xem đều chứa rất nhiều những method kiểu như thế
này.
Nếu như chúng ta mò theo lệnh call thứ 2 nằm trong method Main(), chúng ta sẽ thấy rằng nó không sử dụng cùng method
với lệnh call đầu tiên. Như vậy chúng ta có thể đặt ra 1 giả thuyết là Confuser không dùng 1 decrypt method cho tất cả các
giá trị bất biến trong chương trình, mà mỗi giá trị này sẽ được decrypt bằng 1 method riêng biệt. Nếu trong chương trình
của chúng ta có nhiều các giá trị bất biến hơn, thì bạn sẽ thấy rằng, có những method làm nhiệm vụ decrypt không chỉ một
giá trị bất biến (mà có thể nhiều hơn, 2 hoặc 3…). Vậy thì ở đây, những method khác, nằm ngoài 2 lệnh call trong chương
trình của chúng ta đang nghiên cứu, có tác dụng gì? Chúng không được sử dụng. Nếu chúng ta sử dụng tính năng Analyzer
trong .NET Reflector, chúng ta sẽ thấy không có phần code nào sử dụng đến chúng cả:
Trang 3
Bây giờ cứ thử xem code của một trong các method đó trước, để xem nó làm những gì:
Trang 4
Chữ nhật màu xanh lục là một ví dụ điển hình cho cơ chế “Constant Mutation, bạn có thể đọc thêm trong phần “Constant
Mutation là gì?” nằm ở phía dưới.
Chữ nhật màu đỏ đánh dấu phần cần phải quan tâm trong code của method này. Nếu chúng ta bấm vào thành phần đó,
chúng ta sẽ thấy nó sử dụng static Dictionary<uint, object>. Giả thuyết chúng ta có thể đặt ra ở đây, kèm theo sự liên hệ
với dòng cuối cùng trong phần code được đánh dấu bằng chữ nhật màu da cam( 殧Ī팻깲ઽ㗈嫻[key] = obj2; ) là chương
trình có vẻ như đang thêm các string đã được decrypt vào trong 1 dictionary. Việc này nhằm mục đích giúp cho quá trình
decrypt hiệu quả hơn, chỉ cần thực hiện 1 lần, thay vì việc phải decrypt một giá trị bất biến nhiều lần.
Chữ nhật màu xanh dương cũng khá thú vị bởi vì chúng ta có thể đoán rằng đây chính là phần bắt đầu quá trình decrypt.
Chúng ta nhìn thấy rằng chương trình đang thử lấy một giá trị bất biến từ trong dictionary ra. Và nếu giá trị được lấy ra
thành công, thì chương trình sẽ thực hiện đến dòng này. Nhưng chúng ta nhìn thấy có một tham chiếu đến một thành phần
khác ở đây. Nếu chúng ta mò theo sẽ thấy ( static byte[] ꙿ템韐擑㝜⎳넠; ). Chương trình đang cố gắng copy dữ liệu từ 1
mảng static byte sang 1 mảng mới tạo khác (destinationArray). Có nghĩa là chương trình đã có dữ liệu lưu trong mảng này
từ trước đó. Vậy là mảng byte này đã được khởi tạo và gán giá trị ở một nơi nào đó trong code.
Chữ nhật màu da cam là thuật toán dùng để decrypt. Thuật toán này không phức tạp cho lắm, vậy nên tôi không nghĩ rằng
tôi sẽ phải giải thích quá nhiều.
Vậy nên nếu mảng static byte ở trong chữ nhật màu xanh được gán giá trị từ trước ở đâu đó, thì chúng ta cần phải tìm ra.
Sử dụng chức năng Analyzer trong .NET Reflector chúng ta sẽ thấy:
Ta có thể thấy rằng method constructor của <Module> đã làm gì đó với mảng byte, vậy nên thử xem code của phần này
xem sao:
Trang 5
Chữ nhật màu xanh lục cho thấy chương trình đang cố lấy một vài dữ liệu trong resource của file. Vậy nên chúng ta biết
được phần giá trị bất biến bị encrypt được giấu trong resource đó.
Chữ nhật màu da cam cho thấy các giá trị bất biến được giấu kĩ bên trong resource. Có thể thấy là cả 1 CryptoStream và
Deflatestream được khởi tạo, có nghĩa là phần resource đó vừa bị nén và vừa bị encrypt. Sauk hi dữ liệu được giải nén và
decrypt, phần dữ liệu này được lưu vào stream2.
Chữ nhật màu đỏ chính xác là mục đích mà ta phải xem code của method này. Nó gán giá trị của mảng static byte với phần
dữ liệu đã được giải nén và decrypt đang được lưu trong stream2. Đây chính là nơi lưu trữ các giá trị bất biến đang bị
encrypt.
Đến giờ thì chúng ta đã có một số thông tin quan trọng về cơ chế hoạt động của chương trình. <Module>.cctor gán giá trị
cho 1 mảng byte bằng các dữ liệu đã được decrypt và giải nén lấy từ trong 1 trong các resource có trong file. Mảng byte này
được method decrypt sử dụng để decrypt và trả về giá trị gốc (chưa bị encrypt) khi chương trình hoạt động.
Làm cách nào để dịch ngược?
Có 2 cách để bạn làm điều này. Tôi sẽ chỉ cho bạn cách làm dễ dang trước. Sử dụng namespace System.Reflection và
method invocation để decrypt string.
Như tôi đã nói từ trước, không phải tất cả các method decrypt được sử dụng. Vậy nên việc phải làm đầu tiên là duyệt qua
từng method để xem trong các method đó, method nào được chương trình sử dụng.
Khi ta đã có danh sách các method được sử dụng, ta sẽ thử phân tích code của nơi sử dụng các method đó. Bạn có thể thấy
chúng tương tự như sau:
Việc cần làm là phải lấy 2 tham số đưa vào của lệnh call. Trong hình này, tham số đầu tiên là (uint)2102436103 và tham số
thứ 2 là (ulong)1051137580331621051. Với thông tin này, chúng ta có thể gọi method nhằm mục đích lấy dữ liệu đã được
decrypt:
Trang 6
string plain = Method.Invoke((uint)2102436103, (ulong)1051137580331621051);
Dòng code trên chỉ là pseudocode (mã giả), nhưng bạn cần phải hiểu được ý tưởng của phần này. Mặc dù vậy, tôi không
khuyến khích sử dụng phương pháp này bởi vì nó khôn an toàn. Trên lý thuyết, bất cứ ai cũng có thể tạo ra 1 backdoor
trong method decrypt, và backdoor này sẽ hoạt động khi bạn tiến hành gọi method đó lên. Đó mới chỉ là 1 trong những lý
do cơ bản để giải thích tại sao tôi không sử dụng phương pháp này.
Phần tiếp theo sẽ phức tạp hơn một chút.
Constant Mutation là gì?
Khi chúng ta obfuscate một file bằng Confuser 1.9.0.0, nó sẽ thêm một đống code vào bên trong chương trình của bạn, tùy
theo những phương pháp bảo vệ bạn đã chọn. Và trong các code này thường hay chứa một vài giá trị bất biến rất quan
trọng cho quá trình obfuscate. Những gì confuser làm là chia nhỏ các giá trị bất biến này thành 1 vài biểu thức tính toán
khiến cho việc đọc được các giá trị này trở lên khó hơn. Tuy nhiên trong những file giống như tôi đang minh họa ở đây thì
việc này không quá khó, chúng ta có thể tự thực heienj các biểu thức tính toán để lấy được giá trị bị giấu đi. Ví dụ:
ulong num2 = (ulong) (283444889455579286L + (3461447140L + -2064217636L));
có thể được tính thành:
ulong num2 = 283444890852808790;
Mặc dù việc làm thủ công thì khá dễ dàng, nhưng tôi nhanh chóng gặp phải 1 vấn đề khi cố gắng viết một chương trình tự
động làm việc này. Là bởi vì nếu num2 được khai báo giống như trong ví dụ phía trên, thì chỉ cần 1 lệnh ldc.i8
283444890852808790 là đủ. Nhưng trong code áp dụng mutation, thì sẽ như sau:
ldc.i8 283444889455579286
ldc.i8 3461447140
ldc.i8 -2064217636
add
add
Tôi sẽ giải thích chi tiết hơn tại sao việc này lại trở lên khó khăn như vậy, và một ví dụ để cho bạn thấy bạn sẽ phải làm như
thế nào. Nhưng nó không thực sự phù hợp với mục đích của bài viết này, vậy lên tôi sẽ nói sau này, trong những bài viết
khác. Tôi chỉ muốn cho bạn một cái nhìn tổng quát về “mutation” mà tôi đã nhắc đến trong bài.
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: lvintaeyeon[at]live[dot]com or
my personal blog: http://ltops9.wordpress.com
Enjoy and best regards
Levis
Created Aug 12 2014

More Related Content

What's hot

Các công cụ cần thiết cho quá trình Reverse Engineering .NET (bản đầy đủ)
Các công cụ cần thiết cho quá trình Reverse Engineering .NET (bản đầy đủ)Các công cụ cần thiết cho quá trình Reverse Engineering .NET (bản đầy đủ)
Các công cụ cần thiết cho quá trình Reverse Engineering .NET (bản đầy đủ)Levis Nickaster
 
Hướng dẫn deobfuscate DotnetPatcher 3.1 - Bài dịch
Hướng dẫn deobfuscate DotnetPatcher 3.1 - Bài dịchHướng dẫn deobfuscate DotnetPatcher 3.1 - Bài dịch
Hướng dẫn deobfuscate DotnetPatcher 3.1 - Bài dịchLevis Nickaster
 
Những thuật ngữ thường gặp trong Reverse Engineering .NET
Những thuật ngữ thường gặp trong Reverse Engineering .NETNhững thuật ngữ thường gặp trong Reverse Engineering .NET
Những thuật ngữ thường gặp trong Reverse Engineering .NETLevis Nickaster
 
Tài liệu lập trình PHP từ căn bản đến nâng cao
Tài liệu lập trình PHP từ căn bản đến nâng caoTài liệu lập trình PHP từ căn bản đến nâng cao
Tài liệu lập trình PHP từ căn bản đến nâng caoZendVN
 
Cac giai phap_lap_trinh_c___final_[bookbooming.com]
Cac giai phap_lap_trinh_c___final_[bookbooming.com]Cac giai phap_lap_trinh_c___final_[bookbooming.com]
Cac giai phap_lap_trinh_c___final_[bookbooming.com]bookbooming1
 
Core java 2
Core java 2Core java 2
Core java 2. .
 
Lap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_caoLap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_caoBác Luân
 
Core java 3
Core java 3Core java 3
Core java 3. .
 
Core java 7
Core java 7Core java 7
Core java 7. .
 
Thực hành lập trình led đơn codientu.info--
Thực hành lập trình led đơn   codientu.info--Thực hành lập trình led đơn   codientu.info--
Thực hành lập trình led đơn codientu.info--trungnb22
 
Core java 8
Core java 8Core java 8
Core java 8. .
 
Lớp 8: Bai thuc hanh 1
Lớp 8: Bai thuc hanh 1Lớp 8: Bai thuc hanh 1
Lớp 8: Bai thuc hanh 1Heo_Con049
 

What's hot (19)

Các công cụ cần thiết cho quá trình Reverse Engineering .NET (bản đầy đủ)
Các công cụ cần thiết cho quá trình Reverse Engineering .NET (bản đầy đủ)Các công cụ cần thiết cho quá trình Reverse Engineering .NET (bản đầy đủ)
Các công cụ cần thiết cho quá trình Reverse Engineering .NET (bản đầy đủ)
 
Hướng dẫn deobfuscate DotnetPatcher 3.1 - Bài dịch
Hướng dẫn deobfuscate DotnetPatcher 3.1 - Bài dịchHướng dẫn deobfuscate DotnetPatcher 3.1 - Bài dịch
Hướng dẫn deobfuscate DotnetPatcher 3.1 - Bài dịch
 
Những thuật ngữ thường gặp trong Reverse Engineering .NET
Những thuật ngữ thường gặp trong Reverse Engineering .NETNhững thuật ngữ thường gặp trong Reverse Engineering .NET
Những thuật ngữ thường gặp trong Reverse Engineering .NET
 
Bai 8
Bai 8Bai 8
Bai 8
 
Tài liệu lập trình PHP từ căn bản đến nâng cao
Tài liệu lập trình PHP từ căn bản đến nâng caoTài liệu lập trình PHP từ căn bản đến nâng cao
Tài liệu lập trình PHP từ căn bản đến nâng cao
 
Cac giai phap_lap_trinh_c___final_[bookbooming.com]
Cac giai phap_lap_trinh_c___final_[bookbooming.com]Cac giai phap_lap_trinh_c___final_[bookbooming.com]
Cac giai phap_lap_trinh_c___final_[bookbooming.com]
 
Web201 slide 3
Web201   slide 3Web201   slide 3
Web201 slide 3
 
Core java 2
Core java 2Core java 2
Core java 2
 
Lap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_caoLap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_cao
 
Web201 slide 4
Web201   slide 4Web201   slide 4
Web201 slide 4
 
Core java 3
Core java 3Core java 3
Core java 3
 
Core java 7
Core java 7Core java 7
Core java 7
 
Thực hành lập trình led đơn codientu.info--
Thực hành lập trình led đơn   codientu.info--Thực hành lập trình led đơn   codientu.info--
Thực hành lập trình led đơn codientu.info--
 
Web201 slide 5
Web201   slide 5Web201   slide 5
Web201 slide 5
 
Baigiang01 mo dau
Baigiang01 mo dauBaigiang01 mo dau
Baigiang01 mo dau
 
Core java 8
Core java 8Core java 8
Core java 8
 
C# coban
C# cobanC# coban
C# coban
 
Lớp 8: Bai thuc hanh 1
Lớp 8: Bai thuc hanh 1Lớp 8: Bai thuc hanh 1
Lớp 8: Bai thuc hanh 1
 
File trong c_
File trong c_File trong c_
File trong c_
 

Similar to Phân tích Confuser 1.9.0.0 - Constant Protection - Bản dịch

Seminar clean code
Seminar clean codeSeminar clean code
Seminar clean codeNguyen Thieu
 
Lap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_caoLap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_caoHuy Nguyễn
 
Tu-Hoc-Python-Co-Ban-Trong-10-Phut-NIIT
Tu-Hoc-Python-Co-Ban-Trong-10-Phut-NIITTu-Hoc-Python-Co-Ban-Trong-10-Phut-NIIT
Tu-Hoc-Python-Co-Ban-Trong-10-Phut-NIITNIIT - ICT Hà Nội
 
Tiểu+luận+antoan
Tiểu+luận+antoanTiểu+luận+antoan
Tiểu+luận+antoanBùi Quân
 
Chuong 1. tong quan
Chuong 1. tong quanChuong 1. tong quan
Chuong 1. tong quanVũ Nam
 
An Toàn và bảo mật HTTT-Cơ bản về mã hoá (cryptography)
An Toàn và bảo mật HTTT-Cơ bản về mã hoá (cryptography)An Toàn và bảo mật HTTT-Cơ bản về mã hoá (cryptography)
An Toàn và bảo mật HTTT-Cơ bản về mã hoá (cryptography)dlmonline24h
 
BÀI 3: Các khái niệm cơ bản trong lập trình - Giáo trình FPT
BÀI 3: Các khái niệm cơ bản trong lập trình - Giáo trình FPTBÀI 3: Các khái niệm cơ bản trong lập trình - Giáo trình FPT
BÀI 3: Các khái niệm cơ bản trong lập trình - Giáo trình FPTMasterCode.vn
 
Lập trình C cho VĐK 8051
Lập trình C cho VĐK 8051Lập trình C cho VĐK 8051
Lập trình C cho VĐK 8051Mr Giap
 
Bồi dưỡng HSG Tin chuyên đề thuật toán
Bồi dưỡng HSG Tin chuyên đề thuật toánBồi dưỡng HSG Tin chuyên đề thuật toán
Bồi dưỡng HSG Tin chuyên đề thuật toánNguyễn Đức
 
Kĩ thuật phân tích và thiết kế g
Kĩ thuật phân tích và thiết kế gKĩ thuật phân tích và thiết kế g
Kĩ thuật phân tích và thiết kế gthiendthu2008
 
Lect04 functions
Lect04 functionsLect04 functions
Lect04 functionsHồ Lợi
 
Ky thuat do khoa wep cua mang wi fi
Ky thuat do khoa wep cua mang wi fiKy thuat do khoa wep cua mang wi fi
Ky thuat do khoa wep cua mang wi fiMonera Mark
 
Báo cáo tốt nghiệp Android RSA mã hóa
Báo cáo tốt nghiệp Android RSA mã hóaBáo cáo tốt nghiệp Android RSA mã hóa
Báo cáo tốt nghiệp Android RSA mã hóaPhạm Trung Đức
 

Similar to Phân tích Confuser 1.9.0.0 - Constant Protection - Bản dịch (20)

Seminar clean code
Seminar clean codeSeminar clean code
Seminar clean code
 
Chuong 01
Chuong 01Chuong 01
Chuong 01
 
Chuong 01 mo dau
Chuong 01 mo dauChuong 01 mo dau
Chuong 01 mo dau
 
Lap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_caoLap trinh c_tu_co_ban_den_nang_cao
Lap trinh c_tu_co_ban_den_nang_cao
 
Tu-Hoc-Python-Co-Ban-Trong-10-Phut-NIIT
Tu-Hoc-Python-Co-Ban-Trong-10-Phut-NIITTu-Hoc-Python-Co-Ban-Trong-10-Phut-NIIT
Tu-Hoc-Python-Co-Ban-Trong-10-Phut-NIIT
 
Học python
Học pythonHọc python
Học python
 
Tiểu+luận+antoan
Tiểu+luận+antoanTiểu+luận+antoan
Tiểu+luận+antoan
 
Chuong 1. tong quan
Chuong 1. tong quanChuong 1. tong quan
Chuong 1. tong quan
 
An Toàn và bảo mật HTTT-Cơ bản về mã hoá (cryptography)
An Toàn và bảo mật HTTT-Cơ bản về mã hoá (cryptography)An Toàn và bảo mật HTTT-Cơ bản về mã hoá (cryptography)
An Toàn và bảo mật HTTT-Cơ bản về mã hoá (cryptography)
 
BÀI 3: Các khái niệm cơ bản trong lập trình - Giáo trình FPT
BÀI 3: Các khái niệm cơ bản trong lập trình - Giáo trình FPTBÀI 3: Các khái niệm cơ bản trong lập trình - Giáo trình FPT
BÀI 3: Các khái niệm cơ bản trong lập trình - Giáo trình FPT
 
Lập trình C cho VĐK 8051
Lập trình C cho VĐK 8051Lập trình C cho VĐK 8051
Lập trình C cho VĐK 8051
 
Vb6 16 (10)
Vb6 16 (10)Vb6 16 (10)
Vb6 16 (10)
 
Th.nhapmon lt
Th.nhapmon ltTh.nhapmon lt
Th.nhapmon lt
 
Bồi dưỡng HSG Tin chuyên đề thuật toán
Bồi dưỡng HSG Tin chuyên đề thuật toánBồi dưỡng HSG Tin chuyên đề thuật toán
Bồi dưỡng HSG Tin chuyên đề thuật toán
 
temp.pdf
temp.pdftemp.pdf
temp.pdf
 
Kĩ thuật phân tích và thiết kế g
Kĩ thuật phân tích và thiết kế gKĩ thuật phân tích và thiết kế g
Kĩ thuật phân tích và thiết kế g
 
Debug trong c
Debug trong cDebug trong c
Debug trong c
 
Lect04 functions
Lect04 functionsLect04 functions
Lect04 functions
 
Ky thuat do khoa wep cua mang wi fi
Ky thuat do khoa wep cua mang wi fiKy thuat do khoa wep cua mang wi fi
Ky thuat do khoa wep cua mang wi fi
 
Báo cáo tốt nghiệp Android RSA mã hóa
Báo cáo tốt nghiệp Android RSA mã hóaBáo cáo tốt nghiệp Android RSA mã hóa
Báo cáo tốt nghiệp Android RSA mã hóa
 

Phân tích Confuser 1.9.0.0 - Constant Protection - Bản dịch

  • 1. Trang 1 Phân tích confuser 1.9.0.0 Constant Protection Tác giả: ubbelol (http://ubbecode.wordpress.com) 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. Constant Protection là gì? Khi một chương trình .NET được biên dịch mà không có bất kì biện pháp bảo vệ nào, thì mọi người đều có thể sử dụng một trình decompiler để dịch ngược và xem IL code. Tôi biết, bạn đã hiểu điều này trước khi đọc bài viết này của tôi. Một khi đã có thể xem được IL code, cũng đồng nghĩa với việc người ta có thể xem được tất cả các giá trị bất biến (hay còn gọi là hằng, “constant values”) trong chương trình của bạn. Dưới đây là một ví dụ: Bạn có thể nhìn thấy 2 giá trị bất biến (trong trường hợp này là 2 string), được sử dụng trong code. Trong ví dụ trên, 2 tring đó không mang ý nghĩa gì quá đặc biệ cả, nhưng trong một vài trường hợp đặc biệt, có một vài dữ liệu quan trọng mà bạn cần phải giữ kín, và tìm cách giấu càng kĩ càng tốt. Việc này không chỉ giới hạn ở các string, mà còn có thể áp dụng cả với các dữ liệu là các số. Bây giờ, nếu chúng ta sử dụng “constant confusion của Confuser, thì code của ví dụ phía trên nhìn sẽ như thế này: Hãy để ý vào cái cách mà 2 string ban đầu đã bị thay đổi bởi 2 lệnh call đến method với chúng 1 kiểu tham số, trong trường hợp này là 2 string sẽ được đưa vào. Việc xác định kiểu tham số đưa vào rất quan trọng, tôi sẽ nói đến điều này sau. Nhưng mục đích chính ở đây chính là việc giấu đi các giá trị bất biến để không bị nhìn thấy. Nhưng để chương trình vẫn có thể hoạt động được bình thường, thì các giá trị bất biến này vẫn phải tồn tại. Có nghĩa là giá trị gốc được ẩn giấu đâu đó trong file, và đó chính là những gì chúng ta cần phải tìm.
  • 2. Trang 2 Cách hoạt động như thế nào? Chúng ta sẽ bắt đầu bằng việc xem thử những method mà Confuser thêm vào trong file của chúng ta khi thực hiện việc obfuscate. Nếu chúng ta mò theo lệnh call thực hiện việc thay đổi các string gốc trong hàm Main(), chúng ta sẽ thấy như sau: Method được đánh dấu bằng màu xám là 1 trong 2 lệnh call đầu tiên. Nhưng hãy chú ý thêm rằng: ở đây có 3 method với kiểu của các tham số truyền vào giốn y hệt nhau (tất nhiên là các method này có tên khác nhau). Tại sao lại như vậy? Thực sự thì tôi cũng không dám chắc chắn. Trong chương trình chỉ có 2 string cần phải decrypt, nhưng tại sao ở đây lại có đến 3 method? Không chỉ như thế, những phần code bên trên, khi mở ra xem đều chứa rất nhiều những method kiểu như thế này. Nếu như chúng ta mò theo lệnh call thứ 2 nằm trong method Main(), chúng ta sẽ thấy rằng nó không sử dụng cùng method với lệnh call đầu tiên. Như vậy chúng ta có thể đặt ra 1 giả thuyết là Confuser không dùng 1 decrypt method cho tất cả các giá trị bất biến trong chương trình, mà mỗi giá trị này sẽ được decrypt bằng 1 method riêng biệt. Nếu trong chương trình của chúng ta có nhiều các giá trị bất biến hơn, thì bạn sẽ thấy rằng, có những method làm nhiệm vụ decrypt không chỉ một giá trị bất biến (mà có thể nhiều hơn, 2 hoặc 3…). Vậy thì ở đây, những method khác, nằm ngoài 2 lệnh call trong chương trình của chúng ta đang nghiên cứu, có tác dụng gì? Chúng không được sử dụng. Nếu chúng ta sử dụng tính năng Analyzer trong .NET Reflector, chúng ta sẽ thấy không có phần code nào sử dụng đến chúng cả:
  • 3. Trang 3 Bây giờ cứ thử xem code của một trong các method đó trước, để xem nó làm những gì:
  • 4. Trang 4 Chữ nhật màu xanh lục là một ví dụ điển hình cho cơ chế “Constant Mutation, bạn có thể đọc thêm trong phần “Constant Mutation là gì?” nằm ở phía dưới. Chữ nhật màu đỏ đánh dấu phần cần phải quan tâm trong code của method này. Nếu chúng ta bấm vào thành phần đó, chúng ta sẽ thấy nó sử dụng static Dictionary<uint, object>. Giả thuyết chúng ta có thể đặt ra ở đây, kèm theo sự liên hệ với dòng cuối cùng trong phần code được đánh dấu bằng chữ nhật màu da cam( 殧Ī팻깲ઽ㗈嫻[key] = obj2; ) là chương trình có vẻ như đang thêm các string đã được decrypt vào trong 1 dictionary. Việc này nhằm mục đích giúp cho quá trình decrypt hiệu quả hơn, chỉ cần thực hiện 1 lần, thay vì việc phải decrypt một giá trị bất biến nhiều lần. Chữ nhật màu xanh dương cũng khá thú vị bởi vì chúng ta có thể đoán rằng đây chính là phần bắt đầu quá trình decrypt. Chúng ta nhìn thấy rằng chương trình đang thử lấy một giá trị bất biến từ trong dictionary ra. Và nếu giá trị được lấy ra thành công, thì chương trình sẽ thực hiện đến dòng này. Nhưng chúng ta nhìn thấy có một tham chiếu đến một thành phần khác ở đây. Nếu chúng ta mò theo sẽ thấy ( static byte[] ꙿ템韐擑㝜⎳넠; ). Chương trình đang cố gắng copy dữ liệu từ 1 mảng static byte sang 1 mảng mới tạo khác (destinationArray). Có nghĩa là chương trình đã có dữ liệu lưu trong mảng này từ trước đó. Vậy là mảng byte này đã được khởi tạo và gán giá trị ở một nơi nào đó trong code. Chữ nhật màu da cam là thuật toán dùng để decrypt. Thuật toán này không phức tạp cho lắm, vậy nên tôi không nghĩ rằng tôi sẽ phải giải thích quá nhiều. Vậy nên nếu mảng static byte ở trong chữ nhật màu xanh được gán giá trị từ trước ở đâu đó, thì chúng ta cần phải tìm ra. Sử dụng chức năng Analyzer trong .NET Reflector chúng ta sẽ thấy: Ta có thể thấy rằng method constructor của <Module> đã làm gì đó với mảng byte, vậy nên thử xem code của phần này xem sao:
  • 5. Trang 5 Chữ nhật màu xanh lục cho thấy chương trình đang cố lấy một vài dữ liệu trong resource của file. Vậy nên chúng ta biết được phần giá trị bất biến bị encrypt được giấu trong resource đó. Chữ nhật màu da cam cho thấy các giá trị bất biến được giấu kĩ bên trong resource. Có thể thấy là cả 1 CryptoStream và Deflatestream được khởi tạo, có nghĩa là phần resource đó vừa bị nén và vừa bị encrypt. Sauk hi dữ liệu được giải nén và decrypt, phần dữ liệu này được lưu vào stream2. Chữ nhật màu đỏ chính xác là mục đích mà ta phải xem code của method này. Nó gán giá trị của mảng static byte với phần dữ liệu đã được giải nén và decrypt đang được lưu trong stream2. Đây chính là nơi lưu trữ các giá trị bất biến đang bị encrypt. Đến giờ thì chúng ta đã có một số thông tin quan trọng về cơ chế hoạt động của chương trình. <Module>.cctor gán giá trị cho 1 mảng byte bằng các dữ liệu đã được decrypt và giải nén lấy từ trong 1 trong các resource có trong file. Mảng byte này được method decrypt sử dụng để decrypt và trả về giá trị gốc (chưa bị encrypt) khi chương trình hoạt động. Làm cách nào để dịch ngược? Có 2 cách để bạn làm điều này. Tôi sẽ chỉ cho bạn cách làm dễ dang trước. Sử dụng namespace System.Reflection và method invocation để decrypt string. Như tôi đã nói từ trước, không phải tất cả các method decrypt được sử dụng. Vậy nên việc phải làm đầu tiên là duyệt qua từng method để xem trong các method đó, method nào được chương trình sử dụng. Khi ta đã có danh sách các method được sử dụng, ta sẽ thử phân tích code của nơi sử dụng các method đó. Bạn có thể thấy chúng tương tự như sau: Việc cần làm là phải lấy 2 tham số đưa vào của lệnh call. Trong hình này, tham số đầu tiên là (uint)2102436103 và tham số thứ 2 là (ulong)1051137580331621051. Với thông tin này, chúng ta có thể gọi method nhằm mục đích lấy dữ liệu đã được decrypt:
  • 6. Trang 6 string plain = Method.Invoke((uint)2102436103, (ulong)1051137580331621051); Dòng code trên chỉ là pseudocode (mã giả), nhưng bạn cần phải hiểu được ý tưởng của phần này. Mặc dù vậy, tôi không khuyến khích sử dụng phương pháp này bởi vì nó khôn an toàn. Trên lý thuyết, bất cứ ai cũng có thể tạo ra 1 backdoor trong method decrypt, và backdoor này sẽ hoạt động khi bạn tiến hành gọi method đó lên. Đó mới chỉ là 1 trong những lý do cơ bản để giải thích tại sao tôi không sử dụng phương pháp này. Phần tiếp theo sẽ phức tạp hơn một chút. Constant Mutation là gì? Khi chúng ta obfuscate một file bằng Confuser 1.9.0.0, nó sẽ thêm một đống code vào bên trong chương trình của bạn, tùy theo những phương pháp bảo vệ bạn đã chọn. Và trong các code này thường hay chứa một vài giá trị bất biến rất quan trọng cho quá trình obfuscate. Những gì confuser làm là chia nhỏ các giá trị bất biến này thành 1 vài biểu thức tính toán khiến cho việc đọc được các giá trị này trở lên khó hơn. Tuy nhiên trong những file giống như tôi đang minh họa ở đây thì việc này không quá khó, chúng ta có thể tự thực heienj các biểu thức tính toán để lấy được giá trị bị giấu đi. Ví dụ: ulong num2 = (ulong) (283444889455579286L + (3461447140L + -2064217636L)); có thể được tính thành: ulong num2 = 283444890852808790; Mặc dù việc làm thủ công thì khá dễ dàng, nhưng tôi nhanh chóng gặp phải 1 vấn đề khi cố gắng viết một chương trình tự động làm việc này. Là bởi vì nếu num2 được khai báo giống như trong ví dụ phía trên, thì chỉ cần 1 lệnh ldc.i8 283444890852808790 là đủ. Nhưng trong code áp dụng mutation, thì sẽ như sau: ldc.i8 283444889455579286 ldc.i8 3461447140 ldc.i8 -2064217636 add add Tôi sẽ giải thích chi tiết hơn tại sao việc này lại trở lên khó khăn như vậy, và một ví dụ để cho bạn thấy bạn sẽ phải làm như thế nào. Nhưng nó không thực sự phù hợp với mục đích của bài viết này, vậy lên tôi sẽ nói sau này, trong những bài viết khác. Tôi chỉ muốn cho bạn một cái nhìn tổng quát về “mutation” mà tôi đã nhắc đến trong bài. 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: lvintaeyeon[at]live[dot]com or my personal blog: http://ltops9.wordpress.com Enjoy and best regards Levis Created Aug 12 2014