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


    上一回我们试验了通过反射的方式获取method的源代码。
    这次我们就用一个实例来演示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 

    编译这个程序,运行,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字节码。

  • 相关阅读:
    SmartTimer——一种基于STM32的轻量级时钟调度器
    Python2/3中的urllib库
    Python 解析构建数据大杂烩 -- csv、xml、json、excel
    Python2/3 中执行外部命令(Linux)和程序(exe) -- 子进程模块 subprocess
    Python 中的命令行参数处理 -- argparse、optparse、getopt
    Linux 定时循环执行 python 脚本
    Python2/3的中、英文字符编码与解码输出: UnicodeDecodeError: 'ascii' codec can't decode/encode
    在windows下使用Qt5开发GTK3图形界面应用程序
    qt编译的基于xlib cairo的桌面程序
    debian安装dwm窗口管理器
  • 原文地址:https://www.cnblogs.com/rick/p/517603.html
Copyright © 2020-2023  润新知