Net源代码保护技术与工具的研究
.Net框架,是微软公司面向互联网时代研发的新一代软件开发与应用平台,以其高效率的开发环境,正在逐渐取代旧的技术而占领市场,是未来Windows 系统上软件开发的标准。因为其用了不同以往的新技术,源代码被编译为中间语言(IL)而不是机器码,其中包含了很多源代码的信息与特征,可以轻易的被反汇 编成高级语言的源代码。任何人只要下载一个.NET反编译器就可以轻而易举的反编译出接近原始源代码,进而研究软件的实现细节,窃取版权人的创意,或者破 解程序谋利等等。这就非常不利于软件版权与知识产权的保护。
为应对.Net框架中软件的版权保护问题,微软公司以及第三方公司都研究并给出了一些解决方案,并形成了一系列的产品。通过对程序进行混淆以及加密等措
施,达到干扰反编译软件或使反编译出来的代码难于理解的目的。本文的研究内容就是市场上这类软件的混淆以及加密的过程。当然我们的研究目的不是要非法破解
他人软件,而是要推动版权保护技术得到更快的发展。另外,通过我们的研究,可以总结出一些软件开发过程中版权保护的规范和几个主流工具的性能与安全指数,
给相关的软件开发人员做参考资料。
1 .Net的源代码保护技术
1.1 微软提供的解决方案
1) 微软Visual
Studio 中提供了一个官方的反汇编程序
ildasm,可以将可执行.Net程序(EXE)或动态链接库(DLL)反编译为IL。同时,提供给用户一个防止程序被ildasm反汇编的方案:在用
户工程的AssemblyInfo.cs中加入一行代码:
[assembly: System.Runtime.CompilerServices.SuppressIldasm]
作用是让ILDasm.exe不要工作。加入该行后, 运行ILDasm.exe进行反编译。显示 “受保护的模块 -- 无法进行反汇编”。
不过,目前黑客已经破解了ILDasm.exe,使其可以反编译做了上述标识的文件。所以,该种方案失去了实际的作用。
2) 强名称
强名称是使用相应的私钥,通过程序集文件(包含程序集清单的文件,并因而也包含构成该程序集的所有文件的名称和散列)生成的。强名称的作用就是防止程序集被非法修改。当对程序集修改后,必须重新用私钥再对程序集加一次强名称。另外强名称还有一个用途,就是它可以防止dll被第三方随意调用。给程序集加强名称的工具为Sn.exe,可以通过Sn / ? 命令看到它的具体使用方法。
那么强名称有用吗?网上关于破解强名称的文章很多,ildasm反编译程序集后,在IL文件中将强名称去掉,再利用ilasm编译,就可以解除强名称的限制了。所以说强名称不是一个完善的保护方式。
1.2 名称混淆技术
名称混淆是最简单的混淆,具体操作是将命名空间、类名、函数名、变量名等替换成没有具体含义的字符串,使原来代码中有含义的名称都失去了原来的含义,这对计算机运行这个程序没有任何影响,但是黑客将程序反编译后,得到的都是无法理解的名称,加大了黑客读懂程序的难度。
举例来说,比如右图1是一个注册类。
如果想破解这个程序,反编译后一目了然就知道程序要做什么。但如果名称被混淆后,理解起来就没那么容易了。
所有的混淆工具都可以提供类似这样的名称混淆功能。某些混淆工具,如Babel Obfuscator,还可以将名称混淆成不可见的Unicode字符,这样在反编译工具中,这些混淆后的名称就都成为了不可见的了,或者显示为乱码。进一步增强了程序的难读性。
另外,还需注意的一点是,使用名称混淆时,类库或可执行程序中对外界提供的Public方法不要做名称混淆,否则该方法将无法被外界调用。
实际上这种名称混淆的方式,在应用上是有一定不足的。对于大型程序,经过混淆的几百万行没有注释,变量名随机的代码是没人能看懂的,对知识产权起到了保
护。但是,虽说全部解读出原程序来比较困难,但破解者通过动态调试跟踪程序,是可以理解一些关键内容的,比如破解注册信息等还是能够办到的。
1.3 字符串加密
字符串里经常包含一些输入输出的信息,破解者通过分析这些信息很容易可以理解程序的意图,所以需要将字符串加密,防止这些信息被解读。
字符串加密的实现方法主要分为两种。
第一种方法是通过修改IL代码,把原来的字符串替换为一个加密函数。然后在程序的执行过程中,即时的还原原来的字符串。大部分混淆工具提供的字符串加密方法都是这一种。
我们举一个具体的例子。在加密前,代码为:
MessageBox.Show("Hello World!");
而在加密后,代码变成:
MessageBox.Show(Helper.Decode("A34579dfbbeyu346563345/=="));
这里原来的字符串"Hello
World!"被字符串解函数Helper.Decode("A34579dfbbeyu346563345/==")取代。从中无法再看出原来字符串里
包含的信息。字符串加密通常会和名称混淆一起使用,所以真正使用中不会出现象Helper.Decode这么明显的函数名。
但是,这种方法的弊端是很明显的,破解者直接利用这个字符串解函数的代码写一个小工具,就可以还原出原来的字符串,继而再将字符串自动还原到源代码中。
第二种方法是在加密壳中提供字符串加密技术。这种方法不修改IL代码,而是直接加密元数据中的字符串。工具Remotesoft、MaxtoCode等采用了这种方法。
这类保护也存在着一定弊端,当程序运行后元数据中的字符串会解密到在内存中。通过跟踪内存,可以读取出这些字符串。但比起第一种方法,还是要增加很大破解难度的。
1.4 流程混淆技术
流程混淆目的是使反编译的时候出错,让反编译工具失效。反编译工具通常使用的是静态分析的方法,为了防止静态分析,常见的方式是使用跳转指令,跳转的目
标位置是另一条指令的中间,这样在静态分析时便会出现混乱。具体操作起来即是把方法中的代码分成若干段,并调整每一段在代码中的先后次序,然后利用跳转语
句按照正确的次序连接出本来的流程。原理图如图2所示。
目前主流的混淆器都提供流程混淆,如Dotfuscator Professional版,XenoCode,Babel Obfuscator等。
不过,流程混淆也有它的不足,不能防止ILDasm反编译出IL,因为根据微软的设计,ILDasm无法理解的IL,.Net
Framework也是无法理解的。IL中“br.s 行号”和“br
行号”都是强行跳转的指令,而流程混淆主要是用这2个语句进行逻辑连接的。这就给破解者提供了一个特征。通过人为的分析,总结出规律,然后再编写代码,将
语句的顺序调整回来,代码最终又会被恢复成可以被静态分析工具反编译。
1.5 编译成机器码
微软的Ngen.exe工具,可以将
IL编译为机器码。那么是否可以用此来对源代码进行保护呐?就目前Ngen.exe工具现状来看,答案是否定的。微软开发Ngen.exe工具的目的是加
速.Net程序的启动速度,而不是保护源代码。使用Ngen.exe生成机器码的过程依赖于目标机器的具体软硬件环境,所以必须在目标机器上运行编译,此
时必须提供原始的.Net程序。
此外,目前有一些产品号称可以使.Net程序脱离.Net
Framework运行,是否就是将.Net程序编译为机器码了呐?根据笔者的研究,此类的产品的原理不过是将.Net
Framework重新包装,从而使程序运行的目标机器不用安装.Net Framework而已,这跟把.Net程序编译为机器码是两回事。
1.6 加壳技术
在传统的Win32程序中,经常采用加壳技术来保护软件不被非法修改或反编译。原理是通过一段称为“壳”的保护代码先于程序运行,拿到控制权,然后在内
存中完全解开被加密的程序代码,并将控制权移交给被加密的程序代码。目前加壳技术已经日臻完善,破解的难度越来越大了。
因为.Net技术不同于传统的Win32程序,最终的程序是IL而不是机器码,所以传统的加壳工具无法应用在.Net程序中。经过一段时间的发展,现在也出现了可以给.Net加壳的工具,例如MaxtoCode, Remotesoft Protector等。
解释原理前,首先需要了解一下CLI(通用语言基础结构,Common Language Infrastructure)的解释原理:
CLI接到程序集需要解释的请求后,动态的从内存中取出一段IL代码,然后交由CLI解释成机器语言,提交给CPU执行。
MaxtoCode之类工具的工作原理如下:
当CLI提取IL代码时,MaxtoCode提供的解释环境将内存中加密过的IL代码解密,然后交给CLI。提取完毕后,MaxtoCode再将内存中的这段代码还原回加密状态。
采用这种方法后,IL代码都经过了加密,所以基于静态分析的反编译器是无法反编译的。
1.7 水印
所谓水印是将版权信息或标识之类的数据隐蔽地嵌入.NET程序中,处理后不会影响程序的运行,但是可以跟踪软件的流通源头。对于面向少量客户开发的软
件,如果在交付程序的过程中,针对每一个客户,提供加有不同标识的程序,那么发现盗版后,就可以追查出盗版的源头来,并可以作为证据申请相关的法律维权。
支持给.NET程序加水印的工具,例如有Dotfuscator Professional版,其水印处理算法不会增加应用程序的大小,也不会引入可能破坏应用程序的额外元数据。
1.8 加密锁(加密狗)
加密锁是一种基于硬件的软件版权保护工具,通过一个类似U盘一样形状的USB设备,对软件进行保护。某些加密狗是通过对所要保护软件进行处理,加入一个
验证函数,来验证加密狗是否在机器上插着。更高级的加密狗,可以将程序的核心函数保存在加密狗的硬件中,这样没有加密狗时,既不能运行程序,也使企图对软
件进行反编译的人无法得到这些函数。
目前也出现了支持.Net的加密狗,例如SafeNet公司的圣天狗等。
当然,对于加密狗,也存在一定的风险。某些黑客专门针对各种加密狗进行破解而不是针对某款软件,当某种型号的加密狗被破解后,意味着使用该型号的所有软件都同时被破解了。
2 关于选择混淆工具的建议
以上介绍了很多.Net源代码保护技术,那么该采用那种技术或工具呐?根据使用的对象,这里给出如下的建议:
1) ASP.NET的代码:如果服务器代码在公司内部,此时更需要关注的是,完善网络安全工作与保密制度。做得好的话,可以不用采取代码混淆等保护措施,因为用户通过浏览器是无法获得服务器代码的。如果服务器代码是作为面向客户的产品,那么请参考下面的相关建议。
2)
面向单一客户的软件项目:这种软件的需求往往都是客户自己提出的,实现的方案没有什么技术机密可言,软件一般也没有注册的必要。此时也可以不采用保护的措
施。如果不想让客户了解软件的具体实现代码,可以采用Visual
Studio自带的Dotfuscator免费版进行名称混淆,客户应该就没有能力解读了。
3) 面向多个大客户的商业软件:因为掌握客户具体是谁,出了版权问题更多是采用法律途径解决。代码保护方面,主要是对注册相关的代码进行保护,可以采用Dotfuscator免费版进行名称混淆。或者将相关代码用C或C++实现。
4) 面向公众的商业软件:需要面对各种用户,包括破解者。所以最好采用最强大的和最新版的保护工具,通过前面的技术原理分析,如果采用软件手段推荐采用MaxtoCode之类的加壳工具,硬件手段是使用加密狗。
3 结束语
以上介绍了.Net框架下源代码的保护技术与工具,但这里还是需要特别指出一点:虽然通过技术手段,可以在一定程度上保护软件的知识产权,但纵观世界软
件发展的历史,几乎所有流行的知名软件,经过一段时间,都遭到了破解,说明没有十全十美的保护技术。然而,西方国家的软件正版使用率却非常高,其原因在于
使用盗版软件的法律惩罚力度之大,由此可见最有效的版权保护手段还是相关法制的健全。
参考文献:
[1] Richter J. 框架设计:CLR Via C#[M].2版.周靖,张杰良,译.北京:清华大学出版社,2006.
[2] 蔡学庸. .NET中间语言[EB/OL]. http://msdn.microsoft.com/zh-tw/library/dd229211.aspx.
[3] MaxtoCode加密工具[EB/OL].http://www.maxtocode.com.
[4] Dotfuscator混淆工具[EB/OL].http://www.preemptive.com/products/dotfuscator.
转载自http://hi.baidu.com/lasheng/item/4203225154b239ded48bace4