我被要求更新一些Excel 2003宏,但是VBA项目有密码保护,而且似乎缺乏文档…没人知道密码。
是否有一种方法可以删除或破解VBA项目的密码?
我被要求更新一些Excel 2003宏,但是VBA项目有密码保护,而且似乎缺乏文档…没人知道密码。
是否有一种方法可以删除或破解VBA项目的密码?
当前回答
删除VBA项目密码的一个简单方法是执行以下操作:
将xlsm文件转换为zip 打开VBAProject.bin文件(我更喜欢使用notepad++ (https://notepad-plus-plus.org/downloads/)) 搜索DPB字段 用DPx替换它 保存文件 将zip文件转换为XLSM 打开excel文件 如果出现消息框,请单击“是” 为VBA项目属性设置新密码 关闭并再次打开该文件 输入新密码取消保护
其他回答
保护是Excel中的一个简单的文本比较。 在你最喜欢的调试器中加载Excel (Ollydbg是我选择的工具),找到进行比较的代码并将其修复为总是返回true,这应该可以让你访问宏。
是的,只要你使用的是。xls格式的电子表格(2003年以前Excel的默认格式)。对于Excel 2007以后,默认是.xlsx,这是一个相当安全的格式,这个方法将不起作用。
正如Treb所说,这是一个简单的比较。一种方法是使用十六进制编辑器(参见Windows的十六进制编辑器)简单地交换文件中的密码条目。循序渐进的例子:
Create a new simple excel file. In the VBA part, set a simple password (say - 1234). Save the file and exit. Then check the file size - see Stewbob's gotcha Open the file you just created with a hex editor. Copy the lines starting with the following keys: CMG=.... DPB=... GC=... FIRST BACKUP the excel file you don't know the VBA password for, then open it with your hex editor, and paste the above copied lines from the dummy file. Save the excel file and exit. Now, open the excel file you need to see the VBA code in. The password for the VBA code will simply be 1234 (as in the example I'm showing here).
如果你需要使用Excel 2007或2010,下面有一些其他的答案可能会有帮助,特别是这些:1、2、3。
编辑2015年2月:另一种看起来很有前途的方法,看看Đức Thanh nguy的新答案。
编辑:这是已接受答案的更新版本,应该适用于更多的办公室版本。这很难,但让我们把这个答案说出来吧!
轮到我了,这是建立在kaybee99的优秀答案之上的,它建立在Đức Thanh nguykun的出色答案之上,允许这种方法与32/64位版本的Office一起工作。
概览一下更改的内容,我们避免了push/ret,它仅限于32位地址,并将其替换为mov/jmp reg。
它是如何工作的
Open the file(s) that contain your locked VBA Projects. Create a new file with the same type as the above 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 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 Paste this code in Module2 and run it Sub unprotected() If Hook Then MsgBox "VBA Project is unprotected!", vbInformation, "*****" End If End Sub
Colin Pickard has an excellent answer, but there is one 'watch out' with this. There are instances (I haven't figured out the cause yet) where the total length of the "CMG=........GC=...." entry in the file is different from one excel file to the next. In some cases, this entry will be 137 bytes, and in others it will be 143 bytes. The 137 byte length is the odd one, and if this happens when you create your file with the '1234' password, just create another file, and it should jump to the 143 byte length.
如果您尝试将错误的字节数粘贴到文件中,当您尝试用Excel打开该文件时,您将丢失VBA项目。
EDIT
这对Excel 2007/2010文件无效。标准的。xlsx文件格式实际上是一个。zip文件,包含许多子文件夹,其中格式、布局、内容等存储为xml数据。对于未受保护的Excel 2007文件,只需将.xlsx扩展名更改为.zip,然后打开zip文件并查看所有xml数据。这很简单。
但是,当您对Excel 2007文件进行密码保护时,整个.zip (.xlsx)文件实际上是使用RSA加密进行加密的。不再可以将扩展名更改为.zip并浏览文件内容。
对于Excel 2007,您需要将文件扩展名更改为。zip 在存档中有一个子文件夹xl,在那里你会发现vbaProject.bin。 使用vbaProject.bin执行上面的步骤,然后将其保存回存档中。 修改回您的扩展名和voilà!(意思是遵循上面的步骤)