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

时间:2012-10-12 04:07:39

标签: excel vba encryption excel-vba

这段代码已经在网上漂浮了很多年 - 它显然能够提供密码来解密你不知道密码的excel电子表格。

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

我对这是如何工作感兴趣,但我似乎无法解决这个问题。我假设它是在某个值下加密的,可以通过多种方式获得(网上的一些地方说它会给你原始密码或另一个可以工作的密码)有点像公钥 - 你可以拥有100个公钥,这些公钥都可以使用一个私钥。

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

全部谢谢!

编辑:我发现我发布的示例代码中的 For n = 32 To 126 。使用ASCII表进行交叉引用,该表似乎是从空间到波浪号的所有字符。这是某种词典攻击,由于语法原因我不理解吗?

5 个答案:

答案 0 :(得分:22)

这是一个小世界,因为代码表明我在大约10年前在其他论坛上发布了该代码,并在其他地方看过它 - 我想在John Walkenbach's旧网站上

请务必注意,此代码保护仅适用于工作表保护 - 而不适用于Excel的文件打开或VBA密码。

  • 这篇文章的一个例子是here(下面的屏幕截图)
  • Google搜索excel sheet protection “test” and “zzyw”会提供其他参考资料,例如from Tom Urtis

enter image description here

答案 1 :(得分:9)

引人入胜 - 之前我知道代码片段,但不知道brettdj发布的解释。正如其他人所解释的那样,它是对哈希冲突的蛮力搜索。实际上它似乎是通过反复试验制作的,因为它做了比必要工作更多的工作(生成了194560个组合,但是只有32768个哈希值可能。)

简称Excel的哈希算法(如http://chicago.sourceforge.net/devel/docs/excel/encrypt.html中所述):

  1. 取密码的每个字符的ascii代码。
  2. 将其视为16位有符号数。根据角色的位置将其位移到左侧(第一个字符为1位,第二个字符为2,依此类推)
  3. 将所有字符放在一起,给出16位有符号整数> = 0。
  4. XOR,其结果是密码的长度和幻数。
  5. 了解这一点,人们可以设计如下的蛮力搜索:

    • 最高位始终为零,因此需要测试15位。
    • 将它们分成三个计数器,每个计数器覆盖5位。这样每个计数器都可以代表一个可打印的ascii char。
    • 将这些计数器的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()
        ' http://stackoverflow.com/questions/12852095/how-does-excels-worksheet-password-protection-work
        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 :(得分:3)

只是一个猜测,但它看起来像Excel测试,如果密码是有效的,通过某种散列函数运行它,产生相当小的结果范围,并将其与存储的散列值进行比较。

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

我的分析假定这个例程有效。我还没有测试过。

答案 3 :(得分:0)

代码使用加密密码AAAAAAAAAAA(SPACE)到BBBBBBBBBBB(〜)进行暴力搜索,其中(SPACE)是空格字符(CHR(32)),而(〜)当然是字符126.当密码发现它在消息框中显示密码。

当然,这意味着它只检查长度正好为12个字符的密码,并且只包含大写字母A(ASCII 65)和B(ASCII 66),后跟一个可打印的ASCII字符。 @mkingston是正确的,它测试2 ^ 11 *(126-31)个不同的值。但是没有哈希函数。我认为这不会破解许多电子表格。你最好使用One of these programs from AccessData

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

答案 4 :(得分:-2)

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