首页
社区
课程
招聘
[讨论]一种软件保护手段的分析
发表于: 2008-5-12 11:10 5761

[讨论]一种软件保护手段的分析

2008-5-12 11:10
5761

最近分析了C……t(非国产)软件的注册验证算法,发现它的方法简单,未用加壳、反调试、反反汇编等手段,但似乎无法破解。希望能在这里跟各位高手探讨一下。

和很多共享软件一样,这款软件也是在用户输入正确的用户名/注册码后,才解除试用版的限制。

由于汇编代码很长很难读,这里就以图代话了。验证程序的核心是一个叫 Blowfish 的对称加密器(加密解密使用同一个密钥,加密后的数据和明文长度相同)。图中用圆圈表示这个加密器,上下端的箭头表示密钥,左面输入明文,右面输出密文。



用户名和注册码分别经过两个简单的散列(hash)函数,产生2字节的用户名散列值,和18字节的注册码散列值。

将用户名散列值作密钥,对注册码散列值的高16位字节进行加密,密文(图中蓝色)作为后面要用的密钥。

注册码散列值低2位必须在0-0A00h之间,否则说明注册码错误。用这个值作位移量,在一个事先硬编码的表中取出一个16字节码(图中绿色部分),再用上面得出的密钥(蓝色)对这个码进行两次加密,产生出的16字节码就是最后解密的密钥。

程序中负责解除时间限制、激活注册版的程序代码以加密方式存在,解密的密钥就是上面产生出的16字节码。解密过程包括两次解密,为了确保解密无误,在第一次解密后,要将解密后数据中的几个特定字节与正确值比较,如果有错,图中红色部分就不执行,直接报告注册码错误。如果通过验证,就进行第二步解密(红色部分),用解密结果改写原来加密的程序代码,并且跳转到那里执行,完成软件激活。

个人认为这种方法几乎无法攻破。用改变跳转的方法不行,因为最终完成注册的程序代码是加了密的,没有正确的密钥就无法还原和运行该段程序。用穷举法破解也不现实,因为密钥有16字节(128位)。此外这种方法多次加密所用的密钥都不相关,很难推算出它们之间的关系,无法写出注册机。破解的唯一方法只能是通过研究整个程序,找到激活的方法,然后自己构造一个功能类似原来程序中的激活程序。

如果真是这样,软件保护似乎变得很简单,破解的人也就无技可施了。这里所用的 Blowfish 加密软件是很简单的开源软件,可以方便地加到要保护的程序里。分析的是否正确,还请各位高人指正。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (7)
雪    币: 398
活跃值: (343)
能力值: (RANK:650 )
在线值:
发帖
回帖
粉丝
2
这不是肯德基
2008-5-12 11:16
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
3
随便输入一组注册码    得到一HASH值(需符合规则,低2byte需介于0-0A00)  <=  HASH_1 (18 Byte)
所以 此时硬编码对照到的16Byte已固定.
HASH_1(高16byte) 也固定住

因为用户名的HASH只用2个byte而己.
此用户名HASH由0给他跑到FFFF. 所以应该只要跑 65536 种吧.
2008-5-12 12:07
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
4
若他可根据用户名称而给你注册码的话, 则

1. 注册码 -> 18byte的HASH 应该不是外面公开的那些 (那些公开的都无法预测)
  亦即他无法预测该用第几组硬编码. (低2byte无法预测)

2. 高16byte无法预测
  所以最上面那个圈圈出来的东西他更是无法预测, 不可能光靠 2720 项硬编表

所以最上面那个圈圈很有可能不是用OpenSource的HASH
2008-5-12 12:24
0
雪    币: 209
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
如此有一种正确的方法,只有从正确的密钥入手跟踪。
2008-5-12 14:38
0
雪    币: 125
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
如果不同的密匙+红圈解码后得到的是相同的关键程序段(解除时间限制激活等功能),那就是说解码只与密匙的正确与否有关,与密匙的内容无关,这样肯定可以用改跳来解码。欢迎指点。
2008-5-12 17:01
0
雪    币: 208
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢朋友们参与。

回复3、4楼:

这种保护手段的“门锁”,实际就是指向红圈的那个16字节密钥。

软件作者可以这样构造根据用户名生成注册码的程序:
1. 选定“门锁”,一个16字节的密钥,设它为 M。
2. 随机选 2720 个不同的 16 字节数,保存于一数组 R 中。
3. 用 R[i](i=0, ..., 2719)作密钥,对 M 进行两次解密,结果存于一数组中,设它为 H。这个数组就是放在软件中的硬编码表。
4. 有人来注册,先用他的用户名 hash 出一个2字节数,设为 N。
5. 随机取一小于 2720 的数,设其为 SL。以 N 为密钥,对 R[SL] 进行解码,得到的结果设为 SH。
6. 将 SH 作高16字节,SL 作低2字节,构造出18位的注册码散列值 S。
7. 将 S 进行反 hash,得到注册码,发给用户。本软件所用的 hash 函数不过是把0-9,A-F这几个字符转换成别的值而已。如果不对注册码进行变换,直接把 S 给客户就行。

破解者不知道 M,即使知道上面的步骤也找不到能产生 M 的用户名 N 和注册号 S。

回复6楼:

要正确解码那371字节,估计密钥是唯一的。即使有一错误密钥,能使解密的数据通过红圈左面的验证也没用,因为它只是验证那371字节中的前几个字节,后面解得不对,程序很可能会崩溃。
2008-5-12 23:56
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
8
即然这样, 那效果其实跟"需要向厂商要一组密码来解Code"是一样的道理.
在破解者的眼中其实是一样的. 有M可解, 没M不能解.

同样是有了一组正确的user'pwd, 那就破完了.

只是他弄得比较花俏而己.
2008-5-13 13:24
0
游客
登录 | 注册 方可回帖
返回
//