DOTNET防止反编译

DOTNET防止反编译

目录

第一部分 相关理论
一 防止反编译概述
二 DOTNET编译原理简介
三 被反编译的后果
四 保护方案分类

第二部分 实践
一 Net强名称工具SN.EXE
二 使用Dotfuscator
三 Net加壳与脱壳

第三部分 推荐方案


第一部分 相关理论


一.DOTNET防止反编译概述
    作为商用程序,C#如同 java一样,很容易被反编译。甚至VS还自带了一个反编译的工具。打开 Visual Studio, “工具”->“ILDASM”,就可以直接看到所有的变量,结构体,函数名称,都和你的源码里一模一样。如果使用更强大的 Reflector,就直接看到C#源码了。这对于商用程序的知识产权的保护是很不利的。除了代码会泄露,写在程序里的连接数据库的用户名和密码,都成了明文。
 
有一个办法就是进行混淆。使用它对生成的EXE进行转换。可以将变量名,过程名,都变成无意义字母,这样反编译得到的可读性就会降低好多了。
也可以进行加壳,加壳后的EXE和DLL是不能被反编译出源代码的,但要防止脱壳;如被脱壳则可反编译出源代码。

二.DOTNET编译原理简介
    Dotnet是一种建立在虚拟机上执行的语言,它直接生成 MSIL 的中间语言,再由DotNet编译器 JIT 解释映象为本机代码并交付CPU执行。这种语言的优点就是您不需要去考虑您的程序在那里运行,您只需要把功能做出来,虚拟机会在任何地方实现您的功能。但虚拟机的中间语言由于带了大量的“元数据”信息,所以也极容易被反编译。

三.被反编译的后果。
1.知识产权方面,辛苦研究出来的算法,被公开了。
2.源代码泄漏,被竞争对手拿去和你竞争。
从客户那里想办法copy回一份别的公司的产品,然后反编译后,改改图片,图片以及版权信息和注册信息,就拿出去卖了。正规的公司一套卖二万,它们一套才8千。
3.自己产品的注册机满天飞
4.被别人植入恶意程序,后果得由作者或开发商承担。
    Dotnet的程序集,不保护是不行的。

四.保护方案分类
<一>.由MS提供的非第三方保护方案
a.强名称
强名称使用 sn 命令。
强名称的作用就是防止程序集被非法修改,当对程序集修改后,必须重新用您的私钥再对程序集加一次强名称,这也是如果含有强名称的程序集在混淆或加密后必须要重新加强名称的原因。
网上破解强名称的方法很多,Ildasm反编译加过强名称的程序集后,在IL文件中将强名称的相关信息去掉,再利用Ilasm编译,就可以解除强名称的限制了。有人已经过测试,您的强名称的PublcKey不管是加在程序集中,还是加在Class中,都可以被去掉,所以强名称不是一个完善的保护方式。
    强名称的一个特殊用途,它可以使您的dll不被第三方调用。

b.编译MSIL为本机代码
可以使用 Ngen.exe 将 MSIL 代码编译为本机代码。
Ngen是MS提供的 本机映象生成器,它可以将中间语言程序集编译为本机代码存放在缓存中。Dotnet在内存中建立了一个缓存,这个缓存中存放了许多常用的程序集编译后的本机代码,它们是常驻的,由此来加快Dotnet的执行速度。

<二>.编程技巧保护方案
a.人为混淆
混淆,就是混乱,不明确的意思。MetaData中都有一个Rid,程序集运行时就已经和名称没什么关系了,都使用Rid来调用的,所以可以将名称省去。现在的Dotnet程序集的分析工具都很强大,正引用,反调用都可以用程序来实现,所以即实这么做了,没多大用处。Reflector就有这些功能。
    最简单的混淆是名称混淆,即将 命名空间名、类名、方法名、字段名等统统换成特殊符号或其它符号,目的就是让你不能与以前的名称建立关联。
    流程混淆就是把原来程序的执行流程打乱。比如把一个函数拆成三个小函数,三个小函数通过跳转等方式连接起来,功能和混淆之前的一样。以迷惑反编译者。

b.隐藏程序集
Reflector就是使用这种方式来隐藏自己的核心程序集的。Reflector并不是您看到的那一个可执行程序,它的可执行程序只是一个壳,里面是一个定义和接口,没有实例的方法。它是怎样做的呢?它的核心程序集事实上就是它的一个资源。而这个资源是一个加密的资源。Reflector是在双击第一个需要反编译的Method的时候开始释放这个资源,并对资源解密然后动态的加载。这样做的优点核心程序集是不会在硬盘上留下任何痕迹的,它只解在内存中解密并被加载,你基本上无法得到这个程序集。Dotnet是不允许内存 Dump的。
你可以把你的核心代码加密后做成资源包在程序里,在使用的时候再解密出来,这只需要你自己去实现就可以了。

c.将程序集中的相关Method(方法)编译成Unmanaged(非托管代码)
它可称之为终极的保护手段。简单的说,托管代码就是需要Jit去解释的中间语言代码,而非托管代码就是本机代码。
非托管代码是无法被现在的反编译工具反编译的。在Dotnet程序集中,允许托管代码和非托管代码共存。它的条件就是必须使用VC++.NET非托管方式来写dll,再用VC++托管方式建立工程引入这个本机代码的dll。最终生成一个Dotnet程序集的dll。那么这个程序集里面即有托管代码,又有非托管代码。托管代码是可以反编译的,而非托管代码不可能被反编译。
<三>.第三方保护工具
第三方保护工具较好的厂商有:
Aiasted.SOFT,产品 :MaxtoCode ,种类 :加密、混淆
PerEmptive Solutions,产品 :Dotfuscator Community ,种类 :混淆
Remotesoft,产品 :Remotesoft Protect ,种类 :加密
            产品 :Remotesoft Dotfuscator ,种类 :混淆
XenoCode,产品 :XenoCode ,种类:混淆

第三方工具的保护方式分类
a.混淆
混淆软件一般都有三个功能:字符串加密;名称混淆;流程混淆。
b.打包
ThInstall 是一个打包工具,他可以打包几乎所有的应用程序,也包括Dotnet。将多个Dotnet程序集包在一个大程序里,达到无法反编译的目地。不过既然是打包,在需要运行时肯定会释放,如果找到了释放出来的文件,就跟没保护一样了。
c.加密 
加密保护的软件都有一个共同点,即把Dotnet的反编译引深到Win32的反汇编中了,可惜的是,也限制了Dotnet跨平台的优势。
MaxtoCode的实现原理。MaxtoCode是中国第一款高强度的Dotnet保护软件,在世界的Dotnet保护水平线上也处于优势性的领先。MaxtoCode的原理,它是将程序集中所有的IL进行加密,所以使用反编译器无法看到IL,从而不能进行反编译。基于Framework提取Method的IL作为基础原理,当JIT需要IL时,我就将加过密的IL解密给JIT去编译,这就是MaxtoCode的基本原理。

MaxtoCode 加密的过程及结果:
1.选择程序集 
2.选择高级加密的选项
3.选择混淆的选项
4.加密
5.结果

<四>.加壳
   加壳的全称是可执行程序资源压缩,是保护文件的常用手段。 加壳过的程序可以直接运行,但是不能查看源代码.要经过脱壳才可以查看源代码。
    加壳是利用特殊的算法,对EXE、DLL文件里的资源进行压缩、加密。这个压缩之后的文件,可以独立运行,解压过程完全隐蔽,都在内存中完成。附加指令在原程序上通过Windows加载器载入内存后,先于原始程序执行,得到控制权,执行过程中对原始程序进行解密、还原,还原完成后再把控制权交还给原始程序,执行原来的代码部分。加上外壳后,原始程序代码在磁盘文件中一般是以加密后的形式存在的,只在执行时在内存中还原,这样就可以比较有效地防止破解者对程序文件的非法修改,同时也可以防止程序被静态反编译。

第二部分 实践


一. Net强名称工具SN.EXE
1 编写一个程序,按常规方式编译,提取编译后的程序集和公钥信息,结果如下图所示;

公钥相关信息为空;

2 用VS自带的命令行工具SN.EXE 生成一个公钥对;并存入test.snk 密钥文件;


3 采用2的密钥文件,在命令行用强名称签名的方式对上述程序再次进行编译;


4 再次运行程序提取程序的程序集和公钥信息,结果如下,程序中增加了公钥相关信息;

当执行经过强名称签名的程序集时,如果在强名称签名后该程序集被修改过,则会报异常,不能运行。

二. 使用Dotfuscator
1 使用VS自带的未注册的Dotfuccator进行混淆
Dotfuscator是VS里面一个自带的.NET混淆器和压缩器,它可以帮助您防止您的应用程序被反编译。用Dotfuscator混淆之前反编译的结果如下,可看到全部源代码:

使用Dotfuscator混淆后,再反编译,结果如下;可看出已经有了一定的混淆效果;一些变量名称被替换成了无意义的a、b、c、d等;

2 注册过的Dotfuscator功能有限,可配置选项较少
3 Dotfuscator的配置
安装好Dotfuscator ,打开界面,有几个需要配置的地方: Options、Input、Rename、String Encryption、Build。

三 .Net加壳与脱壳
    以自编Winform程序StrongNamef.exe和xxxxxxxx.dll为需要保护的目标程序为例,来进行加壳与脱壳。
1 未加壳之前用Reflector进行反编译,均可直接反编译出源代码,如下图所示;


2 选择用Sixxpack_2.4进行加壳,加壳后不能反编译出源码,或直接不能反编译,如下二图所示;


以下用各种.Net脱壳软件进行脱壳;

3 使用NETUnpack对上述两个加壳后的程序脱壳,不能脱掉;
4 使用de4dot对上述两个加壳后的程序脱壳,不能脱掉;
5 使用DotnetDumper进行脱壳,该工具不能脱dll的壳,也不能脱StrongNamef.exe所加的壳;
6 用查壳工具PEID V0.95进行查壳,查不到xxxxxxxx.dll所加的壳,对StrongNamef.exe则可查出程序是.Net开发的并带有GUI界面;如下图;如果查不出是什么壳也是安全的;


如果PEID查到壳,则会显示出所查到壳的类型,以下是PEID查到一个叫Nullsoft PiMP Stub壳所显示的示例;


7 用UnPack4Sixxpack进行脱壳,不能脱掉。


8 加壳的注意事项:
1) 关于图标文件,开发项目的图标文件要单独存一份,否则用Sixxpack加壳后程序图标会消失。
2 ) 加壳后原文件有可能变大或变小。
3) 加壳的保护时间一般为1年左右,1年之后有可能有人开发出所用加壳软件对应的脱壳软件放到网上,需要使用更高版本或更新的加壳软件进行加壳
4) 文档需要保密,如果被反编译者知道所用的加壳软件,则可能比较容易被脱壳,从而被反编译。
5) 加壳的程序发布之前需要测试,偶尔的情况下,360杀毒软件会把加过壳的程序误报为病毒。对于别的保护方式进行保护的程序,360也有可能误报为病毒。如果发生此情况,需要在360中选择信任此软件,以后就不会再误报。

第三部分 推荐方案


MactoCode工具的价格为一台电脑带狗1700元, 5台电脑带狗5000多元。
Dotfuscator为VS附带的由第三方国外厂家提供的保护够工具,需要注册才能提供全部功能。登录该第三方厂家网站一直不能注册成功。网上下载的Dotfuscator仅支持到.Net Framework 3.5。

鉴于以上,目前较好的一种方案是;
如果系统可编译为.Net 3.5及以下版本,则先把系统编译为Net 3.5版本,然后用网上下载到的Dotfuscator破解版进行混淆;混淆之后再用Sixxpack_2.4进行加壳。
如果系统须编译为.Net 4.0及以上版本,编译系统后,用Dotfuscator非注册版进行一定程度的混淆;然后再用Sixxpack_2.4进行加壳。

以上方案在1年之后应该要更新所用工具的版本,或寻找更强的混淆和加壳工具。

附件:
程序1:
    提取.Net程序集中的公钥信息。
程序2:
    一种.Net加壳机制的实现,把要保护的程序A作为程序B的嵌入资源,通过运行B来运行A,A作为嵌入资源不能被反编译。
程序3:
    一个DLL,实现替换掉.Net项目中的所有注释为空,替换全部静态变量名为无意义名称。

附件程序暂不提供,可作为了解;找不见了;
 

发布了434 篇原创文章 · 获赞 512 · 访问量 294万+

猜你喜欢

转载自blog.csdn.net/bcbobo21cn/article/details/90484719