读书频道 > 网站 > 网页设计 > 软件加密与解密
1.4.2 混淆技术概述
12-08-25    叶孤城
收藏    我要投稿   

本文所属图书 > 软件加密与解密

本书介绍了如何利用混淆、水印和防篡改等技术,来保护软件免受盗版、篡改和恶意逆向工程的危害,主要内容包括攻击者和防御者用来分析程序的各种主流方法,如何使用代码混淆技术使程序更难以被分析和理解,如何在...立即去当当网订购
只要愿意,你当然可以手工把自己的代码转换成一种难以被对手理解并修改的形式。但在实践中,这种手工代码混淆执行起来太枯燥,也太容易出错[1]。所以更好的办法是编写一个混淆工具,自动地把原本设计良好、易于理解和修改的代码转换得难以读懂且基本上不能修改,就像一团浆糊。混淆器实际上就类似于一个编译器,但是编写它的目的并不是为了生成紧凑高效的代码,而是为了产生你的对手读不懂的东西。

从概念上说,代码混淆器要接受4个参数:被混淆程序P,用户指定的混淆级别,所能接受的最大开销和P中需要混淆的代码的位置,如图1-19所示。




图 1-19
从内部结构上来看,混淆器中含有一组代码混淆算法、为了实施各种混淆转换而必须拥有的程序分析集,以及一种能够挨个把各种用户选择的混淆转换应用到程序P中去的循环。这里使用的程序分析集与编译器、逆向分析工具中所使用的程序分析工具是一样的。而混淆循环则会一直持续到达到你所指定的混淆级别或者程序因为混淆而引起的开销超过了你所能接受的范围为止。混淆器的输出P'在行为上与P是一致的,但是它们的内部结构则大不相同。在实践中,有些混淆器会比上面这个模型更为简化,比如,有的混淆器只需要输入要混淆代码的位置以及混淆级别就可以了。

混淆技术可以分为4大类。结构混淆——程序员把程序组织成类、模块和函数。这类混淆技术就是用来破坏程序的这类总体结构的。数据混淆——混淆程序中所使用的数据。控制流混淆——隐藏程序执行时的控制流结构(比如if或者while语句)。动态混淆——混淆器将往程序中插入一个解释器T,T的存在将使得程序在运行时会不断地改变自身的代码。所以经这类混淆技术混淆过的程序结构应如图1-20所示。





图 1-20
我们将用3章内容来讨论代码混淆的内容。在第4章中,你可以看到许多控制流、数据和结构混淆的算法。我们将讨论这些算法所能带来的混淆程度、破解掉这些保护需要花费多大代价(强度)以及使用这些混淆方法可能给程序带来多大的性能开销(副作用)。在第6章中,我们讨论一些动态混淆技术以及这些技术所能增加的混淆级别、强度和副作用。第5章将介绍一些代码混淆的基础理论。我们特别关心的是确定什么能够被混淆而什么不能。

为了使你对代码混淆有个初步的了解,让我们用下面这个小程序来演示一下相关技术。下面给出的是一段C程序的源代码。我们将依次应用结构混淆、数据混淆、控制流混淆以及动态混淆来处理这段代码。





首先要隐藏的是这一事实:这个程序中的主要业务逻辑是分别在两个函数里完成的。编写这个程序的程序员一定是在某种设计思想的指导下把整个程序分解成3个部分main、foo和bar的。这个结构应该就是这个程序在编写它的程序员心中的模型,所以对于破解软件的黑客一定也很有用。因此要通过把foo和bar函数合并成一个函数foobar来打破程序的这个结构。新函数有3个参数,其中两个是bar函数原有的参数,x和z,foo函数只需要一个参数,所以包含在bar函数的两个参数里就可以了。还有一个参数是用来确定到底应该执行foo函数的代码还是应该执行bar函数的代码的s。下面给出的就是结构混淆后的程序代码。






你看,现在main函数好像是调用了同一个函数2次,但是实际上,它调用的是两个不同的函数。
但是在许多程序里,我们需要保护的秘密是程序中的数据,而不是代码的设计思想。比如在数字版权保护系统中,我们不能让黑客拿到明文的多媒体数据。一般在这种系统中,数据绝不会以明文形式出现,而是被加密成对于攻击者来说难以理解的形式,而且这些数据在程序中也总是以这种加密的形式被操作的。假设在下面这个示例程序中,我们要保护程序中所有整型(int)数的值不会被攻击者获得,而攻击者则主要通过在调试器中运行程序的方式来窥探这些数据。

在这个程序中,对数据只有3种操作:赋值、乘法运算和比较两个值是否相等,我们运气不错!为什么这么说呢?因为我们手头就有一种现成的,可以说就是针对这一情况设计的混淆算法——RSA算法!我们把这一算法的原理和细节放在第4章中详细讨论,现在只给出它的一个实现。令:





再对程序进行一下混淆转换。你看现在程序中已经没有明文的int型数据了吧。





事实上,明文6已经被加密成了12,42已经被加密成了36,7也已经被加密成了37!除了最后解码的时候(在这个演示程序中就是要把明文用printf函数打印出来),程序中一直是处理这些数的密文的。注意,在原来的程序中有一个语句x*7,这句语句中的7在混淆后的代码中已经直接被替换成了37,即E (7)[2]了。

在结构化编程中,总是用适当的嵌套式的条件语句以及循环语句来组织你的程序,这也使得程序易于理解和修改。而控制流混淆的目的就是打乱这些东西——扁平化控制流,通过重写函数,把结构化的语句变成一团浆糊。下面给出的就是经过了控制流混淆处理后的foobar函数,原先优雅的控制结构已经全部变成丑陋的goto语句了。




看一下代码清单1-2,我们又把函数foobar中的代码拆分成两个函数:A和B。光这一点并不能算是很有效的代码混淆方法,但这段代码漂亮就漂亮在:foobar函数每被调用一次,函数A和B就会互相交换一次位置,如图1-21所示。



图 1-21
攻击者不论是用静态方法还是动态技术分析这个程序都很困难。如果他使用静态方法进行分析(不运行程序),结构混淆、数据混淆和控制流混淆已经把程序的组织结构、数据明文以及控制流结构去除了。而如果他试图运行程序进行分析的话,动态混淆已经改变了他关于程序的一个基本假设,即每当程序运行到内存的同一个位置时,该地址上的代码应该是不变的。
 
代码清单1-2 动态混淆的结果,在运行时,函数A和函数B的位置会不断地互换。代码中的swap引
自代码清单6-3







[1]还要补充的是,错了以后还不容易把出错的地方给找出来!因为代码已经被你自己改的面目全非了。
[2]顺便多注一笔给初学者,在编译器或者混淆器产生的,特别是优化编译器产生的代码中,对于这种结果肯定是一个常数的表达式,总是会把结果计算出来,替代掉原有表达式的。
点击复制链接 与好友分享!回本站首页
分享到: 更多
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:1.3 功能
下一篇:1.5 小结
相关文章
图文推荐
JavaScript网页动画设
1.9 响应式
1.8 登陆页式
1.7 主题式
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做最好的IT技术学习网站