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