Visual Basic 写的软件天生就有致命的弱点...
一开始万里千山,一层层阻隔,可是到了后边就有太彰显了,让人抓个正着了!
这与Virual Basic等等一些基于带虚拟库的应用程序构价有大关系...
Virual Basic程序是基于对象程序设计,它没有实现语言层的中的多态,可是在其调用的内部方法,事件,接口却的确存在这多态与继承的封装,它就是COM组件模型,和C++对象模型,Object Pascl对象模型极其类似,只不过它是二进制下实现的多态,其他是语言下c++等无论在语言层次还是底层二进制层次都实现了Call指令的多态虚拟环境...
不多说了,
下边分析一下,注意:Virual Basic COM接口多态与PE IAT动态共享连接不同,VB接口是封装在VM动台库中,正是VBVM与tlb类型库实现了VB等类似脚本语言的多态调用,而IAT动态连接,多个程序可以共享一个系统函数接口,是与PEloader来实现的.而VB COM接口是在应用程序客户端与服务器端的一个约定,比如:接口定义文件约定IDL,和TLB类型库等...
========================================
下边看看VB接口中的SEH机制,和VB COM对象的生成,方法的调用.
第一:SEH
=============Visual Basic事件塑造新SEH机制指针=============
055DF20 55 push ebp
0055DF21 8BEC mov ebp, esp
0055DF23 83EC 0C sub esp, 0C //分配栈内存构造SEH新机制
0055DF26 68 46274000 push <jmp.&MSVBVM60.__vbaExceptHandle>//准备新SEH对首指针进栈,vbaExceptHandle变量储存在SEH入口调用.
0055DF2B 64:A1 00000000 mov eax, fs:[0] //把SEH异常首管理指针给eax,下边要进行替换,因为vb的每一个事件都是基于COM自动化接口方式调用,所以每调用一个COM接口事件,都先建立新的SEH狂架,为了程序异常报告错误!
0055DF31 50 push eax //原来的SEH指针压栈!
0055DF32 64:8925 0000000>mov fs:[0], esp //到这里新的一个事件新的SEH构造了,为以后程序异常扫平道路.
第二:对象构造与生成和对象接口引用与里边的IAT方法调用,
(注意我们这里是(Button实例方法Click事件,不如Form)
===Visual Basic对象实例(一个COM对象或说一个COM接口实例)初始化====
0055DF39 83EC 20 sub esp, 20 //这是VB程序局部变量用的栈分配给对象接口用.
0055DF3C 53 push ebx //ebx=1 //下边程序开始构造对象了...
0055DF3D 56 push esi //esi=0012F5E4
0055DF3E 57 push edi //esi=0012F5E4
0055DF3F 8965 F4 mov [ebp-C], esp
//esp=0012F4C8 Stack ss:[0012F4FC]=00F63A60
0055DF42 C745 F8 E026400>mov dword ptr [ebp-8], 004026E0//对象用到了一个常量...
0055DF49 8B7D 08 mov edi, [ebp+8] //0017A7E1 注意这个参数很奇特,看看我们VB客户程序存根如何与虚拟服务库调用产生的一个约定,这里它是用[ebp+8]来引用的Button对象,现在它还没有实际的意义,要等到下边调用服务器对象类厂方法才能实现真正的一个COM对象,那样才有意义...
0055DF4C 8BC7 mov eax, edi
0055DF4E 83E0 01 and eax, 1
0055DF51 8945 FC mov [ebp-4], eax
0055DF54 83E7 FE and edi, FFFFFFFE //到这里才计算出真正意义的接口实例,edi就是我们com对象,它只向对象首地址也就是QueryInterface方法指针,它是实现检索所有com接口的方法...
0055DF57 57 push edi //保存对象指针
0055DF58 897D 08 mov [ebp+8], edi //看到了么?注意与上边想呼应,[ebp+8]变量是对象引用指针传递约定的地址, 而EDI是保存VB COM对象虚拟指针表另一个局部变量它生存期短,[ebp+8]是客户与服务器约定在我们这个程序里,其他程序不一定啊,要看怎么约定了它生存期长.
0055DF5B 8B0F mov ecx, [edi] //这里把edicom对象指针赋值与ecx变量,这时候ecx也指向com对象的收指针方法:QueryInterFasce
0055DF5D FF51 04 call [ecx+4] //大家看到这一行明白了吧:ecx+4正是com对象二进制的约定也是c++,object pascl对象的约定,而ecx+4是指向了对象的另一个多态方法:AddRef(),很有名气的方法吧,它实现com对象生存期自我管理方法,与dll生存管理期类次,与c++等不同.
0055DF60 8B17 mov edx, [edi]
0055DF62 33C0 xor eax, eax
0055DF64 57 push edi
0055DF65 8945 E8 mov [ebp-18], eax
0055DF68 8945 E4 mov [ebp-1C], eax
0055DF6B FF92 04030000 call [edx+304]
//想必大家对这个edx+304接口指针也能理解了吧...都是二进制的约定嘛!可惜微软没有公开它是哈函数接口,只好硬着头皮分析了...
0055DF71 8B1D 3C104000 mov ebx, [<&MSVBVM60.__vbaObjSet>] ; MSVBVM60.__vbaObjSet
//注意这个vbaObjSet是IAT方法,把它的指针传给ebx变量了.
0055DF77 50 push eax
0055DF78 8D45 E4 lea eax, [ebp-1C]
0055DF7B 50 push eax
0055DF7C FFD3 call ebx
//调用这个vbaObjSet一个对象,这是什么对象呢?看下边:
0055DF7E 8BF0 mov esi, eax
//通过eax把对象指针传进来,给esi变量...
0055DF80 8D55 E8 lea edx, [ebp-18]
0055DF83 52 push edx //注意这个收取我们输入字符串的缓冲区,当然现在还没有具体的数值要等到下边放可...
0055DF84 56 push esi//引用对象指针压栈
0055DF85 8B0E mov ecx, [esi]//对象指针压堆栈.看看与上边对象方法调用雷同吧,绝对雷同,这就是微软定的标准吧,谁可以改恐怕是billgate了
0055DF87 FF91 A0000000 call [ecx+A0] ======//又来一个,大家看到了吧,这个是获得Edit组件文本内容的com虚拟指针...,事先也不知道,看了它的返回值才知道当它把我输入的字符串key赋值给[ebp-18]变量引用的时候才知道,这就是微软的阴险,我反复几次才知道,这中组件方式的调试真麻烦稍微不留身就跑了,你分不起那里是出口,那里是入口,而且大部分都是栈桢切换...
0055DF8D 85C0 test eax, eax
0055DF8F DBE2 fclex //对我输入的字符变量做益出检查
0055DF91 7D 12 jge short 0055DFA5//对就跳,错就check.
0055DF93 68 A0000000 push 0A0
0055DF98 68 B8864100 push 004186B8
0055DF9D 56 push esi
0055DF9E 50 push eax
0055DF9F FF15 28104000 call [<&MSVBVM60.__vbaHresultCheckObj>; //对输入近来的字符串进行位数检测,看看是否是益出了,vbaHresultCheckObj这个函数是从IAT调用入的,非COM指针转进来的.
0055DFA5 8B45 E8 mov eax, [ebp-18]//终于到这里相互照应起来,我输入的字符串' "qiweisue",近来比较了...
0055DFA8 50 push eax
0055DFA9 68 CC864100 push 004186CC ; UNICODE "791225"
0055DFAE FF15 60104000 call [<&MSVBVM60.__vbaStrCmp>] ; //VB程序最大的弱点明码比较.大家看到了吧.如果把它换成COM指针函数,估计就费点劲头!客户与服务器约定大庞大,稍微就会飞掉了,因为VB程序传参数需要大量切换栈内存,要不是把注册号输入的长,否则找就找不到北,还有这个函数也是够明显,够帅的,,,人家作者没有这么傻这只是demo版本的...正式版本需要去买.
================================
到这里 over了,后边剩下的,就是清理堆栈里边的对象和对象接口的引用...
也很好分析了,全部贴上来,给大家比较全面的vb com对象构造与引用,当然底层的存根屏蔽不少细节,还需要自己慢慢挖掘了...
0055DFB4 8BF0 mov esi, eax
0055DFB6 8D4D E8 lea ecx, [ebp-18]
0055DFB9 F7DE neg esi
0055DFBB 1BF6 sbb esi, esi
0055DFBD 46 inc esi
0055DFBE F7DE neg esi
0055DFC0 FF15 D8104000 call [<&MSVBVM60.__vbaFreeStr>] ; MSVBVM60.__vbaFreeStr
0055DFC6 8D4D E4 lea ecx, [ebp-1C]
0055DFC9 FF15 DC104000 call [<&MSVBVM60.__vbaFreeObj>] ; MSVBVM60.__vbaFreeObj
0055DFCF 66:85F6 test si, si
0055DFD2 0F84 AB000000 je 0055E083
0055DFD8 A1 10F05500 mov eax, [55F010]
0055DFDD 85C0 test eax, eax
0055DFDF 75 15 jnz short 0055DFF6
0055DFE1 68 10F05500 push 0055F010
0055DFE6 68 505B4100 push 00415B50
0055DFEB FF15 94104000 call [<&MSVBVM60.__vbaNew2>] ; MSVBVM60.__vbaNew2
0055DFF1 A1 10F05500 mov eax, [55F010]
0055DFF6 8B08 mov ecx, [eax]
0055DFF8 50 push eax
0055DFF9 FF91 FC020000 call [ecx+2FC]
0055DFFF 8D55 E4 lea edx, [ebp-1C]
0055E002 50 push eax
0055E003 52 push edx
0055E004 FFD3 call ebx
0055E006 8BF0 mov esi, eax
0055E008 6A 00 push 0
0055E00A 56 push esi
0055E00B 8B06 mov eax, [esi]
0055E00D FF50 5C call [eax+5C]
0055E010 85C0 test eax, eax
0055E012 DBE2 fclex
0055E014 7D 0F jge short 0055E025
0055E016 6A 5C push 5C
0055E018 68 DC864100 push 004186DC
0055E01D 56 push esi
0055E01E 50 push eax
0055E01F FF15 28104000 call [<&MSVBVM60.__vbaHresultCheckObj>; MSVBVM60.__vbaHresultCheckObj
0055E025 8B1D DC104000 mov ebx, [<&MSVBVM60.__vbaFreeObj>] ; MSVBVM60.__vbaFreeObj
0055E02B 8D4D E4 lea ecx, [ebp-1C]
0055E02E FFD3 call ebx
0055E030 A1 74FD5500 mov eax, [55FD74]
0055E035 85C0 test eax, eax
0055E037 75 10 jnz short 0055E049
0055E039 68 74FD5500 push 0055FD74
0055E03E 68 98A54100 push 0041A598
0055E043 FF15 94104000 call [<&MSVBVM60.__vbaNew2>] ; MSVBVM60.__vbaNew2
0055E049 8B35 74FD5500 mov esi, [55FD74]
0055E04F 8D4D E4 lea ecx, [ebp-1C]
0055E052 57 push edi
0055E053 51 push ecx
0055E054 8B16 mov edx, [esi]
0055E056 8955 CC mov [ebp-34], edx
0055E059 FF15 48104000 call [<&MSVBVM60.__vbaObjSetAddref>] ; MSVBVM60.__vbaObjSetAddref
0055E05F 8B55 CC mov edx, [ebp-34]
0055E062 50 push eax
0055E063 56 push esi
0055E064 FF52 10 call [edx+10]
0055E067 85C0 test eax, eax
0055E069 DBE2 fclex
0055E06B 7D 0F jge short 0055E07C
0055E06D 6A 10 push 10
0055E06F 68 88A54100 push 0041A588
0055E074 56 push esi
0055E075 50 push eax
0055E076 FF15 28104000 call [<&MSVBVM60.__vbaHresultCheckObj>; MSVBVM60.__vbaHresultCheckObj
0055E07C 8D4D E4 lea ecx, [ebp-1C]
0055E07F FFD3 call ebx
0055E081 EB 4F jmp short 0055E0D2
0055E083 A1 74FD5500 mov eax, [55FD74]
0055E088 85C0 test eax, eax
0055E08A 75 10 jnz short 0055E09C
0055E08C 68 74FD5500 push 0055FD74
0055E091 68 98A54100 push 0041A598
0055E096 FF15 94104000 call [<&MSVBVM60.__vbaNew2>] ; MSVBVM60.__vbaNew2
0055E09C 8B35 74FD5500 mov esi, [55FD74]
0055E0A2 8D45 E4 lea eax, [ebp-1C]
0055E0A5 57 push edi
0055E0A6 50 push eax
0055E0A7 8B1E mov ebx, [esi]
0055E0A9 FF15 48104000 call [<&MSVBVM60.__vbaObjSetAddref>] ; MSVBVM60.__vbaObjSetAddref
0055E0AF 50 push eax
0055E0B0 56 push esi
0055E0B1 FF53 10 call [ebx+10]
0055E0B4 85C0 test eax, eax
0055E0B6 DBE2 fclex
0055E0B8 7D 0F jge short 0055E0C9
0055E0BA 6A 10 push 10
0055E0BC 68 88A54100 push 0041A588
0055E0C1 56 push esi
0055E0C2 50 push eax
0055E0C3 FF15 28104000 call [<&MSVBVM60.__vbaHresultCheckObj>; MSVBVM60.__vbaHresultCheckObj
0055E0C9 8D4D E4 lea ecx, [ebp-1C]
0055E0CC FF15 DC104000 call [<&MSVBVM60.__vbaFreeObj>] ; MSVBVM60.__vbaFreeObj
0055E0D2 C745 FC 0000000>mov dword ptr [ebp-4], 0
0055E0D9 68 F4E05500 push 0055E0F4
0055E0DE EB 13 jmp short 0055E0F3
0055E0E0 8D4D E8 lea ecx, [ebp-18]
0055E0E3 FF15 D8104000 call [<&MSVBVM60.__vbaFreeStr>] ; MSVBVM60.__vbaFreeStr
0055E0E9 8D4D E4 lea ecx, [ebp-1C]
0055E0EC FF15 DC104000 call [<&MSVBVM60.__vbaFreeObj>] ; MSVBVM60.__vbaFreeObj
0055E0F2 C3 retn
0055E0F3 C3 retn
0055E0F4 8B45 08 mov eax, [ebp+8]
0055E0F7 50 push eax
0055E0F8 8B08 mov ecx, [eax]
0055E0FA FF51 08 call [ecx+8]
0055E0FD 8B45 FC mov eax, [ebp-4]
0055E100 8B4D EC mov ecx, [ebp-14]
0055E103 5F pop edi
0055E104 5E pop esi
0055E105 64:890D 0000000>mov fs:[0], ecx
0055E10C 5B pop ebx
0055E10D 8BE5 mov esp, ebp
0055E10F 5D pop ebp
0055E110 C2 0400 retn 4
=======================
这是个一个全部的事件调用,里边有com对象构造与引用,方法接口的调用,等
也许你会问一个问题:那么这个方法是IAT嘛,肯定不是,那它是com接口指针调用过来的么嘛,正确了!那谁调用的,答案是:
EVENT_SINK_QueryInterface
EVENT_SINK_Release
EVENT_SINK2_AddRef
===父接口
EVENT_SINK_GetIDsOfNames
EVENT_SINK_Invoke
===自动化接口
给出这个例子是com事件接口方法,与它里边调用的com接口方法有些不同,它是靠:
EVENT_SINK_GetIDsOfNames
EVENT_SINK_Invoke
调用的.正是靠这一个"自动化"实现了动态联编...这不是多态么的体现么!
==========================
末了:
注册编码:791225,明码比较,
删除注册表里边的key,否则就over了.谢谢!!!
有误之处,大狭指点.
版权www.pediy.com
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!