Reverse .NET Software IV

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 29

Bài lưu trữ về Reverse .NET Software III 1.0.2.

9 Rongchaua

Reverse .NET Software IV


Patch và Strong name

www.reaonline.net

1 Giới thiệu_____________________________________________________________________ 2
2 Strong name (Định danh) ___________________________________________________ 3
2.1 Giới thiệu________________________________________________________________________ 3
2.2 Ứng dụng _______________________________________________________________________ 4
2.2.1 Chống giả mạo ___________________________________________________________________________ 4
2.2.2 Bảo mật _________________________________________________________________________________ 4
2.2.3 Khuyết điểm _____________________________________________________________________________ 5
2.3 Khởi động cùng strong name __________________________________________________ 5
2.4 Cách tạo strong name __________________________________________________________ 6
2.5 Bẻ khóa strong name của một assembly đơn _________________________________ 9
2.6 Kết luận ________________________________________________________________________ 10
3 Xóa strong name từ PE Header ____________________________________________ 11
3.1 Ý tưởng_________________________________________________________________________ 11
3.2 .NET file format ________________________________________________________________ 11
3.3 Kết luận ________________________________________________________________________ 16
4 Xóa strong name từ các assembly phụ thuộc _____________________________ 17
5 Xóa strong name bằng Tool________________________________________________ 22
6 Tổng kết_____________________________________________________________________ 23
7 Kiến thức bổ sung __________________________________________________________ 23
7.1 Import Table___________________________________________________________________ 24
7.1.1 Cấu trúc________________________________________________________________________________ 24
7.1.2 Ý nghĩa ________________________________________________________________________________ 27
7.2 Base Relocations Section _____________________________________________________ 27
8 Tài liệu tham khảo__________________________________________________________ 28
9 Lời kết _______________________________________________________________________ 29

Trang 1 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

1 Giới thiệu
• Trong phần III chúng ta đã tìm hiểu các phương pháp patch căn bản cũng như
một số loại bảo vệ thường gặp. Khi chúng ta thực hiện patch, chúng ta gần
như không gặp một khó khăn hoặc trở ngại nào, dù chúng ta thay đổi mã
nguồn, chỉnh sửa source code hoặc thậm chí xóa cả một đoạn code đi chăng
nữa.
• Sở dĩ chúng ta có thể thực hiện việc patch dễ dàng như vậy là do tác giả
không sử dụng một biện pháp phòng ngự nào cho phần mềm. Vì vậy công
việc patch diễn ra rất dễ dàng.
• Nếu như các bạn đã có kinh nghiệm hoặc cơ hội được làm quen các kiểu anti-
patch thế hệ ASM thì chắc cũng có biết qua về CRC Check hoặc MD5 Check.
Các giải thuật check này nhằm đảm bảo tính toàn vẹn và chính xác của một
tập tin. Thực tế, ban đầu các giải thuật check này được đưa vào ứng dụng ở
hệ thống thông tin và truyền tải dữ liệu nhằm để kiểm tra xem một gói dữ liệu
khi gởi đi có bị lỗi trên đường truyển tải hay không. Sau này, các nhà lập trình
đưa phương pháp này vào trong lĩnh vực kỹ thuật phần mềm nhằm chống lại
các cracker sử dụng kỹ thuật patch để patch sản phẩm của họ.
• Trong phần IV này chúng ta sẽ tìm hiểu một phương pháp để anti-patch cho
.NET. Tức là không cho các cracker có thể dễ dàng patch được các sản phẩm
.NET của chúng ta. Phương pháp này còn được ứng dụng trong các lĩnh vực
khác. Tuy nhiên ở đây chúng ta chỉ quan tâm đến khả năng anti-patch của
phương pháp này: đó là phương pháp dùng strong name.
• Tool strong name được tích hợp sẵn ngay trong bộ Visual Studio, cho nên
chúng ta cần cài đặt bộ Microsoft Visual Studio để sử dụng.
• Trước khi xem phần IV này tôi đề nghị các bạn nên xem lại phần III cũng như
các phần trước để nắm vững cách sử dụng các Tool và ôn lại kiến thức cơ sở.
Tôi sẽ không lặp lại các bước nếu như các bước này đã được nêu ở các phần
trước.
• Phần mềm sử dụng trong ví dụ này là (đã đính kèm):
o Sample Crackme with Strong name coded by rongchaua.
o Sample Crackme with Strong name in DLL coded by rongchaua.
• Tool sử dụng :
o Reflector : http://www.aisto.com/roeder/dotnet/
o ILASM và ILDASM: có sẵn khi cài bộ Microsoft Visual Studio .NET.
o IDA: http://www.idapro.com/
o UltraEdit: http://www.ultraedit.com/
o CFF Explorer http://ntcore.com/Files/Explorer_Suite_Setup.zip
o Strong Name Remove Tool: link down xem phần tham khảo.
• LƯU Ý: Do phiên bản Windows mà tôi sử dụng là tiếng Đức nên các bạn chịu
khó so sánh và đọc hướng dẫn. Hình chỉ mang tính chất minh họa.

Trang 2 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

2 Strong name (Định danh)

2.1 Giới thiệu

• Strong name (Định danh) là một dạng chữ ký kỹ thuật số. Nó cho phép chúng
ta “đánh dấu” một assembly sao cho assembly này là duy nhất.
• Một định danh cho assembly bao gồm có 5 phần:
o Một khóa chung: khóa chung của giải thuật RSA.
o Một tên đơn giản: là một chuỗi. Thông thường nó sẽ chứa tên của file
chứa assembly (không có phần mở rộng).
o Phiên bản: số phiên bản. Bao gồm 4 phần có dạng là
Major.Minor.Build.Revision
o Tùy chọn Culture (optional culture)
o Tùy chọn cấu trúc processor ( optional processor architectur)
• Cấu trúc của định danh được thể hiện thông qua hình sau

Version

Cấu trúc
processor,
Khóa chung,
Tên,
Culture

• Các bạn nên xem bài mã hóa RSA của rongchaua để hiểu thêm về chữ ký kỹ
thuật số cũng như cách kiểm tra một chữ ký kỹ thuật số để có được kiến thức
căn bản trước khi đọc tiếp các phần bên dưới. Nếu không các bạn sẽ cảm thấy
khó hiểu vì phần này khá rắc rối.
• Để quá trình định danh được chính xác, thông thường một assembly sẽ được
định danh trong quá trình xây dựng (build). Trong quá trình xây dựng này,
khóa riêng tương ứng với khóa chung ở trong định danh sẽ được sử dụng để
tạo ra chữ ký kỹ thuật số cho assembly (gọi là chữ ký định danh), và chữ ký
định danh này có thể được kiểm tra tính đúng đắn thông qua khóa chung ở
trong định danh.
• Có nhiều cách cũng như có nhiều kỹ thuật khác nhau để tạo một chữ ký định
danh cũng như để quản lý các khóa riêng dùng để ký này. Chúng ta sẽ làm
quen với kỹ thuật ký định danh trong các phần tiếp theo bên dưới.
• Để dễ hiểu chúng ta sẽ tìm hiểu cách thức hoạt động của chữ ký định danh
này.
• Ví dụ: khi một assembly A tham khảo một assembly B đã được định danh, thì
assembly A này sẽ có thông tin định danh từ assembly B (tức là có chữ ký
định danh khi build). Sau đó, nếu assembly A muốn khởi động assembly B,

Trang 3 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

.NET Framework sẽ nạp định danh của assembly B, kiểm tra thông tin về chữ
ký định danh (dùng khóa chung nằm trong định danh của assembly B để tính
ra chữ ký định danh). Nếu chữ ký định danh là hợp lệ (tức là chữ ký định danh
mà assembly A có phải giống chữ ký định danh .NET Framework vừa tính) thì
assembly B sẽ được load. Nếu không thì assembly B sẽ không được load.

2.2 Ứng dụng

2.2.1 Chống giả mạo


• Như chúng ta đã đề cập, ứng dụng của định danh là để thiết lập thuộc tính
cho một assembly là assembly này duy nhất. Điều này sẽ cho phép chúng ta
ngăn ngừa được tình trạng mã nguồn bị ăn cắp bởi các đối tượng nguy hiểm,
sau đó chỉnh sửa assembly với mục đích phá hoại, dùng tên của chúng ta để
ký và tiếp tục phân phối dưới tên của chúng ta.
• Tuy nhiên định dạnh không thể ngăn ngừa đối tượng nguy hiểm lấy toàn bộ
chữ ký định danh, sửa đổi assembly và ký lại bằng khóa của chúng và chuyển
đi tiếp tục dưới tên của chúng. Như vậy việc ký định danh giúp cho chúng ta
không bị giả mạo bởi một kẻ khác. Nhưng vẫn không thể ngăn được việc mất
mã nguồn vào tay các đối tượng nguy hiểm. Dù sao với chức năng chống giả
mạo trên cũng đã là một thế mạnh của việc sử dụng định danh.

2.2.2 Bảo mật


• Ngoài ra định danh còn hỗ trợ trong vấn đề bảo mật. Ví dụ: một công ty có
thể tin tưởng tất cả các mã nguồn đến từ mạng nội bộ của công ty, cũng như
các mã nguồn có mang chữ ký chung của công ty. Thế nhưng giả sử 2 công ty
có trao đổi mã nguồn với nhau. Và vấn đề được đặt ra là làm sao 2 công ty đó
có thể chắc chắn được là mã nguồn mà họ nhận được là từ phía đối tác? Lúc
này định danh sẽ vào cuộc. Nó cho phép cả 2 công ty có thể kiểm tra nguồn
gốc của mã nguồn dựa trên khóa chung nằm trong định danh. Nếu khóa
chung này đúng là từ phía đối tác thì sẽ đánh dấu là đáng tin còn không thì có
thể xóa đi.
• Một điều cần lưu ý là khóa riêng dùng để định danh nên cất giữ cẩn thận vì
chữ ký định danh sau khi gán xong thì không thể nào thu hồi lại được. Tại sao
chúng ta lại quan tâm đến vấn đề này? Rất đơn giản, đó là vì vấn đề giả mạo.
Giả sử công ty A là một công ty có uy tín về phần mềm. Sản phẩm của họ đều
được ký tên bằng chữ ký định danh. Một ngày đẹp trời nào đó, một tổ chức
cracker (criminal hacker) crack được khóa riêng hoặc bằng cách nào đó lấy
được khóa riêng để tạo một chữ ký định danh y chang như của công ty A. Và
kết quả là, nhóm cracker này có thể tung hàng loạt mã độc cũng như
virus,spyware… đến các khách hàng của của công ty A mà không lo sợ là các
mã độc này sẽ bị các khách hàng nghi ngờ.
• Vì vậy, việc sử dụng định danh nên cực kỳ cẩn thận và lúc nào cũng nhớ rằng
khóa riêng phải được cất giữ an toàn.

Trang 4 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

2.2.3 Khuyết điểm


• Việc sử dụng định danh làm cho quá trình xây dựng, nâng cấp và sửa chữa
code trở nên phức tạp hơn.
• Thứ nhất, khi một assembly đã định danh tham khảo đến các assembly khác
thì các assembly này cũng phải được định danh. Điều này có nghĩa là nếu
chúng ta tham khảo đến một assembly của một hãng khác, và assembly
không được ký định danh thì assembly của chúng cũng không thể nào ký định
danh.
• Thứ hai, việc ký định danh gây khó khăn trong việc đánh dấu phiên bản. Bởi
vì một assembly lúc nào cũng cố gắng để nạp phiên bản chính xác của một
assembly mà nó tham khảo đến. Cho nên, giả sử sau khi chúng ta sửa một lỗi
nào đó và nâng phiên bản từ 1.0.0.0 lên 1.0.0.1, thì mọi assembly tham khảo
đến assembly này đều không thể load assembly này lên được. Để khắc phục
lỗi này thì chúng ta bắt buộc phải build lại toàn bộ tất cả các assembly tham
khảo đến assembly này. Tuy nhiên trong một project lớn với hàng ngàn
assembly thì việc build này trở nên cực kỳ phức tạp và tốn nhiều thời gian lẫn
công sức.

2.3 Khởi động cùng strong name


• Bây giờ chúng ta thực hành lại bài kỳ trước và theo dõi sự khác biệt.
• Chạy file SampleCrackmewithStrongname.exe.
• Thực hiện các bước để Remove Nag đã nêu. Và kiểm tra xem coi chương trình
có chạy không.

• Oki, nhấn nút Don’t Send để đóng hộp thoại.


• Như vậy là tác giả crackme đã phủ đầu đòn đầu tiên. Chúng ta không còn có
thể patch dễ dàng như trước nữa. Việc patch đã dẫn đến sự khác biệt giữa chữ
ký vừa được tạo bởi .NET Framework khi chúng ta chạy chương trình với chữ

Trang 5 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

ký được tạo ra khi build chương trình và kết quả là chúng ta không thể thực
thi chương trình này được nữa.
• Do đó bây giờ chúng ta nên tìm hiểu làm thế nào để tạo một chữ ký định danh
để có thể gỡ bỏ hoặc nhảy qua chữ ký định danh này.

2.4 Cách tạo strong name


• Để tạo ra một chữ ký định danh, chúng ta trước tiên cần phải có 1 cặp khóa:
khóa chung và khóa riêng. Cặp khóa này sẽ được lưu trữ trong một file và vì
vậy cho phép chúng ta có thể lưu trữ cũng như bảo mật khóa riêng dễ dàng
hơn.
• Để tạo ra cặp khóa chung và khóa riêng này, chúng ta sẽ sử dụng một tool có
sẵn trong bộ Microsoft Visual Studio SDK: “sn.exe”.
• Trong cửa sổ Console di chuyển đến thư mục SDK của Microsoft Visual Studio
như hình dưới đây

Trang 6 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Ta gõ vào “sn -k strongname.snk”, nếu kết quả như hình dưới là ta đã tạo
được 1 cặp khóa thành công.

• Dùng Windows Explorer browse đến thư mục “…\SDK\v2.0\Bin” ta thấy xuất
hiện một file mới là strongname.snk.

• Bây giờ ta sẽ dùng định danh này để ký định danh một assembly.
• Các bạn có thể tự tạo cho mình một project bất kỳ để thực tập. Các bước dưới
đây chỉ mang tính hướng dẫn.
• Sau khi tạo được một Project. Chúng ta vào Menu Project -> Chọn Properties
như hình.

Trang 7 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Ta chọn Tab Signing, sau đó Browse đến file strongname.snk mà ta đã tạo ra.

• Ở đây chúng ta thấy rằng ngoài việc tạo strong name key file bằng console
chúng ta có thể tạo ngay trong Project bằng cách tại chỗ Sign the assembly,
chọn menu New và điền các thông số thích hợp. Sau khi nhấn Menu New hộp
thoại sau sẽ xuất hiện.

Trang 8 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Như trên đã nói việc bảo vệ khóa riêng rất là quan trọng cho nên ở đây ta
thấy rằng Microsoft Visual Studio .NET đã cho phép chúng ta một tùy chọn cài
đặt password cho key file nhằm tăng cường tính bảo mật cho cặp khóa này.
• Như vậy chúng ta thấy rằng có hai cách để tạo ra chữ ký định danh: console
và gui.
• Sau khi ký định danh xong, build lại chương trình. Và chúng ta thử thay đổi
bất cứ byte nào trong mã nguồn bằng một chương trình Hex Editor nào,
chúng ta đều sẽ gặp một thông báo lỗi như ban đầu đã đưa.

2.5 Bẻ khóa strong name của một assembly đơn


• Bây giờ chúng ta sẽ tìm cách vượt qua khóa định danh của một assembly bị
ký định danh.
• Các bạn dùng ILDASM để dump file SampleCrackmewithStrongName ra một
thư mục.
• Dùng Notepad để mở file này lên. Ngay vào đầu file là thông tin về các
assembly mà assembly SampleCrackme tham khảo đến

Trang 9 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Kéo xuống 1 chút ta sẽ thấy được thông tin của assembly SampleCrackme. Ở
đây ta thấy dạng khóa .publickeytoken của SampleCrackme khác biệt hơn
nhiều so với các assembly ở trên. Nó sử dụng khóa RSA để ký định dạng.

• Bây giờ chúng ta hãy disable chức năng kiểm tra strong name bằng cách đơn
giản là … xóa đoạn code đại diện cho định danh đi, tức là từ .publickey cho
đến hết .ver.
• Sau khi xóa chúng ta có hình như sau.

• Compile lại bằng ilasm, rồi chạy file vừa recompile, ta thấy chương trình chạy
tốt.
• Bây giờ chúng ta thực hiện lại các bước Remove Nag như ở bài III thì chương
trình sẽ chạy tốt và không còn bị crash nữa.

2.6 Kết luận


• Như vậy chúng ta đã phần nào tìm hiểu về strong name (định danh) và cách
remove nó ra khỏi assembly.
• Qua phương pháp trên, ta thấy rằng để nhận biết được một assembly bị định
danh thì ta có thể disassemble nó. Sau đó xem xét các thuộc tính .publickey
của các assembly, nếu có sử dụng khóa chung của RSA thì chắc chắn
assembly cũng như chương trình đó đã sử dụng định danh.
• Phương pháp trên là một phương pháp đơn giản để remove strong name. Tuy
nhiên để hiểu thêm về strong name chúng ta sẽ tìm hiểu một số phương pháp
khác cũng để remove strong name.

Trang 10 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

3 Xóa strong name từ PE Header

3.1 Ý tưởng
• Bây giờ chúng ta sẽ xem qua sự khác biệt giữa một assembly bị định danh và
một assembly không bị định danh dưới góc nhìn về thông tin của PE Header.
Sau đó chúng ta sẽ chỉnh sửa các khác biệt này để assembly trở nên giống
nhau, để đạt được mục đích là chúng ta sẽ xóa được chữ ký định danh.
• Đầu tiên chúng ta nên xem qua một chút về cấu trúc PE của một file .NET.

3.2 .NET file format


• Giống như thế hệ ASM, một file thuộc thế hệ .NET cũng gồm các section quan
trọng là
o .text
o .reloc
o .rsrc
• Dùng CFF Explorer mở file SampleCrackme.exe, mở đến phần Section Header
ta sẽ thấy những thông tin về 3 section trên

• Section .text sẽ chứa các thông tin về


o Import Table
o Import Address Table
o và .NET Section.
• Section .reloc sẽ giúp cho loader định vị lại các địa chỉ một cách chính xác.
• Section .rsrc sẽ chứa Icon chính của assembly, tất cả các resources sẽ được
lưu trong section .NET.
• Bên cạnh các section quan trọng trên, các phần mềm thuộc thế hệ .NET còn
có thêm .NET Directory. Đây là section quan trọng nó chứa tất cả các thiết lập
cần thiết để mô tả file để cho file hoạt động được. Định nghĩa về section này
chúng ta có thể tham khảo tại file CorHdr.h ,thông thường nằm tại
C:\Programme\Microsoft Visual Studio 8\SDK\v2.0\include

Trang 11 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Các thành phần của cấu trúc trên có ý nghĩa như sau:
o cb: Kích thước của cấu trúc.
o MajorRuntimeVersion và MinorRuntimeVersion: Phiên bản của CLR
Runtime.
o MetaData: Một thư mục dữ liệu (Data Directory) giữ thông tin về RVA và
kích thước của MetaData.
o Flags : Cờ, hỗ trợ các cờ sau:

o EntryPointToken và EntryPointRVA: Chỉ đến method EntryPoint. Tùy


theo cờ COMIMAGE_FLAGS_NATIVE_ENTRYPOINT có được set hay
không. Nếu cờ này không được set thì EntryPointToken sẽ đại diện cho
managed entrypoint. Nếu cờ này được set thì EntryPointRVA sẽ đại diện
cho một RVA chỉ đến EntryPoint.

Trang 12 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

o Resources: Thư mục dữ liệu cho Resources. MetaData sẽ tham khảo đến
các Resources này.
o StrongNameSignature: Thư mục dữ liệu cho chữ ký định danh. Section
này chỉ được sử dụng khi cờ COMIMAGE_FLAGS_STRONGNAMESIGNED
được set. Nó cũng ảnh hưởng đến một số vùng trong MetaData.
o CodeManagerTable: Lúc nào cũng bằng 0.
o VtableFixups: Một vài ngôn ngữ không tuân theo mô hình System
Runtime chung. Các ngôn ngữ vì vậy sẽ có một vài hàm ảo và các hàm
ảo này cần được liệt kê ở bảng v-table.
o ExportAddressTableJumps: lúc nào cũng bằng 0.
o ManagedNativeHeader: Lúc nào cũng bằng 0, chỉ tồn tại trong thế hệ
ASM.
• Bây giờ ta dùng tool CFF Explorer để mở 2 file SampleCrackme.exe và
SampleCrackmewithStrongname.exe để so sánh.
• Không định danh

• Có định danh

Trang 13 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Như đã nói ở trên, ta thấy rõ ràng có sự khác biệt ở phần


StrongNameSignature của assembly có ký định danh và không ký định danh.
Chúng ta lưu ý điều này.
• Cờ Flags cũng có sự khác biệt. Khi không có chữ ký định danh thì Flags =
COMIMAGE_FLAGS_ILONLY ( tức là bằng 1 : xem giá trị các cờ ở hình trên)
còn có chữ ký định danh thì Flags = COMIMAGE_FLAGS_ILONLY |
COMIMAGE_FLAGS_STRONGNAMESIGNED (tức là bằng 1+ 8 = 9)
• Ta cũng biết rằng chữ ký này cũng ảnh hưởng ở MetaData. Cho nên chúng ta
tiếp tục xem thêm thông tin ở MetaData. Dùng CFF Explorer xem mục
Assembly của MetaData Tables

Trang 14 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Thư mục Assembly bao gồm một bảng. Bảng này chứa các thông tin về
o HashAlgId: Một hằng số 4 byte thể hiện cho giải thuật dùng để tạo Hash
cho Assembly.
o MajorVersion, Minor Version, BuildNumber, RevisionNumber: hằng số 2
bytes.
o Flags: Một cờ 4 bít.
o PublicKey: khác 0 khi và chỉ khi assembly bị ký định danh và afPublickey
được set
• Cờ có thể có các giá trị sau:

• Như vậy chúng ta đã thấy được sự khác biệt giữa một file bị ký định danh và
một file không bị ký định danh. Bây giờ chúng ta cần sửa đổi tất cả các giá trị
sao cho PE Header của 2 file là giống nhau.
• Đối với file SampleCrackmewithStrongName chúng ta cần phải thay đổi các
giá trị tại những offset như sau:

Member Offset Old Value New Value


StrongNameSignatureRVA 00001028 00002050 00000000
StrongNameSignatureSize 0000102C 00000080 00000000
Flags 00009BCE 00000001 00000000
PublicKey 00009BD2 0072 0000

• Việc chỉnh sửa chúng ta có thể thực hiện bằng CFF Explorer. Click thẳng vào
các giá trị cần sửa, chỉnh sửa giá trị. Sau khi chỉnh sửa xong ta chọn Save As
dưới một tên khác.

Trang 15 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Thực hiện lại các bước Remove Nag như ở bài trước, ta thấy chúng ta có thể
patch mà không bị kiểm tra chữ ký định danh nữa.

3.3 Kết luận


• Như vậy chúng ta đã thực hiện theo một phương cách khác để xóa bỏ chữ ký
định danh. Phương pháp này đòi hỏi chúng ta có một kiến thức về PE Header
nhất định để có thể tìm và sửa đổi các giá trị một cách hợp lý nhất.
• Ngoài ra chúng ta cũng thấy được rằng việc định nghĩa PE Header đều trên
quy tắc lập trình, chúng ta nên tìm hiểu một cách có căn bản thì mới có thể tự
phát triển lên các phương pháp khác được.

Trang 16 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

4 Xóa strong name từ các assembly phụ thuộc


• Như chúng ta cũng đã nêu ở trên, khi một assembly A bị ký định danh và một
assembly B khác tham khảo đến assembly A này. Khi chúng ta thay đổi
assembly A thì assembly B không thể nào tham khảo đến assembly A được
nữa. Vì vậy trong phần này chúng ta sẽ tìm hiểu cách để sửa đổi các assembly
sao cho chúng ta có thể patch được phần mềm mà không gặp trở ngại nào.
• Chúng ta phân tích SampleCrackmewithStrongnameinDll.exe để hiểu rõ thêm.
• Dùng Reflector để phân tích file SampleCrackmewithStrongnameinDll.exe.

• Ta thấy cách check của Crackme hiện tại đã khác hơn so với crackme trước.
Chương trình sẽ gọi method Check của lớp IsRegistered, method này thuộc
assembly Registration.dll. Click vào hàm Check để xem mã nguồn.

• Các kiểm tra khá đơn giản, serial chính là “rongchauawadeptrai”. Tuy nhiên
chúng ta thử patch xem sao.
• Dùng ILDASM để dump file Registration.dll.
• Tại dòng lệnh IL_000b, chúng ta sửa lại thành brtrue.s như hình

Trang 17 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Recompile và Click vào nút Check.

• Phải chăng file này bị ký định danh. Oki, dùng CFF Explorer mở file
Registration.dll lên chỉnh lại các thuộc tính như sau

Trang 18 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Lưu lại đè lên tập tin cũ bằng cách click Save. Chọn Yes trong hộp thoại sau:

• Nhấn nút Check, vẫn crash.


• Dĩ nhiên, vì theo lý thuyết đã phân tích ở trên chúng ta biết rằng assembly
SampleCrackmewithStrongnameindll tham khảo đến assembly Registration
do đó khi chúng ta thay đổi assembly Registration thì assembly
SampleCrackmewithStrongnameinDll không thể nào load assembly
Registration lên được.
• Để giải quyết được sự kiểm tra này chúng ta dùng CFF Explorer load
assembly SampleCrackmewithStrongnameinDll lên.
• Chỉnh lại các thông số như sau:

Trang 19 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Các bước thay đổi giống như ở một assembly đơn. Bây giờ có một phần khác
biệt. Click vào AssemblyRef trong mục MetaData Tables. Chọn Registration,
ta sửa lại giá trị PublicKeyOrToken như hình bên dưới.

Trang 20 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Chọn Save và lưu đè lên file cũ. Bây giờ hãy chạy file và check.

• Như vậy là chúng ta đã hoàn thành việc xóa định danh từ các assembly phụ
thuộc. Tốn nhiều thời gian hơn như thực chất chỉ là xóa định danh của các
assembly đơn và mối quan hệ của chúng.

Trang 21 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

5 Xóa strong name bằng Tool


• Chúng ta sẽ tìm hiểu phương pháp xóa định danh cuối cùng. Xóa định danh
bằng tool.
• Bây giờ chúng ta chạy Tool Strong Name Remove 2.0.0 để mở file
SampleCrackmewithStrongName. Chúng ta sẽ chỉ tìm hiểu cách xóa định
danh đối với assembly đơn. Đối với assembly phụ thuộc các bạn có thể tự tìm
hiểu.
• Mở assembly SampleCrackmewithStrongname.exe. Click nút Verify.

• Click chọn nút Patch nếu có kết quả sau đây là đúng.

Trang 22 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Kết quả cho chúng ta thấy thực chất chương trình cũng thực hiện những sửa
đổi giống như chúng ta.
• Để check chúng ta thực hiện các bước Remove Nag như ở bài 3. And it works.

6 Tổng kết
• Như vậy chúng ta đã tìm hiểu các cách để xóa chữ ký định danh. Có thể bằng
tay hay bằng tool nhưng quan trọng là chúng ta hiểu được phần nào cách hoạt
động của strong name.
• Có nhiều cách khác để xóa định danh nhưng tôi không đề cập ở đây vì thời
lượng có hạn và cũng không thật sự cần thiết. Vì thật sự trong thực tế việc sử
dụng Tool Strong Name Remove cũng đạt được gần như 100% mục đích.

7 Kiến thức bổ sung


• Phần kiến thức bổ sung dưới đây nhằm ôn lại một phần kiến thức về PE
Header của file thế hệ ASM. Do đó các điều ghi dưới đây là cho file thế hệ
ASM.

Trang 23 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

7.1 Import Table


• Import Table thực chất là một struct chứa thông tin về RVA và độ lớn của
IMAGE_IMPORT_DESCRIPTOR. Vấn đề về PE này khá phức tạp, vì cấu trúc đa
tầng và đang chéo của nó. Do đó ở đây chúng ta chỉ quan sát từ cấp độ bao
quát nhất đến cấp độ của Import Table nhằm có một cái nhìn sơ khởi về
Import Table.

7.1.1 Cấu trúc


• PE Header là một thuật ngữ đại diện cho một cấu trúc có tên là
IMAGE_NT_HEADERS. Cấu trúc này được định nghĩa như sau

• Signature là một DWORD chứa giá trị như sau: 0x50, 0x45, 0x00, 0x00. Giá
trị DWORD này đánh dấu phần bắt đầu định dạng của file trong windows.
• FileHeader có kiểu là IMAGE_FILE_HEADER có độ lớn 20 bytes chứa thông tin
về sơ đồ bố trí vật lý và những đặc tính của file.
• OptionalHeader có kiểu là IMAGE_OPTIONAL_HEADER32 có độ lớn 224 bytes.
• Dùng một HexEditor mở một file (thế hệ ASM) bất kỳ lên ta sẽ thấy như sau

• Ở đây chúng ta không đề cập đến phần FileHeader mà sẽ đi nhanh đến phần
ImportTable. Để hiểu rõ hơn các bạn nên đọc tài liệu về PE File Format của
Goppit hoặc bản dịch tiếng Việt của kienmanofwar (xem phần tham khảo bên
dưới).
• IMAGE_OPTIONAL_HEADER32 là kiểu của OptionalHeader có dạng như sau:

Trang 24 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Ở đây ta chỉ lưu ý đến DataDirectory có kiểu là IMAGE_DATA_DIRECTORY.


Data Directory là 128 bytes cuối cùng của OptionalHeader và cũng là thành
phần cuối cùng của IMAGE_NT_HEADERS.

IMAGE_NUMBEROF_DIRECTORY_ENTRIES equ 16

DataDirectory IMAGE_DATA_DIRECTORY IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup(<>)

• Lưu ý tại dòng lệnh khai báo của DataDirectory ta thấy, DataDirectory là một
mảng có độ lớn 16 có cấu trúc IMAGE_DATA_DIRECTORY.
• Các phần tử này được liệt kê bên dưới đây

Trang 25 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Mỗi phần tử này có kiểu IMAGE_DATA_DIRECTORY.

o Virtual Address là địa chỉ ảo tương đối (RVA : Relative Virtaul Address)
của cấu trúc dữ liệu
o isize: chứa kích thước của cấu trúc dữ liệu.
• Dùng LordPE xem một file bất kỳ ta thấy được như sau

Trang 26 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Ta thấy ở đây 16 phần tử của mảng đã được liệt kê cùng với RVA và kích
thước của nó. Phần tử ImportTable cũng vậy. Tất cả đều có RVA và kích thước
như đã được định nghĩa trong cấu trúc IMAGE_DATA_DIRECTORY.
• Như vậy ta đã nắm được cấu trúc và ý nghĩa của ImportTable.

7.1.2 Ý nghĩa
• Xét về ý nghĩa thì Import Table là nơi tập trung các câu lệnh để import các
hàm từ các DLL.
• Khi viết một chương trình, chúng ta thông thường sử dụng các hàm có sẵn
trong các DLL của Windows hoặc tự tạo ra các DLL dùng chung. Khi chúng ta
sử dụng các hàm trong các DLL này thì các thông tin (vị trí, tên hàm) sẽ được
đưa vào Import Table. Như vậy khi chúng ta chạy chương trình thì dựa vào
Import Table, Loader sẽ tìm kiếm và nạp các hàm cần thiết vào trong bộ nhớ
để chương trình chúng ta có thể chạy được.

7.2 Base Relocations Section


• Nhiệm vụ chính của section .reloc là giúp loader tìm đúng được địa chỉ của các
hàm, các chuỗi, dữ liệu … Điều này được thực hiện như sau.
• Đầu tiên khi chúng ta biên dịch một chương trình, thì trình linker sẽ tạo ra cho
chúng ta một file Exe đồng thời cũng giả định một địa chỉ (Base address) trên
bộ nhớ ảo mà tại đó file Exe sẽ được ánh xạ vào. Sau đó địa chỉ (Offset) của
các đoạn mã cũng như dữ liệu sẽ được trình linker đưa vào Exe.
• Như vậy giả sử vì một lý do nào đó, trong khi trình loader đang nạp file exe
vào bộ nhớ ảo thì bị lỗi, khi đó các giá trị giá định mà linker đã xác định trước

Trang 27 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

đó sẽ không còn đúng nữa. Trong tình huống này trình loader sẽ sử dụng các
thông tin trong .reloc section để sửa chữa lại các thông tin đã bị sai lệch.
• Trong trường hợp nếu mọi chuyện tốt đẹp, tức là trình loader có thể nạp
chương trình tại Base Address mà linker đã giả định trước đó thì các thông tin
trong .reloc section sẽ được bỏ qua.
• Ví dụ:
o Khi chúng ta biên dịch chương trình của chúng ta thì linker sẽ giả định
địa chỉ ánh xạ tại Base Address 0x400000.
o Khi chương trình chạy, tại offset 0x11CC là một con trỏ trỏ đến một
chuỗi “rongchauawadeptrai”.
o Chuỗi “rongchauawadeptrai” này được lưu tại offset là 0x303F.
o Như vậy con trỏ sẽ chứa giá trị là 0x40303F.
o Khi chương trình được thực thi ở máy của tôi, vì một lý do nào đó loader
của máy tôi quyết định rằng nó cần phải ánh xạ chương trình từ Base
Address 0x600000. Như vậy ta thấy rằng có một sự khác biệt giữa giả
định và thực tế về địa chỉ Base Address này.
o Độ khác biệt là ∆ = 0x600000 – 0x400000 = 0x200000
o Như vậy ta thấy rằng con trỏ hiện trỏ tới giá trị là 0x40303F sẽ không
còn đúng nữa vì hiện tại chuỗi được lưu tại địa chỉ là 0x60303F.
o Lúc này, để giải quyết vấn đề trên thì loader sẽ tự động cộng thêm đoạn
khác biệt trên cho giá trị của con trỏ. Tức là giá trị của con trỏ sẽ là
0x40303F + 0x200000 = 0x60303F.
• Những mục trong .reloc section gọi là Base relocations bởi vì những mục này
dựa trên địa chỉ Base Address đã được linker giả định. Base relocations là một
list của những địa chỉ (offset) của dữ liệu và những đoạn mã. Mỗi một mục
Base relocation được đóng gói thành một chuỗi của nhiều đoạn có chiều dài
khác nhau. Mỗi đoạn này sẽ mô tả relocation cho một trang 4KB bộ nhớ ánh
xạ.

8 Tài liệu tham khảo


• Strong name :
http://msdn.microsoft.com/msdnmag/issues/06/07/CLRInsideOut/default.asp
x
• Building Security Awareness in .NET Assemblies
http://www.codeproject.com/dotnet/NeCoder01.asp
• Removing StrongName Signature in .NET Applications của Newbie_Cracker
http://www.tuts4you.com/blogs/request.php?1197
• The .NET File Format
http://pmode.net/USERS/116/Files/dotnetformat.htm#NETDir
• Portable Executable File Format Compendium V11
http://arteam.accessroot.com/tutorials.html?fid=112
• [PE Tutorials] http://www.reaonline.net/forum/showthread.php?t=1881
• Strong Name Explained
http://www.codeproject.com/dotnet/StrongNameExplained.asp

Trang 28 của 29
Bài lưu trữ về Reverse .NET Software III 1.0.2.9 Rongchaua

• Strong Name Remove 2.0.0.0


http://www.codeproject.com/dotnet/StrongNameRemove20.asp

9 Lời kết
• Tôi viết bài lưu trữ này nhằm lưu lại một chút kiến thức mà tôi có được trong
quá trình reverse phần mềm. Bài lưu trữ này chỉ mang tính tham khảo và tôi
không có ý định viết nó như một tài liệu tham khảo thật sự. Vì vậy trong một
số mục tôi chỉ nêu lên những ý chính thật cần thiết và dĩ nhiên sẽ còn nhiều
thiếu sót. Tôi hi vọng các bạn sẽ thông cảm cho những thiếu sót của tôi.
• Do những suy nghĩ trên mang đầy tính chủ quan vì vậy nếu có những sai sót
xin các bạn vui long liên hệ với tôi để tôi kịp thời sửa chữa.
• Bài lưu trữ này được viết như một tài liệu tham khảo cho các anh, em ở REA vì
vậy tôi xin tặng bài viết này cho anh, em trong REA.
• Bài viết ở trên chỉ mang tính học tập, tôi không chịu trách nhiệm khi các bạn
sử dụng các kiến thức ở trên vào việc của các bạn.

Rongchaua chấp bút


My Email : rongchaua@reaonline.net
My Website : www.rongchaua.nth12a1.com
Nếu tôi có gì sai sót, vui lòng liên hệ email trên để “mắng vốn”.
16.12.2006-29.12.2006

Trang 29 của 29

You might also like