|
前几天看了一下一个试用版的小软件,想看看它数据库的设计,没想到数据库竟然加了密。想找个解密软件把它打开,可是找了两三个解密软件竟然都要我钱!气愤至极就想自己写一个。花了整整两天,找了不少资料,才把这个小东西弄出来,现在整理一下这个过程的收获吧。
首先提一下,对于access数据库的加密原理,很多是参考了网上的资料,部分是自己发现的。在网上找资料的过程中,有两篇文章的参考意义比较大,分别是:
《实验室:破解所有版本Access密码》作者不详。
文章出处:飞诺网(http://dev.firnow.com/course/7_d ... /2007614/51856.html)
《access数据库加密系统的安全性及其保护措施》作者:南亦民,张舞杰。
文章出处:http://www.qikan.com.cn/Article/zsjs/zsjs200708/zsjs20070812.html
特此感谢两篇文章及其作者!
这两篇文章都解释了access数据库的加密原理,破解方法也大同小异。最后我发现,第一篇文章使用的方式含有巧合的因素,无法解开所有的加密数据库;而第二篇文章所使用的方式没有什么问题,但是我发现它还有可以改进的地方。因此,我采用了一种和前面两者稍有差别的解密方式,目前还未发现有解不开的情况。在下面的介绍中我会解释一下这两篇文章所使用的方式的一点不足。
Access数据库加密原理:
access数据库的加密方式并不是统一的:access97和access2000以上版本的加密方式不一样。access97数据库的加密方式非常简单,网上的资料也非常多,这里只是简单提一下,不详细展开。而我的解密软件也是针对access2000-2003版的数据库,因为它们的加密方式都是一样的(以下针对access2000进行说明)。
对于access97数据库,它有一串固定的密匙,通过将用户设置的密码(最长可以设置14位)和这串密匙进行异或操作,然后把异或的结果作为加密串保存在这个文件头部第66个字节到第79个字节共14个字节的位置。由于所有数据库使用同一串密匙,结合异或操作“和同一个数两次异或结果不变”的特点,建一个没有密码的空数据库,得到密匙和加密串进行异或操作,就可以得到密码,所有说比较简单。
但是对于access2000数据库,加密方式有了较大的改进。具体有以下几个方面:
一:access2000数据库不再使用固定的密匙,其密匙是根据日期随机产生的,所以不同日期新建的数据库文件其密匙不相同。
二:access2000允许用户使用更长的数据库密码,最长可以达到20位。
三:虽然access2000数据库也是把密码保存在文件中,开始位置也还是第66位,但是access2000不再连续存放数据库密码的加密串,而是隔位存放,即从66开始到104结束的所有偶数位为密匙以及加密串存放的位置。
Access数据库破解方式:
我开始的思路是:既然知道了access2000的密匙是随机产生的,那么文件中除了保存了加密串之外,一定还记录了密匙的信息。加密串的位置是固定的,而只要能够从文件中找出密匙,就可以得到密码。
通过对比不同日期产生的数据库文件后发现:如果把20位密匙抽取出来存放在一个字节数组中的话可以看出,只有其中的10位是随日期改变的,其余10则是固定的。如下(密匙使用16进制数表示):
66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100 102 104
__ ec __ 9c __ 28 __ 8a __ 7b __ df __ 13 __ b1 __ 79 __ 7c
而除了这10位下划线表示的密匙之外,还有另外7位也随着日期的不同而改变,分别是:114 115 116 117 118 119 120
这组不是参与加密的密匙,但是我觉得它是真正保存了文件新建日期的地方。进一步对比发现,记录日期的应该是后面三位。由于密匙只和新建日期有关,同一天新建的数据库文件有相同的密匙,所以真正对获取密匙有帮助的是后面118到120三位。
所以,在理论上可以通过这三位密匙获取文件的新建日期而后获取该日期的加密密匙。可是由于无法知道access对日期的加密方式以及日期和密匙间的对应方式,这个方法可行性不高,只有另辟蹊径了。
由以上分析知道,同一天新建的数据库文件具有相同的加密密匙,那么一个最简单的破解方式就是新建一个和欲解密数据库相同日期的数据库文件,获取里面的加密密匙,和欲解密数据库的加密串进行异或操作,就可以很轻松的获取数据库的加密密码。
这种方式虽然简单,可是适合手工操作,不大适用于我想写的解密软件中。因此还得寻找其他方式。
由《access数据库加密系统的安全性及其保护措施》这篇文章知道,虽然access数据库的密匙是随机产生的,可是密匙之间有一定的联系,并且总共只有256组密匙。得到其中一组密匙,结合密匙之间的联系,就可以得到其余的255组密匙。而该文章的作者就是使用通过获取这256组密匙然后使用这256组密匙进行“暴力”破解的方式来获取密码的,这就是我前文所说的觉得可以改善的地方,原因下面再介绍。
虽然该文章作者表明数据库密匙只有256组,并且相互之间有一定的联系,可是并没有说明这个“联系”是什么以及如何通过其中一组密匙去得到其他255组。
所以,我选择先获取两组密匙,看看能否找出其中的联系。多次测试对比后终于发现了这两组密匙之间的联系:把两组密匙对应位置的字符进行异或操作,所得到的结果相同!再结合《access数据库加密系统的安全性及其保护措施》里作者提到的密匙只有256组,我发现的获取密匙的规律:当获取到其中一组密匙后,将这组密匙分别和1到255进行异或,就可以得到其余的255组密匙(先暂且把这1到255叫做“日期因子”)。其实由于每一位密匙都是用两位的16进制数表示的以及该作者提到的256这个数字,早就应该想到这个规律了。
发现了这个规律之后,就发现了另一个获取密匙的途径了。前文提到,密匙以及加密串是存放在文件的66到104的偶数位。而真正随日期产生的密匙则是存放在以下位置:
66 70 74 78 82 86 90 94 98 102
__ __ __ __ __ __ __ __ __ __
其余10个密匙是固定的。
这里我们可以发现,access将用户设置的密码和这20位的密匙进行异或操作之后,将得到的结果覆盖掉原来的这20位密匙就成为了该数据库的加密串。所以,如果用户设置的密码少于19位的话,最后一个根据时间随机产生的密匙位102并不会被覆盖掉。而由以上分析的256组密匙产生的方式就可以知道,只要有一位根据日期随机产生的密匙位没有被覆盖掉, 就可以通过另一组已知的密匙来得到加密的密匙。具体方式是:通过其中一位没有被覆盖掉的密匙位,和另一组已知的密匙的对应位置的字符进行异或操作,就可以得到前文所说的“日期因子”。而由于这两组密匙对应位置进行异或操作后得到的“日期因子”相同,所以可以通过这个获得的“日期因子”将前面被加密串覆盖掉的密匙找回来,最后通过找回来的完整加密密匙和加密串再进行一次异或操作,就可以得到密码明文了。
这个方法也就是我前文提到我参考的第一篇文章的作者所使用的方法。但是他还没有发现这个规律,他是采用一位一位测试的方式来解密,最后发现第98位的密匙位很“特殊”!通过这个密匙位结合我上面提到的方法他就解开了很多数据库的密码。
而我之所以说第一篇文章采用的方式含有巧合成分的原因也在此:这个密匙位之所以“特殊”,只是因为它的位置靠后,没有被加密串覆盖掉而已。所以如果用户设置的密码再短一些,前面几个密匙位也可以很“特殊”,而如果密码再长一些,这个密匙位就不那么“特殊”了!
我想看到这里很多读者已经发现问题了:就是如果用户的密码是19位或者20位的话,都将覆盖掉所有根据日期随机产生的密匙位,那么这个破解方法就行不通了!!
确实是这样。此时,我想到了不参与加密的那七个根据日期改变的密匙位。
之前没有发现256组密匙之间的规律以及日期的加密方式,单纯靠这七位密匙得到密码太难。现在既然知道了密码之间有“日期因子”这东西存在,我想先通过一个密码少于19位的数据库,得到其密匙和已知密匙之间的日期因子,再通过118到120这三位和日期相关的密匙位,看能否通过一定的解密方式得到这个“日期因子”,从而得到118到120这三位到“日期因子”的加密方式,这样就可以只通过118到120这三个密匙位解开所有密码长度的数据库。
可是在这个过程中我发现,这个加密方式并没有前面的那么简单,并且,即使我不知道这个日期到日期因子的加密方式,通过暴力破解的方式也可以破解出来。因此,就失去了继续研究的兴趣了。
现在说说我为什么觉得第二篇文章的作者所使用的方式可以进一步改善。该作者一律采用通过256组密匙进行“暴力”破解的方式来获取密码。通过我前面的介绍可以知道,当用户设置的密码少于19位的时候,不需要使用这种暴力的方式就可以直接破解出来。
虽然使用这种“暴力”的方式时间并不至于太长,毕竟只有256组情况,看是还是有一定的时间花费的。另外,我想能把一个access数据库的密码设置成19位或者20位的人估计不多吧!因此大多数时候是不需要使用“暴力”破解的!
下面就说说我所使用的方式了!我首先获取最后一个根据日期随机产生的密匙位,通过前文提到的方法进行破解。如果破解失败了,则说明用户设置的密码大于或等于19位,则前面的那些密匙位也不必再进行测试了,就直接使用“暴力”的方式进行破解。而这就是我为什么叫自己的破解方式为“半暴力式”破解的原因。
这种方式解决了第一篇文章作者那个破解方法的bug,不存在巧合的成分;而且大部分情况下可以比第二篇文章的作者使用的方式花更少的时间,算是一个小小的改进吧。
我通过这个方式写的东西还没有遇到破解不开的数据库,如果有朋友使用该方法后破解不开数据库,欢迎交流。
说到这里顺便介绍一下:第二篇文章的标题是《access数据库加密系统的安全性及其保护措施》,就是说里面除了讲怎么破解之外,还继续讲了该如何更好的保护数据库。从这里可以看出人家作者比我厚道一点!
前文说到,access97和access2000的加密方式是不一样的,那么破解方式自然也不一样了,所以人家写的破解软件如果不是像我这样只针对access2000-2003的话,就得先获取数据库文件的版本信息才能决定选择哪种破解方式。这个其实也很简单:数据库的版本信息与0x14处的字节有关,如果是0就为Access97,如果是1就为Access2000或2002。而该文作者所说的“保护措施”就是把这个字节给改咯,让破解软件无法获得版本信息,也就无法破解了!
我觉得这个方法也不是万全的:哪个人要是留一手把两种破解方法都给你试一遍你也没辙了!由于这个我觉得不是很高明的保护措施人家已经说了,我又没有更好的措施,所有怎么保护就不提了吧。
还有一点就是,如果有朋友研究出来了那118到120和我所谓的“日期因子”的联系方式的话,请不吝赐教!
最后,之所以会有这个小东西问世,就是因为觉得人家写这么个小东西还要卖钱,不可思议!所有我打算写完后免费给人使用。可是由于我用java写的,我想大部分人的机器上是运行不了的了,而要让这个几K的东西带上个100M的jre,那简直是开玩笑。而我也没有什么心思去搞jre的精简了,所有就没有上传到网上。如果有朋友想要软件或者要java源码的话,留言留下邮箱我发给你,并且不用客气!! |
|