首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

.NET CIL 系列第三篇:IL 反組譯與重組譯實戰(Round-trip Engineering)

     編輯:關於.NET

什麼是 Round-trip Engineering?

利用 ildasm.exe 將組件反組譯為 IL 程式碼,修改後再用 ilasm.exe 重新編譯為組件。適用情境:

  • 修改無原始碼的組件
  • 優化編譯器產生的低效 IL
  • 補充 COM 互通時遺失的 IDL 屬性(如 [helpstring])
工具提示: reflector.exe 可將 IL 轉為 C#,但無法處理 C# 不支援的 IL 結構,此時必須使用 ildasm.exe。

實戰步驟:從 Hello World 到 MessageBox

1. 建立原始 C# 程式

// HelloProgram.cs
using System;

class Program {
    static void Main(string[] args) {
        Console.WriteLine("Hello CIL code!");
        Console.ReadLine();
    }
}

2. 編譯並反組譯

csc /out:D:\HelloCilCode\HelloProgram.exe D:\HelloCilCode\HelloProgram.cs
ildasm.exe D:\HelloCilCode\HelloProgram.exe /out:HelloProgram.il

產生 HelloProgram.il 與 HelloProgram.res,原始 .cs 與 .exe 可刪除。

3. 分析 IL 結構

// 外部組件參考
.assembly extern mscorlib {
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89)
  .ver 2:0:0:0
}

// 目前組件定義
.assembly HelloProgram {
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}

.module HelloProgram.exe
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003
.corflags 0x00000001

// 類別定義
.class private auto ansi beforefieldinit Program
       extends [mscorlib]System.Object
{
  .method private hidebysig static void Main(string[] args) cil managed
  {
    .entrypoint
    .maxstack 8
    IL_0000: nop
    IL_0001: ldstr "Hello CIL code!"
    IL_0006: call void [mscorlib]System.Console::WriteLine(string)
    IL_000b: nop
    IL_000c: call string [mscorlib]System.Console::ReadLine()
    IL_0011: pop
    IL_0012: ret
  }

  .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
  {
    .maxstack 8
    IL_0000: ldarg.0
    IL_0001: call instance void [mscorlib]System.Object::.ctor()
    IL_0006: ret
  }
}

關鍵觀察

  • 呼叫 .NET 類型時必須使用「組件友好名稱 + 完整型別名稱」格式:[mscorlib]System.Console::WriteLine(string)
  • .entrypoint 標示程式進入點
  • .maxstack 宣告評估堆疊最大深度
  • 程式碼標籤(IL_XXXX:)可自訂或移除(無分支/迴路時)

4. 修改 IL:加入 MessageBox

目標:引用 System.Windows.Forms.dll,在 Main 中呼叫 MessageBox.Show。

// 新增外部組件參考
.assembly extern System.Windows.Forms
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89)
  .ver 2:0:0:0
}

// 修改 Main 方法
.method private hidebysig static void Main(string[] args) cil managed
{
  .entrypoint
  .maxstack 8
  ldstr "CIL is way cool"
  call valuetype [System.Windows.Forms]System.Windows.Forms.DialogResult
       [System.Windows.Forms]System.Windows.Forms.MessageBox::Show(string)
  pop
  ret
}

注意: 版本號與公開金鑰權杖需依實際 GAC 中組件調整(可從 C:\Windows\assembly 查詢)。

5. 重新編譯

ilasm /exe HelloProgram.il /output=NewAssembly.exe

成功後執行 NewAssembly.exe 將彈出訊息方塊。

常用 ilasm 參數

參數用途
/debug包含偵錯資訊(區域變數名稱、行號)
/dll輸出 .dll
/exe輸出 .exe(預設)
/key使用 .snk 強名稱簽署
/output指定輸出檔名

下一步預告

下一篇將深入探討 IL 指令與屬性的語法語意,掌握 IL 程式設計核心。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved