Mariusz Górski
Mariusz Górski

Reputation: 399

Cracking Sheet Password with VBA

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

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 ?

Upvotes: 20

Views: 75799

Answers (5)

user16217249
user16217249

Reputation: 1

If the VBA don't work because you have new excell just save as the file in compatabile with excell 2003, and if asked for extra security choose no. Then all with vsb and one usable password will be AAAAAAAAA :D

Upvotes: -1

KuN
KuN

Reputation: 1211

In addition to @Alexander Don'valderath solution, you might also want to make sure there is no vba re-protect the worksheet every time you open one.

(edited from Joji Thomas Eapen's original answer)
To unlock the the password-protected vbaProject,

  1. Open the vbaProject.bin file with an Hex edtior, I used HxD
  2. Search for DPB= and replace it with DPx=
  3. Save the file and copy it back to the zip (again, drag and drop works)
  4. Open the XLSM/XLSX file and confirm to the “Unexpected error (40230)” error
  5. Save it to a new file and review the code in VBA editor

Upvotes: 0

The accepted answer doesn't work for worksheets protected on Excel >2016 with SHA-512, but it's very easy to work around considering excel 2016 uses office openxml specification which is open source.

This method is also backwards compatible so it's another way to break the older proprietary md5 sheet protection rather than cracking it. Simply save-as from a .xls version to a .xlsx version before you try it.

Method

  1. Rename your .xlsx/.xlsm file to .zip.
  2. Right click-Extract all to a folder using windows explorer.
  3. Open the xl\worksheets folder and open the file with the correct sheet name.
  4. Search for "sheetProtection":

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

  1. Delete the whole node and save the file.
  2. Select all of the files at the root of the folder that you extracted the files to, right click it and click Send to -> Compressed (zipped) folder.
  3. Renamed the resulting file to it's original .xlsx/.xlsm extension

Open the file, and the protection on that sheet will be gone.

Upvotes: 15

Blackhawk
Blackhawk

Reputation: 6120

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.

The best description by far I've encountered of 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:

  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.

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.

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

Upvotes: 18

Klaudas
Klaudas

Reputation: 25

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

Upvotes: 0

Related Questions