.NET单机软件保护策略(1)防反编译

.NET单机软件的保护有两大难点,分别是:

  • 编译的结果不是机器码,而是IL代码,反编译非常容易。

  • 不联网的软件没听说过不能破解的。

所以,我们的保护策略也不是说绝对的安全,只是能防多少是多少。

首先对于第一点,我们先看一个例子,以产生直观的感受。假设我们写了一个简单的软件,代码如下所示:

static void Main(string[] args)
{
    if (!CheckVerify("my_password"))
    {
        return;
    }

    int result = Calculate();
    Console.WriteLine("计算结果是:" + result);
}

//软件认证
static bool CheckVerify(string password)
{
    return password == "secret";
}

//需要保护的核心代码
static int Calculate()
{
    return 100;
}

编译成exe之后,我们使用ILSpy这款工具对其进行反编译,得到的结果如下图所示:

可以看到,这跟源码几乎没有区别!就算CheckVerify函数用了极其复杂的算法,我把它都注释掉,改成return true再重新编译,不就破解了吗?而且,要保护的算法让人一览无遗,还谈什么专利、什么研究结果。

为此,我们需要对软件进行一些代码保护。在保护之后,上述的程序在反编译之后,得到如下的结果:

可以看出,原来一个简单的类,变成了多个类,而且一个类里面有大量方法,每个方法不知所云。当然,既然程序能正常运行,说明代码的逻辑是通的,只要有恒心,迟早能看懂这些代码,不过就需要比较高的成本了。

对于源代码的保护,有以下的方法:

  • 强命名:强命名是把源程序进行数字签名,当程序被改动之后,就会无法运行。例如我们在上述例子中的CheckVerify里插入一句return true(在IL代码层修改),程序就会报错,无法运行。当然,强命名也是很容易破解的,只要反编译,把签名信息去掉即可。

  • 代码混淆:就是把代码里原来正儿八经的命名改成乱七八糟的字符,甚至是不可见的乱码。就比如把CheckVerify这个函数名,改成n7R4Xm3qfd03J,可读性差了一大截。当代码多了以后,要理清原代码的思路就会很困难。

  • 控制流程混淆:打乱原代码中的流程,插入大量不相关的代码,降低代码可读性。例如我们要执行num=3这么简单的代码,如果改成:

    a=4
    
    if(a!=4)
    
    	num=2
    
    else
    
    	num=3

    这样,可读性就会差很多了。

  • 字符串加密:在上面的CheckVerify函数里面,有一句if(password=="secret"),那谁都知道secret这个密码了。字符串加密会对代码里的字符串进行加密,在用的时候再进行解密。

  • 防调试:当软件检测到用户在调试代码时,退出程序。检测的一种方法是检测时间,例如两句代码明明很近,但到达代码的时间用了1秒,那很可能是被调试了,可以退出程序。

  • 加壳:加壳是把我们原来整个软件进行加密,然后在外面加一层壳,这个壳是另外一个程序,用于对原软件进行解密和运行。这样的话,原软件的代码只会出现在内存中,破解难度会增加。

源代码保护的方法还有很多,在此不赘述。如果想要自己对软件做上面的保护,那需要对PE文件、对IL代码有非常深刻的认识,不是一般人可以做的(我也不行)。一般我们使用一些工具辅助,我用过的软件有:

  • ConfuserEx:免费开源的,比较好,但几年前就没更新了,只支持.NET Framework。

  • .NET Reactor:收费,比较好,一直有更新。

  • Dotfuscator:收费,比较难用,中间还会出错。

  • Smart Assembly:收费,只有代码混淆,效果不好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值