我被要求更新一些Excel 2003宏,但是VBA项目受到密码保护,而且似乎缺乏文档...没有人知道密码。
有没有一种方法可以删除或破解VBA项目的密码?
你可以尝试这种不需要进行十六进制编辑的直接 VBA
方法。它适用于任何文件(*.xls, *.xlsm, *.xlam ...)。
经测试可用于:
Excel 2007
Excel 2010
Excel 2013 - 32位版本
Excel 2016 - 32位版本
想要64位版本?请参考这个答案。
工作原理
我将尽力解释它的工作原理,请原谅我的英文。
- VBE(Visual Basic Editor)会调用一个系统函数来创建密码对话框。
- 如果用户输入正确的密码并点击确定,该函数返回1。如果用户输入错误的密码或点击取消,该函数返回0。
- 对话框关闭后,VBE检查系统函数的返回值。
- 如果返回值为1,VBE会"认为"密码正确,因此被锁定的VBA项目将被打开。
- 下面的代码使用用户自定义函数与原始函数的内存进行交换,当调用该函数时,它将始终返回1。
使用代码
请先备份您的文件!
- 打开包含锁定的VBA项目的文件。
- 创建一个新的xlsm文件,并将以下代码存储在Module1中。
代码由Siwtom(昵称),一位越南开发者创作
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项目已取消保护!", vbInformation, "\*\*\*\*\*"
End If
End Sub
- 返回到您的VBA项目并享用吧。