“绝对安全”的本地序列号验证方法

一种“绝对安全”的序列号验证方法

声明:

​ 所谓的“绝对安全”:只是在自己目前的知识范围内认为其“绝对安全”(其实也不是QAQ),天下逆向破解大神何其之多,这种验证方法也只是分享出来,供大家学习交流。

从逆向系统序列号学到的一种“绝对安全”的本地序列号验证方法,不需要联网验证只需要本地,即可实现攻击者“无法破解”,使得序列号只能由开发者提供。下面介绍一下这种序列号验证的代码思想,有以下四个步骤(顺序不固定):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1.使用单向hash算法作为验证的核心,比如sha512:

if(sha512(checkBytes) == 硬编码的哈希值):
subKey = checkBytes

其中checkBytes应为大于等于8字节的字节串,每个字节取值范围0-255,一般由其他算法得到。

2.获取一些固定信息(如本计算机MAC地址)或者其他用户的输入(比如UserName),使用算法变换得到一组数据tmpData。
举例:
取sha512(The MAC Address of Computer)结果的16/32/etc字节作为流密码的密钥,流密码的输入可以固定,得到一组输出streamCipher

3.输入序列号变换算法随意,假定变换后得到的输出为serialNumber,checkBytes的来源如下:

checkBytes = serialNumber ^ streamCipher

将serialNumber和streamCipher进行变换得到checkBytes,例子中使用一个简单的异或算法,也没有任何问题。

4.经过上面三个步骤的,攻击者可能可以强制跳转绕过哈希算法的校验,下面最最最关键的核心部分来了,在哈希校验通过以后,checkBytes赋值给了subKey,在程序的某处运用subKey进行如下操作:

decryptFinalKey = sha512(subKey + "00 00 00 01")

decryptFinalKey可以根据自己的喜好,取decryptFinalKey中的16/32/48/64字节,解密校验的"最终的数据""最终的数据"可以是安装系统中最后加载的文件系统,也可以是软件序列号最终的校验代码,也可以是软件进行安装的安装代码等等。试想一下,如果攻击者强制通过哈希算法校验,那么其在这一步必然无法正确解密"最终的数据",前面逆向分析的成果都将无用,化作泡影。

以上四个步骤按照开发顺序一般是先2,3(3,2),后1,4。每个步骤使用的算法自定,只要校验的核心思想没有产生变化,大概都是”无法破解”的吧,且确实符合一个UserName对应一个序列号这种序列号验证的基本思想。

但是存在的问题还是有的,即如果攻击者买了一个序列号,那么不管序列号经过如何复杂的混淆,变换,加解密,解编码得到serialNumber,攻击者都可以通过调试得到serialNumber,而streamCipher的变换输入来源攻击者也是知道的(比如UserName),那么攻击者即可通过调试获得checkBytes的正确值,程序自然也就破解了。

解决办法:

1.不断加强校验步骤中的混淆算法,逆向过程会让人十分头疼,将劝退一部分逆向人员。

2.不断加强保护技术,包括但不限于虚拟机技术,反调试技术,混淆代码技术,新的壳算法等待,或者这些方法的混合使用,将劝退大部分逆向人员。

但就算是这样,每年最新的游戏不还是照样被国外大神们破解了么(吐槽)。。。攻防之间,攻击者与防御者相互促进相互学习,可能这就是安全的独特魅力吧!