这次我们就用一个实例来演示dump一个程序集中的所有类型和方法的IL源代码。
首先打开VS2005 新建一个C#的windows程序:
在窗体添加添加一个2个 button,2个label,一个textbox,一个 checkbox,一个savefiledialog。
界面如下:
事件代码如下:
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
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字节码是否一样。
当然结果应该是一样的。
这里主要有三个关键函数
private void DumpAssembly(Assembly ass, string path);
private void DumpMethod(MethodBase mb, StreamWriter sw);
private void DumpType(Type tp, StreamWriter sw);
这三个就是一个例子演示如何dump整个程序集。
如要dump 一个加密的dll,我们就可以直接用这个程序来改,
首先添加引用,引用那个dll,然后随便实例话一个该dll中的type。
然后获取该dll的 Assembly 对象,再调用DumpAssembly函数即可。
好了,今回就到这里,下回再讲解怎么理解、查看IL字节码。