我们都知道当数据过多的时候,我们制作Excel图表就会显得非常的复杂,图表上面的内容就会特别多。Excel老玩家就会想到用切片器制作动态可变化的图表来显示。今天我们就来学习一下一个比......
2023-01-08
网络上的一段代码,代码里运用APIHook来绕过VBA的密码保护机制,在VBE中可以直接查看加密的VBA工程而不需要密码验证。今天有空,对原作者代码做了一定的修改,使其可以运行于64位的Office之上,完美支持32和64位Office。
具体代码如下:
'***************************************************************************
'*
'*MODULENAME:ProtectedVBAprojectPicklock(PVP)
'*AUTHOR&DATE:tt.t
'*23April2007
'*ModifiedByMarsWang
'*www.office26.com
'*E-Mail:ttui(AT)163.com,sohu邮箱垃圾邮件太多已经不用了
'*
'*Usage:运行FrmHookMain窗口,点补丁,然后双击工程窗口中有密码保护的模块
'*应该能够直接打开了:)
'*
'*
'*DESCRIPTION:在写中文字符串转换为拼音函数(HzToPy)过程中,第一次发现VBA功能的强大.
'*于是这次尝试将其他语言中比较好写的APIHOOK移植成VBA代码,
'*正好顺便把VBA密码保护去掉,喜欢加密码的朋友不要生气啊:)
'*总的来说VBA的写法和其他语言区别不大,但VBA毕竟不太方便,代码必须放在标准模块中.
'*再有就是对指针的支持实在有限,于是最后选择了一种写起来最简单的APIhook方法,
'*就是所谓的陷阱法.如果你不太清楚什么是APIHOOK,请求助于google.
'*
'*Theory:这里就不说APIhook的方法了,都是传统方法没什么可说的,这里只
'*简单说下VBA模块密码解除.其实这些我也不是很了解,毕竟知道加密过程
'*用处不大,这个问题上我比较关心结果:)
'*判断有密码以及提示输入密码都是VBE6.dll干得好事.如果有密码,
'*VBE6.dll会调用DialogBoxParamA显示VB6INTL.dll资源中的第4070号
'*对话框(就是那个输入密码的窗口),若DialogBoxParamA返回值非0,
'*则VBE会认为密码正确,然后乖乖展开加密模块的资源.很显然其中存在很大
'*漏洞,就像给日记本加上了锁,但里面全是活页,我们不需要打开锁,只要从侧面
'*取出活页就可以了.这个从侧面取活页的过程就是hook住DialogBoxParamA函数,
'*若程序调用DialogBoxParamA装入4070号对话框,我们就直接返回1,让
'*VBE以为密码正确.
'*
'*PS:PVP是在一个叫AdvancedVBAPasswordRecovery(AVPR)的软件启发下
'*作出来的,AVPR提供了一个VBABackdoor功能就是跳过密码直接查看工程资源.
'*它的原理和PVP一样,但用了通用性比较差的方法,适用系统比较有限,而PVP的方法
'*理论上适用于所有采用第4070号对话框录入密码的Office系统.
'*
'*
'***************************************************************************
OptionExplicit
DimHookBytes(0To5)AsByte
DimOriginBytes(0To5)AsByte
DimFlagAsBoolean
#IfWin64Then
DimpFuncAsLongPtr
PrivateDeclarePtrSafeSubMoveMemoryLib"kernel32"Alias"RtlMoveMemory"_
(DestinationAsAny,SourceAsAny,ByValLengthAsLongPtr)
PrivateDeclarePtrSafeFunctionVirtualProtectLib"kernel32"(lpAddressAsAny,_
ByValdwSizeAsLongPtr,ByValflNewProtectAsLong,lpflOldProtectAsLong)AsLong
PrivateDeclarePtrSafeFunctionGetModuleHandleALib"kernel32"(ByVallpModuleNameAsString)AsLongPtr
PrivateDeclarePtrSafeFunctionGetProcAddressLib"kernel32"(ByValhModuleAsLongPtr,_
ByVallpProcNameAsString)AsLongPtr
PrivateDeclarePtrSafeFunctionDialogBoxParamLib"user32"Alias"DialogBoxParamA"(ByValhInstanceAsLongPtr,_
ByValpTemplateNameAsLong,ByValhWndParentAsLongPtr,_
ByVallpDialogFuncAsLongPtr,ByValdwInitParamAsLongPtr)AsLong
PrivateFunctionGetPtr(ByValValueAsLongPtr)AsLongPtr
'获得函数的地址
GetPtr=Value
EndFunction
#Else
DimpFuncAsLong
PrivateDeclareSubMoveMemoryLib"kernel32"Alias"RtlMoveMemory"_
(DestinationAsLong,SourceAsLong,ByValLengthAsLong)
PrivateDeclareFunctionVirtualProtectLib"kernel32"(lpAddressAsLong,_
ByValdwSizeAsLong,ByValflNewProtectAsLong,lpflOldProtectAsLong)AsLong
PrivateDeclareFunctionGetModuleHandleALib"kernel32"(ByVallpModuleNameAsString)AsLong
PrivateDeclareFunctionGetProcAddressLib"kernel32"(ByValhModuleAsLong,_
ByVallpProcNameAsString)AsLong
PrivateDeclareFunctionDialogBoxParamLib"user32"Alias"DialogBoxParamA"(ByValhInstanceAsLong,_
ByValpTemplateNameAsLong,ByValhWndParentAsLong,_
ByVallpDialogFuncAsLong,ByValdwInitParamAsLong)AsInteger
PrivateFunctionGetPtr(ByValValueAsLong)AsLong
'获得函数的地址
GetPtr=Value
EndFunction
#EndIf
PublicSubRecoverBytes()
'若已经hook,则恢复原API开头的6字节,也就是恢复原来函数的功能
IfFlagThenMoveMemoryByValpFunc,ByValVarPtr(OriginBytes(0)),6
EndSub
PublicFunctionHook()AsBoolean
DimTmpBytes(0To5)AsByte
#IfWin64Then
DimpAsLongPtr
#Else
DimpAsLong
#EndIf
DimOriginProtectAsLong
Hook=False
'VBE6.dll调用DialogBoxParamA显示VB6INTL.dll资源中的第4070号对话框(就是输入密码的窗口)
'若DialogBoxParamA返回值非0,则VBE会认为密码正确,所以我们要hookDialogBoxParamA函数
pFunc=GetProcAddress(GetModuleHandleA("user32.dll"),"DialogBoxParamA")
'标准apihook过程之一:修改内存属性,使其可写
IfVirtualProtect(ByValpFunc,6,&H40,OriginProtect)<>0Then
'标准apihook过程之二:判断是否已经hook,看看API的第一个字节是否为&H68,
'若是则说明已经Hook
MoveMemoryByValVarPtr(TmpBytes(0)),ByValpFunc,6
IfTmpBytes(0)<>&H68Then
'标准apihook过程之三:保存原函数开头字节,这里是6个字节,以备后面恢复
MoveMemoryByValVarPtr(OriginBytes(0)),ByValpFunc,6
'用AddressOf获取MyDialogBoxParam的地址
'因为语法不允许写成p=AddressOfMyDialogBoxParam,这里我们写一个函数
'GetPtr,作用仅仅是返回AddressOfMyDialogBoxParam的值,从而实现将
'MyDialogBoxParam的地址付给p的目的
p=GetPtr(AddressOfMyDialogBoxParam)
'标准apihook过程之四:组装API入口的新代码
'HookBytes组成如下汇编
'pushMyDialogBoxParam的地址
'ret
'作用是跳转到MyDialogBoxParam函数
HookBytes(0)=&H68
MoveMemoryByValVarPtr(HookBytes(1)),ByValVarPtr(p),4
HookBytes(5)=&HC3
'标准apihook过程之五:用HookBytes的内容改写API前6个字节
MoveMemoryByValpFunc,ByValVarPtr(HookBytes(0)),6
'设置hook成功标志
Flag=True
Hook=True
EndIf
EndIf
EndFunction
PrivateFunctionMyDialogBoxParam(ByValhInstanceAsLong,_
ByValpTemplateNameAsLong,ByValhWndParentAsLong,_
ByVallpDialogFuncAsLong,ByValdwInitParamAsLong)AsInteger
IfpTemplateName=4070Then
'有程序调用DialogBoxParamA装入4070号对话框,这里我们直接返回1,让
'VBE以为密码正确了
MyDialogBoxParam=1
Else
'有程序调用DialogBoxParamA,但装入的不是4070号对话框,这里我们调用
'RecoverBytes函数恢复原来函数的功能,在进行原来的函数
RecoverBytes
MyDialogBoxParam=DialogBoxParam(hInstance,pTemplateName,_
hWndParent,lpDialogFunc,dwInitParam)
'原来的函数执行完毕,再次hook
Hook
EndIf
EndFunction
相关文章
我们都知道当数据过多的时候,我们制作Excel图表就会显得非常的复杂,图表上面的内容就会特别多。Excel老玩家就会想到用切片器制作动态可变化的图表来显示。今天我们就来学习一下一个比......
2023-01-08
在工作中,可能许多朋友都会碰到一个情况,那就是工作簿和工作表数据的合并操作。如何将上百个工作簿快速合并到一个表格中,许多朋友可能会觉得不可思议。今天我们就来教大家学习一......
2023-01-08
今天在这里为你分享5个Excel文本函数,这些拆分和组合函数,你一定会用上的。①LEFT函数公式:=LEFT(A2,1)在Excel表格中,需要想要拆分汉字,想从哪里开始就从那哪里开始。首先选定单元格......
2023-01-08
相信大家也和我一样,才开始看到Excel可以当做翻译软件的时候会很好奇,这究竟是怎样做到的?其实,这个方法并不是很难,它是由一个函数公式而制作出来的,好了,首先我们一起来看看成......
2023-01-08
函数可以说是所用快捷方法中最为简单的一种方法,为什么很多人认为函数用起来很难了?主要是因为它拥有很长的函数公式,记不住。其实不管是学Excel函数,还是学习其他的一些快捷方法......
2023-01-08