Excel S02 | Gỡ bỏ mật khẩu file VBA

Trong bài này, chúng ta sẽ tìm hiểu cách gỡ bỏ mật khẩu project VBA của Office

Mục đích

Đôi lúc có những Add-ins, file của người khác chứa những Macro rất hay, chúng ta muốn mở nó ra xem code được viết như thế nào, nhằm tinh chỉnh cho phù hợp với vấn đề của mình.
Tuy nhiên thông thường thì các Project VBA ấy sẽ được bảo vệ (Password Protected). Qua tham khảo trên mạng có cách sử dụng HxD để thay chuỗi DPB (Hex Editor ), tuy nhiên mình đã thử và không được. Có lẽ cách đó sử dụng cho các phiên bản Office cũ hơn.
Tìm kiếm trên StackOverflow thì có bài này: Is there a way to crack the password on an Excel VBA Project? và mình đã áp dụng thành công.
Đối tượng sử dụng: các loại file Office chứa macro (*.xls, *.xlsm, *.xlam …), thậm chí là cả Power Point (.pptm, .ppam).
CHÚ Ý : Code dưới đây sử dụng cho phiên bản Office 32 Bit. Cho phiên bản 64 Bit, ghé thăm link phía trên ở câu trả lời số 4.

Giải pháp

Giả sử chúng ta cần unlock VBA Project của 1 file Excel (*.xls, *.xlsm, *.xlam …)

  1. Back up file trước. Sau đó mở file đó ra.
  2. Tạo 1 file mới Ctrl + N. Bật Alt + F11. Chuột phải vào Sheet 1 ở cửa sổ Project, chọn Insert » Module
  3. Ấn vào Module1 vừa tạo ra, chọn View Code F7, paste đoạn code ở dưới vào
  4. Để chuột ở Sub cuối cùng (unprotected) và Run it F5
  5. Mở lại VBA project ở file của bạn và View Code bình thường.

code credited to Siwtom

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
Option Explicit

Private Const PAGE_EXECUTE_READWRITE = &H40

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

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

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

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

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

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

Private Function GetPtr(ByVal Value As Long) As Long
    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 Long
    Dim OriginProtect As Long

    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 Long, _
        ByVal pTemplateName As Long, ByVal hWndParent As Long, _
        ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer
    If pTemplateName = 4070 Then
        MyDialogBoxParam = 1
    Else
        RecoverBytes
        MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _
                           hWndParent, lpDialogFunc, dwInitParam)
        Hook
    End If
End Function

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

Enjoy!