天天看點

某殼對.Net程式加密的原理及解密探讨三(執行個體解密)

上一回我們試驗了通過反射的方式擷取method的源代碼。

這次我們就用一個執行個體來示範dump一個程式集中的所有類型和方法的IL源代碼。

首先打開VS2005 建立一個C#的windows程式:

在窗體添加添加一個2個 button,2個label,一個textbox,一個 checkbox,一個savefiledialog。

界面如下:

某殼對.Net程式加密的原理及解密探讨三(執行個體解密)

事件代碼如下:

  1  public class Form1 : Form

  2       {

  3             // Methods

  4             //選擇IL位元組碼儲存檔案

  5             private void button1_Click(object sender, EventArgs e)

  6 {

  7       if (this.saveFileDialog1.ShowDialog() == DialogResult.OK)

  8       {

  9             this.textBox1.Text = this.saveFileDialog1.FileName;

 10       }

 11 }

 12              //點選開始dump。

 13             private void button3_Click(object sender, EventArgs e)

 14 {

 15       this.button3.Enabled = false;

 16       this.DumpAssembly(Assembly.GetExecutingAssembly(), this.textBox1.Text);

 17       MessageBox.Show("dump ok");

 18       this.button3.Enabled = true;

 19 }

 20             //這個函數将一個Assembly全部dump到path中。

 21             private void DumpAssembly(Assembly ass, string path)

 22 {

 23       StreamWriter writer1 = new StreamWriter(path, false);

 24       Type[] typeArray1 = ass.GetTypes();

 25       for (int num1 = 0; num1 < typeArray1.Length; num1++)

 26       {

 27             this.DumpType(typeArray1[num1], writer1);

 28       }

 29       writer1.Flush();

 30       writer1.Close();

 31 }

 32 

 33             //dump單個類型,由dumpassembly調用

 34              private void DumpType(Type tp, StreamWriter sw)

 35 {

 36       BindingFlags flags1 = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;

 37       string text1 = tp.ToString();

 38       sw.Write("TYPE: " + text1 + "\r\n");

 39       if (tp.IsEnum)

 40       {

 41             sw.Write("IsEnum ");

 42       }

 43       if (tp.IsImport)

 44       {

 45             sw.Write("IsImport ");

 46       }

 47       if (tp.IsNested)

 48       {

 49             sw.Write("IsNested ");

 50       }

 51       if (tp.IsClass)

 52       {

 53             sw.Write("IsClass");

 54       }

 55       sw.Write("\r\n");

 56       if ((text1 != "InFaceMaxtoCode") || !this.checkBox1.Checked)

 57       {

 58             sw.Write("**********Begin MemberInfo**********\r\n");

 59             MemberInfo[] infoArray1 = tp.GetMembers(flags1);

 60             for (int num1 = 0; num1 < infoArray1.Length; num1++)

 61             {

 62                   MemberInfo info1 = infoArray1[num1];

 63                   sw.Write(info1.MemberType.ToString() + "\t" + infoArray1[num1].ToString() + "\r\n");

 64                   if ((info1.MemberType == MemberTypes.Method) || (info1.MemberType == MemberTypes.Constructor))

 65                   {

 66                         this.DumpMethod((MethodBase) info1, sw);

 67                   }

 68             }

 69             sw.Write("**********  End MemberInfo**********\r\n");

 70             sw.Write("\r\n\r\n");

 71       }

 72 }

 73 

 74  

 75 

 76         //dump單個方法,由dumptype調用

 77          private void DumpMethod(MethodBase mb, StreamWriter sw)

 78 {

 79       MethodBody body1 = mb.GetMethodBody();

 80       if (body1 != null)

 81       {

 82             byte[] buffer1 = body1.GetILAsByteArray();

 83             try

 84             {

 85                   sw.Write("\tMaxStackSize: " + body1.MaxStackSize.ToString());

 86                   sw.Write("\tCodeSize: " + buffer1.Length.ToString());

 87                   sw.Write("\r\n");

 88             }

 89             catch (Exception exception1)

 90             {

 91                   MessageBox.Show("1:" + mb.ToString() + "\r\n" + exception1.ToString());

 92             }

 93             foreach (LocalVariableInfo info1 in body1.LocalVariables)

 94             {

 95                   sw.Write("LocalVar: " + info1.ToString());

 96                   sw.Write("\r\n");

 97             }

 98             sw.Write("\r\n\r\n");

 99             StringBuilder builder1 = new StringBuilder();

100             foreach (byte num1 in buffer1)

101             {

102                   builder1.Append(num1.ToString("X2"));

103             }

104             sw.Write(builder1.ToString());

105             sw.Write("\r\n\r\n");

106             foreach (ExceptionHandlingClause clause1 in body1.ExceptionHandlingClauses)

107             {

108                   sw.Write(clause1.ToString());

109                   sw.Write("\r\n");

110             }

111             sw.Write("\r\n");

112       }

113 }

114 

115  

116 

117             

118      

119       }

120 

121 

編譯這個程式,運作,dump出il位元組碼,

然後拿 maxtocode加密。再運作,dump出il位元組碼,然後找一個method 如 button1_click,比較一下他們的IL位元組碼是否一樣。

當然結果應該是一樣的。

這裡主要有三個關鍵函數

這三個就是一個例子示範如何dump整個程式集。

如要dump 一個加密的dll,我們就可以直接用這個程式來改,

首先添加引用,引用那個dll,然後随便執行個體話一個該dll中的type。

然後擷取該dll的 Assembly 對象,再調用DumpAssembly函數即可。

好了,今回就到這裡,下回再講解怎麼了解、檢視IL位元組碼。