1,486
社区成员
发帖
与我相关
我的任务
分享
Set oXL = CreateObject("Excel.Application")
,再在DLL里面运行上面那段代码,发现启动的Excel不具备解锁项目的功能。Option Explicit
Private Declare Sub CopyMemory Lib "Kernel32" Alias "RtlMoveMemory" ( _
ByRef Dest As Any, _
ByRef Sour As Any, _
ByVal Size As Long)
Private Declare Function VirtualProtect Lib "Kernel32" ( _
ByVal lpAddress As Long, _
ByVal dwSize As Long, _
ByVal flNewProtect As Long, _
ByRef lpflOldProtect As Long) As Long
Private Declare Function GetModuleHandleW Lib "Kernel32" ( _
ByVal lpModuleName As Long) 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 "DialogBoxParamW" ( _
ByVal hInstance As Long, _
ByVal pTemplateName As Long, _
ByVal hWndParent As Long, _
ByVal lpDialogFunc As Long, _
ByVal dwInitParam As Long) As Long
Private mlFlag As Long
Private Function FreeProtect() As Long
If (mlFlag) Then
FreeProtect = 1&
Else
FreeProtect = HookAPI()
End If
End Function
Private Function GetPtr(ByVal Value As Long) As Long
GetPtr = Value
End Function
Private Function HookAPI() As Long
Dim arrBuff(5) As Byte
Dim hModule As Long
Dim lpFunc As Long
Dim lRetVal As Long
Dim p&, w As Long
lRetVal = vbTrue
hModule = GetModuleHandleW(StrPtr("user32.dll"))
lpFunc = GetProcAddress(hModule, "DialogBoxParamA")
If (0& = VirtualProtect(ByVal lpFunc, 6&, &H40, w)) Then GoTo E_FinalExit
Call CopyMemory(arrBuff(0&), ByVal lpFunc, 1&)
If (&H68 = arrBuff(0)) Then
lRetVal = 1&
Else
p = GetPtr(AddressOf MyDialogBoxParam)
Call CopyMemory(arrBuff(1&), p, 4&)
arrBuff(0) = &H68
arrBuff(5) = &HC3
Call CopyMemory(ByVal lpFunc, arrBuff(0&), 6&)
lRetVal = vbFalse
mlFlag = vbTrue
End If
Call VirtualProtect(ByVal lpFunc, 6&, w, 0&)
E_FinalExit:
HookAPI = lRetVal
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 Long
If (4070& = pTemplateName) Then
MyDialogBoxParam = 1&
Else
MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, hWndParent, lpDialogFunc, dwInitParam)
End If
End Function
此处共4个函数,其中 FreeProtect( ) 是导出函数,其它3个只是辅助函数(不导出的)。
调用FreeProtect( ) 操作成功返回0、操作失败返回-1;
如果“已经成功执行”后再次(或多次)被调用,则返回值是1(当然你也可以改为其它值)。
这段代码,编译成“标准dll”只用于VBA环境中调用; 若在其它环境中使用则不保证“安全性”。
Option Explicit
' DLL文件路径,按“实际情况”写,才能保存正常加载。
' 否则,可能只有放到System32(或SysWOW64)中,才能“省略路径”。
Private Declare Function FreeProtect Lib "E:\Temp\VBA.dll" () As Long
Private Sub Main()
Select Case FreeProtect()
Case 0&: Debug.Print "“密码保护”解除操作成功。"
Case 1&: Debug.Print "“密码保护”已经成功解除了。"
Case Else: Debug.Print "操作失败……" ' 返回值 = -1
End Select
End Sub
3. “操作成功”后,查看带“密码保护VBA工程”的代码时,已经不用输入密码了。
当然,这个dll没有写“还原”的接口,因此只能“退出Excel时才关闭”那个“新建文档”。 否则,会造成Excel崩溃。
(因为“关闭”时,dll释放了,而HOOK没有还原,会造成非法内存访问。)