《加密与解密》-保护篇-软件保护技术
1.防范算法求逆
基本概念:
注册码验证:
用向软件作者提交用户码U,申请注册。
软作者计算出注册码R=f(U),将结果返回合法用户。
用户在软件注册界面输人U和R
软件通过验证F(U,R)的值是否合法来判定用户的合法性。
堡垒战术:
(各种注册方案,看不懂,略)
游击战术:
2.抵御静态分析:
花指令:
通过前面的介绍我们可以知道,“无用的字节”干扰了反汇编工具对指令起始位置的判断,从
而导致反汇编的结果错误。如果能让反汇编工具正确地识别指令的起始位置,就能达到去除花指令的目的
例如,可以把那些无用的字节都替换成单字节指令。最常见的一种替换方法是把无用的字
节替换成nop指令,即十六进制数90h,示例如下。
OllyDbg的一个花指令去除插件就是利用这个原理来去除花指令的。它根据收集的花指令特征码,将垃圾数据替换为nop指令,从而使反汇编工具正常工作。
SMC技术实现:
"SMC”是"SeIf-Modifying Code”的缩写,
也就是说,可以在一段代码执行之前对它进行修改利用SMC技术的这个特点,在
设计加密方案时,可以把代码以加密形式保存在可执行文件中,然后在程序执行时动态解密,这样
可以有效地“对付“静态分析一一一如果要了解被加密代码的功能,就只能动态跟踪或者分析出解密
函数的位置并编写程序来解密这些代码了。
(初步实现SMC反跟踪示例,看不懂,略)
信息隐藏:
对一些关键信息进行隐藏处理,可以在一定程度上增加静态反编译的难度。例如.对“软件已
经过期,请购买”等数据进行隐藏处理.可以有效防止解密者根据这些信息利用静态反汇编快速找
到程序判断点进行破解。信息隐藏的实现思路很多,例如将要显示的字符加密存放,在需要时将其
解密并显示出来。
简单的多态变形技术:
不过从病毒制造者的角度来看,多态引擎往意味着将病毒代码用某种算法编码(算法可能是
即时生成的,也可能是密码学算法),然后,引擎会生成一个充满干扰指令的解码器,以便在运行
时对病毒代码进行解码〈这样做可能会使依靠静态扫描特征码的杀毒软件失去作用)。但是,现在
的杀毒软件已经可以在运行期扫描特征码了,因此多态的效果大不如前。此外,因为多态需要还原
明文代码,所以对反调试也没有太大的作用。多态就像代码的一层壳,只要被穿过就没有用了。
变形则是把一段代码重新编码。虽然仍然使用x86指令集,但是像"addeax,5”这样的指令可
能被换成等价的5个"inc灬"指令,面且可以用jmp指令打乱代码的顺序。此类变换会使代码迅
速膨胀,因此,注重体积的病毒不会过多地使用变形(但在壳中可以不关心体积)。在保护
一个几KB的小文件时,会将文件膨胀到将近2MB,并尽量地将代码变形,从而很好地干扰分析人
员。ExeCryptor之所以有不错的强度,就是因为它有一个很好的变形混淆引擎,可以把壳代码变得
非常“难看”,当然也难以跟踪和分析。不过,ExeCryptor的作者没有对变形引擎自身进行保护。forgot
曾经修改了它的主程序,迫使它产生了一个没有经过变形的外壳体,从而轻松地分析了它的整个保
护过程。因此,如果在壳中使用变形引擎,不要忘记保护主程序的引擎代码。
混淆通常以多态变形引擎的垃圾生成器出现,一般是指一些花指令和无用的代码。有些时候,
变形也叫作混淆,并伴随着扩散。这里的“扩散”和香农信息论中的“扩散”不是一回事,只是对
混淆过的代码再次进行混淆,进一步消除原始代码的特征而已。
3.文件完整性校验:
磁盘文件校验的实现:
校验和:
内存映像校验:
1.对整个代码数据进行校验
2.校验内存代码校验
4.代码和数据结合:
1.在软件程序中有一段加密的密文C,既可以是注册版本中的一段关键代码,也可以是使用
注册版程序的某个功能所必需的数据。
2.当用户输人用户名和序列号之后,计算解密用的密钥:密钥=F(用户名,序列号)。
3.对密文进行解密:明文M=Decrypt(密文C,密钥)。
4.给解密的代码加上异常处理代码。如果序列号不正确,产生的垃圾代码一定会导致异常:
如果序列号正确,则生成代码正常,不会导致异常。这一步也可通过第5步来实现。
5利用某种散列算法计算出明文M的校验值:Hash(明文M),散列算法可以采用MD5,SHA
等。然后,检查校验值是否正确如果校验值不正确,说明序列号不正确,就拒绝执行。
(具体实现,没时间看,略)
5.关于软件保护的忠告
0尽量自行开发保护机制,不要依赖任何非自行开发的代码。在不影响效率的情况下,可以
用虚拟机保护软件(例如VMProtect等)处理需要保护的核心代码。
0不要依赖壳的保护。加密壳都能被解开或脱壳、现在的许多壳转向虚拟机加密方向就是利
用了这一特点。如果时间允许且有相应的技术能力,可以设计自己的加壳/压缩方法。如果
采用现成的加壳工具,最好不要选择流行的工具。保护强度与流行程度成反比,越是流行
的工具,就越可能由于被广泛深人地研究而有了通用的脱壳/解密办法。
0增加对软件自身完整性的检查,包括对磁盘文件和内存映像的检查,以防止有人未经允许
就修改程序,进而达到破解的目的。DLL和EXE可以互相检查完整性。
0不要采用一目了然的名字来命名函数和文件,例如,'IsLicensedVet*ion""key.dat"等。所有
与软件加密相关的字符串都不能以明文形式直接存放在可执行文件中,这些字符串最好是
动态生成的。
0给用户的提示信息越少越好,因为任何蛛丝马迹都可能导致解密者直接到达加密的核心代
码处。例如,发现破解企图后,不要立即向用户发送提示信息、可以在系统的某个地方做
一个记号,经过一段随机时间后使软件停止工作,或者使软件“装作”正常工作,但在所
处理的数据中加人一些“垃圾"。
0将注册码和安装时间记录在多个地方。
0检查注册信息和时间的代码越分散越好。不要调用同一个函数或判断同一个全局标志。如
果这样做,只要修改一个地方,其他的地方就都被破解了。
0不要通过GetLocalTimeO和GetSystemTime()这种众所周知的函数来获取系统时间。可以通过
读取关键系统文件的修改时间来获取系统时间的相关信息。
0如果有可能,应采用连网检查注册码的方法,而且数据在网上传输时需要加密。
.编程时在软件中嵌人反跟踪代码,以提高安全性。
0在检查注册信息时插人大量无用的运算以误导解密者,并在查出错误的注册信息后加人延
时机制。
0为软件保护增加一定的随机性。例如,除了在启动时检查注册码,还可以在软件运行的某
个时刻随机检查注册码。随机值还可以很好地防范那些模拟工具的解密(例如软件狗模拟
程序)0
0如果采用注册码的保护方式,最好是一机一码,即注册码与机器特征相关。这样,一台机
器上的注册码就无法在另外一台机器上使用,从而防止注册码被散播所造成的影响。在机
器号的算法上不要太迷信硬盘序列号,因为使用相关工具可以修改其值。
0如果试用版与正式版是独立的版本,且试用版软件不具有某项功能,则不要只禁用相关菜
单,而要彻底删除相关代码,使编译后的程序中根本没有相关的功能代码。
0如果软件中包含驱动程序,则最好将保护判断代码放在驱动程序中。驱动程序在访问系统
资源时受到的限制比普通应用程序少得多、这也给软件设计者提供了发挥的余地。
0如果采用keyfile的保护方式,则keyfile的体积不能太小。可将其结构设计得复杂一些,在
程序中的不同位置对keyfile的不同部分进行复杂的运算和检查。
自己设计的检查注册信息的算法不能过于简单,最好采用比较成熟的密码学算法〈可以在
0
网上找到大量的源代码)。

浙公网安备 33010602011771号