*仅支持后缀为.xls,.xlsx的文档,最大支持5M
你上传的excel文档,你必须拥有该文件的完全使用权,或者该文件归属与你,否则禁止使用本工具
1:可以对全版本office(97,2003,2007,2010,2013,2016,2019)的excel文档进行无损限制解除
2:另外还支持由金山wps生成的excel(xls,xlsx)文档的相关无损限制解除
本工具可解除限制范围有:
右侧的excel限制都可以使用本工具解除---》
可以取消标记为最终状态
可以取消保护当前工作表
可以取消保护工作簿结构
可以取消只读限制
以上限制无论是否设置了密码,都可以在不提供密码的情况下,进行限制解除
备注:金山wps保存时设置的私密文档,登录指定账号才能打开的限制,本工具无法为您解除,忘悉知
非workbook复制,所以可以100%保证文档的结构和数据的完整
如果你执意想要找回保护当前工作表的密码,好吧,我来告诉你有多难:
Excel使用一种在XML文件中以哈希形式存储用于工作表保护的密码的方法。
从Excel 2013版本开始,哈希值很大,很难通过Bruteforce找回密码,而Excel 2010的哈希值是2个字节,可以被大约65536次尝试找到密码。
Excel 2010工作表保护方法
为了保护工作表,密码的哈希值存储在相应工作表名称的xlm文件中,而哈希值存储在workbook.xml文件中,以保护整个工作簿。
以下是密码1表“ 123456789”受保护时存储的哈希值。(在文件xl / worksheets / sheet1.xml中)
<sheetProtection password="9690" sheet="1" objects="1" scenarios="1"/>
为什么变成了9690?这是用了某种哈希算法F来进行转换的
比如:F("123456789") = "9690"
如果F是一种成熟的哈希算法,几乎没有冲突,那就很难找到一个合适的碰撞点,但是
由于某种原因,表格的保护方法必须弱于主表加密,所以这种加密,可以非常容易碰撞到相同的"9690"这个值,但是密码肯定和你原来的不一样,但是可以正常使用
这种加密方式就不再介绍了,网上有很多vba脚本
Excel 2013工作表保护方法
作为哈希算法,使用了Sha2类型的Sha512,因此哈希值是512位(= 64字节),并且使用了salt,因此即使使用Rainbow表(预先计算了哈希值的表),也无济于事。
哈希值的计算如下。
hashValue = sha256(密码||盐)
由于salt值为24个字符,因此如果创建哈希表,则约为24 * 8 = 192位。
下面看具体操作
把你的xlsx文件,修改成后缀为zip,找到文件 xl\worksheets\sheet1.xml
提取加密信息hashValue和saltValue(一般在2013中才会用到这么强的加密)
<sheetProtection algorithmName="SHA-512" hashValue="nx9HCR+xJ8Mkgdon2xwZ4QRJxCdluc5mbfkDyy4PS05BaOP8vfUrvvaV/9A++i0kdPLdCk01tDT84jomvoh5sA==" saltValue="Hby4xyZo7dYNNHwQTF0vWA==" spinCount="100000" sheet="1" objects="1" scenarios="1"/>
下面是找回保护当前工作表密码的完整代码,请跑一下,感受一下速度
之所以慢,是因为那十万次迭代
#! /usr/bin/env python 2.7.11 #coding=utf-8 #本脚本改造成opencl,使用NVIDIA GeForce GTX 750 Ti来全速测试,每秒仅能达到500H /s import hashlib from base64 import b64encode, b64decode import struct workbookAlgorithmName="SHA-512" workbookHashValue="nx9HCR+xJ8Mkgdon2xwZ4QRJxCdluc5mbfkDyy4PS05BaOP8vfUrvvaV/9A++i0kdPLdCk01tDT84jomvoh5sA==" workbookSaltValue="Hby4xyZo7dYNNHwQTF0vWA==" workbookSpinCount="100000" def findpassword(password): alg = workbookAlgorithmName.replace('-', '').lower() if alg not in hashlib.algorithms: raise Exception("Algorithm %s not in %r" % (alg, hashlib.algorithms)) alg = getattr(hashlib, alg) count = int(workbookSpinCount) digests = [] salt = workbookSaltValue salt = b64decode(salt) m = alg() m.update(salt) # data is binary, length = 16 m.update(password.encode('utf-16-le')) # window's "unicode" encoding h = m.digest() #这里的十万次迭代循环加密,能慢到吐血 #平时加密和取消密码,时间很短暂,几乎很难感觉到,但对爆破却是致命的打击 for i in xrange(count): m = alg() m.update(h) m.update(struct.pack("<I", i)) # little endian 4-byte unsigned integer iterator h = m.digest() digest = b64encode(h) print digest print "log:", digest, u"密码找到了" if digest == workbookHashValue else u"密码不正确" if __name__ == '__main__': #这里可以使用字典 findpassword("bugscaner")
那么,你准备好放弃了吗?