Есть ли способ взломать пароль в проекте Excel VBA? - PullRequest
444 голосов
/ 22 июня 2009

Меня попросили обновить некоторые макросы Excel 2003, но проекты VBA защищены паролем, и, похоже, не хватает документации ... никто не знает пароли.

Есть ли способ удаления или взлома пароля в проекте VBA?

Ответы [ 22 ]

634 голосов
/ 16 декабря 2014

Вы можете попробовать этот прямой VBA подход, который не требует редактирования HEX. Это будет работать для любых файлов (* .xls, * .xlsm, * .xlam ...).

Проверено и работает на

Excel 2007
Excel 2010
Excel 2013 - 32-битная версия .
Excel 2016 - 32-битная версия .

Ищете 64-битную версию? См https://stackoverflow.com/a/31005696/4342479

как это работает

Я постараюсь объяснить, как это работает - извините, пожалуйста, за мой английский.

  1. VBE вызовет системную функцию для создания диалогового окна пароля.
  2. Если пользователь вводит правильный пароль и нажимает ОК, эта функция возвращает 1. Если пользователь вводит неправильный пароль или нажимает Отмена, эта функция возвращает 0.
  3. После закрытия диалогового окна VBE проверяет возвращаемое значение системной функции
  4. если это значение равно 1, VBE будет «думать», что пароль правильный, поэтому будет открыт заблокированный проект VBA.
  5. Приведенный ниже код заменяет память исходной функции, использованной для отображения диалогового окна ввода пароля, с пользовательской функцией, которая всегда будет возвращать 1 при вызове.

с использованием кода

Пожалуйста, сначала сделайте резервную копию ваших файлов!

  1. Откройте файл (ы), которые содержат ваши заблокированные проекты VBA
  2. Создайте новый файл xlsm и сохраните этот код в Module1

    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. Вставьте этот код под кодом выше в Module1 и запустите его

    Sub unprotected()
        If Hook Then
            MsgBox "VBA Project is unprotected!", vbInformation, "*****"
        End If
    End Sub
    
  4. Возвращайтесь к своим проектам VBA и наслаждайтесь.

209 голосов
/ 22 июня 2009

Да, если вы используете электронную таблицу формата .xls (по умолчанию для Excel до 2003 года). Для Excel 2007 и более поздних версий по умолчанию используется .xlsx, что является довольно безопасным форматом, и этот метод не будет работать.

Как говорит Треб, это простое сравнение. Один из способов - просто заменить пароль в файле с помощью шестнадцатеричного редактора (см. Шестнадцатеричные редакторы для Windows ). Пошаговый пример:

  1. Создайте новый простой файл Excel.
  2. В части VBA установите простой пароль (скажем, 1234).
  3. Сохраните файл и выйдите. Затем проверьте размер файла - см. Получено Stewbob'scha
  4. Откройте файл, который вы только что создали, в шестнадцатеричном редакторе.
  5. Скопируйте строки, начиная со следующих клавиш:

    CMG=....
    DPB=...
    GC=...
    
  6. ПЕРВОЕ РЕЗЕРВНОЕ КОПИРОВАНИЕ файл excel, для которого вы не знаете пароль VBA, затем откройте его с помощью своего шестнадцатеричного редактора и вставьте скопированные выше строки из фиктивного файла.

  7. Сохраните файл excel и выйдите.
  8. Теперь откройте файл excel, в котором вам нужен код VBA. Пароль для кода VBA будет просто 1234 (как в примере, который я показываю здесь).

Если вам нужно работать с Excel 2007 или 2010, ниже могут помочь некоторые другие ответы, в частности: 1 , 2 , 3 .

РЕДАКТИРОВАТЬ Фев 2015: для другого метода, который выглядит очень многообещающим, посмотрите на этот новый ответ Đức Thanh Nguyễn.

161 голосов
/ 05 ноября 2010

Существует другое (несколько более простое) решение, без проблем с размером. Я использовал этот подход сегодня (в файле 2003 XLS, используя Excel 2007) и был успешным.

  1. Резервное копирование файла xls
  2. Откройте файл в HEX-редакторе и найдите DPB=... part
  3. Измените строку DPB=... на DPx=...
  4. Открыть файл xls в Excel
  5. Открыть редактор VBA ( ALT + F11 )
  6. магия: Excel обнаруживает неверный ключ (DPx) и спрашивает, хотите ли вы продолжить загрузку проекта (в основном игнорируя защиту)
  7. Вы сможете перезаписать пароль, поэтому измените его на то, что вы можете запомнить
  8. Сохранить файл xls *
  9. Закройте и снова откройте документ и примените магию VBA!

* ПРИМЕЧАНИЕ. Убедитесь, что вы изменили пароль на новое значение, в противном случае при следующем открытии электронной таблицы Excel сообщит об ошибках (непредвиденная ошибка), а затем при доступе к списку модулей VBA вы увидите имена исходных модулей, но при попытке открыть формы / код / ​​и т. д. появляется другая ошибка Чтобы исправить это, вернитесь в Свойства проекта VBA и установите новое значение пароля. Сохраните и снова откройте документ Excel, и все будет хорошо!

147 голосов
/ 23 июня 2015

Я основываюсь на фантастическом ответе Тхана Нгуйена, чтобы этот метод мог работать с 64-битными версиями Excel. Я использую 64-разрядную версию Excel 2010 в 64-разрядной версии Windows 7.

  1. Откройте файл (ы), которые содержат ваши заблокированные проекты VBA.
  2. Создайте новый файл xlsm и сохраните этот код в Module1

    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. Вставьте этот код в Module2 и запустите его

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

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ Это сработало для меня, и я задокументировал это здесь в надежде, что это кому-нибудь поможет. Я не полностью протестировал его . Обязательно сохраните все открытые файлы, прежде чем продолжить работу с этой опцией.

63 голосов
/ 24 июня 2009

У Колина Пикарда отличный ответ, но есть один «остерегаться» этого. Есть случаи (я еще не выяснил причину), где общая длина записи "CMG = ........ GC = ...." в файле отличается от одного файла Excel до следующий. В некоторых случаях эта запись будет 137 байтов, а в других - 143 байта. Длина 137 байт является нечетной, и если это происходит при создании файла с паролем «1234», просто создайте другой файл, и он должен перейти к длине 143 байта.

Если вы попытаетесь вставить в файл неправильное количество байтов, вы потеряете ваш проект VBA, когда попытаетесь открыть файл в Excel.

EDIT

Недопустимо для файлов Excel 2007/2010. Стандартный формат файла .xlsx на самом деле представляет собой файл .zip, содержащий многочисленные подпапки с форматированием, макетом, содержимым и т. Д., Которые хранятся в виде данных XML. Для незащищенного файла Excel 2007 вы можете просто изменить расширение .xlsx на .zip, затем открыть файл zip и просмотреть все данные xml. Это очень просто.

Однако, когда вы защищаете файл Excel 2007 паролем, весь файл .zip (.xlsx) фактически шифруется с использованием шифрования RSA. Больше невозможно изменить расширение на .zip и просмотреть содержимое файла.

52 голосов
/ 26 июня 2015

Для файлов типа .xlsm или .dotm вам нужно сделать это немного по-другому.

  1. Измените расширение файла .xlsm на .zip.
  2. Откройте файл .zip (с помощью WinZip или WinRar и т. Д.) И перейдите в папку xl.
  3. Извлеките файл vbaProject.bin и откройте его в Hex Editor (я использую HxD , он абсолютно бесплатный и легкий.)
  4. Найдите DPB, замените на DPx и сохраните файл.
  5. Замените старый файл vbaProject.bin новым включенным в zip-файл.
  6. Измените расширение файла обратно на .xlsm.
  7. Открытая рабочая книга пропускает предупреждающие сообщения.
  8. Откройте Visual Basic внутри Excel.
  9. Перейдите в Инструменты> Свойства VBAProject> Вкладка Защита.
  10. Введите новый пароль и сохраните файл .xlsm.
  11. Закройте и снова откройте, и ваш новый пароль будет работать.
34 голосов
/ 25 марта 2011

Стоит отметить, что если у вас есть файл Excel 2007 (xlsm), вы можете просто сохранить его как файл Excel 2003 (xls) и использовать методы, описанные в других ответах.

16 голосов
/ 12 апреля 2010

Вы пытались просто открыть их в OpenOffice.org?

Некоторое время назад у меня была похожая проблема, и я обнаружил, что Excel и Calc не понимают шифрование друг друга и поэтому имеют прямой доступ практически ко всему.

Это было некоторое время назад, поэтому, если бы это была не просто случайность с моей стороны, это также могло быть исправлено.

12 голосов
/ 20 июня 2014

Для Excel 2007 и более поздних вам нужно изменить расширение вашего файла на .zip В архиве есть подпапка xl, там вы найдете vbaProject.bin. Выполните шаг выше с vbaProject.bin, затем сохраните его обратно в архиве. Измените свое расширение и вуаля! (то есть следуйте инструкциям выше)

11 голосов
/ 06 апреля 2011

В случае, если ваш блок CMG="XXXX"\r\nDPB="XXXXX"\r\nGC="XXXXXX" в вашем файле «известного пароля» короче существующего блока в файле «неизвестного пароля», добавьте шестнадцатеричные строки с конечными нулями, чтобы получить правильную длину.

, например

CMG="xxxxxx"\r\nDPB="xxxxxxxx"\r\nGC="xxxxxxxxxx"

в файле с неизвестным паролем, должно быть установлено

CMG="XXXX00"\r\nDPB="XXXXX000"\r\nGC="XXXXXX0000" для сохранения длины файла.

У меня также была эта работа с файлами .XLA (формат 97/2003) в Office 2007.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...