קיבלתי מלקוח קובץ עם סיומת xlsm, זהו קובץ  המכיל פקודות מאקרו בשפת VBA (סוג של פיתוח לאקסל).

    כשפתחתי את הקובץ – על חלק מהמחשבים זה עבד, ובחלקם קיבלתי את ההודעה הבאה:

    Microsoft Visual Basic for Applications ————————— Compile error in hidden module: טופס_ראשי. This error commonly occurs when code is incompatible with the version, platform, or architecture of this application. Click "Help" for information on how to correct this error.

     

     

    במחשבה לאחור, העובדה שזה עבד על חלק מהמחשבים, רמזה לזה, שהקוד תקין, ובחלק מהמחשבים חסר reference.

    כדי לבדוק מה קורה ניסיתי לפתוח את הקוד [כדי לראות את הטאב של מפתחים, צריך ללכת ל – קובץ, אפשרויות, התאמה אישית של רצועת הכלים, ולסמן את מפתחים], שם יש לחצן בשם “הצג קוד” אשר פותח את החלון של VBA.

    ברגע שעשיתי זאת קיבלתי בקשה לסיסמא

    image

     

    שזה כבר בעייה גדולה, כיוון שלא היה לי מושג מי המפתח.

    כדי לפתור את הבעייה, מצאתי את התהליך הבא כאן. (ההסברים הטכניים, שם, בקצרה – תיבת הסיסמא של VBA עובדת שלאחר הכנסת סיסמא, במידה וזה תקין הוא מחזיר 1 אחרת 0, הקוד שתראו בהמשך מחליף (זמנית) את הפונקציה בזיכרון כך שהיא תמיד תחזיר 1 ללא פתיחת בקשת הסיסמא)

     

    פתחתי אקסל חדש ולחצתי על “הצג קוד” בטאב המפתחים. שם יצרתי שני מודולים חדשים,

    image

    לאחר ההוספה עץ המודולים נראה כך:

    image

     

    כאשר במודול 1 אני כותב את הקוד הבא.

    Code Snippet
    Option Explicit On

    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

     

    במודול מס 2, נכתוב את הקוד הבא.

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

     

    כעת נריץ את המודול השני, לאחר הריצה של הקוד, לא נתבקש יותר להכניס סיסמא.

    בשלב הזה פתחתי את References תחת Tools וראיתי שחסר לי Reference כלשהו (מגרסה קודמת של אקסל), בחרתי את המקבילה מהגרסה הרלוונטית המותקנת במחשב.

    והכל בא על מקומו בשלום.