Sunteți pe pagina 1din 13

MODULE NAME: mainFuncs

''Created by Anton Pivkach (lbeliarl@gmail.com)

Option Base 1

'Declare Function GetTickCount Lib "kernel32.dll" () As Long


Declare PtrSafe Function GetTickCount Lib "kernel32.dll" () As Long 'win64_bit

Public CopiedExcel As Boolean


Public RenamedZIP As Boolean
Public CreatedTMPFolder As Boolean

Public ProtectedSheets() As Long

Sub GeneralSub()

CopiedExcel = False
RenamedZIP = False
CreatedTMPFolder = False

'Check if any selection exists


If (Sheet1.CheckVBA.Value Or Sheet1.CheckWB.Value Or Sheet1.CheckWS.Value) = False Then
MsgBox "Please select at least one checkBox!", vbInformation, "Excel Unlocker"
Exit Sub
End If

ChDir (Environ("USERPROFILE") & "\Desktop")


'Select the file
Fname = Application.GetOpenFilename(filefilter:="Excel files (*.xlsx; *.xlsm), *.xlsx; *.xlsm",
MultiSelect:=False)

'Check if file selected


If Fname = False Then
Exit Sub
End If

''Check if workBook has password for opening


On Error Resume Next
Dim tmpWB As Workbook

''Disable AutoRun macro


Application.EnableEvents = False

Set tmpWB = Workbooks.Open(Fname, ReadOnly:=True, Password:="", UpdateLinks:=False,


IgnoreReadOnlyRecommended:=True)

If Err.Number > 0 Then


MsgBox "Selected Workbook is encrypted (Password for Openning)!" & vbCrLf & "This program doesn't
works with such files.", vbCritical, "Excel Unlocker"
''Return original settings (AutoRun macro)
Application.EnableEvents = True
Exit Sub
End If
On Error GoTo 0

''Check if WorkBook is in Shared mode


If tmpWB.MultiUserEditing = True Then
''Close WorkBook
tmpWB.Close saveChanges:=False
MsgBox "Selected Workbook is in Shared Mode!" & vbCrLf & "Please change mode to Exclusive (non
Shared) and try again", vbExclamation, "Excel Unlocker"
''Return original settings (AutoRun macro)
Application.EnableEvents = True
Exit Sub
End If

''Check if VBProjec protected


ProjectProtected = ProtectedVBProject(tmpWB)
''Check if WorkBook is protected
WBookProtected = PrWB(tmpWB)
''Checx if Sheets is protected
WBookSheetsProtected = PrWSheets(tmpWB)

''Close WorkBook
tmpWB.Close saveChanges:=False
Set tmpWB = Nothing

'String for output msgs


Dim OutMSG As String
OutMSG = ""

''Create Scripting Object


Dim FSO As Object
Set FSO = CreateObject("scripting.filesystemobject")

''Call procedure for each action-----------------------------


''WorkBook------------------------------
If Sheet1.CheckWB.Value = True Then
If WBookProtected = True Then
OutMSG = UnprotectWBook(Fname)
Else
OutMSG = OutMSG & vbCrLf & "Selected WorkBook has no WorkBook Password Protection."
End If
'ChangeWBStatus
WBookProtected = False
End If

''Vba-----------------------------------
If Sheet1.CheckVBA.Value = True And FSO.GetExtensionName(Fname) = "xlsm" Then
'Check whether WorkBook has VBA Project protection
If ProjectProtected = True Then

'Check whether WorkBook has Password Protection (internal ZIP encryption)


If WBookProtected = True Then
OutMSG = OutMSG & vbCrLf & UnprotectWBook(Fname)
End If

''Call VBA unlock


OutMSG = OutMSG & vbCrLf & ChangePasswordForVBA(Fname)
Else
OutMSG = OutMSG & vbCrLf & "Selected WorkBook has no VBA Project protection."
End If
End If

''WorkSheet----------------------------
If Sheet1.CheckWS.Value = True Then
If WBookSheetsProtected = True Then

'Check whether WorkBook has Password Protection (internal ZIP encryption)


If WBookProtected = True Then
OutMSG = OutMSG & vbCrLf & UnprotectWBook(Fname)
End If

''Call Sheets unlock


OutMSG = OutMSG & vbCrLf & UnprotectWSheets(Fname)
Else
OutMSG = OutMSG & vbCrLf & "Selected WorkBook has no WorkSheets Protection."
End If
End If

''Check if returning to previous state is required


If RenamedZIP = True Then

''Rename back to .xlsm file


FSO.GetFile(rename_to_zip(copy_excel_file(Fname))).Name =
FSO.GetFileName(copy_excel_file(Fname))

''Delete tmp files--------------------------


' If FSO.FolderExists(FileNameFolder & "\") Then
' FSO.deletefolder FileNameFolder
' End If

End If

If RenamedZIP Or CopiedExcel Then


OutMSG = OutMSG & vbCrLf & vbCrLf & "Unlocked file saved under the name: '" & "Unprotected_" &
FSO.GetFileName(Fname) & "' in the same folder"
End If

Set FSO = Nothing

''Return original settings (AutoRun macro)


Application.EnableEvents = True

MsgBox OutMSG, vbInformation, "Excel Unlocker"

End Sub

Function ChangePasswordForVBA(Fname As Variant) As String

Application.StatusBar = "Resetting VBA Project password..."

''Copy Excel file and Rename to ZIP


name_of_exel_file = copy_excel_file(Fname)

If name_of_exel_file = "" Then ''Missing Write acces


ChangePasswordForVBA = "Missing Write access"
Exit Function
End If

CopyFname = rename_to_zip(name_of_exel_file)

''TMP Folder
FileNameFolder = create_TMP_folder

'Object for work with ZIP file


Set oApp = CreateObject("Shell.Application")

''Set to false
ProjectFileFound = False

''Cycle trought Zip archive


For Each fileNameInZip In oApp.Namespace(CopyFname).items
'find 'xl' folder
If fileNameInZip = "xl" Then
'find vbaProject.bin
For Each subFile In fileNameInZip.Getfolder.items
'extract 'vbaProject.bin' file
If subFile = "vbaProject.bin" Or subFile = "vbaProject" Then
''Move bin file to tmp folder
oApp.Namespace(FileNameFolder).movehere subFile
ProjectFileFound = True
Exit For
End If
Next
End If
Next

''HASH for Password = 'macro'


Dim PasswordString As String
PasswordString =
"282A84CBA1CBA1345FCCB154E20721DE77F7D2378D0EAC90427A22021A46E9CE6F17188A"

''if VbaProject exists


If ProjectFileFound = True Then
tmpMSG = ""
tmpMSG = ChangeDPBValue(FileNameFolder & "\vbaProject.bin", PasswordString) ''DPB change

''Overwirte existing vbaProject.bin file


oApp.Namespace(CopyFname).items.Item("xl").Getfolder.CopyHere FileNameFolder &
"\vbaProject.bin"

'Keep script waiting until Compressing is done


On Error Resume Next
Do Until oApp.Namespace(CopyFname).items.Item("xl").Getfolder.items.Item("vbaProject.bin").Name
= "vbaProject.bin" Or _
oApp.Namespace(CopyFname).items.Item("xl").Getfolder.items.Item("vbaProject.bin").Name =
"vbaProject"
Application.Wait (Now + TimeValue("0:00:01"))
Loop
On Error GoTo 0

If tmpMSG = "" Then


ChangePasswordForVBA = "Password for VbaProject: 'macro'"
Else
ChangePasswordForVBA = tmpMSG
End If

Else
ChangePasswordForVBA = "File don't have VbaProject!"
End If

Set oApp = Nothing

Application.StatusBar = ""

End Function

Function UnprotectWBook(Fname As Variant) As String


Dim UL As Workbook
Dim lockedWB As Workbook

''Remember this WB name


Set UL = ThisWorkbook

LockedWBName = copy_excel_file(Fname)

If LockedWBName = "" Then ''Missing Write access


UnprotectWBook = "Missing Write access"
Exit Function
End If

''Disable AutoRun macro


Application.EnableEvents = False
''Disable Alerts
Application.DisplayAlerts = False
''Dissable screen updating
Application.ScreenUpdating = False

''Open Locked WB
On Error Resume Next ''Prevent error for WriteProtection Password
Set lockedWB = Workbooks.Open(LockedWBName, notify:=False, WriteResPassword:="",
UpdateLinks:=False, IgnoreReadOnlyRecommended:=True)

''Check for Write password---------------


If Err.Number <> 0 Then
'Open original file
Set lockedWB = Workbooks.Open(Fname, ReadOnly:=True, UpdateLinks:=False,
IgnoreReadOnlyRecommended:=True)
'Save as Unlocked
lockedWB.SaveAs LockedWBName, WriteResPassword:="", ReadOnlyRecommended:=False
End If

On Error GoTo 0

''Return original settings (AutoRun macro)


Application.EnableEvents = True

''Randomize HASH values to improve chance of quick break


Sheet3.Calculate

'''HASH values calculated based on algorithm described here:


'http://stackoverflow.com/questions/12852095/how-does-excels-worksheet-password-protection-work

''Sort
UL.Worksheets("hash_table").AutoFilter.Sort.SortFields.Clear
UL.Worksheets("hash_table").AutoFilter.Sort.SortFields.Add Key:= _
Range("B1:B32769"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption _
:=xlSortNormal
With UL.Worksheets("hash_table").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With

s_t = GetTickCount
ETR = 0

''Enable errors resuming


On Error Resume Next

Do ''Dummy loop to enable early exit from For

For i = 2 To 32769
DoEvents

''update changes by 1% Calculate ETR


If i Mod 300 = 0 Then
e_t = GetTickCount
If ETR > 0 Then
ETR = (ETR + ((32769 - i) / 300 * (s_t - e_t) / 1000)) / 2
Else
ETR = (32769 - i) / 300 * (s_t - e_t) / 1000
End If

Application.StatusBar = "WB Protection password guessing: " & Format((i / 32769), "0%") & " / Max
ETR: " & Format(TimeSerial(0, 0, ETR), "hh:mm:ss")
s_t = GetTickCount
End If

lockedWB.Unprotect UL.Worksheets("hash_table").Cells(i, 1).Value


If Not (lockedWB.ProtectWindows Or lockedWB.ProtectStructure) = True Then

UnprotectWBook = "Allowable WB Protection password: '" &


UL.Worksheets("hash_table").Cells(i, 1).Value & "'"
Application.StatusBar = "WB Protection password guessing: " & Format((i / 32769), "0%") & " ->
Success!!!"
Exit Do
End If

Next i
Loop Until 1 = 1

''Disable errors resuming


On Error GoTo 0

''Save WB
lockedWB.Close saveChanges:=True

Application.StatusBar = ""

Application.DisplayAlerts = True
Application.ScreenUpdating = True

End Function
Function UnprotectWSheets(Fname As Variant) As String ''Fname As Variant

Application.ScreenUpdating = False

Application.StatusBar = "Remove Sheets password..."

''Copy Excel file and Rename to ZIP


CopyFname = rename_to_zip(copy_excel_file(Fname))
''TMP Folder
FileNameFolder = create_TMP_folder

'Object for work with ZIP file


Set oApp = CreateObject("Shell.Application")

''Extract locked sheets


For i = 1 To UBound(ProtectedSheets)
DoEvents

Application.StatusBar = "Sheets Protection / extracting " & "sheet" & ProtectedSheets(i)

''Move .xml file to tmp folder


oApp.Namespace(FileNameFolder).movehere oApp.Namespace(CopyFname &
"\xl\worksheets").items.Item("sheet" & ProtectedSheets(i) & ".xml")

Next i

''Dim xmlDoc As MSXML2.DOMDocument


''Dim objNode As IXMLDOMSelection

''Process each locked sheet----------------------

''Create XML object


Set xmlDoc = CreateObject("MSXML2.DOMDocument")

For i = 1 To UBound(ProtectedSheets)

Application.StatusBar = "Sheets Protection / removing protection of " & "sheet" & ProtectedSheets(i)

'Load XML file (sheet)


xmlDoc.Load FileNameFolder & "\sheet" & ProtectedSheets(i) & ".xml"

''Set Node sheetProtection


Set objSelecion = xmlDoc.getElementsByTagName("sheetProtection")
''Revmove node
objSelecion.removeAll
''Save changes
xmlDoc.Save FileNameFolder & "\sheet" & ProtectedSheets(i) & ".xml"

Next i

''Overwirte existing sheets in ZIP file------------------------


For i = 1 To UBound(ProtectedSheets)
Application.StatusBar = "Sheets Protection / compressing " & "sheet" & ProtectedSheets(i)

'' prevent compressing error----


On Error Resume Next
Do
oApp.Namespace(CopyFname & "\xl\worksheets").CopyHere FileNameFolder & "\sheet" &
ProtectedSheets(i) & ".xml"

DoEvents
Application.Wait (Now + TimeValue("0:00:01"))
Loop Until Err.Number = 0
On Error GoTo 0
'Keep script waiting until Compressing is done
On Error Resume Next
Do Until oApp.Namespace(CopyFname & "\xl\worksheets").items.Item("sheet" & ProtectedSheets(i) &
".xml").Name = CStr("sheet" & ProtectedSheets(i) & ".xml")
DoEvents
Application.Wait (Now + TimeValue("0:00:01"))
Loop
On Error GoTo 0
Next i

Application.StatusBar = ""

UnprotectWSheets = "All the Sheets have been unprotected"


Application.ScreenUpdating = True

End Function
MODULE NAME: auxiliaryFuncs

Option Base 1

Function ProtectedVBProject(ByRef wb As Workbook) As Boolean


' returns TRUE if the VB project in the active document is protected
Dim VBC As Integer

VBC = -1
On Error Resume Next
VBC = wb.VBProject.VBComponents.Count
On Error GoTo 0

If VBC = -1 Then
ProtectedVBProject = True
Else
ProtectedVBProject = False
End If

End Function

Function PrWB(ByRef wb As Workbook) As Boolean

PrWB = False

If wb.ProtectWindows Then PrWB = True


If wb.ProtectStructure Then PrWB = True

If PrWB = True Then


'try for password protection
On Error Resume Next
wb.Unprotect
If Err.Number = 0 Then PrWB = False
On Error GoTo 0
End If

End Function

Function PrWSheets(ByRef wb As Workbook) As Boolean

PrWSheets = False

''Arrays for storing protected wsheets


i=0

For Each SH In wb.Sheets


If SH.ProtectContents Or SH.ProtectDrawingObjects Or SH.ProtectScenarios Then
i=i+1
ReDim Preserve ProtectedSheets(i)
ProtectedSheets(i) = SH.Index
PrWSheets = True
End If
Next

End Function

Function copy_excel_file(file_to_copy)

''Create Scripting Object


'Dim FSO As Object
Set FSO = CreateObject("scripting.filesystemobject")

'Define new name


UnprotecedFilePath = FSO.GetParentFolderName(file_to_copy) & "\Unprotected_" &
FSO.GetFileName(file_to_copy)

''Check if file already copied


If CopiedExcel = False Then
On Error Resume Next
''Copy
FSO.CopyFile file_to_copy, UnprotecedFilePath, True

''Check for access error


If Err.Number <> 0 Then
MsgBox "You have no Write access to the folder: '" & FSO.GetParentFolderName(file_to_copy) & "'",
vbCritical, "Excel Unlocker"

copy_excel_file = ""
Exit Function
End If

On Error GoTo 0
'Save flag
CopiedExcel = True
End If

Set FSO = Nothing

''return path
copy_excel_file = UnprotecedFilePath

End Function
Function rename_to_zip(file_to_rename)

''Create Scripting Object


Dim FSO As Object
Set FSO = CreateObject("scripting.filesystemobject")

''Create new name


ZIPFilePath = FSO.GetParentFolderName(file_to_rename) & "\" & FSO.GetBaseName(file_to_rename) &
".zip"

''Check if file already renamed


If RenamedZIP = False Then
'chekc if file with such name exists
If FSO.FileExists(ZIPFilePath) Then FSO.DeleteFile ZIPFilePath, True
'Change extension
FSO.MoveFile file_to_rename, ZIPFilePath
'Save flag
RenamedZIP = True
End If

Set FSO = Nothing

''Return path
rename_to_zip = ZIPFilePath

End Function

Function create_TMP_folder()

''Path to tmp folder


FileNameFolder = Environ("tmp") & "\UnlockFolderTMP"

If CreatedTMPFolder = False Then


''Create Scripting Object
'Dim FSO As Object
Set FSO = CreateObject("scripting.filesystemobject")

''Delete if previous files exists


Do While FSO.FolderExists(FileNameFolder & "\")
FSO.deletefolder FileNameFolder

DoEvents
Application.Wait (Now + TimeValue("0:00:01")) '' wait until deletion is done
Loop

'Make the tmp folder in User tmp


FSO.CreateFolder FileNameFolder

'Destroy FSO
Set FSO = Nothing

'Set Flag
CreatedTMPFolder = True
End If

create_TMP_folder = FileNameFolder

End Function

Function ChangeDPBValue(PathToBinFile As String, HASHPassword As String) As String

''Dim adoStream As ADODB.Stream


''Dim adoBin As ADODB.Stream

Dim PasswordArrayByte() As Byte

Set adoStream = CreateObject("ADODB.Stream")


Set adoBin = CreateObject("ADODB.Stream")

ReDim PasswordArrayByte(Len(HASHPassword))

''Convert String to byte


For i = 1 To Len(HASHPassword)
PasswordArrayByte(i) = Asc(Mid(HASHPassword, i, 1))
Next i

''Read TXT data fine 'DPB' value


With adoStream
.Mode = 3 'adModeReadWrite
.Type = 2 'adTypeText
.Charset = "us-ascii"
.Open
.LoadFromFile (PathToBinFile)
bytes = .ReadText

''Find Start of Value pos


StartPosVal = InStr(1, bytes, "DPB=", vbTextCompare) + 5

''IF there is no DPB value


If StartPosVal = 5 Then
.Close
Set adoStream = Nothing
Set adoBin = Nothing
ChangeDPBValue = "VBA Protection Not found"
Exit Function
End If

''Find End of Value pos


EndPosVal = InStr(StartPosVal, bytes, """", vbTextCompare) - 1
'Define lenght
ValLength = EndPosVal - StartPosVal + 1

If Len(HASHPassword) < ValLength Then


'add additional '0' if coded password is longer
ReDim Preserve PasswordArrayByte(Len(HASHPassword) + ValLength - Len(HASHPassword))

For i = Len(HASHPassword) + 1 To UBound(PasswordArrayByte)


PasswordArrayByte(i) = Asc(0)
Next i
End If

.Close
End With

''Read binary data


With adoStream
.Mode = 3 'adModeReadWrite
.Type = 1 'adTypeBinary
.Open
.LoadFromFile (PathToBinFile)

''Create empty stream object


With adoBin
.Mode = 3 'adModeReadWrite
.Type = 1 'adTypeBinary
.Open
End With

'copy first part of bytes (till start of 'DPB' value)


.Position = 0
.CopyTo adoBin, StartPosVal - 1

'copy new DPB value


adoBin.Write (PasswordArrayByte)

'copy remaining part of bytes (after 'DPB' value)


.Position = EndPosVal ''Set position to remaining part
.CopyTo adoBin

'save to file
adoBin.SaveToFile PathToBinFile, 2 'adSaveCreateOverWrite
adoBin.Close

.Close
End With

Set adoStream = Nothing


Set adoBin = Nothing
ChangeDPBValue = ""

End Function

'Sub Auto_Open()
'
''''Add ADO library if required---------------------------------------------
''ADOAssigned = False
''
''For i = 1 To ThisWorkbook.VBProject.References.Count
'' ''Debug.Print ThisWorkbook.VBProject.References.Item(i).Name
'' If ThisWorkbook.VBProject.References.Item(i).Name = "ADODB" Then
'' ADOAssigned = True
'' End If
''Next i
''
''If ADOAssigned = False Then
'' ThisWorkbook.VBProject.References.AddFromFile Environ("CommonProgramFiles") &
"\System\ado\msado15.dll"
''End If
'
'
'End Sub

S-ar putea să vă placă și