分享

“ngen.exe ” CLR本机映像生成器

 scholes_goal 2012-12-28
保护方案分类  
  下面,我开始介绍一下.NET的各种保护方案。  
  我把Dotnet的保护分为三大类  
  1. 由m$   提供的非第三方保护方案  
  a) 强名称  
  强名称是MS提供的保护机制。  
  它需要使用   sn   这个命令。  
  强名称是什么意思呢?在这里稍作解释。强名称的作用就是防止程序集被非法修改,当对程序集修改后,必须重新用您的私钥再对程序集加一次强名称,这也是如果 含有强名称的程序集在混淆或加密后必须要重新加强名称的原因。  
  Sn   /   ?   可以看到它的使用方法,如果你安装的   Framework是中文的,那么
参数的解释也是中文的,我就不多讲了。  
  那么强名称有用吗?网上轻松破解强名称的方法很多,Ildasm反编译加过强名称的程序集后,在IL文件中将强名称的相关信息去掉,再利用Ilasm编译,就可 以解除强名称的限制了。这个我已经过测试过,您的强名称的PublcKey不管是加在程序集中,还是加在Class中,都可以被去掉,所以强名称不是一个 完善的保护方式。不过在这里要说一下,如果有一个好的方案能和强名称一起使用,那么将建立一个非常好的机制,防修改,防滥用。  
  说到滥用,这是强名称的一个特殊用途,它可以使您的dll不被第三方调用,如果您的dll能保护自己的话。  
  关于强命称讲到这里,他的使用方式有必要的情况下,我们以后再深入的讲解。  
   
  b) 编译MSIL为本机代码   (误区?)  
  关于这一点,我经常能在MS上的社区看到有MVP这样面对问题:  
  问:C#写的程序能编译成本机代码吗?  
  答:可以,使用   Ngen.exe   即可以   MSIL   代码编译为   本机代码。  
  MVP这样回答错了吗?其实,严格的说,MVP的回答是没错的,Ngen.exe的确是可以将   MSIL   编译为本机代码,并可以使JIT不需要进行再次编译MSIL。这样能加快程序的执行效率。  
  但用户这样的问题其实,并不是对执行效率不满意,而是对中间语言不满意,可惜   Ngen   并不能解决用户的问题。  
  让我们来浅浅的分析一下   Ngen的工作吧。  
  Ngen是MS提供的   本机映象生成器,它可以将中间语言程序集编译为本机代码存放在缓存中。这里请大家注意,是存放在缓存中,Dotnet在内存中建立了一个缓存,这个缓存中 存放了许多常用的程序集编译后的本机代码,它们是常驻的,由此来加快Dotnet的执行速度。  
  所谓一个本机代码,因为本机映射时,会映射出一些   Framework   里需要的Method,编译为汇编就是  Call   0x0200000这样的样子,而这些东西必须是事件编译好的。那么理论上说   Ngen   必须要在当前执行的机器上运行,而直接编译成本机代码的程序copy到另一个地方不一定可以用,而且我一直没有找到能将缓存中的本机代码   copy   出来的方法。  
  讲到这里,不知道大家明白我的意思没有,不管如何   Ngen.exe   只是一个提速的工具,因为要执行编译为本机代码必须还是要原程序集,而原程序集中存在MSIL,所以让程序无法脱离被反编译的目地。  
  大家回家,如果有空,可以做做试验。  
  Ngen   /show   就可以看到缓存中所有的已编译好的程序集,所以Dotnet并不慢。  
  Ngen   <assembly   path   or   display   name>   可以把指定程序集映象为本机代码。  
  Ngen   /?   可以看到其它参数  
   
  以上是ms提供的工具,下在讲讲,自己在编程的过程中,如何使用技巧来防止破解或反编译。  
  2. 编程技巧保护方案  
  在这里,我会给大家介绍两种三种方式  
  1. 人为混淆  
  在这里,我就要先简单的讲讲什么叫做混淆  
  混淆顾名思意,就是混乱,不明确的意思。MetaData中都有一个Rid,程序集运行时就已经和名称没什么关系了,都使用Rid来调用的,所以可以将名 称省去。  
  什么叫人为混淆呢,就是人为的制造混淆。  
  曾经看过一个程序集,手工的将一个Method折成几十个或上百个,从而达到让你看不懂的目的。不过可惜的说一句:现在的Dotnet程序集的分析工具都 很强大,正引用,反调用都可以用程序来实现,所以即实这么做,了没多大用处。著名的Reflector就有这些功能。  
  2. 隐藏程序集  
  刚刚谈到了Reflector,它就是使用这种方式来隐藏自己的核心程序集的。相信我,Reflector并不是您看到的那一个可执行程序,它的可执行程 序只是一个壳而以,里面是一个定义和接口,没有实例的方法。如果你想得到他是怎样反编译的核心,恐怕你会在它这个迷宫中迷失方向。  
  它是怎样做的呢?让我来告诉你,它的核心程序集事实上就是它的一个资源。而这个资源是一个加密的资源。如果我没记错,他应该是在双击第一个需要反编译的 Method的时候开始释放这个资源,并对资源解密然后动态的加载。这样做的优点核心程序集是不会在硬盘上留下任何痕迹的,它只解在内存中解密并被加载, 你基本上无法得到这个程序集。而且Dotnet是不允许内存   Dump的。  
  大家是不是觉得这种保护方法不错呢?你可以把你的核心代码加密后做成资源包在程序里,在使用的时候再解密出来,这只需要你自己去实现就可以了。  
  不过我还得说句负责任的话,如果你有精力,并且很有耐心和技术,相信你还是可以在几天时间内找出它的核心程序集解密算法的位置。并成功的解出它的资源程序集。  
  如果是高手又非常有经验,这种方式的加密手段应该是秒杀。  
   
  3. 将程序集中的相关Method(方法)编译成Unmanaged(非托管代码)  
  下面介绍的内容是不管你是菜鸟,或是高手,都无法得到核心代码的方  
  它可称之为终极的保护手段,因为它就是“非托管代码”。  
  什么是托管代码,什么是非托管代码。  
  简单的说,托管代码就是需要Jit去解释的中间语言代码,而非托管代码  
  就是本机代码。下面要介绍的方式就是教您如何在自己的程序集中即拥有托管代码,又拥有非托管代码。注意,非托管代码是无法被现在的反编译工具反编译的。  
  特别注意一点,我没有自己试过,但我看人做过,并得到了证实。  
  在Dotnet程序集中,允许托管代码和非托管代码共存,怎样实现呢?这并不是无偿的,这是需要条件的。它的条件就是必须使用VC++.NET非托管方式 来写dll,再用VC++托管方式建立工程引入这个本机代码的dll。最终生成一个Dotnet程序集的dll。那么这个程序集里面即有托管代码,又有非 托管代码。托管代码是可以反编译的,而非托管代码不可能被反编译。  
  有人可能要问了,这和自己用VC++写个dll有什么区别?区别就是这样的结合更紧密一些,而且也不能用常规的分析Asm的工具去分析这个dll。  
  这里还要解释一个误解,有人说,利用Win32的本机代码写注册算法,并生成dll供给Dotnet程序集调用,防止破解。其实这句话只说对了一半,这只 能增加破解注册机的难度,并防止不了破解。为什么呢?因为注册对不对还是要在Dotnet程序集中进行判断,所以,只要改掉这个判断,一样达到了破解效果。但是如果要分析注册算法,那可就 是困难了一些了。  
  3. 第三方保护工具  
  下面,我们讲一讲第三方的保护工具和概念  
  第三方保护工具较好的厂商有:  
  1. Aiasted.SOFT    
  a) 产品   :MaxtoCode   ,种类   :加密、混淆  
  2. PerEmptive   Solutions  
  a) 产品   :Dotfuscator   Community   ,种类   :混淆  
  3. Remotesoft  
  a) 产品   :Remotesoft   Protect   ,种类   :加密  
  b) 产品   :Remotesoft   Dotfuscator   ,种类   :混淆  
  4. XenoCode  
  a) 产品   :XenoCode   ,种类:混淆  
  5. 其它的一些公司,最近上海有一款公司出了国内第一款混淆工具,如果大家要选择混淆产品的话,支持一下国产也不错。  
   
  第三方工具的保护方式分类  
  1. 混淆
  这是目前最流行的方式吧。今天我们就来做个剖析。让大家去衡量一下混淆的强度如何。  
  混淆软件一般都有三个功能  
  1. 字符串加密  
  2. 名称混淆  
  3. 流程混淆  
  目前流行的混淆软件有  
  XenoCode、Dotfuscator、Remotesoft,MaxtoCode里也集成了少许混淆功能。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多