пятница, 22 января 2010 г.

Взлом пароля Excel. Макрос VBA, на основе Excel

Существует простой способ взломать забытый пароль Excel. И что немаловажно, сделать это можно абсолютно бесплатно с помощью самого Excel.
Итак если файл открывается, но Вам необходимо убрать защиту листа или книги, используйте надстройку, которую я написал:


Идея алгоритма заключается в использовании недостатка стандартного метода шифрования Excel. Программа перебирает пароли от 1 до 8 символов. Последний символ пароля подбирается из диапазона кодов от 32 до 255. Остальные символы подбираются из кодов 65 и 66. В результате используется пароль отличный от оригинального, но тем не менее рабочий. К сожалению для открытия файла, через Workbook.Open(), этот метод не подходит. Метод также не работает в Excel 2007, где используется более стойкий алгоритм шифрования. Исключение составляет французская версия Excel 2007, где из-за местных законов шифрование остается прежним.

Ниже приведен исходный код надстройки для взлома пароля в Excel:

Const MENUNAME = "ЗАЩИТА"
'Установка ярлыка меню
Sub Auto_Open()
    Install
    MsgBox "Меню установлено, используйте ""ЗАЩИТА->Снять защиту"" для снятия защиты с активной книги Excel и всех листов"
End Sub

'Взлом всех паролей, путем перебора.
Sub BruteForceUnprotect()
    Dim ProtectedObjects As New Collection
    Const LastCharStart = 32
    Const LastCharFinish = 255
    
    Application.DisplayAlerts = False
    
    'Добавление защищенной книги в набор объектов для вскрытия
    If (ActiveWorkbook.ProtectStructure Or ActiveWorkbook.ProtectWindows) Then
        ProtectedObjects.Add ActiveWorkbook
    End If
    
    'Добавление в набор защищенных листов
    On Error Resume Next
    For Each WSheet In ActiveWorkbook.Worksheets
        WSheet.Protect ("")
        If Not WSheet.Unprotect("") Then: ProtectedObjects.Add WSheet
    Next
    On Error GoTo 0
    
    'Поиск подставного пароля. Оригинальный пароль не может быть восстановлен этим способом.
    For i = 1 To 255
        fakepassword = FakePass(i)
        If ProtectedObjects.Count = 0 Then: Exit For
        For LastCharIndex = LastCharStart To LastCharFinish
            Password = fakepassword & Chr(LastCharIndex)
            If ProtectedObjects.Count > 0 Then
                For j = 1 To ProtectedObjects.Count
                    If UnprotectObject(ProtectedObjects(j), Password) = True Then
                        ProtectedObjects.Remove (j)
                        If ProtectedObjects.Count > 0 Then: j = j - 1
                    End If
                Next
            End If
        Next
    Next
    
    If ProtectedObjects.Count = 0 Then
        MsgBox "Пароли на текущую книгу и листы сняты!"
    Else
        MsgBox "Похоже используется нестандартное шифрование. Защита некоторых объектов не может быть снята."
    End If
    Application.DisplayAlerts = True
End Sub
Function UnprotectObject(obj, pass)
  UnprotectObject = False
  On Error GoTo WrongPassword
  obj.Unprotect pass
  UnprotectObject = True
WrongPassword:
End Function
'Возвращает пароль на основе переданного числового значения
Function FakePass(Value)
    Mask = 1
    FakePass = ""
    While Mask <= Value
        If (Value And Mask) = 0 Then
            FakePass = "A" & FakePass
        Else
            FakePass = "B" & FakePass
        End If
        Mask = Mask * 2
    Wend
    If Len(FakePass) > 0 Then: FakePass = Right(FakePass, Len(FakePass) - 1)
End Function
'Установка меню
Sub Install()
    Uninstall True
    AddButton MENUNAME, "Снять защиту", "BruteForceUnprotect"
    AddButton MENUNAME, "Удалить меню надстройки", "Uninstall"
End Sub
'Удаление меню надстройки
Sub Uninstall(Optional silent = False)
    If Not silent Then
        If MsgBox("Вы действительно желаете удалить меню надстройки ?", vbYesNo) = vbNo Then
            Exit Sub
        End If
    End If
    On Error Resume Next
    Application.CommandBars("Worksheet Menu Bar").Controls(MENUNAME).Delete
    On Error GoTo 0
End Sub
'Добавить пункт в меню
Sub AddButton(menu As String, submenu As String, macro As String, Optional descr As String = "")
    On Error GoTo createmenu
    If IsNull(Application.CommandBars("Worksheet Menu Bar").Controls(menu)) Then: GoTo createmenu
    On Error GoTo create
    If IsNull(Application.CommandBars("Worksheet Menu Bar").Controls(menu).Controls(submenu)) Then: GoTo create
    End
createmenu:
    Set mnu = Application.CommandBars("Worksheet Menu Bar").Controls.Add(Type:=10)
    mnu.Caption = "&" & menu
    mnu.Visible = True
    
create:
    Set Button = Application.CommandBars("Worksheet Menu Bar").Controls(menu).Controls.Add(Type:=1, ID:=2950)
    With Button
        .DescriptionText = descr
        .TooltipText = descr
        .Caption = "&" & submenu
        .Style = 3
        .OnAction = macro
    End With
End Sub

среда, 20 января 2010 г.

Взлом пароля в Word.

Взломать пароль на чтение документа MS Word можно используя сам Word. Никаких дополнительных утилит для этого не требуется

Проделайте следующее:
1. Откройте документ.
2. Нажмите Alt+Shift+F11. Откроется Microsoft Script Editor.
3. Нажмите Ctrl+F и наберите "pass" (без кавычек) в поле Find what.

4. Нажмите Find Next. Поиск подсветит строку вида: <w:UnprotectPassword>1234F8E7</w:UnprotectPassword>

5. Выделите всю строку и удалите ее
6. Нажмите Ctrl+S чтобы сохранить документ
7. Закройте окно Microsoft Script Editor
8. Выберите Сервис->Снять защиту. Защита на чтение будет снята, после чего можно вносить изменения.

вторник, 19 января 2010 г.

Последняя ячейка в диапазоне.

В канонических учебниках по VBA, для Excel можно встретить пример получения последней ячейки вида:

Set LastCell = ActiveSheet.SpecialCells(xlLastCell)

В целом здесь все правильно, за исключением одного момента. Иногда, после вставки и очистки данных в конце листа, последняя ячейка оказывается пустой.
Тогда как на практике гораздо важнее получить последнюю ячейку в заполненном диапазоне. Используя свойство UsedRange это легко сделать.

Пример:
Set LastCell = ActiveSheet.UsedRange.SpecialCells(xlLastCell)

понедельник, 18 января 2010 г.

VBA. Чтение и запись в Excel. Оптимизация.

1. Оптимизация с помощью Range.Resize()
Впервые столкнувшись с задачей программно прочитать содержимое ячеек Excel, многие используют самый очевидный способ: цикл чтений Cells(row,column).value.

Пример:
For i = 1 To 10
  destination.Cells(i,1).value = source.Cells(i,1).value 
Next


Не трудно заметить, что в данном примере было произведено 10 чтений.

Для ускорения чтения и записи данных из Excel, через VBA, всегда используйте метод класса Range: Resize(). Метод Resize() позволяет прочитать указанный диапазон ячеек в массив, для последующей обработки.

Пример:
arSales = Array()
arSales = source.Cells.Resize(10,1)

В данном примере, в массив arSales помещаются 10 строк и один столбец с листа source. По сравнению с чтением в цикле, данный метод работает в разы быстрее, поскольку чтение происходит за один этап. Таким-же образом данные помещаются в место назначения.

Пример:
destination.Cells.Resize(10,1) = arSales

Если имеется заданная переменная класса Range, то для получения массива можно просто использовать свойство Range.Value
Пример:
Set rng = Range("DATA")
arSales = rng.Value

2. Отключение вычислений на время записи данных.
При каждой записи ячейки Excel из кода VBA, программа автоматически пересчитывает все формулы в книге. Это вызывает серьезное замедление.
Для ускорения записи имеет смысл отключить автоматические вычисления и обновление экрана.

Пример:
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.EnableEvents = False


После произведения необходимых действий в VBA, можно вернуть настройки.

Пример:

Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True

3. Использование условного форматирования.

Иногда необходимо заполнить и форматировать(раскрасить) таблицу Excel, используя VBA. Для решения этой задачи есть два способа.
Первый, "в лоб": форматировать каждую ячейку или диапазон ячеек в цикле непосредственно из программы. У этого способа два недостатка: скорость и неудобство форматирования.

Второй, оптимизированный способ: задать условное форматирование для заполняемого диапазона. Например, в условном форматировании можно проверять одно или несколько значений в заполняемой строке и если оно не пустое, форматировать всю строку. Таким образом при вставке значений в новую строку, из VBA, формат (цвет, шрифт) будет меняться автоматически, вне кода. Этот способ оптимален по скорости и удобен тем, что форматирование производится визуально.

Для реализации этого метода можно создать xls-файл, с заголовком и одной строкой, с заданным условным форматированием. Формат этой строки необходимо скопировать в строки, которые будут заполнятся. Поскольку задать формат одновременно для большого кол-ва ячеек нельзя, то делать это придется блоками.

Пример:
rowscount = 20000 ' Кол-во форматируемых строк
colscount= 5 ' Кол-во форматируемых столбцов
onepass = 1024 ' Кол-во строк форматируемых за один проход
src_row = 1 ' Номер строки с заданным условным форматированием
For i = src_row+1 To rowscount Step onepass
  Rows(src_row).Resize(1, colscount).Copy
  If i + onepass > rowscount Then: onepass = rowscount - i
  Rows(i).Resize(onepass, colscount).PasteSpecial _ 
    Paste:=xlPasteFormats, _
    Operation:=xlNone, _
    SkipBlanks:=False, _ 
    Transpose:=False
Next


Теперь можно вставлять значения. Настройки цвета и шрифта будут применяться автоматически.