用 VBA 破解表密码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19953979/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 17:11:02  来源:igfitidea点击:

Cracking Sheet Password with VBA

excelvbaexcel-vba

提问by Mariusz Górski

I found this VBA code to unlock sheets without knowing the password:

我发现这个 VBA 代码可以在不知道密码的情况下解锁工作表:

Sub PasswordBreaker()

  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)
   ActiveWorkbook.Sheets(1).Select
   Range("a1").FormulaR1C1 = 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

My question is: What kind of exploit does it use to work?

我的问题是:它使用什么样的漏洞来工作?

In other words, how come this generated string of A's and B's can be used as the password to a sheet inside a particular workbook ?

换句话说,为什么生成的 A 和 B 字符串可以用作特定工作簿中工作表的密码?

回答by Blackhawk

The Excel worksheet password protection works by converting the input password to a hash and stores it. A hash is a one-way algorithm that crunches up the bits, losing some information along the way, but generating a fingerprint of the original data. Because of the loss of data, it is impossible to reverse a hash to get the original password, but in the future if someone types in a password it can be hashed and compared against the stored hash. This (usually) makes it more secure than simply storing the password as a string to compare against.

Excel 工作表密码保护的工作原理是将输入密码转换为哈希并存储它。散列是一种单向算法,它处理位,在此过程中丢失一些信息,但会生成原始数据的指纹。由于数据丢失,不可能通过反向散列来获得原始密码,但将来如果有人输入密码,则可以对其进行散列并与存储的散列进行比较。这(通常)使它比简单地将密码存储为字符串来比较更安全。

The best description by far I've encounteredof how brute forcing the Excel hashing algorithm works is on the page @mehow links to, posted by Torben Klein. His answer can be summed up as:

到目前为止,我在Torben Klein 发布的 @mehow 链接到页面上遇到的关于强制执行 Excel 散列算法如何工作的最佳描述。他的回答可以概括为:

  1. The Excel hash function maps the large space of possible passwords to the small space of possible hashes.
  2. Because the hashing algorithm generates such small hashes, 15 bits, the number of possible hashes is 2^15 = 32768 hashes.
  3. 32768 is a tiny number of things to try when computing power is applied. Klein derives a subset of the input passwords that cover all of the possible hashes.
  1. Excel 散列函数将可能密码的大空间映射到可能散列的小空间。
  2. 因为散列算法生成如此小的散列,15 位,可能的散列数是 2^15 = 32768 个散列。
  3. 32768 是应用计算能力时要尝试的一小部分。Klein 派生了一个输入密码的子集,涵盖了所有可能的散列。

Based on this description of Excel's hashing function, the following code generates the same hash as Excel which you can use to test Klein's function.

根据Excel 散列函数的描述,以下代码生成与 Excel 相同的散列,您可以使用它来测试 Klein 的函数。

Option Explicit
'mdlExcelHash

Public Function getExcelPasswordHash(Pass As String)
    Dim PassBytes() As Byte
    PassBytes = StrConv(Pass, vbFromUnicode)
    Dim cchPassword As Long
    cchPassword = UBound(PassBytes) + 1
    Dim wPasswordHash As Long
    If cchPassword = 0 Then
        getExcelPasswordHash = wPasswordHash
        Exit Function
    End If

    Dim pch As Long
    pch = cchPassword - 1
    While pch >= 0
        wPasswordHash = wPasswordHash Xor PassBytes(pch)
        wPasswordHash = RotateLeft_15bit(wPasswordHash, 1)
        pch = pch - 1
    Wend

    wPasswordHash = wPasswordHash Xor cchPassword
    wPasswordHash = wPasswordHash Xor &HCE4B&
    getExcelPasswordHash = wPasswordHash
End Function

Private Function RotateLeft_15bit(num As Long, Count As Long) As Long
    Dim outLong As Long
    Dim i As Long
    outLong = num
    For i = 0 To Count - 1
        outLong = ((outLong \ 2 ^ 14) And &H1) Or ((outLong * 2) And &H7FFF) 'Rotates left around 15 bits, kind of a signed rotateleft
    Next
    RotateLeft_15bit = outLong
End Function

回答by Alexander Don'valderath

This doesn't work for worksheets protected on Excel 2016, but it's very easy to work around considering it's backwards compatible.

这不适用于在 Excel 2016 上保护的工作表,但考虑到它向后兼容,很容易解决。

If you unzip the xlsx/xlsmand go to the xl\worksheetsfolder, you will find a list of xml files corresponding to the sheets in your workbook.

如果解压缩xlsx/xlsm并转到该xl\worksheets文件夹,您将找到与工作簿中的工作表对应的 xml 文件列表。

Open the file that corresponds to the protected worksheet, and search for "sheetProtection", in this instance Excel seems to have used SHA-512 with a salt, (wow, that's going to be hardnow we know the salt..):

打开与受保护工作表对应的文件,并搜索“sheetProtection”,在这种情况下,Excel 似乎使用了带盐的 SHA-512,(哇,现在我们知道盐了,这将很难......):

<sheetProtection algorithmName="SHA-512" hashValue="j1woDldvfHE8IVB1F82CN/pmfOdOkpxkkZURiZJSGISjkJRIfM1G7EFwJsEeE1H+sf7s6sLIYSCuHPJG5Tpozw==" saltValue="QX8YeX/qfspqhDemAUEwSw==" spinCount="100000" sheet="1" objects="1" scenarios="1"/>

So instead of trying to crack it, we will just delete the whole sheetProtection Xml node and protection goes away entirely. You can save-as from an old version to this version if you want to use this method too.

因此,与其尝试破解它,不如删除整个 sheetProtection Xml 节点,保护就完全消失了。如果您也想使用此方法,可以将旧版本另存为此版本。

Re-zip the file contents after saving that xml file and name it back to xlsx/xlsmand open it.

保存该 xml 文件后重新压缩文件内容并将其重新命名为xlsx/xlsm并打开它。

回答by Klaudas

Function breakIT()
   Dim pass, bin As String: Dim dec As Integer
   On Error Resume Next
   For dec = 0 To 2047
     bin = WorksheetFunction.Dec2Bin(dec)
     For char_last = 32 To 126
        pass = Right("0000000000" & bin, 11)
        pass = Replace(pass, "0", "A"): pass = Replace(pass, "1", "B")
        pass = pass & Chr(char_last)
        ActiveSheet.Unprotect pass
        If Not ActiveSheet.ProtectContents Then 
           MsgBox "Sheet unprotected! Optimal pass: " & pass: On Error GoTo 0: Exit function
        EndIf 
     Next
   Next
End Function


Sub Worksheet_pass_break()
If ActiveSheet.ProtectContents = True Then
    breakIT
Else
    Select Case MsgBox("Sheet not protected. Do you want to protect it now for testing?", vbYesNo, "Not protected")
     Case vbYes
        random_text = ""
        Randomize
        For i = 1 To 10: random_text = random_text & Chr(Int((94 * Rnd) + 32)): Next i
        ActiveSheet.Protect "#TEST_Pass#_123456" & random_text
        breakIT
    Case vbNo
        Exit Sub
    End Select
End If
End Sub