Excel的工作表密码保护是如何工作的?

17

这段代码已经在网络上流传了很多年 - 它似乎能够提供一个密码用于解密您不知道密码的Excel电子表格。

http://www.theofficeexperts.com/VBASamples/Excel02.htm

我对它的工作原理很感兴趣,但我似乎无法弄清楚。我假设它是加密在某个值下,可以通过多种方式得到该值(网络上的一些地方说它会提供原始密码或其他有效的密码),有点像公钥 - 你可以有100个公钥,它们都与单个私钥一起使用。

对我来说,它似乎正在创建整数变量并使用特定数字填充它们,然后将该数字转换为相关字符。这些不总是相同的吗?如果是这样,Excel保护是否有“主密码”?

谢谢大家!

编辑:我注意到我发布的示例代码中的For n = 32 To 126。与ASCII表进行交叉引用,看起来这是从空格到波浪号的所有字符。由于语法问题,这是我没有理解的字典攻击吗?


5
旧款办公文档格式中的密码保护使用的是密码学等价物“湿T恤”的方式:“有覆盖,但一切仍然可见”。它从未被设计成“安全”的。如果您需要安全性,那么更新的“x”版本确实使用了更好的加密技术,并且更难被破解。 - Marc B
@MarcB 真的很对 - 喜欢这个评论 - Adrian Cornish
1
办公文件中没有主密钥。使用的算法非常容易破解(例如,Elcomsoft的Office密码恢复应用程序可以几乎立即获取旧式Office密码)。没有字典,也没有艰苦的工作。只需要进行一些位操作,将一些额外的水添加到T恤上,使其更加透明。 - Marc B
1
@MarcB 实际上,工作表解锁代码在Xl2010上也适用。 - brettdj
1
很遗憾的是,VBA保护也毫无价值,甚至比工作表保护更容易被绕过。 - SWa
显示剩余3条评论
5个回答

22

这是一个小世界,正如代码所示,我大约10年前在另一个论坛上贴出了这个代码,当时我在John Walkenbach的旧网站上看到了它。

需要注意的是,此代码保护仅适用于工作表保护 - 不适用于Excel文件打开或VBA密码。

  • 完整的解释可以在这里看到(下面是屏幕截图)
  • 谷歌搜索excel sheet protection “test” and “zzyw”可以找到其他参考资料,例如来自Tom Urtis的这篇文章

输入图像描述


1
很高兴我的猜测有些得到了验证 :). 16位哈希函数相当简单。我猜这只是工作表保护而不是工作簿保护。你知道OP发布的例程是否从哈希函数产生所有不同的结果吗?我想我可以测试一下,但我有点懒。 - mkingston
@brettdj,我有点困惑,你的解释与微软文档不符。你是说当你最初编写这段代码时,哈希值被存储为一系列A和B的16位值,后跟一个ASCII字符,而你的代码只是尝试了所有哈希值吗? - vy32
@vy32 这不是我的代码,我在别处看到它后发布到 Experts-Exchange。我不清楚您所指的 MSFT 文档是什么? - brettdj

11

编辑(2020年):从Excel 2013开始,保护方案显然已经改变。因此,原始答案只有历史意义了。

新的保护机制使得使用最先进的SHA-512哈希算法几乎不可能检索密码。但是,如果您可以在几秒钟内轻松地取出它,为什么要破解呢?

  • 解压缩.xlsx.xlsm文件
  • 编辑xl/worksheets/sheet<num>.xml
  • 搜索并删除<sheetProtection... />标记
  • 保存、重新压缩,享受吧

原始答案(适用于Excel 2010及以下版本)

很有趣 - 我之前知道代码片段,但不知道brettdj发布的解释。正如其他人所解释的那样,这是一种哈希碰撞的暴力搜索。实际上,由于它做了比必要的工作还要多(生成了194560个组合,但只有32768个哈希值),因此似乎是通过试错方法制作的。

简而言之,Excel的哈希算法(如http://chicago.sourceforge.net/devel/docs/excel/encrypt.html中所解释的):

  1. 获取密码每个字符的ASCII代码。
  2. 将其视为16位有符号数字。根据字符的位置向左移动其位(第一个字符1位,第二个字符2位,依此类推)。
  3. 将所有字符进行异或运算,得到一个16位有符号整数 >=0。
  4. 将该结果与密码的长度和一个魔术数字进行异或运算。

了解这一点后,可以设计以下暴力搜索:

  • 最高位始终为零,因此有15位要测试。
  • 将它们分成三个计数器,每个计数器覆盖5位。这样每个计数器都可以表示可打印的ASCII字符。
  • 将这些计数器的ASCII表示包装在一个密码字符串中,以使它们彼此不影响。

最简单的方法是使用一个11字符密码,并将计数器放置在位置1、6和11。步骤2中的位移使计数器位正确:第一个计数器(“x”)向左移动1位,第二个计数器(“y”)向左移动6位,第三个计数器(“z”)向左移动11位。在哈希的按位表示中,计数器影响以下位:

bit: 76543210 76543210
cnt: -zzzzyyy yyxxxxxz

XOR操作可以忽略,因为XOR参数始终是常量。出于相同的原因,可以添加一个恒定的偏移量(例如64)。此外,其他密码字节(2-5、7-10)使用什么字符并不重要。

通过迭代所有可能的x、y、z组合,最终可以找到与原始密码产生相同哈希值的密码。

Public Sub demo()
    ' https://dev59.com/LWcs5IYBdhLWcg3wcDiZ
    Dim x As Integer, y as Integer, z as Integer
    Dim part1 As String, part12 As String
    Dim sh As Worksheet
    Set sh = ThisWorkbook.Worksheets(1)

    sh.Protect "$ome_Insanely_Long_and_c0mplex_password! [(which i$ imp*ssible t0 re-member)]"

    For x = 64 To 95
        ' pad with dots, so that x, y and z affect nonoverlapping bits of the hash.
        part1 = Chr(x) + "...."
        For y = 64 To 95
            part12 = part1 + Chr(y) + "...."
            For z = 64 To 95
                On Error Resume Next
                    sh.Unprotect part12 + Chr(z)
                    If Err.Number = 0 Then
                        Debug.Print "Password: '" & part12 + Chr(z) & "'"
                        Exit Sub
                    End If
                On Error GoTo 0
            Next
        Next
    Next
End Sub

2
当我尝试运行此代码时,它没有起作用。但是,这个页面包含了一个过程(由Norman Harker和JE McGimpsey修改)来解锁受保护的工作表(而且它非常好用)。 - ARich
2
这是我迄今为止看到的最好的解释,从技术上讲也是唯一正确的,因为它确定了真正可能的“密码”数量为2^15 = 32768。Excel的哈希函数是一个满射函数,将大量输入密码映射到少量密码。Torben确定了一组与可能哈希集合Bijective相对应的输入密码子集,创建了一个经过优化的版本,常常被复制的暴力破解密码软件。 - Blackhawk
谢谢,这个算法效率更高!@ARich 我追踪了mcgimpsey.com上的算法,发现它是由挪威人Einar Ståle Huse开发的。他的Excel插件链接在1998年发布在这里,有人回复了实际代码。 - xXhRQ8sD2L7Z
使用“解压 .xlsx 或 .xlsm 文件”进行解锁无法对“文件级保护”起作用。 在这种情况下,整个Excel文件被加密,其格式不同于ZIP。 请参阅此处“文件级别”或“工作簿/工作表级别”保护之间的差异: https://support.microsoft.com/zh-cn/office/excel%E4%B8%AD%E7%9A%84%E4%BF%9D%E6%8A%A4%E5%92%8C%E5%AE%89%E5%85%A8-be0b34db-8cb6-44dd-a673-0b3e3475ac2d - Jan Šotola
正确。据我所知,文件级别的保护除了暴力破解方法外是无法破解的。请注意问题标题中的“工作表”一词 :-) - Torben Klein

3

我猜测,Excel通过一种哈希函数验证密码是否有效,该函数产生的结果范围很小,并将其与存储的哈希值进行比较。

据推测,这个函数是在测试所有这些值,直到找到一个有效的密码。根据使用的值来判断,哈希函数产生2 ^ 11 *(126-31)个不同的值,所有这些值都可以由此代码生成的值产生。

我的分析假设这个程序能够正常工作。我没有进行过测试。


谢谢你解决了这个问题。我也在同样的方向上努力,但是一直卡在那里! - Andrew White

0

这段代码使用加密密码AAAAAAAAAAA(空格)到BBBBBBBBBBB(~)进行暴力搜索,其中(空格)是空格字符(CHR(32)),而(~)当然是字符126。当找到密码时,它会在消息框中显示密码。

当然,这意味着它只检查长度为12个字符且仅由大写字母A(ASCII 65)和B(ASCII 66)组成的密码,后面跟着可打印的ASCII字符之一。@mkingston正确指出它测试了2^11 *(126-31)个不同的值。但没有哈希函数。我认为这不会破解很多电子表格。你最好使用AccessData中的这些程序之一

有关ActiveSheet.Protect和ActiveSheet.Unprotect的更多详细信息,请参阅http://msdn.microsoft.com/en-us/library/office/aa191957(v=office.10).aspx


首先增加最后一个字符。从AA..A & chr(32)到AA..A & chr(126)。然后从AA..B & chr(32)到AA..B & chr(126)。 - mkingston
抱歉,可能是在你之前勉强发出了评论 :) - mkingston
谢谢,这回答得很好!所以每次尝试新的时候,它都会运行对ActiveSheet.Unprotect的测试,返回一个表示成功与否的布尔值?太有趣了!理论上,我链接的代码可以被修改为运行所有可能的字符和可变字符长度,对吧?这些外部程序是如何工作的?它们是否使用某种API来访问Unprotect函数? - Andrew White
4
@andrewwhite,实际上这并没有正确理解此代码的应用。正如“我不认为这会破解很多电子表格”所示。 - brettdj
@brettdj,它不会破解很多电子表格,因为大多数电子表格的加密密码不仅由恰好这个长度的字母A或B组成,而且后面还跟着ASCII字符之一。例如,此代码将无法破解密码“PASSWORD”。 - vy32
3
请阅读我提供的链接。 - brettdj

-3
Sub FindPassword()
    'Breaks worksheet password protection.
    Dim i As Integer, j As Integer, k As Integer
    Dim l As Integer, m As Integer, n As Integer
    Dim i1 As Integer, i2 As Integer, i3 As Integer
    Dim i4 As Integer, i5 As Integer, i6 As Integer
    On Error Resume Next
    For i = 65 To 66: For j = 65 To 66: For k = 65 To 66
    For l = 65 To 66: For m = 65 To 66: For i1 = 65 To 66
    For i2 = 65 To 66: For i3 = 65 To 66: For i4 = 65 To 66
    For i5 = 65 To 66: For i6 = 65 To 66: For n = 32 To 126
    ActiveSheet.Unprotect Chr(i) & Chr(j) & Chr(k) & _
        Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & Chr(i3) & _
        Chr(i4) & Chr(i5) & Chr(i6) & Chr(n)
    If ActiveSheet.ProtectContents = False Then
        MsgBox "One usable password is " & Chr(i) & Chr(j) & _
            Chr(k) & Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & _
            Chr(i3) & Chr(i4) & Chr(i5) & Chr(i6) & Chr(n)
         Exit Sub
    End If
    Next: Next: Next: Next: Next: Next
    Next: Next: Next: Next: Next: Next
End Sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接