zoukankan      html  css  js  c++  java
  • 某壳对.Net程序加密的原理及解密探讨二

    自上次写第一篇文章到现在不知不觉两个月过去了,这篇文章我们将介绍怎么获取解密后的IL字节代码。
    我们先回顾一下前文,在上一回我们提到“InFaceMaxtoCode.Startup 正常启动后,在整个程序集中只会运行一次。”。
    当时这种说法是很武断的,如果 “InFaceMaxtoCode.C______(num2, num3)” 的返回值总是 false的话,该函数就会被执行多次,
    不过根据后来动态调试的结果,我们证实了“InFaceMaxtoCode.C______(num2, num3)” 的返回值为 true,因此上次的说法是正确的。

    现在言归正传,怎么取得解密后的代码呢?大概两个方向,
    1.正面交锋,直接攻破maxtocode的运行库。
    这就将问题直接回到了传统的win32层面,不过这个东西是业内人士写的在这方面的保护工作做得很好,像我这样的菜鸟就很难直接攻破了。
    我曾有一个设想,就是通过分析运行库找到解密函数的入口,然后弄一个stub dll,hook这个地方,把解密后的il代码dump出来。
    实际跟踪几次后我就放弃了。从跟踪到的信息来看,我猜测,运行库是通过 mscorwks.dll 挂接到 jit,在jit的前面实时解密代码。
    理论上我们也可以挂一个到jit前面,在那里dump解密的il代码,不过这个实现的方式,还不清楚,如果弄明白了,也就能写一个同样原理的加密软件了。
    这个难度比较大,所以我最终放弃了这个方案。

    2.避开运行库,我们直接利用dotNet 2.0的特性获取IL代码。
    如是我就试着用2.0写了一个winform程序,加密,运行,发现报错。
    maxtocode3.1不支持2.0的winform程序,这就使我的这个方案实验夭折了。
    两个月过去了,发现maxtocode升级到3.11了修正了这个bug,今天终于可以继续实验了。

    我们来建一个简单的winform程序。一个窗体,然后一个按钮。
    代码如下:


     1
     using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.Data;
     5 using System.Drawing;
     6 using System.Text;
     7 using System.Windows.Forms;
     8 using System.Reflection;
     9 using Spaces;
    10 namespace Test5
    11 {
    12     public partial class Form1 : Form
    13     {
    14         public Form1()
    15         {
    16             InitializeComponent();
    17         }
    18    
    19         private void TestMethod()
    20         {
    21             //  [7/17/2006]
    22             int i = 0;
    23             i = 1;
    24             i++;
    25             if(i>0)
    26             {
    27                 MessageBox.Show("OK");
    28             }
    29         }
    30 
    31         private void button1_Click(object sender, EventArgs e)
    32         {
    33             Type tp = this.GetType();
    34 
    35             MethodInfo mi = tp.GetMethod("TestMethod",
    36                 BindingFlags.NonPublic|BindingFlags.DeclaredOnly|
    37                 BindingFlags.Public|BindingFlags.Static
    38                 |BindingFlags.Instance);
    39             if(mi == null)
    40             {
    41                 MessageBox.Show("err");
    42                 return;
    43             }
    44             MethodBody mb = mi.GetMethodBody();
    45             byte[] bt= mb.GetILAsByteArray();
    46             StringBuilder sb = new StringBuilder();
    47             for (int i = 0; i < bt.Length; i++)
    48             {
    49                 sb.Append(bt[i].ToString("X2"));
    50                 sb.Append(" ");
    51             }
    52             string stxt = sb.ToString();
    53             MessageBox.Show(stxt);
    54                        
    55         } 
    56      
    57     }
    58 }


    编译运行,我们点击按钮就能看到 TestMethod 的IL字节码。
    然后用maxtocode加密在运行,同样能看到 TestMethod 的IL字节码。
    两次看到的结果一样的,这个是当然了,如果不一样,maxtocode就破坏了程序的正确性了。

    好了,我们的实验成功了。

    看到这里大家应该知道怎么获取解密后的IL代码了吧。

    这种方式比在内存里面找代码或者hook到maxtocode解密后dump代码的方式要优越很多,
    因为内存dump的方式你还要担心运行时的函数覆盖率,没有运行到的就dump不到。

    这种方式我们利用 DotNet的反射机制,可以枚举出程序集中的所有类型,以及每个类型的所有方法,成员,字段,构造函数等。


    初步实验了一下,对于加了密的dll文件还是比较好弄的,2.0的、1.1的都能弄出IL代码来。
    对于exe文件还有一关需要解决,那就是如何将我们的DotNet dll程序集插入到exe的运行空间中去。


    今回就先到这里了,下回再实际写程序演练获取解密后的IL字节代码。

    ps:不知道大家手上是否有破解到的 Reflector 的源代码,如果有丢一份给我,感激不尽。

  • 相关阅读:
    ZKEACMS 的两种发布方式
    一步一步教你如何制件 ZKEACMS 的扩展组件/插件
    三张图片看懂ZKEACMS的设计思想
    ZKEACMS 模板组件扩展
    ZKEACMS 如何使用组件自定义样式/编辑样式
    关于简单的Excel多页签底层导出_电子底账导出为例(.net core)
    Javascript中,数学方法可以分成以下几类: constans(常数)、power functions(乘方函数)、trigonometic functions(三角函数)、rounding functions(舍入函数)、random numbers(随机数字)
    AutoCAD.Net/C#.Net QQ群:193522571 对字符串进行四则运算
    AutoCAD.Net/C#.Net QQ群:193522571 利用反射将父类中的属性传递到子类中,实测效率不高
    AutoCAD.Net/C#.Net QQ群:193522571 将DataTable集合 B加入到DataTable A中,应用于两个或以上的只有单行数据的无主键的datatable的合并 Merge
  • 原文地址:https://www.cnblogs.com/rick/p/504525.html
Copyright © 2011-2022 走看看