Accessing Password Protected Excel VBA

In a recent assignment at my office last week, I came across a situation where I had to make some changes in the VBA code of an excel document. The excel document was something getting used from long time and there was no one having details related to password through which VBA code in that document was protected. Also there was no related supporting document available. I was in a situation where I required getting the access of VBA code without password.

After a lot of search on web and spending quite some time, I was able to access the VBA code without knowing the password. Although there are a lot of information already available on web related to the topic, however most of the information are either in bits and pieces or not very simple to understand for a non techie person.

Hence I decided to write this blog to present the information in simplest manner possible. Give it a try if you are in similar situation and I am sure this is going to work for you as well. Please follow all steps precisely as mentioned.

Before we jump into steps to access the password protected VBA, it make sense to understand how it works. When we try to access password protected VBA document, the VBE (Visual Basic Editor) will call in build system function to create the password dialogue box. This dialogue box is where the user will enter password to access the document and will click on OK. If the user enters correct password and press OK, the system function will return 1. If the user enters incorrect password or click cancel, the system function will return 0. After the dialogue box is closed, the Visual Basic Editor (VBE) will check the value entered. If the value is 1, VBE will think that the password is right and will open the document. On the other hand, if the value is 0, VBE will think that password is incorrect and will not allow access to the document. The trick that we are going to use is basically to swap the value of 0 to 1 by using a code that can be written easily or can be taken from this post and included in your excel document. Hope this basic helps in making the concept a little easier. Lets jump into the steps now.

For the ease of understanding, I have created a sample VBA document called “Password_Test”. As you can see below, when I try to open this VBAProject, it prompts for a password to be entered.

Okay, so now we will go to the steps directly.

Step 1: First step first. make sure you take a backup of your original file and keep it at a different location in your PC or Laptop so that if accidentally we corrupt the file then we have a backup readily available.

Step 2: Create a new file with .xlsm extension.

An XLSM file is a macro-enabled spreadsheet created by Microsoft Excel, a widely used spreadsheet program that comes with every edition of the Microsoft Office suite.

For ease of understanding, I have named this file as “macro.xlsm”. To create this file, open MS Excel application and then go to File->SaveAs->location and then name your file as macro.xlsm. You can also choose file type from drop down.

Step 3: Open you locked VBA project file. In our case, its “Password_Test”.

Step 4: Open the new blank file that we just created. In our case its “macro.xlsm”

Step 5: We need to insert certain code in our new created “macro.xlsm” file. Once the file is open, click “ctrl+F11” to open the Visual Basic Editor. Once your VBE is open, you will see a screen like this.

Step 6: Select VBAProject (macro.xlsm) then go to Insert and click on Module. A blank page will open on right panel of the VB Editor.

Step 7: On the blank page that open on right of VBE, copy and paste below mentioned code:

Option Explicit

Private Const PAGE_EXECUTE_READWRITE = &H40

Private Declare PtrSafe Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As LongPtr, Source As LongPtr, ByVal Length As LongPtr)

Private Declare PtrSafe Function VirtualProtect Lib "kernel32" (lpAddress As LongPtr, _
ByVal dwSize As LongPtr, ByVal flNewProtect As LongPtr, lpflOldProtect As LongPtr) As LongPtr

Private Declare PtrSafe Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As LongPtr

Private Declare PtrSafe Function GetProcAddress Lib "kernel32" (ByVal hModule As LongPtr, _
ByVal lpProcName As String) As LongPtr

Private Declare PtrSafe Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As LongPtr, _
ByVal pTemplateName As LongPtr, ByVal hWndParent As LongPtr, _
ByVal lpDialogFunc As LongPtr, ByVal dwInitParam As LongPtr) As Integer

Dim HookBytes(0 To 5) As Byte
Dim OriginBytes(0 To 5) As Byte
Dim pFunc As LongPtr
Dim Flag As Boolean

Private Function GetPtr(ByVal Value As LongPtr) As LongPtr
    GetPtr = Value
End Function

Public Sub RecoverBytes()
    If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 6
End Sub

Public Function Hook() As Boolean
    Dim TmpBytes(0 To 5) As Byte
    Dim p As LongPtr
    Dim OriginProtect As LongPtr

    Hook = False

    pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")


    If VirtualProtect(ByVal pFunc, 6, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then

        MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6
        If TmpBytes(0) <> &H68 Then

            MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6

            p = GetPtr(AddressOf MyDialogBoxParam)

            HookBytes(0) = &H68
            MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4
            HookBytes(5) = &HC3

            MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6
            Flag = True
            Hook = True
        End If
    End If
End Function

Private Function MyDialogBoxParam(ByVal hInstance As LongPtr, _
ByVal pTemplateName As LongPtr, ByVal hWndParent As LongPtr, _
ByVal lpDialogFunc As LongPtr, ByVal dwInitParam As LongPtr) As Integer

    If pTemplateName = 4070 Then
        MyDialogBoxParam = 1
    Else
        RecoverBytes
        MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _
                   hWndParent, lpDialogFunc, dwInitParam)
        Hook
    End If
End Function

Step 8: Repeat Step 6 and 7 and paste following code in “Module 2”

Sub unprotected()
    If Hook Then
        MsgBox "VBA Project is unprotected!", vbInformation, "*****"
    End If
End Sub

Step 9: We are almost done. Next you need to run your code. To run the code, click on small Play button on the menu bar on top

You will see a message like this. Click on “OK” and your locked VBA project will be accessible now. Please note: This trick will work on 64 bit MS Excel only.