我被要求更新一些Excel 2003宏,但是VBA项目有密码保护,而且似乎缺乏文档…没人知道密码。
是否有一种方法可以删除或破解VBA项目的密码?
我被要求更新一些Excel 2003宏,但是VBA项目有密码保护,而且似乎缺乏文档…没人知道密码。
是否有一种方法可以删除或破解VBA项目的密码?
当前回答
您可以尝试这种不需要HEX编辑的直接VBA方法。它将适用于任何文件(*.xls, *.xls, *.xls)。xlsm, *。xlam……)。
测试和工作:
Excel 2007 Excel 2010 Excel 2013 - 32位版本 Excel 2016 - 32位版本
寻找64位版本?请看这个答案
它是如何工作的
我会尽我最大的努力解释它是如何工作的-请原谅我的英语。
The VBE will call a system function to create the password dialog box. If user enters the right password and click OK, this function returns 1. If user enters the wrong password or click Cancel, this function returns 0. After the dialog box is closed, the VBE checks the returned value of the system function if this value is 1, the VBE will "think" that the password is right, hence the locked VBA project will be opened. The code below swaps the memory of the original function used to display the password dialog with a user defined function that will always return 1 when being called.
使用代码
请先备份您的文件!
Open the file(s) that contain your locked VBA Projects Create a new xlsm file and store this code in 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 Paste this code under the above code in Module1 and run it Sub unprotected() If Hook Then MsgBox "VBA Project is unprotected!", vbInformation, "*****" End If End Sub Come back to your VBA Projects and enjoy.
其他回答
万一你的街区 没有发生= \ r \ nDPB“XXXX”=“XXXXX”\ r \ nGC =“XXXXXX” 如果您的“已知密码”文件比“未知密码”文件中的现有块短,请用后面的零填充十六进制字符串以达到正确的长度。
e.g.
CMG=“xxxxxx”\r\nDPB=“xxxxx”\r\nGC=“xxxxx”
在未知密码文件中,应设置为
CMG="XXXX00"\r\nDPB="XXXXX000"\r\nGC="XXXXXX0000"保留文件长度。
我在office 2007中也使用过。xla(97/2003格式)文件。
对于Windows 10机器上的Excel 2016 64位,我使用了十六进制编辑器来更改受保护的xla的密码(尚未对任何其他扩展进行测试)。 提示:在执行此操作之前创建备份。
我采取的步骤:
在十六进制编辑器中打开vba(例如XVI) 搜索这个DPB 将DPB更改为其他内容,如DPX 保存它! 重新打开.xla,将出现一条错误消息,继续。 您现在可以通过打开属性并转到password选项卡来更改.xla的密码。
我希望这对你们中的一些人有所帮助!
我基于Đức Thanh nguynun的精彩回答,让这种方法适用于64位版本的Excel。我在64位的Windows 7上运行Excel 2010 64位。
Open the file(s) that contain your locked VBA Projects. Create a new xlsm file and store this code in 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 Paste this code in Module2 and run it Sub unprotected() If Hook Then MsgBox "VBA Project is unprotected!", vbInformation, "*****" End If End Sub
这对我来说很有效,我在这里记录了它,希望它能帮助别人。我还没有完全测试过。请确保在继续此选项之前保存所有打开的文件。
如果该文件是一个有效的zip文件(前几个字节是504b——用于.xlsm等格式),那么解压缩该文件并查找子文件xl/vbaProject.bin。这是一个CFB文件,就像.xls文件一样。按照XLS格式的说明(应用于子文件),然后压缩内容。
对于XLS格式,您可以使用本文中的其他一些方法。我个人更喜欢搜索DPB=块并替换文本
CMG="..."
DPB="..."
GC="..."
有空格。这样就避免了CFB容器大小的问题。
Access、Excel、Powerpoint或Word文档上的VBA项目密码(带有扩展名. accdb . xlsm . xltm . docm . dotm . potm . ppsm的2007、2010、2013或2016版本)可以轻松删除。
这只是将文件名扩展名更改为. zip,解压缩文件,并使用任何基本的十六进制编辑器(如XVI32)来“打破”现有密码的问题,这会“混淆”Office,因此它会在下次打开文件时提示输入新密码。
步骤总结:
rename the file so it has a .ZIP extension. open the ZIP and go to the XL folder. extract vbaProject.bin and open it with a Hex Editor "Search & Replace" to "replace all" changing DPB to DPX. Save changes, place the .bin file back into the zip, return it to it's normal extension and open the file like normal. ALT+F11 to enter the VB Editor and right-click in the Project Explorer to choose VBA Project Properties. On the Protection tab, Set a new password. Click OK, Close the file, Re-open it, hit ALT+F11. Enter the new password that you set.
此时,如果您愿意,您可以完全删除密码。
完整的说明和我制作的“way back when”视频在YouTube上。
令人震惊的是,这种解决方法已经存在多年了,而微软还没有解决这个问题。
这个故事的寓意是什么?
Microsoft Office VBA项目密码不依赖于任何敏感信息的安全。如果安全性很重要,请使用第三方加密软件。