VBA解析VBAProject 06——清除VBA工程密码
时间:2022-07-28
本文章向大家介绍VBA解析VBAProject 06——清除VBA工程密码,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
如果你收到过一些这样的Excel文件,文件里有VBA代码,实现了很好的功能,可是作者却对VBA工程进行了加密,你可能会非常希望查看到里面的VBA代码。
会想到的最直接的办法当然就是要到密码,可这个一般做不到,这个时候有什么办法能够查看VBA代码呢?
前面介绍的提取模块代码可以做到,这里再介绍一种直接清除密码的功能。
VBAProject工程里面,一定会有个数据流PROJECT,这个文件提取后,得到的内容大致如下:
ID="{7A581A9B-0F9A-480B-8C0A-1C59D52CAB04}"
Document=ThisWorkbook/&H00000000
Document=Sheet1/&H00000000
Module=MMain
Module=MTestStack
HelpFile=""
Name="vbapSpaceTest"
HelpContextID="0"
VersionCompatible32="393222000"
CMG="A4A64B844D9151915191519151"
DPB="B5B75AB77AC97BC97BC9"
GC="C6C429A22BA23DA33DA3C2"
[Host Extender Info]
&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000
[Workspace]
ThisWorkbook=0, 0, 0, 0, C
Sheet1=0, 0, 702, 415,
MMain=25, 25, 756, 571,
MTestStack=275, 275, 1435, 844, Z
VBAProject工程是否设置了密码,信息就保存在了这个数据流中,只需要把下面的内容清除掉就可以了:
CMG="A4A64B844D9151915191519151"
DPB="B5B75AB77AC97BC97BC9"
GC="C6C429A22BA23DA33DA3C2"
至于为什么可以看下官方的资料。
所以,知道了这样能够清除密码,我们要做的只是改写一个复合文档的数据流就可以了:
'清除vba工程密码
'清除CMG=" | DPB=" | GC="
'清除VBA工程密码
'Return 返回出错信息
Function UnProtectProject() As String
Dim ret As String
Dim b() As Byte
ret = cf.GetStream(PrePath & "PROJECT", b)
If VBA.Len(ret) Then
UnProtectProject = ret
Exit Function
End If
Dim strSrc As String
strSrc = VBA.StrConv(b, vbUnicode)
Dim arr(2) As String
arr(0) = "CMG="""
arr(1) = "DPB="""
arr(0) = "GC="""
Dim i As Long
Dim index As Long, index2 As Long
Dim strtmp As String
Dim flag As Boolean
flag = False
For i = 0 To 3 - 1
index = VBA.InStr(strSrc, arr(i))
If index Then
flag = True
index2 = VBA.InStr(index, strSrc, vbNewLine)
If index2 Then
strtmp = VBA.Mid$(strSrc, index, index2 - index + 2)
strSrc = VBA.Replace(strSrc, strtmp, "")
Else
UnProtectProject = "CVBAProject: UnProtectProject没有找到ODOA"
Exit Function
End If
End If
Next
If Not flag Then
UnProtectProject = "CVBAProject: 没有设置VBA工程密码"
Exit Function
End If
b = VBA.StrConv(strSrc, vbFromUnicode)
ret = cf.ReWriteStream(PrePath & "PROJECT", b)
If VBA.Len(ret) Then
UnProtectProject = ret
Exit Function
End If
End Function
另外再分享一种可以直接查看带密码的VBAProject的方法:
'复制内存
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
'该函数根据对话框模板资源创建一个模态的对话框。在显示对话框之前,函数把一个应用程序定义的值作为WM_INITDIALOG消息的IParam参数传到对话框过程,应用程序可用此值来初始化对话框控制。
'Private Declare Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As Long, hDialogTemplate As DLGTEMPLATE, ByVal hWndParent As Long, ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) 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() '若已经Hook,则恢复原API开头的6字节,也就是恢复原来函数的功能
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
'VBE6.dll调用DialogBoxParamA显示VB6INTL.dll资源中的第4070号对话框(就是输入密码的窗口)
'若DialogBoxParamA返回值非0,则VBE会认为密码正确,所以我们要hook DialogBoxParamA函数
pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")
'标准api hook过程之一:修改内存属性,使其可写
If VirtualProtect(ByVal pFunc, 6, &H40, OriginProtect) <> 0 Then
'标准api hook 过程之二:判断是否已经hook,看看API的第一个字节是否为&H68
'若是则说明已经hook
MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6
If TmpBytes(0) <> &H68 Then
'标准api hook 过程之三:保存原函数开头字节,这里是6个字节,以备后面恢复
MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6
'用Addresof获取MyDialogBoxParam,这里我们写一个函数
'GetPtr作用仅仅是返回Addressof MyDialogBoxParam的值,从而实现将
'MyDialogBoxParam的地址赋给p的目的
p = GetPtr(AddressOf MyDialogBoxParam)
'标准的api hook过程之四:组装API入口的新代码
'HookBytes组成如下汇编
'push MyDialogBoxParam的地址
'ret
'作用是跳转到MyDialogBoxParam函数
HookBytes(0) = &H68
MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4
HookBytes(5) = &HC3
''标准的api hook过程之五:用HookBytes的内容改写API前6个字节
MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6
'设置hook成功标准
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
'有程序调用DialogBoxParamA装入4070号对话框,这里就我们直接返回1,让VBE以为密码正确了
MyDialogBoxParam = 1
Else
'有程序调用DialogBoxParamA,但装入的不是4070号对话框,这里我们调用RecoverBytes函数恢复原来函数的功能,再进行原来的函数
RecoverBytes
MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, hWndParent, lpDialogFunc, dwInitParam)
'原来的函数执行完毕,再次hook
Hook
End If
End Function
这个是在网上看到的,至于原理其实不大理解。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 带权树 -- 哈夫曼树,与它的那张哈夫曼编码表
- 【python-动态规划】0-1背包问题
- python之列表推导和生成器表达式
- 二叉树的前中后序遍历
- 【tensorflow2.0】处理结构化数据-titanic生存预测
- 【pandas】pandas中的常见函数
- 走进STL - 哈希表,散装称重么
- 第八届蓝桥杯省赛javaB组题目解析
- 拥抱STL - 类/结构体元素查询与排序
- 【tensorflow2.0】处理图片数据-cifar2分类
- 操作系统实验多线程编程中的读者优先和写者优先
- 【python】使用csv库以字典格式读写csv文件
- 基于TypeScript封装Axios笔记(八)
- springmvc之HttpMessageConverter<T>
- django-模板之静态文件加载(十四)