17

我发现这个 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

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

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

4

5 回答 5

16

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

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

  1. Excel 散列函数将可能密码的大空间映射到可能散列的小空间。
  2. 因为散列算法生成如此小的散列,15 位,可能的散列数是 2^15 = 32768 个散列。
  3. 32768 是应用计算能力时要尝试的极少数事情。Klein 派生出输入密码的子集,涵盖所有可能的哈希值。

根据对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
于 2013-11-13T15:46:21.560 回答
8

接受的答案不适用于在 Excel >2016 上使用 SHA-512 保护的工作表,但考虑到 excel 2016 使用开源的 office openxml 规范,很容易解决。

这种方法也是向后兼容的,因此它是打破旧的专有 md5 表保护而不是破解它的另一种方法。在尝试之前,只需将一个.xls版本另存为另一个版本。.xlsx

方法

  1. 将您的.xlsx/.xlsm文件重命名为.zip.
  2. 右键单击-使用 Windows 资源管理器将所有内容提取到文件夹。
  3. 打开xl\worksheets文件夹并使用正确的工作表名称打开文件。
  4. 搜索“sheetProtection”:

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

  1. 删除整个节点并保存文件。
  2. 选择您提取文件到的文件夹根目录下的所有文件,右键单击它并单击Send to -> Compressed (zipped) folder
  3. 将生成的文件重命名为其原始.xlsx/.xlsm扩展名

打开文件,该表上的保护将消失。

于 2018-12-10T16:53:17.040 回答
0
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
于 2014-05-23T07:36:54.277 回答
0

除了@Alexander Don'valderath 解决方案之外,您可能还想确保每次打开工作表时都没有 vba 重新保护工作表。

(编辑自 Joji Thomas Eapen 的原始答案
要解锁受密码保护的 vbaProject,

  1. 使用 Hex 编辑器打开 vbaProject.bin 文件,我使用的是 HxD
  2. 搜索DPB=并替换为DPx=
  3. 保存文件并将其复制回 zip(同样,拖放工作)
  4. 打开 XLSM/XLSX 文件并确认出现“意外错误 (40230)”错误
  5. 将其保存到新文件并在 VBA 编辑器中查看代码
于 2021-01-18T07:16:25.580 回答
-1

如果 VBA 不起作用,因为您有新的 Excel,只需将文件另存为与 Excel 2003 兼容的文件,如果要求额外的安全性,请选择否。那么所有带有 vsb 和一个可用密码的都是 AAAAAAAAA :D

于 2021-06-13T20:27:49.287 回答