12
Trang 1 .NET Reverse Engineering – Advanced Patching, Playing with IL Viết bởi: Levis Nickaster (http://ltops9.wordpress.com) LỜI MỞ ĐẦU Advanced Patching? Cái tên này do tôi tự đặt ra, để phân biệt với phương pháp Basic Patching trong .NET. “Basic Patching” là gì? Cũng là do tôi tự gọi thế :D. Basic Patching đơn giản chỉ là trong quá trình Cr@cking thì thường có các câu lệnh so sánh kiểu điều kiên (if..else...) và việc đa số các bạn thường làm là chuyển brtrue thành brfalse trong IL code, và ngược lại để vượt qua quá trình kiểm tra. Phương pháp basic patching này rất hiệu quả trong khá nhiều trường hợp. “Khá nhiều” chứ không phải tất cả. Vậy nên phương pháp advanced patching này giải quyết được mọi thứ mà Basic patching không làm được. Advanced Patching có thể thay đổi một phần hoặc toàn bộ chức năng của 1 chương trình, thêm các đoạn code mới (code injection), hoặc là làm gì cũng được, tùy theo ý thích của các bạn. Nghe rất hay phải không? Tất nhiên là hay, nhưng để thực hiện được advanced patching thì các bạn sẽ cần nhiều kiến thức hơn, mà tôi sẽ cố găng trình bày + giới thiệu những tài liệu hữu ích có liên quan, trong bài viết này. Và nên nhớ là, Advanced Patching chưa hẳn là cái tôi muốn các bạn nắm được ngay sau khi đọc bài viết này, mà cái các bạn cần là những kiến thức tôi sẽ nói sau đầy. Ở cuối bài viết tôi sẽ lấy ví dụ trong việc patch 1 ứng dụng thương mại (commercial application). Nhưng theo đúng tiêu chí của bài viết này, việc patch chỉ mang tính chất nghiên cứu và học tập Bạn cần có những gì? Chắc chắn là phải biết lập trình và có hiểu biết về .NET, ở mức basic cũng tạm đủ rồi. Bên cạnh đó các bạn sẽ cần vài công cụ sau: - 1 .NET Decompiler: .NET Reflector cũng ổn, tôi thích dùng SimpleAssemblyExplorer hơn vì nó miễn phí và rất mạnh. Trong tut này tôi sẽ dùng cả 2. Riêng với Reflector thì các bạn cần có thêm 1 plugin nữa là ByteViewer viết bới CodeCracekr - 1 Hex Editor: Tôi khuyến khích các bạn nên dùng CFF Explorer, vì CFF Explorer cho đến hiện tại là chương trình support việc phân tích cấu trung file .NET tốt nhất mà tôi có thể tìm thấy được. - 1 IDE và .NET Framework: Phần này thì tùy chọn, không bắt buộc các bạn phải có. Tìm hiểu về .NET thì nên là cài vào trong máy những thành phần này. Tôi không thích Visual Studio lắm, và để demo thì tôi thường dùng SharpDevelop OK, hãy cùng bắt đầu nào.

Reverse Engineering .NET - Advanced Patching, Playing with IL

Embed Size (px)

Citation preview

Page 1: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 1

.NET Reverse Engineering – Advanced Patching, Playing with IL

Viết bởi: Levis Nickaster (http://ltops9.wordpress.com)

LỜI MỞ ĐẦU

Advanced Patching? Cái tên này do tôi tự đặt ra, để phân biệt với phương pháp Basic Patching trong

.NET. “Basic Patching” là gì? Cũng là do tôi tự gọi thế :D. Basic Patching đơn giản chỉ là trong quá trình

Cr@cking thì thường có các câu lệnh so sánh kiểu điều kiên (if..else...) và việc đa số các bạn thường làm

là chuyển brtrue thành brfalse trong IL code, và ngược lại để vượt qua quá trình kiểm tra. Phương pháp

basic patching này rất hiệu quả trong khá nhiều trường hợp. “Khá nhiều” chứ không phải tất cả.

Vậy nên phương pháp advanced patching này giải quyết được mọi thứ mà Basic patching không làm

được. Advanced Patching có thể thay đổi một phần hoặc toàn bộ chức năng của 1 chương trình, thêm

các đoạn code mới (code injection), hoặc là làm gì cũng được, tùy theo ý thích của các bạn. Nghe rất hay

phải không? Tất nhiên là hay, nhưng để thực hiện được advanced patching thì các bạn sẽ cần nhiều kiến

thức hơn, mà tôi sẽ cố găng trình bày + giới thiệu những tài liệu hữu ích có liên quan, trong bài viết này.

Và nên nhớ là, Advanced Patching chưa hẳn là cái tôi muốn các bạn nắm được ngay sau khi đọc bài viết

này, mà cái các bạn cần là những kiến thức tôi sẽ nói sau đầy.

Ở cuối bài viết tôi sẽ lấy ví dụ trong việc patch 1 ứng dụng thương mại (commercial application). Nhưng

theo đúng tiêu chí của bài viết này, việc patch chỉ mang tính chất nghiên cứu và học tập

Bạn cần có những gì? Chắc chắn là phải biết lập trình và có hiểu biết về .NET, ở mức basic cũng tạm đủ

rồi. Bên cạnh đó các bạn sẽ cần vài công cụ sau:

- 1 .NET Decompiler: .NET Reflector cũng ổn, tôi thích dùng SimpleAssemblyExplorer hơn vì nó

miễn phí và rất mạnh. Trong tut này tôi sẽ dùng cả 2. Riêng với Reflector thì các bạn cần có thêm

1 plugin nữa là ByteViewer viết bới CodeCracekr

- 1 Hex Editor: Tôi khuyến khích các bạn nên dùng CFF Explorer, vì CFF Explorer cho đến hiện tại là

chương trình support việc phân tích cấu trung file .NET tốt nhất mà tôi có thể tìm thấy được.

- 1 IDE và .NET Framework: Phần này thì tùy chọn, không bắt buộc các bạn phải có. Tìm hiểu về

.NET thì nên là cài vào trong máy những thành phần này. Tôi không thích Visual Studio lắm, và

để demo thì tôi thường dùng SharpDevelop

OK, hãy cùng bắt đầu nào.

Page 2: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 2

MỘT VÀI ĐIỀU CŨ

Advanced Patching là kĩ thuật thay đổi một hay nhiều các IL code, và không chỉ dừng lại ở việc patch các

IL code thường thấy như brtrue, brtrue.s, brfalse, brfalse.s.... Vì vậy cần phải có kiến thức về MSIL/CIL/IL

nhiều hơn.

Đối với nhiều người mới, thì họ thường không có sự phân biệt giữa .NET PE file và native PE file. Bởi vì

trong mắt họ chúng đều là file PE cả. Thế nên tôi sẽ nhắc lại 1 chút về .NET PE file, và tại sao chúng ta

phải biết và sử dụng IL thay vì đọc ASM code giống như đối với native PE.

.NET PE file thường được coi là PE file “nửa mùa” vì chúng không chứa mã máy thực sự, mà chứa thứ

mà chúng ta cần tìm hiểu – IL Code. IL code là 1 dạng ngôn ngữ được dùng làm input cho JIT Compiler

trong quá trình vận hành, JIT Compiler chuyển IL Code này thành machine code, từ đó hệ điều hành mới

có thể thực thi được chương trình. Chứ hệ điều hành không thể đọc và hiểu được IL Code. IL Code là 1

dạng ngôn ngữ được chuyển về dạng đọc được từ các IL bytecode, là phần chính để tạo lên một .NET PE

File. Quá trình hoạt động của 1 chương trình .NET được mô tả trong hình dưới đây:

Các Decompiler .NET hoạt động dựa trên việc đọc IL bytecode và chuyển chúng về dạng của các ngôn

ngữ bậc cao, thế nên việc dịch ngược .NET tương đối là thuận lợi vì có thể đọc code dễ dàng, không mấy

khó khăn như đối với native PE. Các ngôn ngữ bậc cao là output này thực tế chỉ là 1 lớp bọc ngoài cùng

để khiến việc dịch ngược trở nên dễ dàng hơn, còn thực tế mọi thao tác của chúng ta đều hướng đến

các IL code/IL bytecode.

MSIL/CIL/IL CODE?

Về IL code, có rất nhiều sách nói riêng về ngôn ngữ này, cho nên tôi sẽ không đi vào nói chi tiết về nó,

mà sẽ chỉ cố gắng tóm tắt được những đặc điểm quan trọng của IL code. Các cuốn sách và link nên đọc:

- .NET IL Assembler ebook

- Expert .NET 2.0 IL Assember ebook

- Common Intermediate Language at Wikipedia

- Introduction to IL Assembly Language at CodeProject

Page 3: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 3

Bên cạnh đó thì các bạn có thể tìm kiếm thêm trên Google với từ khóa “IL code” hoặc “MSIL language”.

MSIL, CIL, hay IL đều là 1 cả, cho nên chúng ta có thể dùng tên nào cũng được. Tôi thì hay gọi là IL vì dễ

nhớ và viết cũng nhanh :D.

1 đoạn IL code hiển thị trong SAE

Những thứ đầu tiên mà chúng ta cần biết khi đọc IL code là:

- IL là 1 ngôn ngữ thực hiện các biểu thức hay thao tác đều dựa nhiều vào stack, và cách hoạt

động cũng tương tự như cách hoạt động của stack, có nghĩa là LIFO (last-in, first-out). Dữ liệu

được đẩy vào cuối cùng sẽ là dữ liệu nằm trên cùng, và được lấy ra đầu tiên.

o Tôi lấy luôn ví dụ trên wikipedia như sau: ldloc.0 //Load giá trị tại biến cục bộ đầu tiên vào stack

ldloc.1 //Load giá trị tại biến cục bộ thứ hai vào stack

add //Thực hiện phép cộng

stloc.0 //Lưu lại kết quả vào biến cục bộ đầu tiên

Ta có thể thấy được chương trình thực hiện tuần tự từ trên xuống dưới, để thực hiện

một biểu thức a=a+b. Tất cả mọi dữ liệu đều phải đưa vào trong stack trước khi có thể

thực hiện xử lý dữ liệu.

- IL mang đặc điểm của một ngôn ngữ lập trình hướng đối tượng (OOP). Chúng ta có thể khởi tạo

object mới, hoặc là invoke các method có sẵn của object khác,....

o Cũng lại lấy luôn ví dụ trong Wikipedia. Có 1 class Foo() như sau:

Page 4: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 4

- class public Foo

{

- . method public static int32 Add(int32, int32) cil managed

- {

- . maxstack 2 // Khai báo độ lớn tối đa mà stack có thể

dùng

- ldarg.0 // Lấy tham số đầu tiên đưa vào stack

- ldarg.1 // lấy tham số thứ 2 đưa vào stack

- add // Thực hiện phép cộng

- ret // trở về

- }

}

Code dưới đâu có thể gọi được method Add() trong class Foo ở trên:

ldc.i4.2 //Đưa số nguyên có giá trị = 2 vào stack

ldc.i4.3 //Đưa số nguyên có giá trị = 3 vào stack

call int32 Foo::Add(int32, int32) //Gọi method Add() của Foo

stloc.0 //Lưu kết quả vào trong biến cục bộ đầu tiên

Code trên tương đương với việc thực hiên code int r = Foo.Add(2,3)

VD cho việc thực hiện tạo object mới:

ldc.i4.1 //Đưa số nguyên có giá trị = 1 vào stack

ldc.i4.4 //Đưa số nguyên có giá trị = 4 vào stack

//newobject gọi method ctor của class Car

newobj instance void Car::.ctor(int, int)

stloc.0 // myCar = new Car(1, 4); Lưu vào biến cục bộ

ldc.i4.1 //Đưa số nguyên có giá trị = 1 vào stack

ldc.i4.3 //Đưa số nguyên có giá trị = 2 vào stack

//newobject gọi method ctor của class Car

newobj instance void Car::.ctor(int, int)

stloc.1 // yourCar = new Car(1, 3); Lưu vào biến cục bộ

- IL là ngôn ngữ bao gồm rất nhiều các chỉ lệnh (instruction) khác nhau. Các chỉ lệnh này là 1 dạng

viết tắt của các từ khóa trong tiếng Anh. Vì vậy cách tốt nhất để ghi nhớ ý nghĩa các chỉ lệnh đó

là hãy đọc các chỉ lệnh này dưới dạng tiếng Anh. Danh sách các chỉ lệnh này các bạn có thể đọc

tại trang Wikipedia, hoặc đọc các sách phía trên tôi đã đề cập. Có một công cụ rất gọn nhẹ và

hữu ích, các bạn nên có công cụ này trong gói “đồ nghề” của mình, đó là MSIL Opcode Table,

công cụ này sẽ liệt kê các IL instrcution và các thông tin li

VD: brtrue = branch (if) true, ldloc = load (from) local variable, stloc = store (into) local

variable, ldarg = load argument, newobj = new object, callvirt = call virtual...

OK, vậy là tạm đủ để giới thiệu sơ qua về IL code, các bạn nên đọc các tài liệu trong link tôi đã viết phái

trên để tìm hiểu sâu hơn về ngôn ngữ này. Về cơ bản, các bạn cần phải nắm được 3 đặc điểm tôi đã nêu

ra. Bây giờ chúng ta sẽ đi đến phần khó hơn một chút, đó là phần tìm hiểu xem IL bytecode của 1

method được lưu trữ nhue thế nào trong 1 .NET PE file.

Page 5: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 5

IL BYTECODE

IL bytecode chính là IL Code được biểu diễn dưới dạng nhị phân (binary) và được lưu giữ trong .NET PE

file. Nói thế này có vẻ hơi khó hiểu, tôi cứ nói nôm nà là các bạn mở 1 file .NET trong 1 hex editor, nhìn

thấy các byte trong đó, thì IL code là những byte nằm ở vị trí nhất định, thường thì nằm trong section

text của file. Trong 1 file .NET thường chỉ có 3 section: .text (chứa metadata và bytecode cũng như

resource (.NET Resource)), .rsrc (chứa resource - ở đây là native resource như Icon hay VERSIONINFO),

.reloc (relocation section). Ở đây tôi sẽ không tập trung vào việc phân tích cấu trúc của file .NET cũng

như cấu trúc của 1 .NET Metadata vì nó rất dài. Tôi đang dịch một bài viết về .NET PE File Format của

Daniel Pistelli (tác giả của CFF Explorer) trên CodeProject, và hi vọng sẽ hoàn thành sớm. Bây giờ thì bạn

có thể vào link trên để đọc bản tiếng Anh, rất chi tiết và đầy đủ.

Thế nên, ở phần này tôi sẽ tập trung đến cách xác định vị trí của bytecode của 1 method nhất định trong

chương trình, và tìm hiểu qua về cấu trúc của method dưới dạng bytecode.

Trong .NET Reflector, các bạn sẽ thấy rất dễ dàng khi đọc code vì code được hiển thị dưới dạng của các

ngôn ngữ bậc cao. Reflector cũng hỗ trợ việc hiển thị dưới dạng IL code nhưng lại không hiển thị các IL

bytecode. Chính vì vậy nên chúng ta cần đến plugin ByteViewer mà tôi đã nhắc đến ở phần đầu bài viết

này. Hãy cài đặt vào Reflector và chúng ta sẽ có thêm 2 lựa chọn ở phần Code Display:là BV_IL&Byte để

hiển thị cả IL code và bytecode dương ứng, và BV_Bytes để chỉ hiển thị IL Bytecode.

BV_IL&Bytes với IL code và bytecode được viết dưới dạng chú thích ngay bên cạnh

Page 6: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 6

BV_Bytes chỉ hiển thị các bytecode

OK, trong Reflector là thế, vậy thì tôi muốn tìm code trong 1 Hex Editor thì sẽ làm thế nào?

Để làm điều này, chúng ta cần biết được Token của method đó. Token nôm na là 1 giá trị DWORD lưu

giữ index của Table xác định trong Metadata, và 1 index khác trỏ đến phần tử trong table đó. Có nghĩa là

ở đây có 2 index, và index thường được biểu diễn dưới dạng hexadecimal. VD: tôi có 1 token như sau:

0600002B, thì “06” ở đầu là index của Method Table, còn 2B là index đến method nằm trong method

Table đó (ta có 1 cái table tên là Methods, trong table này chứa tất cả các method có trong chương

trình, các method này đều được đánh số thứ tự). Về các table và metadata, các bạn hãy đọc trong bài

của Daniel Pistelli.

OK, từ method token này ta có thể tìm được RVA của method, và từ RVA có thể lấy được offset của

method đó. Có nghĩa là Method -> Token -> RVA -> Offset.

Tôi sẽ post lại cái ảnh phía trên ở đây, kèm theo 1 chút thay đổi:

Mặc định thì Reflector không hiển thị được Method token, nhưng với plugin trên thì chúng ta có thể lấy

token của method rất dễ dàng. Trong các chương trình khác (ILDASM, SAE,...) thì cũng rất dễ để lấy được

token.

Page 7: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 7

Sau khi có được token thì chúng ta mở file .NET đó trong CFF Explorer, VD tôi có là 06000003, có nghĩa là

index 3 trong Method Table. Trong CFF Explorer, ở panel bên trái, ta chọn .NET Directory -> Metadata

Stream -> #` -> Tables. Sau đó ở k panel bên phải sẽ hiện ra 1 loạt các Table, ta tìm table có tên Methods

và expand nó ra sẽ thấy các method nằm trong đó, có đánh số thứ tự rõ ràng kèm theo tên. Tìm đến

method index 3, nhìn sang bên phải là sẽ hiện lên các thông tin về method đó, trong đó có giá trị RVA

mà ta cần tìm:

OK, RVA của method đó là 00002074. Bây giờ ta lại dùng tiếp tính năng khác của CFF Explorer là Address

Converter (nằm ngay phía dưới của panel bên trái). Điền RVA tìm được vào khung RVA, và ấn Enter,

chúng ta sẽ đến được với offset chứa bytecode:

Page 8: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 8

Có 1 điều cần phải lưu ý là ở đây không chỉ có IL bytecode, mà phần binary đầu tiên là còn chứa 1 đoạn

dât của Method Header, đoạn method header này giúp jit compiler (và cả cách trình decomplie xác định

được thuộc tính của toàn bộ method đó).

Có 2 dạng method Header, 1 là Tiny Header, 2 là Fat Header. Theo blog của Zsozso có mô tả rất chi tiết

về 2 dạng method header này. Tôi sẽ tóm tắt lại những gì quan trọng:

Tiny Header là 1 byte nằm đầu tiên tại offset chứa method. 1 byte = 8 bit, 2 bit đầu tiên để xác định đó

là Tiny header, và 6 bit tiếp theo xác định độ dài của toàn bộ IL bytecode của method. 2 bit đầu tiên cố

định là 0x02.

Tiny Header chỉ được sử dụng trong các trường hợp sau:

- Trong method không sử dụng biến cục bộ

- Trong method không sử dụng exception handler.

- Trong method không có data section bổ sung

- Độ dài của toàn bộ IL bytecode của method không vượt quá 64 byte.

- Maxstack của method không được vượt quá 8.

Vì tiny header bị giới hạn trong 1 byte, cho nên không thường gặp, Đa phần các trường hợp đều là Fat

Header. Fat Header thì phức tạp và chứa nhiều thông tin hơn Tiny Header.

Page 9: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 9

Fat Header gồm có:

2 byte đầu: thường thấy là 0x3013 (Little Endian). Trong đó chia thành các bit nhỏ, chứa các giá trị như

sau:

- Bit 0- bit 11: Fat format được set ở vị trí bit 0, giá trị là 1 -> Fat Header =0x3 (010b=0x2,

110b=0x3, bit đầu chuyển từ 0 thành 1). Bit thứ 8 để xác định xem có extra section trong

method không, Bit thứ 10 xác định là các constructor method luôn được gọi cho các biến cục bộ.

- Bit 12-15: Kích thước của toàn bộ Fat Header, Ksoos này được nhân với 4 để ra toàn bộ kích

thước cần dùng của Fat Header. Số này luôn là 3, 3x4=12, kích thước của toàn bộ Fat Header =

12 byte.

Byte thứ 2: kích thước 1 WORD. Ghi giá trị của maxstack.

Byte thứ 4: kích thước 1 DWORD: Ghi kích thước của toàn bộ IL bytecode trong method

Byte thứ 8: Kích thước 1 DWORD, Metadata Token trỏ đến một signature nằm trong metadata table,

tham chiếu đến 1 mục nhất định trong #Blob String, mô tả kiểu giá trị của các biến cục bộ có trong

method (viết tắt là LocalVarSigTok). Nếu giá trị này bằng 0, có nghĩa là trong method không có biến cục

bộ.

OK, thế là xong về 2 method header. Tôi sẽ lấy ví dụ về 1 Fat Header, cũng là method đã chụp ở trong

các hình trên. Data của Toàn bộ Method này:

133002002C0000000100001100032C0B027B0100000414FE012B0117000A062D0E0002

7B010000046F1200000A00000203281300000A002A

Trong đó:

- Màu đỏ: Fat Header

- Màu cam: Maxstack. Maxstack=3, có nghĩa là sẽ có tối đa 3 giá trị có thể được push vào stack

- Màu xanh lục: Size of code. 0x2C. Method này có 44 bytecode

- Màu xanh dương: LocalValSigTok

- Màu tím: IL bytecode

Thế là chúng ta đã biết được cách xác định thông tin và cách biểu diễn của một method trong .NET file.

Thực tế là phần này không được trực tiếp sử dụng trong Advance Patching, nhưng rất quan trọng để bạn

có thể hiểu mình đang làm gì trong khi thực hiện Advanced Patching

ADVANCED PATCHING

Mấy ngày trước, tôi đi kiếm một chương trình Disk Defraggement, và tình cờ tôi đọc được 1 bài Review

về Diskeeper nên kéo về xem thử để mong “kiếm chác” được gì đó. Và tình cờ nó được viết bằng .NET.

Về cách tôi tìm ra tử huyệt để patch, tôi sẽ không nói ở đây, các bạn có thể tự tìm. Tử huyệt nằm ở file

DkUserCtrl.dll, method GetData(), class ProductManager. Ta sẽ thấy 1 đoạn code như thế này:

Page 10: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 10

1 biến kiểu bool có tên là IsTrialware được gán giá trị bằng việc đọc thông tin từ trong 1 file XML nào đó.

Nếu biến này có giá trị true, thì chương trình sẽ chạy ở trial mode, nếu mang giá trị false, thì chương

trình sẽ là Full :p. Vậy thì tôi muốn set cố định cho isTrialware luôn là false, thì tôi sẽ phải thay đổi code

nhiều hơn là Basic Patch, và ở đây cũng ko có cái if...else... nào để tôi có thể patch cả. Tôi muốn 1 code

như thế này:

This.DkProductData.isTrialware = false

Đoạn code trong IL sẽ như sau:

Chi tiết:

115 L_018d: ldloc.2 //Load local variable 2 to stack

116 L_018e: ldstr "isTrialware" //Load string to stack

//Call method

117 L_0193: call System.Boolean

DkUserCtrl.XmlHelper::GetXmlBoolValue(System.Xml.XmlNode,System.String)

118 L_0198: stfld System.Boolean

DkUserCtrl.DK_PRODUCT_DATA::isTrialware //Store value to object

119 L_019d: ldarg.0 //load the first argument

120 L_019e: ldfld DkUserCtrl.DK_PRODUCT_DATA

DkUserCtrl.ProductManager::DkProductData //load the field to stack

Code ở line 115,116 và 117 tương ứng với code sau: XmlHelper.GetXmlBoolValue(node, "isTrialware");

Page 11: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 11

Bây giờ tôi sẽ xóa 3 lines này đi và thêm vào 1 dòng code mới để gán luôn cho giá trị của isTrialware =

false. Với kiểu boolean thì chỉ có 2 giá trị là 0 (false) và 1 (true). Vì thế cho nên chúng ta cần push 1 giá trị

0 vào stack. Vậy thì tôi sẽ dùng instruction ldc.i4.0, có nghĩa là LoaD Constant Integer (with) 4 bytes (size)

(and value is) 0. Vậy là trong stack có giá trị = 0. Chỉ lệnh stfld ở line 118 sẽ save vào isTrialware. Các bạn

nên sử dụng SAE để edit IL code sẽ dễ hơn rất nhiều so với sử dụng các công cụ khác. Cuối cùng, chúng

ta có được:

IL code sau khi được thay đổi

Hiển thị dưới dạng high level language

Kết quả (Full Edition)

Page 12: Reverse Engineering .NET - Advanced Patching, Playing with IL

Trang 12

Job done!

Ví dụ phía trên chỉ 1 ví dụ rất cơ bản cho việc Advance Patching. Chúng ta có thể làm nhiều hơn, thậm

chí xóa toàn bộ IL code của 1 method và thay thế lại bằng code mới của chúng ta. Điều này rất hữu ích

và có thể nói là luôn thành công trong các trường hợp.

OK, Tôi nghĩ thế là cũng tạm ổn để kết thúc bài viết này rồi.

KẾT LUẬN

Qua bài viết này, hi vọng các bạn sẽ nhận được 1 thứ gì đó có ích cho bản thân mình đẻ có thể áp dụng

trong việc thực hiện Reverse Engineering .NET. Advanced Patching chỉ là ứng dụng rất nhỏ, quan trọng là

việc đọc hiểu được IL code và hiểu được cấu trúc của method cũng như 1 phần cấu trúc của .NET PE file.

Và cũng như thường lệ, cuối cùng là lời cảm ơn. Đầu tiên là Daniel Pistelli, tác giả của CFF Explorer và rất

nhiều tutorial liên quan đến .NET File format. Tiếp đến là 0xd4d, tác giả của de4dot và WICKY Hu, tác giả

của SAE. Cũng xin cảm ơn rất nhiều anh em, bạn bè, tiền bối và hậu bối trong giới “giang hồ mạng”

Hacking & Security tại Việt Nam. Họ đã giúp đỡ và chia sẻ với tôi rất nhiều, tạo cho tôi nhiều cơ hội để

tiếp tục đi xa hơn trong con đường “vọc” và “vạch” này. Cụ thể ư? Nhiều quá tôi không kể hết được, rất

nhiều anh trong REA, HVA, Cin1, REPT, đại gia đình Mi2 JSC (đặc biệt là sếp CISSP luannt ) cũng như

các bạn trẻ khác (nhiều quá, tôi không kể hết, những ai có cùng đam mê, đã gặp tôi, hoặc nói chuyện,

thảo luận với tôi thì đều được liệt vào đây cả, và đặc biệt nhất,(luôn luôn vậy) là em Elvis.. Cảm ơn các

bạn, những người đang đọc bài viết này, đã bỏ thời gian quý báu ra để nghe tôi “chém gió”. Hẹn gặp lại

trong các bài viết tiếp theo. Tôi sẽ viết nhiều bài viết nữa bởi với tôi, “learning is sharing” mà.

Best regards

Levis

Jan 28 2015