雖然VBA程序加了密碼使程序代碼不可見,但這也很容易被破解。網(wǎng)上一查,果然有一段VBA代碼寫了如何破解Excel里的VBA密碼。破解的方法是新建一個(gè)Excel文件,用開發(fā)工具創(chuàng)建一個(gè)模塊,只要把下面這段代碼寫到這個(gè)模塊里,然后打開待破解的帶宏程序的Excel文件,運(yùn)行下面代碼中的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
對(duì)于solidworks的VBA程序也有其他工具可以輕松破解,無(wú)論是多長(zhǎng)多復(fù)雜的密碼,都能輕松破解。為了保護(hù)程序代碼,必須另辟蹊徑,使用封裝DLL的方法可能是其中一個(gè)選擇。下面就以最簡(jiǎn)單的實(shí)例說明如何制作dll文件,并在Excel里使用。首先,在Visual Studio里創(chuàng)建一個(gè)VB類庫(kù)項(xiàng)目,如下圖所示。注意選擇的是含有.NET Framework、VB和Windows這三個(gè)特征的那種類庫(kù),不要選成“通用windows”類庫(kù)。項(xiàng)目名稱可使用默認(rèn)的ClassLibrary1,當(dāng)然也可以自行命名。
創(chuàng)建好項(xiàng)目后,程序自動(dòng)打開項(xiàng)目,可在資源管理器里看到當(dāng)前項(xiàng)目已自動(dòng)創(chuàng)建了一個(gè)類Class1。右鍵選中這個(gè)Class1,刪除它。
在資源管理中再用右鍵選中項(xiàng)目名稱,選擇“添加”-->"類",在彈出的選項(xiàng)里選擇“COM類”,這時(shí)就自動(dòng)創(chuàng)建了一個(gè)名為COMClass1的類,并自動(dòng)生成了如下的代碼:<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)> _
Public Class ComClass1
#Region "COM GUID"
' 這些 GUID 提供此類的 COM 標(biāo)識(shí)
' 及其 COM 接口。若更改它們,則現(xiàn)有的
' 客戶端將不再能訪問此類。
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
' 可創(chuàng)建的 COM 類必須具有一個(gè)不帶參數(shù)的 Public Sub New()
' 否則, 將不會(huì)在
' COM 注冊(cè)表中注冊(cè)此類,且無(wú)法通過
' CreateObject 創(chuàng)建此類。
Public Sub New()
MyBase.New()
End Sub
End Class
我們需要在這個(gè)類里添加自己的方法,但是不能刪除原有的代碼,下面添加一個(gè)方法Test,用于計(jì)算2個(gè)整數(shù)相加,代碼改成下面這樣:<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)> _
Public Class ComClass1
#Region "COM GUID"
' 這些 GUID 提供此類的 COM 標(biāo)識(shí)
' 及其 COM 接口。若更改它們,則現(xiàn)有的
' 客戶端將不再能訪問此類。
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
' 可創(chuàng)建的 COM 類必須具有一個(gè)不帶參數(shù)的 Public Sub New()
' 否則, 將不會(huì)在
' COM 注冊(cè)表中注冊(cè)此類,且無(wú)法通過
' CreateObject 創(chuàng)建此類。
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
程序?qū)懲旰?,在Visual Studio的主菜單里選擇“生成”-->"生成ClassLibrary1",(可能會(huì)要求以管理員身份打開Visual Studio才可以生成),ClassLibrary1是默認(rèn)的項(xiàng)目名稱,根據(jù)你所取的項(xiàng)目名稱不同,這個(gè)子菜單名稱也會(huì)不同。此時(shí)在項(xiàng)目目錄下的bin\debug文件夾中就生成了ClassLibrary1.dll文件和ClassLibrary1.tlb文件。此時(shí),新建一個(gè)Excel文件,打開開發(fā)工具,新建一個(gè)Visual Basic模塊,在編輯器的主菜單中選擇“工具”-->"引用"就可以看到ClassLibrary1已經(jīng)被添加到引用里,勾選ClassLibrary1,如下圖。
在Excel的模塊里寫下調(diào)用方法,如下:Sub main()
Dim cls As New ComClass1
Debug.Print cls.Test(10, 20)
End Sub
至此,程序在本機(jī)運(yùn)行完全沒問題了。但是把Excel保存成xlsm文件后復(fù)制到其它電腦運(yùn)行,卻是報(bào)錯(cuò)的。原因是找不到ClassLibrary1.tlb這個(gè)文件,即使我們把這個(gè)文件也復(fù)制過去,仍然是報(bào)錯(cuò),這是因?yàn)檫@個(gè)自定義的dll文件沒有在這臺(tái)電腦里注冊(cè)過。為什么在其它電腦沒注冊(cè)就不可以使用,在自己電腦同樣也沒注冊(cè)卻可以使用?這是因?yàn)樵谟肰isual Studio編譯程序時(shí),Visual Studio已經(jīng)自動(dòng)注冊(cè)了這個(gè)dll,這也是為什么要求用管理員身份運(yùn)行Visual Studio才可以編譯程序的原因。那么在其它電腦該如何注冊(cè)dll文件呢。首先,要新建一個(gè)注冊(cè)批處理文件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
上面這段批處理文件的意思是,先將當(dāng)前目錄下(%~dp0%就表示當(dāng)前批處理文件所在目錄)的ClassLibrary1.dll文件復(fù)制到C:\windows\目錄下,然后調(diào)用C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe程序,注冊(cè)ClassLibrary1.dll文件,同時(shí)在C:\windows\里生成一個(gè)ClassLibrary1.tlb文件。批處理文件寫好后,把ClassLibrary1.dll文件和批處理文件regist.bat放在同一個(gè)文件夾里。用管理員身份運(yùn)行regist.bat文件,完成dll文件注冊(cè)。此時(shí)再打開帶有宏程序的Excel文件,運(yùn)行程序就不會(huì)再報(bào)錯(cuò)了。
該文章在 2024/9/18 9:02:53 編輯過