发信人: williamlong(蓝色月光)
整理人: williamlong(2002-07-03 12:38:14), 站内信件
|
安全备忘录
Rainbow的目标是尽量避免被加密锁保护的软件被盗用的可能。由于我们的用户市场变得越来越不安全,随着设计复杂的盗版工具的增加,Rainbow的分销商和用户就保密方面的培训必须加强。毕竟,真正的软件安全措施仍依靠开发商的反“解密”策略的实施。
我们的确需要不断发展软件保护措施。太平洋周边国家有很多人,正在使用各种技术,从事解密工作。他们可以从其他同伙那里得到联机帮助,以及诊断工具用以帮助探测到硬件设备是如何工作的,以及具有加密锁保护的软件其内存上的变化。一旦成功,他们就可以得意地确认不再受到任何版权限制。
在这些新市场上的软件供应商的产品要生存下来是非常困难的。一旦软件保护程序被破坏,许多太平洋区域的合法的分销渠道将终止销售,因为他们不能与手段丰富而且价格又低的盗版软件竞争。开发商最终对试图“解密”做出对策,但其对于解密所做出的设计和反应(例如代码自毁)不应让其他要解密的组织得知。
这里所讨论的软件保护是Rainbow公司反“解密”的保护方案。越少人知道我们所建议的方法,它就越安全。因此,此文件应仅给那些有资格的开发商;而不是以试用组件的方式交给软件盗用者和竞争对手,他们可能将其售出。
为了对付已流行的解密方法以及新一代的解密设备,保护策略需要经常被更新。新的“解密”资料非常重要,从这里我们可以观察到其薄弱环节。通过提供的最新的解密数据,Rainbow工程组可以开发新方法,在解密之门被打开之前,击败解密组织的企图。因此,需要代理商和海外的分销机构分销商收集盗版材料(有关于Rainbow公司及其竞争者)以确保销售世界各地的Rainbow产品的安全性。
解密方法
下表对解密的三种方法:通信、代码和算法进行分析,定义并解释了其中的一些特性:
解密 通信 代码 算法
定义 记录并存贮在应用程序和加密锁之间的通信。 通过调试器或反汇编器删除或修改查询/比较/处理序列(软件断点) 推导加密算法,破解所有的基于加密锁的保护(一般的解密)
时间 自动调整 对应代码的数量,以便于跟踪 根据算法的复杂性、长度、可预测性和易处理性
技巧级别 最方便 困难,在汇编语言下,要求单步进行。 总的来说比较困难,并且花费昂贵,需要硬件和加密知识
破解对象 任何数据量小的保护:内存保护,使用PC机硬件参数的纯软件保护,小范围的算法查询(<100K) 单个的应用程序 所有依靠加密锁产品的应用程序(SuperPro, Hardlock,等),
对策 在加密锁上使用随机询问,以增加询问方式的方法增加数据量。要求算法功能性很强,能够支持大于100K的询问 加大被跟踪代码的数量,包括增加软件加密点,将上述有关加密的三个步骤分开。加密并校验代码。 在ASIC上运行的,可以对抗大量随机分析的可靠的算法。
一般指南
保护某个应用程序的最简单方法是将此应用程序的外面封装一个具有保护性的外壳,在此应用程序可以运行之前,需要检验外壳的保密锁。这个过程非常简单,仅需要几秒种。它在一定级别上提供巧妙的反盗窃方法。
更佳的方法是将所有的调用集中到程序码中。虽然此方法更加复杂,但它可以提供更高一级的保密措施。此文件论述了如何在保密锁中成功地调用应用程序,以便于在盗版日益昌獗的软件市场保护好我们的应用程序。
最佳的方法是将这两种手段结合起来,在应用程序多次调用保密锁,然后再用外壳保密程序保护此应用程序。运用硬件加密锁保护应用程序的方法将在以下几页中概括和描述。
合理使用加密手段保护应用程序是非常重要的。它可以防止某些人使用一般流行的解密技术破解加密程序。我们建议您使用本文所描述的方法,但要根据具体情况灵活实施。
在记录和模拟的破密方法
最常见的软件解密者使用的方法是记录在加密锁和应用程序之间的通信。将这些数据记录之后,解密者可以为来自加密锁的每项询问或调用仿制响应。
解密者在应用程序和加密锁之间可以对许多通信点进行记录,包括动态链接库和系统驱动程序。因此,需要对任何级别的破密手段进行反记录和模拟方案。幸运的是,这种防御措施非常简单:在记录设备上使用无规律可寻的随机数据。
在经常执行的代码部分进行大量随机询问,多次运行此步骤,使要记录的数据量会溢出记录设备。随机询问意味着增加在应用程序和保密锁之间的通信,其响应则被忽略掉,但是在特定的时候,此应用程序生成一个“真实”的询问,对此询问的答复是已知的,分析其响应可得知保密锁是否在起作用。
已知的询问结果可被保存在代码的几个地方或可被存在一个询问和响应数组中。数组越大,就越益于保密。将此数组分成几个通过代码扩充的数组,并通过使用特定的应用程序算法来选择,更进一步加强应用程序的安全性。
数组方法要求专门的保密知识,因为在对记录和模拟进行探测之后,解密者还需要对数据进行搜索。因此,如果使用几组询问方法并且这些方法都被加密的话,那么效果是最好的。综合使用上述方法可以对付在记录和模拟上着手解密手段。
1. 综合使用已知询问和随机调用
以各种不同的随机询问掩护真实的软件断点
对随机询问的答复进行处理,但是最终忽略它们,并不真正使用他们。
增加要记录的询问数目(潜势是无穷的)
几个随机询问的伪代码例子:
X=Rand() AND 3 //第一例
For I=0 to X
R=query(rand())
EndFor
While NO userInput //第二例
UserInput=getCmd() //在等待用户输入时提供随机询问
R=query(rand())
End While
If (rand() MOD 2=0) then //第三例
R=Query(Q) //如果随机数目相等,执行一个真实询问
If(R<>Expected R) then
<error response>
endif
endif
2. 使用询问数组和询问响应来改变询问顺序
 对一个已知的调用/响应对表使用随机索引
TSize=SizeOfQueryTable //已知询问的常量
X=Rand() MOD tSize //为已知的表生成随机索引
Q=A[X].Q //使用随机索引执行一个真实的询问
If R<> A[X].R then
<error response>
Endif
 将表分成更小的表, 并将他们分别放在代码中彼此远离的地方
 在一个表中存贮询问,并在另一个中存放答复
 通过计算得出彼此相关的各种表的不同索引
此方法的优越性在于解密者永远不知道是否所有的真正询问都已发出。即使一个软件程序被解密,也并不意味着另外一个程序被同样的方法破解。
3. 检验非法操作引起的一个错误
 更改驱动器的参数(Pro的族码或SuerPro的FindNext)并验证加密锁出现故障的通信。
 执行非法活动诸如缩减一个存贮单元或对一个锁定的存贮单元写程序然后验证错误
以上方法可以很好地防止用普通记录设备进行跟踪的解密者,通过某个断点监听和破密。
在代码中删除询问
另外一个常用的盗密技术是改动代码,删除对加密锁的调用。通常以调试器跟踪代码或反汇编代码实现。
加强对抗调试器的手段
调试程序是一个乏味的过程,因此最佳防御措施是增加需要计算的代码的数量。它包括增加检验加密锁的代码数并通过校验码来检查代码的完整性。
1. 在代码中多次执行调用
 每调用一次代码,解密者就需要对其进行分析、解密。因此,代码中调用的次数越多就会越安全。建议将每个应用程序的价格除以20美元所得值就是应该调用的数目。
 在那些很少使用的代码中置入一些调用,那么解密者看似已破解的应用程序在被启用时便会发生死机现象。
 保护动态链接数据库和可执行文件,增大代码量。
2. 将调用分开,根据时间和代码决定测试和处理
 增加要跟踪的代码数量,从而增加解密者需要花费的时间
 通过增加软件测试点的范围,将一个真实的软件断点伪装成一个随机询问
3. 用响应的数据执行一项操作,而不仅仅是测试它
 删除包含正确响应值的显示的代码
 通过使用响应数据增加跟踪的附加时间
 将响应作为一个数组的索引、常量、计算单元或效验码
 将响应作为一个指针来控制程序执行或者作为在不同表中跳转的索引。
 使用响应来加密或解密部分代码。
4. 如果测试失败,不要宣布这是由于解密的原因所造成的
 不要在出错时提示出错信息,诸如:“内存错误,请与技术支持联系”等。
 在测试错误以后,继续使用随机询问,迷惑解密者,掩盖实际处理点
 改动错误响应,隐藏被探测到的故障的时间和地点
5. 不要定义包含查询功能的单独函数,并且在你的代码中调用它
 这会导致在代码执行中跳转到代码的某个特定位置
 容易被跳过,一个单独的代码段只有一个执行序列
6. 在代码中使用宏
 在编译时,一个完整的代码拷贝将替代宏
 每个软件断点都需要完整的代码
 大多数的高级语言提供类似宏的功能
7. 屏蔽中断
 锁住键盘和一些调试器
 注意中断所需要的时间(在Macs上是1/60秒,在DOS上是15毫秒)
 在Intel机器上,在0环执行一些核心计算(OS核心模式)
8. 根据不同的数据执行不同的软件处理
 强迫解密者在解密的时候模拟不同的环境
 根据系统时钟、日期、有效磁盘空间、安装目录下的日期、和诸如处理器和OS版本等系统信息改变要执行的安全代码。
9. 利用效验码检测对程序的修改
 使用诸如CRC这样的有效的算法。
 对代码的不同部分计算效验和,以便进一步增加代码的复杂化
 重叠要被效验的代码区域
 当探测到非法修改时,减小计数器使得算法不能使用
对付反汇编程序的方法
将机器指令翻译为汇编代码的反汇编程序和工具暴露了程序的保密过程。为预防反汇编程序,必须将部分代码进行加密,或者在程序中包含从不执行的不完整的汇编指令。
1. 对部分代码进行加密
 要求写访问权限。另外需要注意的是象DOS扩充模式和Windows这样的在保护模式下的应用程序
 在SuperPro系统驱动器上使用Sprox来克服保护模式上的技术难点
 不能在共享代码的环境下使用,例如Windows 的动态链接库
2. 使用汇编代码隐藏命令
 通过将函数地址和返回值压入堆栈的方式调用函数,然后执行返回的命令
 插入几个字节,用于存放复杂的命令,例如:
MOV DX,qrerySrring
CALL _QueryProc
CMP AX,responseString
DB A5 MOVS命令的Intel操作码,它使用接下来的4或8个字节,根据访问而定
JE programCont 反汇编程序将把这4个字节的命令作为数据;
3. 将命令存放在一个数组中,并且将控制移交个它
 将通用函数作为数据贮存起来,达到隐藏的目的
 用机器语言指令载入一个数组,将最后一个指令返回
 例如,在C语言中:
Char codeStr[6]; //提供存贮机器指令的空间
Typedef int(*funcPtr)(void);
FuncPtr fp; //声明fp作为一个函数地址
//用 Intel指令来载入数组,以得到DOS版本
codeStr[]=0xb8;codeStr[]=0x00; // MOV AX,3000
codeStr[]=0x30;codeStr[]=0xcd; // INT21
codeStr[]=0x21;codeStr[]=0xcb; // RETF
Fp=(funcPtr) codeStr; //将数组地址计算为一个功能地址
Version=(*fp)() //将代码作为一个函数来执行
规定有效范围
开发商可以在授权协议中声明,保护其合法地位:
禁止对产品或其中某一部分做删除、模仿或颠倒设计,在未经授权的情况下严禁改动加密设备。不许窃取以可执行文件或目标代码形式提供的文件资源或汇编代码。
这些声明可弥补许多国家的版权法上的许多漏洞。
对加密锁的破坏
使用ASIC可有效地防止解密者对硬件的破坏,因此,大多数解密者的注意力盯在了与硬件相关的软件接口上。用户保护软件接口或驱动器的工作就变得至关重要。Rainbow公司尽一切努力以确保用于新产品中的算法将最大程度减少对硬件加密锁的破解。增强算法的一些方法包括:
1) 在美国政府允许出口的前提下,逐步扩大芯片容量。
2) 在加密领域中聘用一些业界的专家,这些人在世界上有高度的知名度,可以帮助Rainbow公司在算法的计算设计上变得更加有利。
3) 使用行业中被认证的芯片评估软件,检验所使用的加密的可靠性。
----
|
|