雖然VBA程序加了密碼使程序代碼不可見,但這也很容易被破解。網上一查,果然有一段VBA代碼寫了如何破解Excel里的VBA密碼。破解的方法是新建一個Excel文件,用開發工具創建一個模塊,只要把下面這段代碼寫到這個模塊里,然后打開待破解的帶宏程序的Excel文件,運行下面代碼中的PasswordCracking()方法,就可以把待破解的宏程序密碼去除。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
Private Sub RecoverBytes()
If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 12
End Sub
Private 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
Sub PasswordCracking()
If Hook Then
MsgBox "VBA Project password protection has been removed.", vbInformation, "Password Cracking"
Else
MsgBox "No encryption VBA Project found.", vbInformation, "Password Cracking"
End If
End Sub
對于solidworks的VBA程序也有其他工具可以輕松破解,無論是多長多復雜的密碼,都能輕松破解。為了保護程序代碼,必須另辟蹊徑,使用封裝DLL的方法可能是其中一個選擇。下面就以最簡單的實例說明如何制作dll文件,并在Excel里使用。首先,在Visual Studio里創建一個VB類庫項目,如下圖所示。注意選擇的是含有.NET Framework、VB和Windows這三個特征的那種類庫,不要選成“通用windows”類庫。項目名稱可使用默認的ClassLibrary1,當然也可以自行命名。
創建好項目后,程序自動打開項目,可在資源管理器里看到當前項目已自動創建了一個類Class1。右鍵選中這個Class1,刪除它。
在資源管理中再用右鍵選中項目名稱,選擇“添加”-->"類",在彈出的選項里選擇“COM類”,這時就自動創建了一個名為COMClass1的類,并自動生成了如下的代碼:<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)> _
Public Class ComClass1
#Region "COM GUID"
' 這些 GUID 提供此類的 COM 標識
' 及其 COM 接口。若更改它們,則現有的
' 客戶端將不再能訪問此類。
Public Const ClassId As String = "9bc632f6-cb98-40dd-809d-584ac35f7dd9"
Public Const InterfaceId As String = "09b8d875-d7b9-4531-9634-65b97fe76177"
Public Const EventsId As String = "3a401de1-af99-4f46-9347-c1fc9298a453"
#End Region
' 可創建的 COM 類必須具有一個不帶參數的 Public Sub New()
' 否則, 將不會在
' COM 注冊表中注冊此類,且無法通過
' CreateObject 創建此類。
Public Sub New()
MyBase.New()
End Sub
End Class
我們需要在這個類里添加自己的方法,但是不能刪除原有的代碼,下面添加一個方法Test,用于計算2個整數相加,代碼改成下面這樣:<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)> _
Public Class ComClass1
#Region "COM GUID"
' 這些 GUID 提供此類的 COM 標識
' 及其 COM 接口。若更改它們,則現有的
' 客戶端將不再能訪問此類。
Public Const ClassId As String = "9bc632f6-cb98-40dd-809d-584ac35f7dd9"
Public Const InterfaceId As String = "09b8d875-d7b9-4531-9634-65b97fe76177"
Public Const EventsId As String = "3a401de1-af99-4f46-9347-c1fc9298a453"
#End Region
' 可創建的 COM 類必須具有一個不帶參數的 Public Sub New()
' 否則, 將不會在
' COM 注冊表中注冊此類,且無法通過
' CreateObject 創建此類。
Public Sub New()
MyBase.New()
End Sub
Public Function Test(ByVal a As Integer, ByVal b As Integer) As Integer
Test = a + b
End Function
End Class
程序寫完后,在Visual Studio的主菜單里選擇“生成”-->"生成ClassLibrary1",(可能會要求以管理員身份打開Visual Studio才可以生成),ClassLibrary1是默認的項目名稱,根據你所取的項目名稱不同,這個子菜單名稱也會不同。此時在項目目錄下的bin\debug文件夾中就生成了ClassLibrary1.dll文件和ClassLibrary1.tlb文件。此時,新建一個Excel文件,打開開發工具,新建一個Visual Basic模塊,在編輯器的主菜單中選擇“工具”-->"引用"就可以看到ClassLibrary1已經被添加到引用里,勾選ClassLibrary1,如下圖。
Sub main()
Dim cls As New ComClass1
Debug.Print cls.Test(10, 20)
End Sub
至此,程序在本機運行完全沒問題了。但是把Excel保存成xlsm文件后復制到其它電腦運行,卻是報錯的。原因是找不到ClassLibrary1.tlb這個文件,即使我們把這個文件也復制過去,仍然是報錯,這是因為這個自定義的dll文件沒有在這臺電腦里注冊過。為什么在其它電腦沒注冊就不可以使用,在自己電腦同樣也沒注冊卻可以使用?這是因為在用Visual Studio編譯程序時,Visual Studio已經自動注冊了這個dll,這也是為什么要求用管理員身份運行Visual Studio才可以編譯程序的原因。那么在其它電腦該如何注冊dll文件呢。首先,要新建一個注冊批處理文件regist.bat,用記事本或其它文本編輯器在regist.bat里寫下如下代碼:set p=ClassLibrary1
set w=C:\Windows\
copy =%~dp0%p%.dll %w%%p%.dll
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe %w%%p%.dll /tlb:%w%%p%.tlb /codebase
pause
上面這段批處理文件的意思是,先將當前目錄下(%~dp0%就表示當前批處理文件所在目錄)的ClassLibrary1.dll文件復制到C:\windows\目錄下,然后調用C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe程序,注冊ClassLibrary1.dll文件,同時在C:\windows\里生成一個ClassLibrary1.tlb文件。批處理文件寫好后,把ClassLibrary1.dll文件和批處理文件regist.bat放在同一個文件夾里。用管理員身份運行regist.bat文件,完成dll文件注冊。此時再打開帶有宏程序的Excel文件,運行程序就不會再報錯了。
該文章在 2024/9/18 9:02:53 編輯過