Thứ Sáu, 29 tháng 6, 2012

MSIL – Sử dụng IL Disassembler (ildasm.exe) và IL Assembler (ilasm.exe)


Đây là hai công cụ được tích hợp khi bạn cài Visual Studio và .Net. Như tên gọi của nó, bạn có thể dùng hai công cụ này để phân tích một file PE của .Net thành mã nguồn IL (Intermediate Language) và biên dịch mã IL trở lại thành file PE. Bạn có thể thấy chúng khá đơn giản và không mất nhiều thời gian để nắm được.

IL Disassembler (ildasm.exe)

Như tên gọi của nó, đây là chương trình dùng để Cách đơn giản nhất để bắt đầu là tiến hành nghiên cứu mã IL của một chương trình đơn giản như “Hello World!” chẳng hạn.
Chương trình in ra màn hình Console viết bằng C#:
01using System;
02
03namespace ConsoleApplication1
04{
05    class Program
06    {
07        public static void Main()
08        {
09            Console.WriteLine("Hello World!");
10        }
11    }
12}
Nhấn Ctrl+F5 để chạy chương trình mà không cần Debug, bạn sẽ thấy cửa sổ in ra dòng “Hello World” và file PE cũng được tạo ra trong thư mục Debug của bạn.
Để disassembly một file PE của .Net, bạn có thể dùng chương trình Disassembler được tích hợp sẵn khi bạn cài VS là ILdasm.exe (MSIL Disassembler). Bạn có thể tìm chương trình này theo đường dẫn sau (Windows XP)::
VS 2005
C:\Program Files\Microsoft.NET\FrameworkSDK\bin\
VS 2008
C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\
Bạn có thể xem hướng dẫn cụ thể cách dùng chương trình này trên MSDN:
Nếu bạn không gọi được chương trình này bằng chức năng Run trong Start menu, bạn cần thêm đường dẫn thư vào biến môi trường “Path” của Windows tùy theo phiên bản .Net của bạn.
Bây giờ bạn mở chương trình ildasm.exe lên và chọn File > Open chọn đến file PE vừa được build ra (của tôi là ConsoleApplication1.exe). Bạn sẽ thấy giao diện chương trình hiển thị nội dung của file này dưới dạng cây như sau:
ildasm
Các biểu tượng của mỗi node đặc trưng cho từng loại thông tin của file. Bạn có thể xem trong bảng sau (từ MSDN):
ildasm_symbols
Để xem mã IL của một mục nào đó, bạn double-click vào mục đó (node lá của cây). Ví dụ đây là mã IL được tạo ra của phương thức Main():
ildasm_MainMethod
Đọc đoạn mã có lẽ bạn cũng hiểu được phần nào bởi vì nó có những điểm tương tự như trong mã C# mà ta viết ở trên. Tuy nhiên bài viết này chỉ có mục đích giới thiệu về cách sử dụng chương trình chứ không nhằm mục đích nói về IL. Các bài viết giới thiệu về IL sẽ được tôi trình bày khi có dịp.
Một tính năng khá cần thiết là chương trình phép bạn dump mã nguồn chương trình dưới dạng IL thành file văn bản với phần mở rộng .il. Bạn có thể sửa chữa mã nguồn này rồi build lại để tạo chương trình mới. Mặc dù có thể chưa rành về IL nhưng bạn cũng có thể hiểu và sửa được một vài phần trong chương trình. Hãy thử thay đổi chương trình để thay vì in ra dòng “Hello World!”, chương trình sẽ in ra “Hello World from IL!”.
OK, bây giờ bạn vào File > Dump, giữ bảng Dump options như mặc định rồi nhấn OK, sau đó lưu lại file vào nơi thích hợp với tên test.il. Bạn có thể thấy ngoài file test.il, còn có một file là test.res được tạo ra, đây là file chứa các resource của chương trình. Tuy nhiên bạn không cần phải sử dụng đến file này, ta chỉ cần file chứa mã IL là đủ.
Mở file test.res lên bằng notepad, bạn có thể thấy phần đầu chứa khá nhiều thông tin của chương trình (phần metadata), cuộn xuống dưới bạn sẽ thầy phần “CLASS MEMBERS DECLARATION” chứa mã IL của lớp Program. Việc đơn giản mà bạn cần làm là sửa chuỗi “Hello World!” trong phần được chọn trên thành “Hello World from IL!”, sau đó save và đóng notepad lại.
01// [...]
02// =============== CLASS MEMBERS DECLARATION ===================
03
04.class private auto ansi beforefieldinit ConsoleApplication1.Program
05       extends [mscorlib]System.Object
06{
07  .method public hidebysig static void  Main() cil managed
08  {
09    .entrypoint
10    // Code size       13 (0xd)
11    .maxstack  8
12    IL_0000:  nop
13    IL_0001:  ldstr      "Hello World from IL!"
14    IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
15    IL_000b:  nop
16    IL_000c:  ret
17  // end of method Program::Main
18
19  .method public hidebysig specialname rtspecialname
20          instance void  .ctor() cil managed
21  {
22    // Code size       7 (0x7)
23    .maxstack  8
24    IL_0000:  ldarg.0
25    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
26    IL_0006:  ret
27  // end of method Program::.ctor
28
29// end of class ConsoleApplication1.Program
30
31// =============================================================
32
33// *********** DISASSEMBLY COMPLETE ***********************
34// WARNING: Created Win32 resource file C:\Documents and Settings\Root\Desktop\test.res
Tiếp theo chúng ta cần phải dùng đến IL Assembler (ilasm.exe) để biên dịch file này thành một PE file.

IL Assembler (ilasm.exe)

Chương trình này không nằm chung thư mục với ildasm, vì đây là chương trình được tích hợp khi cài .Net, bạn có thể tìm nó tại thư mục sau (Windows XP):
C:\Windows\Microsoft.NET\Framework\vx.y.z\
(x.y.z là phiên bản .Net)
Bạn có thể cho đường dẫn này vào biến môi trường Path giống như phần trên để chạy được trong Command Prompt. Xem hướng dẫn sử dụng của MSDN tại link sau
Bây giờ bạn mở Command Prompt của Windows, chuyển đến đường dẫn chưa file test.il và biên dịch file test.il bằng lệnh sau (nếu bạn không chuyển đến đúng đường dẫn thì có thể dùng đường dẫn tuyệt đối):
Ilasm test.il
Nếu biên dịch thành công chương trình sẽ xuất ra hai dòng lệnh cuối sau và tạo ra file test.exe trong cùng thư mục:
Writing PE file
Operation competeled successfully
Sau đó bạn thực thi file test.exe bằng cách gõ test và chương trình sẽ xuất ra câu “Hello World from IL” mà lúc nãy bạn đã sửa.
ILasm (IL Assembler)
Như vậy bạn đã biết cách cơ bản sử dụng hai chương trình IL Disassembler (ildasm.exe) và IL Assembler (ilasm.exe), cũng như bạn có thể sửa được mã nguồn của các file PE của .Net. Mặc dù đây là những vấn đề căn bản nhưng nó có thể giúp ích rất nhiều sau khi bạn có những kiến thức về lập trình IL.

Không có nhận xét nào: