579 Stimmen

Gibt es eine Möglichkeit, das Kennwort für ein Excel-VBA-Projekt zu knacken?

Ich wurde gebeten, einige Excel 2003-Makros zu aktualisieren, aber die VBA-Projekte sind passwortgeschützt, und es scheint, dass es an Dokumentation mangelt... niemand kennt die Passwörter.

Gibt es eine Möglichkeit, das Kennwort für ein VBA-Projekt zu entfernen oder zu knacken?

815voto

Đức Thanh Nguyễn Punkte 8629

Sie können dies direkt versuchen VBA Ansatz, der keine HEX-Bearbeitung erfordert. Sie funktioniert für alle Dateien (*.xls, *.xlsm, *.xlam ...).

Getestet und funktioniert auf:

Excel 2007
Excel 2010
Excel 2013 - 32-Bit-Version
Excel 2016. 32-Bit-Version

Suchen Sie eine 64-Bit-Version? Siehe diese Antwort

Wie es funktioniert

Ich werde mein Bestes tun, um zu erklären, wie es funktioniert - bitte entschuldigen Sie mein Englisch.

  1. Das VBE ruft eine Systemfunktion auf, um das Passwort-Dialogfeld zu erstellen.
  2. Wenn der Benutzer das richtige Passwort eingibt und auf OK klickt, gibt diese Funktion 1 zurück. Wenn der Benutzer das falsche Kennwort eingibt oder auf Abbrechen klickt, gibt diese Funktion 0 zurück.
  3. Nachdem das Dialogfenster geschlossen wurde, prüft der VBE den Rückgabewert der Systemfunktion
  4. Wenn dieser Wert 1 ist, "denkt" das VBE, dass das Passwort richtig ist, und das gesperrte VBA-Projekt wird geöffnet.
  5. Der folgende Code tauscht den Speicher der ursprünglichen Funktion, die zur Anzeige des Kennwortdialogs verwendet wird, gegen eine benutzerdefinierte Funktion aus, die beim Aufruf immer 1 zurückgibt.

Verwendung des Codes

Bitte sichern Sie zuerst Ihre Dateien!

  1. Öffnen Sie die Datei(en), die Ihre gesperrten VBA-Projekte enthalten

  2. Erstellen Sie eine neue xlsm-Datei und speichern Sie diesen Code in Modul1

    code credited to Siwtom (nick name), a Vietnamese developer

    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
  3. Fügen Sie diesen Code unter dem obigen Code in Modul1 und führen Sie es aus

    Sub unprotected()
        If Hook Then
            MsgBox "VBA Project is unprotected!", vbInformation, "*****"
        End If
    End Sub
  4. Kehren Sie zu Ihren VBA-Projekten zurück und genießen Sie es.

228voto

Colin Pickard Punkte 44501

Ja, solange Sie eine .xls Tabellenkalkulation (Standardeinstellung für Excel bis 2003). Für Excel 2007 und höher ist die Standardeinstellung .xlsx das ein ziemlich sicheres Format ist, und diese Methode wird nicht funktionieren.

Wie Treb sagt, ist es ein einfacher Vergleich. Eine Methode besteht darin, den Kennworteintrag in der Datei einfach mit einem Hex-Editor auszutauschen (siehe Hex-Editoren für Windows ). Schritt-für-Schritt-Beispiel:

  1. Erstellen Sie eine neue einfache Exceldatei.

  2. Legen Sie im VBA-Teil ein einfaches Kennwort fest (z. B. 1234).

  3. Speichern Sie die Datei und beenden Sie sie. Überprüfen Sie dann die Dateigröße - siehe Stewbob's gotcha

  4. Öffnen Sie die soeben erstellte Datei mit einem Hex-Editor.

  5. Kopieren Sie die Zeilen, die mit den folgenden Tasten beginnen:

    CMG=....
    DPB=...
    GC=...
  6. ERSTE SICHERUNG die Excel-Datei, für die Sie das VBA-Kennwort nicht kennen, öffnen Sie sie mit Ihrem Hex-Editor, und fügen Sie die oben kopierten Zeilen aus der Dummy-Datei ein.

  7. Speichern Sie die Excel-Datei und beenden Sie sie.

  8. Öffnen Sie nun die Excel-Datei, in der Sie den VBA-Code sehen möchten. Das Kennwort für den VBA-Code lautet einfach 1234 (wie in dem Beispiel, das ich hier zeige).

Wenn Sie mit Excel 2007 oder 2010 arbeiten müssen, finden Sie unten einige andere Antworten, die Ihnen helfen könnten, insbesondere diese: 1 , 2 , 3 .

EDITAR Feb 2015: Eine weitere vielversprechende Methode finden Sie unter diese neue Antwort von C. Thanh Nguyn.

221voto

kaybee99 Punkte 4200

Ich habe auf der fantastischen Antwort von c Thanh Nguyn aufgebaut, damit diese Methode auch mit 64-Bit-Versionen von Excel funktioniert. Ich verwende Excel 2010 64-Bit auf 64-Bit Windows 7.

  1. Öffnen Sie die Datei(en), die Ihre gesperrten VBA-Projekte enthalten.

  2. Erstellen Sie eine neue xlsm-Datei und speichern Sie diesen Code in Modul1

    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
  3. Fügen Sie diesen Code in Modul2 und führen Sie es aus

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

HAFTUNGSAUSSCHLUSS Das hat bei mir funktioniert, und ich habe es hier dokumentiert, in der Hoffnung, dass es jemandem weiterhilft. Ich habe es nicht vollständig getestet. . Bitte stellen Sie sicher, dass Sie alle geöffneten Dateien speichern, bevor Sie mit dieser Option fortfahren.

184voto

Pieter Punkte 2111

Es gibt eine andere (etwas einfachere) Lösung, ohne die Größenprobleme. Ich habe diesen Ansatz heute angewandt (auf eine XLS-Datei aus dem Jahr 2003, mit Excel 2007) und war erfolgreich.

  1. Sichern Sie die xls-Datei
  2. Öffnen Sie die Datei in einem HEX-Editor und suchen Sie die DPB=... Teil
  3. Ändern Sie die DPB=... Zeichenkette bis DPx=...
  4. Öffnen Sie die xls-Datei in Excel
  5. Öffnen Sie den VBA-Editor ( ALT + F11 )
  6. die Magie: Excel entdeckt einen ungültigen Schlüssel (DPx) und fragt Sie, ob Sie mit dem Laden des Projekts fortfahren möchten (im Grunde wird der Schutz ignoriert)
  7. Sie können das Passwort überschreiben, also ändern Sie es in etwas, das Sie sich merken können.
  8. Speichern Sie die xls-Datei*.
  9. Schließen Sie das Dokument und öffnen Sie es erneut, um Ihre VBA-Magie anzuwenden!

*HINWEIS: Vergewissern Sie sich, dass Sie das Kennwort auf einen neuen Wert geändert haben, da Excel sonst beim nächsten Öffnen der Kalkulationstabelle Fehler meldet (Unerwarteter Fehler). Wenn Sie dann auf die Liste der VBA-Module zugreifen, sehen Sie zwar die Namen der Quellmodule, erhalten aber eine weitere Fehlermeldung, wenn Sie versuchen, Formulare/Code/etc. zu öffnen. Um dieses Problem zu beheben, gehen Sie zurück zu den VBA-Projekteigenschaften und setzen Sie das Kennwort auf einen neuen Wert. Speichern Sie das Excel-Dokument, öffnen Sie es erneut, und schon sollte es funktionieren!

122voto

VePe Punkte 841

Ich wiederum baue auf der hervorragenden Antwort von kaybee99 auf, die auf der fantastischen Antwort von c Thanh Nguyn aufbaut, damit diese Methode sowohl mit x86- als auch mit amd64-Versionen von Office funktioniert.

Ein Überblick über die Änderungen: Wir vermeiden push/ret, das auf 32-Bit-Adressen beschränkt ist, und ersetzen es durch mov/jmp reg.

Getestet und funktioniert auf

Word/Excel 2016 - 32-Bit-Version .
Word/Excel 2016 - 64-Bit-Version .

wie es funktioniert

  1. Öffnen Sie die Datei(en), die Ihre gesperrten VBA-Projekte enthalten.

  2. Erstellen Sie eine neue Datei mit demselben Typ wie oben und speichern Sie diesen Code in Modul1

    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 11) As Byte
    Dim OriginBytes(0 To 11) 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)), 12
    End Sub
    
    Public Function Hook() As Boolean
        Dim TmpBytes(0 To 11) As Byte
        Dim p As LongPtr, osi As Byte
        Dim OriginProtect As LongPtr
    
        Hook = False
    
        #If Win64 Then
            osi = 1
        #Else
            osi = 0
        #End If
    
        pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")
    
        If VirtualProtect(ByVal pFunc, 12, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then
    
            MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, osi+1
            If TmpBytes(osi) <> &HB8 Then
    
                MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 12
    
                p = GetPtr(AddressOf MyDialogBoxParam)
    
                If osi Then HookBytes(0) = &H48
                HookBytes(osi) = &HB8
                osi = osi + 1
                MoveMemory ByVal VarPtr(HookBytes(osi)), ByVal VarPtr(p), 4 * osi
                HookBytes(osi + 4 * osi) = &HFF
                HookBytes(osi + 4 * osi + 1) = &HE0
    
                MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 12
                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
  3. Fügen Sie diesen Code in Modul2 und führen Sie es aus

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X