用 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
Cracking Sheet Password with 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 散列算法如何工作的最佳描述。他的回答可以概括为:
- The Excel hash function maps the large space of possible passwords to the small space of possible hashes.
- Because the hashing algorithm generates such small hashes, 15 bits, the number of possible hashes is 2^15 = 32768 hashes.
- 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.
- Excel 散列函数将可能密码的大空间映射到可能散列的小空间。
- 因为散列算法生成如此小的散列,15 位,可能的散列数是 2^15 = 32768 个散列。
- 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
/xlsm
and go to the xl\worksheets
folder, 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
/xlsm
and 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