探秘,64位Office VBA能否与VB6再续良缘?64位VB6能否继续躺赢?
长文告警,建议收藏后再阅读,谢谢。
前言
1、VBA已升64位,VBE环境还可编译DLL
64位VBA编译,大概就是这么个过程
很多接触过、听说过VBA的朋友,经常说VBA是解释执行的,没法编译,是离不开Office环境的。VBA虽然简单强大,但也只不过是Office的深阁闺秀而已,是羞于见人的。仿佛世界是公平的,让VBA满世界跑,那还得了。遇到VBA编译的话,多半会惊愕地问一句:VBA能编译?
其实,Office的VBE环境编译VBA代码为DLL,早已不是什么新鲜事。早在XP时代初期,微软就专门推出过Office的开发版,里面就包含了这些功能。但那时(本世纪初那会)售价近1000美刀,所以国内知道的人很少。
原理,大概是这样
笔者在前面的分享(《VBA可以编译吗?》)里也已介绍了一部分,但笔者当时是使用的32位Office,在WOW64的庇佑(遮掩)下,没感觉VB有什么障碍,对这个64位Office下的急迫性体会不是很深。所以,觉得VBE编译VBA没啥优势,更何况还是PCODE,不如使用VB6编译来得专业,毕竟VB工具链的分工就是这样的。
2、VB6IDE停更,64位编译无望,能否继续牵手Office,啃老Windows?
直到网友(VB领域的资深研究者)说没必要再研究VB,微软官方都已放弃。其他人这么说,权当是笑话,因为VB转向VBA又不是近5年或10年的事,而是26年前就定了的。所以这一次隐约感觉到里面有问题了,于是装了64位Office,来一探究竟,便有了《Office的VBE环境若能编译64位的DLL,VB6岂不是坐拥第二春?》。
尽管32位应用通过WOW64环境,得以在64位Windows上生存,甚至继续开发。但VB6编译的32位PE,不得不面临与其他64位PE之间的沟通交流的问题。微软官方那句"64位应用不能载入32位DLL,32位应用也不同载入64位DLL",让32位的VB6很是尴尬。
64位Office将VBA升级到了7.0,有了名符其实的64位真身,与其相关的一众对象(Dictionary、FileSystemObject、Encoder、Regexp等)所依赖的PE也有了64位版本。唯独VB6,微软官方信誓旦旦地说,别想了,不会再有了。
对,就是这段,太伤人了
早前便说了,VB6的真实身份是VBA,与Office喜结连理,也算一代功臣的功名所在。曾经VB6在指针(包括函数指针)、内联汇编、多线程、驱动等专业领域,不断被爱好者发掘扩展,不仅可以写正儿八经的企业应用(如用友),还能玩一手黑客炫技(如注入Hook)。现在,不带她玩了,看见64位就像老鼠见了猫,颜面何在?说好的VB代表着Windows的特色呢?
笔者曾经说VB/VBA里,CopyMemory不是VB里内存操作(常被广大VB/VBA人士用于指针操作)的最佳实现,更不是VB/VBA指针该有的样子。结果,连64的门槛儿都跨不过去,还吹个毛线?如果OfficeVBA能编译出64位DLL,尽管是PCODE,那意义也是非同凡响啊!
VBA编译的64位DLL,按照微软的说法,依然不能为VB6所用。但是,可以使用64位资源,以64位方式扩展64位Office,并且还能将扩展后的Office对象导出。这样,VB6就可以不费一枪一弹,继续啃老Windows,继续以躺赢的姿态供各位业余编程爱好者玩耍!不说这技术性能怎么样,光不需要继续加码学习,把精力用到更有价值的地方,想想都是很美好滴。
3、分享初衷促深入,一探究竟真学习
啥也不说了...
也有网友说大把优秀便捷的工具遍地都是,不必死抱VB不放。其实,这并非死抱(抱残守缺),作为BASIC衣钵传承的VB6,是一项伟大的历史遗产。其意义不仅在于天然适合编程的启蒙教育(由教育者设计用于计算机教学,解决计算机使用的高门槛问题,参考《VB前传,从教学到游戏,再到系统,似乎每步都是精心设计》),更在于为广大非IT人士提供了现代编程的『浅水区』。
所以国内计算机普及教育从早期的QBASIC到现在的VB6,都是这一系列的,那不是没有道理。更何况VB6与VBA如此之近,Office在民间办公领域又占据着统治地位。学习VB为日后踏入社会,步入工作岗位,提高效率还是蛮有帮助的。
对于业余编程人员,能够在极短时间,极少投入的情况下,尝鲜编程方式使用计算机,开启效率的全新模式,未尝不是件好事!对于编程爱好者而言,VB也是不可多得的好材料,通过学习借鉴VB内部的东西(往深里去,VB会像C一样,直奔系统底层而去),也会让自己的知识结构大为受益。
所以,探究VB6在64位下的正确打开方式,不仅能惠及广大VB/VBA人士,也能给那些研究32/64位兼容编程的人员提供些参考信息。作为非IT适用的编程技术框架分享者,笔者有必要在前几篇的基础上,图文并茂地再给大家伙分析分析。
一、64位VBA编译的DLL,堪用否?
在上篇中,按照图1编译出的DLL,笔者分析了其初步结构,不是很乐观。那本篇,继续分析其在64位Office上是否可以使用呢?毕竟WOW64兼容层能让32位匹配到64位,毕竟64位上的32位也只是忽悠人的另一方秘境之地。
是骡子是马,拉出去遛下不就知道了
赶紧打开心爱的Excel,Alt+F11进入VBE,引用待测试DLL,没报错,好迹象。写测试过程,智能提示和补全没问题,VBE能识别该DLL的接口,正如上图5、6所示,说明该DLL为COM组件。然后,在源码上下断点,准备F8逐行执行源码。
VB/VBA的这点好(源码级调试),就足以让人爱不释手。利用COM,其他开发工具都能实现VB/VBA这样的智能提示和代码补全,但要让源码逐句执行,随意在指定源码语句上下断点,直接在IDE中跟踪源码里变量的值,没有一个强大的解释器,肯定是不行的。
通观已有编码工具中,二进制编译型的就排除了,其他基于COM的,目前也唯有.NET有这个潜力,但是连VB.NET都前途未卜,所以目前来看VBA的解释器,微软不会轻言放弃,更不会轻易开源。微软为了迎合开源,于去年将GW-BASIC开源了。要知道,这货还是微软抱IBM大腿时期的产品,处理器还是808X。尽管开源社区呼呼开源其他型号CPU的BASIC解释器,但微软却明确表示Sorry,不能提供。
哎,没忍住,强吹了一波VB,不过笔者希望读者可以在自己的项目中,思考如何借鉴VB/VBA的这些特性。好了,来看看运行结果,与预期的差不多,不能创建自动化对象。
二、64位VBA编译出了32位DLL,为何不能用?
1、难道依赖MSVBVM60.DLL,成了祸首?
COM无疑,但VB6的运行库是个什么鬼?
在前篇《Office的VBE环境若能编译64位的DLL,VB6岂不是坐拥第二春?》中,分析了该DLL文件结构信息,如上图所示。和VB6编译的程序一样,导入模块只有MSVBVM60.DLL。这里也提一句安全方面的,如果没有那些针对VB的现成工具,VB程序对于逆向人员而言的确是一个不小的挑战。
但是为何VBA里为何会冒出VB6的运行库?在笔者以往虚拟机相关分享中,提到了VBA虽然与VB6同属一个体系,但二者的功能实现却是相互独立的。VBE编译并不需要VB6的编译器,这就更加确定VBE编译的DLL是PCODE。要实现编译还需要链接器,由于笔者没有Office的开发版,也不太清楚现在微软还有没有开发版(哪位有,可以提供给笔者进一步分析),所以借用了VB6的链接器,难道是链接器Link.exe在作祟?
要知道MSVBVM60.DLL虽然仍处于系统级支持,但在64位Windows上,只有32位版本。再加上微软官方的那句狠话,估计不会有64位的MSVBVM60.DLL了。这就又回到了老问题上,既然VBE编译的DLL为32位,那也不能用64位的MSVBVM60.DLL吧。所以,目前问题还不在MSVBVM60.DLL的版本上,而在于何时引入了MSVBVM60.DLL?
2、难道Link.exe除了组装外,还干了供应商的活儿?
链接器的原材料就是一堆OBJ文件,一种COFF结构的文件,源码早就编译好了。一般链接器按照PE结构,将这堆OBJ文件的内容,进行合并组装就完事了。按理Link.exe不会对代码进行动刀,自然也不会影响导入模块。为了一探究竟,有必要查看下OBJ文件的内容。
喏,一眼就看出来了
简单地用记事本打开编译过程中的OBJ,MSVBVM60.DLL已经赫然在列了,说明VBE在调用链接器前的编译阶段,就自有主张了,与链接器Link.exe并无关系。为了进一步说明上图中的问题,笔者将VBE中的代码用VB6编译为PCODE,来看下图:
有没有发现点什么?
没错,一旦编译,资源之间就有正儿八经的依赖关系,并且静态资源会在导入表中体现出来,而不是VBA依附于Office环境那样寄人篱下。同时也说明,VB6使用的Declare语句(API),只是向VB运行库进行声明,实际调用却是动态的,所以导入表中看不见其他库资源。所以,VB/VBA中使用Declare语句是一个运行时概念,效率自然没有静态编译的高了。这就是很多人鄙视VB6原因之一,实际上VB6默认不支持编译标准DLL的槽点,也该记到VB/VBA的Declare机制上。
从上图对比中还可以发现,从32位的VB6,到64位的VBA,指针从4字节变为8字节了。说明64位的VBA,期待的是64位MSVBVM60.DLL。看到这里,大家心里是不在犯嘀咕:散了吧,敢情半天,又是截图又是左顾右盼的,就讲了『VBA甩了VB6,单飞了?』讲爱情故事呢?
三、Windows终于给VB6断奶了?
没有64位的MSVBVM60.DLL,不能用熟悉的方式构建64位DLL了,就差临门一脚了,的确挺可惜的。不过别光顾着悲伤,请看《VB/VBA(代表32位)如何继续在64位Win上抖机灵(二)? 》。
64位Windows上的32位进程,是个伪货,人家可是正儿八经的64位进程。只不过系统会利用WOW64兼容层,隔离32与64位资源,才有32与64之分。这是一种简单粗暴,却行之有效的方法,也不是64位系统时的临时起意,而是当年16位向32位过渡时就想好了。
当64位Windows不能直接运行当年16位程序时,大家再次开始对Windows的兼容,担忧不已,认为不做切割舍弃,兼容的屎山就会压垮Windows。笔者以为,其实完全不是这样滴,兼容的真正压力在Intel那里,Windows这个前端表演者就是捡便宜的。事实上,64位Windows不能直接运行当年的16应用程序,除了依赖的库资源已发生变化外,更主要的是因为线程环境结构中,用于兼容的标志位被挪用给32位了。
而当大家去查微软官方文档时,会发现官网对WOW64轻描淡写道:这货是64位用户态实现。所以,作为用户态兼容层,WOW64也不可能跑到所谓32位核心态,不然逻辑就太扯了,屎山的推论更会塞满大街小巷。
既然同属用户态,又要作为兼容层,WOW64那一堆dll想要脱离进程机制(不到用户空间),以一种超然的方式存在,也不太可能。唯一正确的推论(无需专业知识),WOW64的64位dll与32位进程里的那堆dll,打得正火热呢!为毛系统能用,VB6就不能用呢?用户态还有什么见不得人的特权层?
显然不符合微软的宣传,也不符合众多安全工作者的反馈。所以VB6是可以使用WOW64机制,直接与64位DLL耍滴。既然如此,VB6没有64位版本,又会损失什么呢?当然可以继续躺着啃老Windows呀!
为什么,32位进程看不到WOW64那一堆dll呢?很多隐藏模块的方法可以看一看,链嘛,就是方便摘掉某个节点。既然32位看不见,也摸不着WOW64,64位进程又不用,要如何才能洞见玄机呢?
欢迎关注BtOfficer,更多精彩仍在继续,有严肃的技术,也有轻松的唠嗑,期待你的加入!