我被要求更新一些Excel 2003宏,但是VBA项目受密码保护,而且似乎缺少文档...没人知道密码。
有没有办法删除或破解VBA项目上的密码?
我被要求更新一些Excel 2003宏,但是VBA项目受密码保护,而且似乎缺少文档...没人知道密码。
有没有办法删除或破解VBA项目上的密码?
Answers:
您可以尝试这种VBA
不需要十六进制编辑的直接方法。它适用于任何文件(* .xls,*。xlsm,*。xlam ...)。
经过测试并适用于:
Excel 2007
Excel 2010
Excel 2013-32位版本
Excel 2016-32 位版本
寻找64位版本?看到这个答案
我会尽力解释它的工作原理-请原谅我的英语。
请先备份您的文件!
创建一个新的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
将此代码粘贴到Module1中的上述代码下并运行
Sub unprotected()
If Hook Then
MsgBox "VBA Project is unprotected!", vbInformation, "*****"
End If
End Sub
回到您的VBA项目并享受。
是的,只要您使用.xls
格式电子表格即可(Excel的默认设置是2003年)。对于Excel 2007及更高版本,默认值为.xlsx
,这是一种相当安全的格式,该方法将不起作用。
正如Treb所说,这是一个简单的比较。一种方法是使用十六进制编辑器简单地换出文件中的密码条目(请参阅Windows的十六进制编辑器)。分步示例:
复制以以下键开头的行:
CMG=....
DPB=...
GC=...
第一次备份您不知道VBA密码的excel文件,然后使用十六进制编辑器将其打开,然后从虚拟文件中粘贴以上复制的行。
如果您需要使用Excel 2007或2010年的工作,也有一些其他的答案在下面这可能帮助,特别是这些:1,2,3。
编辑 2015年2月:对于另一种看似很有希望的方法,请看ĐứcThanhNguyễn的新答案。
CMG...
字符串比原始字符串长,则可以安全地增加文件的长度。
我基于ĐứcThanhNguyễn的绝妙答案,允许该方法与64位版本的Excel一起使用。我在64位Windows 7上运行Excel 2010 64位。
创建一个新的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
将此代码粘贴到Module2中并运行
Sub unprotected()
If Hook Then
MsgBox "VBA Project is unprotected!", vbInformation, "*****"
End If
End Sub
免责声明这对我有用,我已在此处记录了此文档,希望对您有所帮助。我还没有完全测试它。在继续此选项之前,请确保保存所有打开的文件。
还有另一种(稍微容易些)解决方案,没有大小问题。我今天(在使用Excel 2007的2003 XLS文件上)使用了这种方法,并且成功了。
DPB=...
零件DPB=...
字符串更改为DPx=...
*注意:请确保已将密码更改为新值,否则下次打开电子表格Excel时将报告错误(意外错误),然后在访问VBA模块列表时,现在将看到源模块,但在尝试打开表格/代码/等时收到另一个错误。要解决此问题,请返回到VBA项目属性,然后将密码设置为新值。保存并重新打开Excel文档,您应该一切顺利!
科林·皮卡德(Colin Pickard)有一个很好的答案,但是对此有一个“警惕”。在某些情况下(我还没有找到原因),文件中“ CMG = ........ GC = ....”条目的总长度与一个excel文件不同。下一个。在某些情况下,该条目将为137个字节,在其他情况下将为143个字节。137个字节的长度是奇数,如果在使用“ 1234”密码创建文件时发生这种情况,则只需创建另一个文件,它应跳至143个字节的长度。
如果尝试将错误数量的字节粘贴到文件中,则尝试使用Excel打开文件时,将丢失VBA项目。
编辑
这对于Excel 2007/2010文件无效。标准.xlsx文件格式实际上是.zip文件,其中包含许多子文件夹,这些子文件夹的格式,布局,内容等均以xml数据存储。对于不受保护的Excel 2007文件,您可以将.xlsx扩展名更改为.zip,然后打开zip文件并浏览所有xml数据。非常简单。
但是,当您用密码保护Excel 2007文件时,整个.zip(.xlsx)文件实际上是使用RSA加密进行加密的。不再可能将扩展名更改为.zip并浏览文件内容。
对于.xlsm
或.dotm
文件类型,您需要使用稍微不同的方法。
.xlsm
文件扩展名更改为.zip
。vbaProject.bin
文件并在Hex编辑器中打开它(我使用HxD,它完全免费且轻巧。)DPB
并替换为DPx
并保存文件。vbaProject.bin
文件替换为压缩文件中的新文件。.xlsm
。.xlsm
文件。值得指出的是,如果您有Excel 2007(xlsm)文件,则可以将其另存为Excel 2003(xlsm)文件,并使用其他答案中概述的方法。
1.
将.xlsm转换为.xls会2.
破解.xls 的代码3.
将.xlsm转换为.xlsx会将4.
代码从.xls中的模块放入。 xlsx并将其另存为.xlsm
轮到我了,这是基于kaybee99的出色答案而建立的,它基于ĐứcThanhNguyễn的出色答案,使该方法可以同时用于x86和amd64版本的Office。
关于更改的概述,我们避免将push / ret限制为32位地址,而将其替换为mov / jmp reg。
经过测试并在
Word / Excel 2016-32 位版本。
Word / Excel 2016-64位版本。
怎么运行的
创建与上述类型相同的新文件,并将此代码存储在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 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
将此代码粘贴到Module2中并运行
Sub unprotected()
If Hook Then
MsgBox "VBA Project is unprotected!", vbInformation, "*****"
End If
End Sub
如果您的
CMG="XXXX"\r\nDPB="XXXXX"\r\nGC="XXXXXX"
您的“已知密码”文件中的块比“未知密码”文件中的现有块短,请用尾随的零填充十六进制字符串以达到正确的长度。
例如
CMG="xxxxxx"\r\nDPB="xxxxxxxx"\r\nGC="xxxxxxxxxx"
在未知的密码文件中,应设置为
CMG="XXXX00"\r\nDPB="XXXXX000"\r\nGC="XXXXXX0000"
保留文件长度。
我在Office 2007中也使用.XLA(97/2003格式)文件。
从Excel 2007开始,您需要将文件扩展名更改为.zip。在存档中,有一个子文件夹xl,在该文件夹中将找到vbaProject.bin。对vbaProject.bin执行上述步骤,然后将其保存回存档中。修改回您的扩展名和名字!(表示按照上述步骤操作)
可以轻松删除 Access,Excel,Powerpoint或Word文档(2007, 2010, 2013 or 2016
带有扩展名的版本.ACCDB .XLSM .XLTM .DOCM .DOTM .POTM .PPSM
)上的VBA项目密码。
只需将文件扩展名更改为.ZIP
,解压缩文件并使用任何基本的十六进制编辑器(例如XVI32)即可。)来“破解”现有密码,这会使Office感到“混乱”,因此下次文件被提示时提示输入新密码。开了
.ZIP
扩展名。ZIP
并转到XL
文件夹。vbaProject.bin
并使用十六进制编辑器将其打开DPB
为DPX
。.bin
文件放回zip,将其恢复为普通扩展名,然后像正常一样打开文件。VBA Project Properties
。Protection
选项卡上,设置新密码。OK
,关闭文件,重新打开它,然后按ALT + F11。此时,您可以选择完全删除密码。
我在YouTube上提供了我制作的“时光倒流”的分步视频的完整说明。
令人震惊的是,这种解决方法已经存在多年了,而Microsoft尚未解决此问题。
这个故事的主旨?
为了保护任何敏感信息的安全,请不要依赖 Microsoft Office VBA Project密码。如果安全性很重要,请使用第三方加密软件。
Colin Pickard大多数情况下是正确的,但是不要将整个文件的“打开密码”保护与VBA密码保护混淆,后者与前者完全不同,并且与Office 2003和2007相同(对于Office 2007,重命名将该文件保存为.zip,并在zip文件中查找vbaProject.bin。从技术上讲,编辑文件的正确方法是使用OLE复合文档查看器(如CFX)打开正确的流。当然,如果您只是替换字节,那么普通的旧二进制编辑器可能会起作用。
顺便说一句,如果您想知道这些字段的确切格式,请立即进行记录:
http://msdn.microsoft.com/zh-cn/library/dd926151%28v=office.12%29.aspx
我尝试了上面的一些解决方案,但没有一个适合我(excel 2007 xlsm文件)。然后,我发现了另一个甚至可以检索密码的解决方案,而不仅仅是破解它。
将此代码插入模块,运行它并花一些时间。它将通过蛮力恢复您的密码。
Sub PasswordBreaker()
'Breaks worksheet password protection.
Dim i As Integer, j As Integer, k As Integer
Dim l As Integer, m As Integer, n As Integer
Dim i1 As Integer, i2 As Integer, i3 As Integer
Dim i4 As Integer, i5 As Integer, i6 As Integer
On Error Resume Next
For i = 65 To 66: For j = 65 To 66: For k = 65 To 66
For l = 65 To 66: For m = 65 To 66: For i1 = 65 To 66
For i2 = 65 To 66: For i3 = 65 To 66: For i4 = 65 To 66
For i5 = 65 To 66: For i6 = 65 To 66: For n = 32 To 126
ActiveSheet.Unprotect Chr(i) & Chr(j) & Chr(k) & _
Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & Chr(i3) & _
Chr(i4) & Chr(i5) & Chr(i6) & Chr(n)
If ActiveSheet.ProtectContents = False Then
MsgBox "One usable password is " & Chr(i) & Chr(j) & _
Chr(k) & Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & _
Chr(i3) & Chr(i4) & Chr(i5) & Chr(i6) & Chr(n)
Exit Sub
End If
Next: Next: Next: Next: Next: Next
Next: Next: Next: Next: Next: Next
End Sub
汤姆(Tom)-我最初是因为出现了一个男生错误,因为我没有看到字节大小,而是从“ CMG”设置中复制并粘贴到后续条目。但是,这是两个文件之间的两种不同的文本大小,就像Stewbob警告的那样,我丢失了VBA项目。
使用HxD,有一个计数器跟踪您选择的文件数量。从CMG开始复制,直到计数器读取8F(十六进制为143),然后粘贴到锁定文件时也是如此-我最终在粘贴末尾添加了两倍于“ ...”的数字,看起来有点奇怪,几乎感觉到了不自然,但确实有效。
我不知道它是否很关键,但是在重新在Excel中打开文件之前,我确保关闭了十六进制编辑器并关闭了excel。然后,我不得不浏览菜单以打开VB编辑器,进入VBProject属性,然后输入“新”密码来解锁代码。
我希望这有帮助。
对于Windows 10计算机上的Excel 2016 64位,我使用了十六进制编辑器来更改受保护的xla的密码(尚未针对任何其他扩展名对此进行测试)。 小费:在执行此操作之前,请创建备份。
我采取的步骤:
希望对您有所帮助!
您的excel文件的扩展名更改为xml。并在记事本中打开它。密码文本可在xml文件中找到。
您会看到下面的线条;
Sheets("Sheet1").Unprotect Password:="blabla"
(对不起,我的英语不好)
如果您在工作,Java
可以尝试一下VBAMacroExtractor
。从中提取VBA脚本后,.xlsm
我发现那里的密码是纯文本的。