某壳对.Net程序加密的原理及解密探讨三(实例解密)

时间:2021-04-18 16:03:27
上一回我们试验了通过反射的方式获取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字节码是否一样。
当然结果应该是一样的。

这里主要有三个关键函数
            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字节码。