solly 发表于 2019-7-31 18:44

160 个 CrackMe 之 101 - Acid_Cool_178.4(VB6 Native)VB事件处理的分析和增删改!

本帖最后由 solly 于 2019-8-3 08:19 编辑

160 个 CrackMe 之 101 -- Acid_Cool_178.4 是一个 VB6 编译的原生程序,破解相对简单,但破解不是本文重点,本文重点在于对 VB 表单及控件的事件进行分析,并对事件进行增加,删除或修改等。


第一部分    脱壳和破解


当然,我们还是把这个 CrackMe 破解了再説。先看看文件信息,如下所示:

有壳,先脱壳,用 OD 载入,如下图所示,可用 ESP 定律脱壳:

利用 ESP 定律,很快就可以来到 OEP,如下图所示,可以看到,这是一个 VB6 编译的程序:

这时候可以进行脱壳,用 OD 直接脱壳好象不能运行,我们使用 LordPE 1.6 脱壳,“用管理员身份”启动 LordPE 进行脱壳:

在 loadPE 中直接 Dump full... 即可,保存脱壳后的程序,然后运行脱壳后程序,其界面如下所示:

包括两个窗口,一个主界面窗口,一个背景窗口。


首先,对于 VB 程序,用 VB Decompiler 反编译看看,看看有哪些表单、控件,以及事件等信息。


上图是展开了全部事件的情况,Form4 有一个函数,没有事件。其它表单都有事件,没有函数。


先看看 CrackMe 的 Info,是一个破解説明,提示你要完成破解的两个任务:
1、使文本框可以输入字母通过 check;
2、去除 NAG。


关闭信息对话框,会重新返回主界面,这次点“Task1”,界面如下:

如果你在文本框中输入纯数字,点“Check”时,数字不会被清空,一直在文本框内。
但如果你的输入中包含非数字字母或标点等,点“Check”时,文本框就会被清空,CrackMe 的 Task1 就是要去除这个限制,输入任何内容都不会清空。


在 VB Decompiler 中,我们可以找到这个功能是在 Form1 中。在 Form1 的 Command1 按钮Click 事件中进行检查的,如下图所示:

如上图,我们直接来看看其事件处理函数,该函数的代码如下所示:
;==========去除输入非数字字符时,会清空输入内容的限制 ==================================================
; TASK1:
0042ED80    55               push    ebp
0042ED81    8BEC               mov   ebp, esp
0042ED83    83EC 0C            sub   esp, 0C
0042ED86    68 36114000      push    <jmp.&MSVBVM60.__vbaExceptHandler>
0042ED8B    64:A1 00000000   mov   eax, dword ptr fs:
0042ED91    50               push    eax
0042ED92    64:8925 00000000   mov   dword ptr fs:, esp
0042ED99    83EC 30            sub   esp, 30
0042ED9C    53               push    ebx
0042ED9D    56               push    esi
0042ED9E    57               push    edi
0042ED9F    8965 F4            mov   dword ptr , esp
0042EDA2    C745 F8 A0104000   mov   dword ptr , 004010A0
0042EDA9    8B75 08            mov   esi, dword ptr
0042EDAC    8BC6               mov   eax, esi
0042EDAE    83E0 01            and   eax, 1
0042EDB1    8945 FC            mov   dword ptr , eax
0042EDB4    83E6 FE            and   esi, FFFFFFFE
0042EDB7    56               push    esi
0042EDB8    8975 08            mov   dword ptr , esi
0042EDBB    8B0E               mov   ecx, dword ptr
0042EDBD    FF51 04            call    dword ptr
0042EDC0    8B16               mov   edx, dword ptr
0042EDC2    33C0               xor   eax, eax
0042EDC4    56               push    esi
0042EDC5    8945 E8            mov   dword ptr , eax
0042EDC8    8945 E4            mov   dword ptr , eax
0042EDCB    8945 D4            mov   dword ptr , eax
0042EDCE    FF92 00030000      call    dword ptr
0042EDD4    8B1D 28104000      mov   ebx, dword ptr [<&MSVBVM60.__vbaObjS>; MSVBVM60.__vbaObjSet
0042EDDA    50               push    eax
0042EDDB    8D45 E4            lea   eax, dword ptr
0042EDDE    50               push    eax
0042EDDF    FFD3               call    ebx
0042EDE1    8BF8               mov   edi, eax
0042EDE3    8D55 E8            lea   edx, dword ptr
0042EDE6    52               push    edx
0042EDE7    57               push    edi
0042EDE8    8B0F               mov   ecx, dword ptr
0042EDEA    FF91 A0000000      call    dword ptr                    ; GetDlgText()
0042EDF0    85C0               test    eax, eax
0042EDF2    DBE2               fclex
0042EDF4    7D 12            jge   short 0042EE08
0042EDF6    68 A0000000      push    0A0
0042EDFB    68 10BB4200      push    0042BB10
0042EE00    57               push    edi
0042EE01    50               push    eax
0042EE02    FF15 1C104000      call    dword ptr [<&MSVBVM60.__vbaHresultCh>; MSVBVM60.__vbaHresultCheckObj
0042EE08    8B45 E8            mov   eax, dword ptr
0042EE0B    C745 E8 00000000   mov   dword ptr , 0
0042EE12    8945 DC            mov   dword ptr , eax
0042EE15    8D45 D4            lea   eax, dword ptr
0042EE18    50               push    eax
0042EE19    C745 D4 08000000   mov   dword ptr , 8
0042EE20    FF15 40104000      call    dword ptr [<&MSVBVM60.#561>]         ; 调用 MSVBVM60.rtcIsNumeric() 判断输入的字符串是否数字
0042EE26    66:8BF8            mov   di, ax                               ; 标志
0042EE29    8D4D E4            lea   ecx, dword ptr
0042EE2C    F7D7               not   edi                                  ; 取反
0042EE2E    FF15 94104000      call    dword ptr [<&MSVBVM60.__vbaFreeObj>] ; MSVBVM60.__vbaFreeObj
0042EE34    8D4D D4            lea   ecx, dword ptr
0042EE37    FF15 08104000      call    dword ptr [<&MSVBVM60.__vbaFreeVar>] ; MSVBVM60.__vbaFreeVar
0042EE3D    66:85FF            test    di, di                               ; 检查标志(patch 这里为:xor di, di)
0042EE40    74 41            je      short 0042EE83                     ; 纯数字则跳转(也可以patch 这里为 jmp 0x0042EE83)
0042EE42    8B0E               mov   ecx, dword ptr
0042EE44    56               push    esi
0042EE45    FF91 00030000      call    dword ptr
0042EE4B    8D55 E4            lea   edx, dword ptr
0042EE4E    50               push    eax
0042EE4F    52               push    edx
0042EE50    FFD3               call    ebx
0042EE52    8BF0               mov   esi, eax
0042EE54    68 24BB4200      push    0042BB24                            ; 空串
0042EE59    56               push    esi
0042EE5A    8B06               mov   eax, dword ptr
0042EE5C    FF90 A4000000      call    dword ptr                   ; SetDlgText(""),当输入不是纯数字时清空文本框
0042EE62    85C0               test    eax, eax
0042EE64    DBE2               fclex
0042EE66    7D 12            jge   short 0042EE7A
0042EE68    68 A4000000      push    0A4
0042EE6D    68 10BB4200      push    0042BB10
0042EE72    56               push    esi
0042EE73    50               push    eax
0042EE74    FF15 1C104000      call    dword ptr [<&MSVBVM60.__vbaHresultCh>; MSVBVM60.__vbaHresultCheckObj
0042EE7A    8D4D E4            lea   ecx, dword ptr
0042EE7D    FF15 94104000      call    dword ptr [<&MSVBVM60.__vbaFreeObj>] ; MSVBVM60.__vbaFreeObj
0042EE83    C745 FC 00000000   mov   dword ptr , 0
0042EE8A    68 AEEE4200      push    0042EEAE
0042EE8F    EB 1C            jmp   short 0042EEAD
0042EE91    8D4D E8            lea   ecx, dword ptr
0042EE94    FF15 98104000      call    dword ptr [<&MSVBVM60.__vbaFreeStr>] ; MSVBVM60.__vbaFreeStr
0042EE9A    8D4D E4            lea   ecx, dword ptr
0042EE9D    FF15 94104000      call    dword ptr [<&MSVBVM60.__vbaFreeObj>] ; MSVBVM60.__vbaFreeObj
0042EEA3    8D4D D4            lea   ecx, dword ptr
0042EEA6    FF15 08104000      call    dword ptr [<&MSVBVM60.__vbaFreeVar>] ; MSVBVM60.__vbaFreeVar
0042EEAC    C3               retn
0042EEAD    C3               retn
0042EEAE    8B45 08            mov   eax, dword ptr
0042EEB1    50               push    eax
0042EEB2    8B08               mov   ecx, dword ptr
0042EEB4    FF51 08            call    dword ptr
0042EEB7    8B45 FC            mov   eax, dword ptr
0042EEBA    8B4D EC            mov   ecx, dword ptr
0042EEBD    5F               pop   edi
0042EEBE    5E               pop   esi
0042EEBF    64:890D 00000000   mov   dword ptr fs:, ecx
0042EEC6    5B               pop   ebx
0042EEC7    8BE5               mov   esp, ebp
0042EEC9    5D               pop   ebp
0042EECA    C2 0400            retn    4

关键代码是一个调用:MSVBVM60.rtcIsNumeric(),通过这个函数,判断输入的字符串是否是一个纯数字字符串,因此 Patch 也很简单,如下图所示:

直接将 0x0042EE3D 处的指令 testdi, di 改成 xordi, di 就可以了。再输入非数字字符,点“Check"也不会将文本框清空了。如下所示:

这样 patch 一下,第一个任务完成。

第 2 个任务是去除 NAG,在主界面上点"Task2",首先弹出一个 NAG 窗口,如下图所示:

点”Move On“后,会关闭 NAG 窗口,打开另一个窗口:

表示没有其它 NAG 了,就是前面一个 NAG 窗口需要移除。

再次来到 VB Decompiler,可以看到,在主界面显示 NAG 窗口 Form3,Form3 再显示 Form4,要去除 NAG,只要在主界面的事件中直接显示 Form4,跳过 Form3 即可。下图是主界面显示 Form3:


我们到 OD 中看看显示 Form3 的代码,如下图所示:

具体代码如下所示(关键部分):
0042F261|> \A1 4C004300         mov   eax, dword ptr
0042F266|.85C0                test    eax, eax
0042F268|.75 10               jnz   short 0042F27A
0042F26A|.68 4C004300         push    0043004C
0042F26F|.68 74B04200         push    0042B074
0042F274|.FF15 68104000       call    dword ptr [<&MSVBVM60.__vbaNew2>]               ;MSVBVM60.__vbaNew2
0042F27A|>83EC 10             sub   esp, 10
0042F27D|.B9 0A000000         mov   ecx, 0A
0042F282|.8BDC                mov   ebx, esp
0042F284|.894D DC             mov   dword ptr , ecx
0042F287|.B8 04000280         mov   eax, 80020004
0042F28C|.83EC 10             sub   esp, 10
0042F28F|.890B                mov   dword ptr , ecx
0042F291|.8B4D D0             mov   ecx, dword ptr
0042F294|.8BD0                mov   edx, eax
0042F296|.8B35 4C004300       mov   esi, dword ptr

再看看 Nag 窗口对 Form4 的显示:

在 OD 看看代码如下所示:

然后,我们将主界面上对 Form3 的引用和操作,全部改成 Form4 的即可,如下图所示:

具体改动后的代码如下,共 4 个位置有改动:
0042F261    A1 4C004300   mov   eax, dword ptr                 ;改成对变量 的引用
0042F266    85C0            test    eax, eax
0042F268    75 10         jnz   short 0042F27A
0042F26A    68 4C004300   push    00430074                               ;改成对变量 的引用
0042F26F    68 74B04200   push    0042A4E8                               ;改成对 Form4 资源的引用
0042F274    FF15 68104000   call    dword ptr [<&MSVBVM60.__vbaNew2>] ; MSVBVM60.__vbaNew2
0042F27A    83EC 10         sub   esp, 10
0042F27D    B9 0A000000   mov   ecx, 0A
0042F282    8BDC            mov   ebx, esp
0042F284    894D DC         mov   dword ptr , ecx
0042F287    B8 04000280   mov   eax, 80020004
0042F28C    83EC 10         sub   esp, 10
0042F28F    890B            mov   dword ptr , ecx
0042F291    8B4D D0         mov   ecx, dword ptr
0042F294    8BD0            mov   edx, eax
0042F296    8B35 4C004300   mov   esi, dword ptr                 ;改成对变量 的引用
如果简单一点,也可以只修改对表单资源的引用,改动一个即可:
0042F26F    68 74B04200   push    0042A4E8                               ;改成对 Form4 资源的引用

这样,就可以去除 NAG 窗口的显示了,在主界面点击"Task2",就会显示 Form4 了:

这个时候,主界面隐藏了,但是当我们关闭这个 Form4 后,并不会象前面两个表单一样,会重新返回到主界面。
关闭 Form4 后,程序只剩下背景窗口,主界面出不来了。下一部分我们来解决这个问题。

下面进行第二个主题,VB 事件的探索。

第二部分    VB 事件处理探索


通过 VB Decompiler 可以看到 Form4 有一个函数,但并没有使用,如下所示:

在 OD 中,可以看到其代码如下所示:

所选部分,正是对主界面的引用,也就是显示主界面的代码,所以,这个函数可以显示主界面,但事件却丢失了,因此,我们需要将这个事件加上去。

我们首先要把处理事件的流程了解清楚,才有可能处理这个问题。

因此,我们先随便在另一个表单的一个事件中下一个断点。如下所示,在 Form1 的 Command1_Click() 事件下一断点:


然后,在 CrackMe 中打开 task1,输入几个字符,点”Check“,程序就会断下来,如下图所示:


然后,一路 F8 返回到 MSVBVM60 的地址空间,如下图所示:


我们在 call eax 前面下一个断点,然后 F9 ,再回到界面,点”Check“,然后又会断下来,如下所示:


我们在 call eax 处,按 F7 进入调用,来到下面:

可以看到,VB 先调用一个事件入口的 Stub,然后再跳转到事件处理代码中去的。

下面我们用 IDA 打开脱壳后的 CrackMe ,查看这些事件的引用关系,首先我们找到与上图类似的代码处,来查看其引用关系,如下图所示(用的是Form4):

可以看出,在一片内存区,有这些 Event_Stub 的地址引用,然后找其中一个,并查看其相关内存片,如下图所示:

推测,这些事件就是在这里填充 Event_stub 的地址,有很多空间为0,我在这里填上12个地址,如上图选择部分,保存以后,去反编译验证,如下图所示,是反编译结果:

可以看出,果然没有猜错,一下子多出了12个事件,到这里,大家就应该差不多明白了 VB 中的事件保存结构了。

于是我们数一下顺序,看看Unload事件在第几个位置并记好,先看看 Form4 那个函数,如下所示,选中函数第1条指令:

可以看到,有一个跳转指向这里,于是转到该跳转处,如下图:

正是一个与 Event_Stub 类似的 Func_Stub。记住其地址:0x0042A6B0,然后返回到前面我们改了12个地址的事件地址区,进行Unload事件的修正,如下图所示:

只剩下一个地址:0x0042A6B0。保存文件,再次反编译,如下图所示:

是不是函数变成事件了,哈哈!!!

还有,那个事件 Stub 代码中,有一个参数需要调整,这个参数是调整 Me 对象参数的。如下所示:

经过与基它函数对比和调校,确定为 0x38,上图含4C法调整Form显示顺序的修改。在文件中的位置如下:

这样修改后,就能正确执行事件过程了。当关闭 Form4 时,就会重新显示主界面了。

注意,应在数据窗口中修改 0x0000FFFF 为 0x00000038,因0x38小于0xFF,在指令窗口修改会改变数据格式。不符合 Stub 格式,可以正常运行,但反编译显示会不正确。


上面提到了4C法调整显示顺序的问题,但是主界面的 Load 事件会显示背景,如果要跳过背景的显示,还需要象去除 NAG 一样,修改主界面的Load事件的代码,

在 OD 中 Ctrl+G,输入上面函数地址:

来到函数,象修改去除 NAG 代码一样,修改即可去除背景的显示:



前面来了一段去背景窗口的小插曲,现在我们讨论一下给控件增加一个事件的方法,我们以 From4 的 Label1 控件为例作分析。

先在 IDA 中找一找 Label1的事件地址块:

如上图所示,找到 Label1 的事件地址块,上面红框下面的dd 12h dup(0) 就是 18 个 Label 事件地址块,目前没有一个事件。

我们按照事件代码格式,找一个空白区构建一个事件代码如下:


具体代码如下:
0042FFA0    816C24 04 34000000   sub   dword ptr , 34
0042FFA8    E9 03000000          jmp   0042FFB0
0042FFAD    90                   nop
0042FFAE    90                   nop
0042FFAF    90                   nop
0042FFB0    33C0               xor   eax, eax
0042FFB2    90                   nop
0042FFB3    C3                   retn


上面那个 0x34 也是根据运行条件去调整。同时,返回指令(ret),可以根据事件函数的参数个数进行调整(参考其它事件),如下图所示:




然后,在事件地址块中填充这个事件的地址,如下图所示(数据区):


注意,最好在数据区填充代码,保证4字节的数据格式正确,并且 jmp 后要有偏移,不要直接跳转下一条指令(汇编码 E9 00000000),也是因为反编译不能正确显示,但可以正确执行。


下面修改文件,如下数据区:

填充事件地址:

然后再填充指令:



保存以后,看看反编译后的效果:

正确显示。

那个Me对象修正码,如下所示,修正堆栈中的地址:

如果不对,会报错,需要修正,如下图所示:

修改堆栈中的地址后,该地址指向 Me 对象,原则上这个地址与指令区间的地址接近,自己去判断,正确的话才能运行,当然我这个新增代码才一条指令,并没有引用 Me 对象,指向不对也不会报错 。


要检查是否正确,在该事件中的代码上下一个断点,然后在 Form4 中去点击一下 Label1,如果能断下来,表示这个事件就是正确调用了的。


最后,上面讲了修改和新增事件,最后如果要删除事件,最简单,将事件地址块中的相应事件地址清 0 即可解决(前面讲的去除背景窗口显示,可以将主界面的 Load() 事件删除即可,操作更简单)。

第三部分    p-code 的事件简单分析


前面讨论了 VB Native 代码的事件处理方法,如果是 p-code 代码的呢,是不是也一样,是的,差不多。

下面以 160 个 CrackMe 之 038 - CyberBlade.2 作分析説明。过程就简化了,除了指令,其它过程基本一样。


如上图,先找到事件的 Stub,与前面的一样,Stub 的代码还是 Native 代码,格式稍有不同,大体还是一样。
具体代码如下,6个事件 stub:
0040304C    B8 5C000000   mov   eax, 5C                         ; About_Click()
00403051    66:3D 33C0      cmp   ax, 0C033
00403055    BA 54DD4000   mov   edx, 0040DD54                   ; 函数信息块地址,位于函数代码尾部
0040305A    68 42104000   push    <jmp.&MSVBVM50.MethCallEngine>
0040305F    C3            retn                                    ; 跳转到 MSVBVM50导出函数 MethCallEngine()
00403060    B8 60000000   mov   eax, 60                         ; Command1_Click()
00403065    66:3D 33C0      cmp   ax, 0C033
00403069    BA 80E64000   mov   edx, 0040E680                   ; 函数信息块地址,位于函数代码尾部
0040306E    68 42104000   push    <jmp.&MSVBVM50.MethCallEngine>
00403073    C3            retn                                    ; 跳转到 MSVBVM50导出函数 MethCallEngine()
00403074    B8 54000000   mov   eax, 54                         ; Command2_Click()
00403079    66:3D 33C0      cmp   ax, 0C033
0040307D    BA 00DD4000   mov   edx, 0040DD00                   ; 函数信息块地址,位于函数代码尾部
00403082    68 42104000   push    <jmp.&MSVBVM50.MethCallEngine>
00403087    C3            retn                                    ; 跳转到 MSVBVM50导出函数 MethCallEngine()
00403088    B8 58000000   mov   eax, 58                         ; Form_Initialize()
0040308D    66:3D 33C0      cmp   ax, 0C033
00403091    BA 38DC4000   mov   edx, 0040DC38                   ; 函数信息块地址,位于函数代码尾部
00403096    68 42104000   push    <jmp.&MSVBVM50.MethCallEngine>
0040309B    C3            retn                                    ; 跳转到 MSVBVM50导出函数 MethCallEngine()
0040309C    B8 58000000   mov   eax, 58                         ; Form_Load()
004030A1    66:3D 33C0      cmp   ax, 0C033
004030A5    BA B4E14000   mov   edx, 0040E1B4                   ; 函数信息块地址,位于函数代码尾部
004030AA    68 42104000   push    <jmp.&MSVBVM50.MethCallEngine>
004030AF    C3            retn                                    ; 跳转到 MSVBVM50导出函数 MethCallEngine()
004030B0    B8 74000000   mov   eax, 74                         ; txtkey.KeyPress()
004030B5    66:3D 33C0      cmp   ax, 0C033
004030B9    BA B0DD4000   mov   edx, 0040DDB0                   ; 函数信息块地址,位于函数代码尾部。 == 0x00402A74
004030BE    68 42104000   push    <jmp.&MSVBVM50.MethCallEngine>
004030C3    C3            retn                                    ; 跳转到 MSVBVM50导出函数 MethCallEngine()


因为是 p-code,最后不是 jmp 了,而是通过 ret 指令跳转到 MSVBVM60 中去执行事件的 P-code 代码了。
上在的 edx 参数,是一个指向 p-code 事件的信息块,这个与原生代码有区别,如下图所示一个信息块,并且,每个信息块紧接在事件代码的后面。
;; 事件信息块
0040E68074 2A 40 00 04 00 F4 00 14 04 3C 00 00 00 00 00t*@..?<.....
0040E69000 00 00 00 00 00 00 00 24 00 00 00 00 00 06 00........$......
信息块中包括了对象引用地址,局部变量空间大小,p-code 代码长度等数据。

同样,事件对应也有事件地址块,这个与原生代码的格式一样:
; 事件地址块
00402D0884 2B 40 00 74 2A 40 00 30 10 40 00 36 10 40 00?@.t*@.0@.6@.
00402D183C 10 40 00 74 30 40 00 00 00 00 00 00 00 00 00<@.t0@.........      0x00403074
00402D2800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402D3800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402D4800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402D5800 00 00 00 00 00 00 00 00 00 00 00 AC 2B 40 00............?@.
00402D6874 2A 40 00 30 10 40 00 36 10 40 00 3C 10 40 00t*@.0@.6@.<@.
00402D7800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402D8800 00 00 00 00 00 00 00 9C 30 40 00 00 00 00 00.........@.....       0x0040309C
00402D9800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402DA800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402DB800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402DC800 00 00 00 00 00 00 00 00 00 00 00 88 30 40 00............?@.       0x00403088
00402DD800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402DE800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402DF8D4 2B 40 00 74 2A 40 00 30 10 40 00 36 10 40 00?@.t*@.0@.6@.
00402E083C 10 40 00 4C 30 40 00 00 00 00 00 FC 2B 40 00<@.L0@.....?@.       0x0040304C,菜单只有两个可定制事件
00402E1874 2A 40 00 30 10 40 00 36 10 40 00 3C 10 40 00t*@.0@.6@.<@.
00402E2860 30 40 00 00 00 00 00 00 00 00 00 00 00 00 00`0@.............      0x00403060
00402E3800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402E4800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402E5800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402E6800 00 00 00 00 00 00 00 24 2C 40 00 74 2A 40 00........$,@.t*@.
00402E7830 10 40 00 36 10 40 00 3C 10 40 00 00 00 00 000@.6@.<@.....
00402E8800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402E9800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402EA800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402EB800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402EC800 00 00 00 00 00 00 00 4C 2C 40 00 74 2A 40 00........L,@.t*@.
00402ED830 10 40 00 36 10 40 00 3C 10 40 00 00 00 00 000@.6@.<@.....
00402EE800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402EF800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402F0800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402F1800 00 00 00 74 2C 40 00 74 2A 40 00 30 10 40 00....t,@.t*@.0@.
00402F2836 10 40 00 3C 10 40 00 00 00 00 00 00 00 00 006@.<@.........
00402F3800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402F4800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402F5800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402F689C 2C 40 00 74 2A 40 00 30 10 40 00 36 10 40 00?@.t*@.0@.6@.
00402F783C 10 40 00 00 00 00 00 00 00 00 00 00 00 00 00<@.............
00402F8800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402F9800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402FA800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402FB800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402FC800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
00402FD800 00 00 00 C4 2C 40 00 74 2A 40 00 30 10 40 00....?@.t*@.0@.
00402FE836 10 40 00 3C 10 40 00 00 00 00 00 00 00 00 006@.<@.........
00402FF800 00 00 00 00 00 00 00 00 00 00 00 B0 30 40 00............?@.       0x004030B0
0040300800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
0040301800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
0040302800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
0040303800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
0040304800 00 00 00                                    ....

下面在 OD 中来看看这个事件 stub:

我们在注册码验证按钮的事件代码处,下一断点。
然后到 CrackMe 界面,按 ”Check“按钮,触发事件,断在我们下的断点处,按F8 跟踪,来到 MSVBVM60 的空间。如下图:


这里是不是与原生的 Event_Stub 类似??差不多吧!!!
;;;============MSVBVM50 事件调用入口 Stub ===============================================================
741C2FFC >294424 04       sub   dword ptr , eax             ; Me 对象指针修正
741C3000    B9 02E31B74   mov   ecx, 741BE302
741C3005^ E9 39A2FFFF   jmp   741BD243



修正 Me 指针后,指向应用的数据区。


继续,这里有是作准备的。

取得数据区对象地址。

生成 Me 对象。

开始准备 p-code 代码的指令指针了(相当于原生代码的 EIP)。

正式完成,这个时候,esi 指向事件函数的第1条指令,准备执行事件函数了。
函数p-code 代码如下(VB Explorer 反编译):

下面是,上面分析的代码(MSVBVM中的事件 Stub 代码):
;;;============MSVBVM50 事件入口代码 ====================================================================
741BD243    55                  push    ebp
741BD244    8BEC                mov   ebp, esp
741BD246    83EC 78             sub   esp, 78
741BD249    53                  push    ebx
741BD24A    56                  push    esi
741BD24B    57                  push    edi
741BD24C    8BDA                mov   ebx, edx                        ; ebx == edx == 0x0040E680,传入的参数,指向函数信息块
741BD24E    895D B0             mov   dword ptr , ebx
741BD251    894D 94             mov   dword ptr , ecx
741BD254    8B15 64F01C74       mov   edx, dword ptr
741BD25A    0BD2                or      edx, edx
741BD25C    0F85 09630000       jnz   741C356B
741BD262    8B15 6CF01C74       mov   edx, dword ptr
741BD268    8B3B                mov   edi, dword ptr             ; ebx == edx,传入的参数, edi==>对象地址
741BD26A    8B77 34             mov   esi, dword ptr
741BD26D    8975 AC             mov   dword ptr , esi
741BD270    8B77 04             mov   esi, dword ptr
741BD273    8B76 14             mov   esi, dword ptr
741BD276    8B76 0C             mov   esi, dword ptr
741BD279    8975 D4             mov   dword ptr , esi
741BD27C    8955 BC             mov   dword ptr , edx
741BD27F    C745 B8 00000000    mov   dword ptr , 0
741BD286    81F9 02E31B74       cmp   ecx, 741BE302
741BD28C    0F84 94000000       je      741BD326
741BD292    0FB74B 06         movzx   ecx, word ptr          ; 局部数据缓冲区大小,word == 0x00F4
741BD296    C745 C4 00000000    mov   dword ptr , 0
741BD29D    8BFC                mov   edi, esp
741BD29F    8BC1                mov   eax, ecx
741BD2A1    2BF8                sub   edi, eax
741BD2A3    3B7A 70             cmp   edi, dword ptr
741BD2A6    0F82 5D630000       jb      741C3609
741BD2AC    8BFC                mov   edi, esp
741BD2AE    3D 00100000         cmp   eax, 1000
741BD2B3    0F83 3D630000       jnb   741C35F6
741BD2B9    2BF8                sub   edi, eax
741BD2BB    830F 00             or      dword ptr , 0
741BD2BE    2BE1                sub   esp, ecx                        ; 生成局部变量空间
741BD2C0    8BFC                mov   edi, esp                        ; edi 为栈顶
741BD2C2    C1E9 02             shr   ecx, 2                        ; ecx /= 4,变为 DWORD 长度
741BD2C5    33C0                xor   eax, eax
741BD2C7    F3:AB               rep   stos dword ptr es:         ; 局部变量清 0
741BD2C9    8945 C0             mov   dword ptr , eax         ; 清 0
741BD2CC    8945 CC             mov   dword ptr , eax         ; 清 0
741BD2CF    8BFA                mov   edi, edx
741BD2D1    66:837B 1C 00       cmp   word ptr , 0            ; word == 0
741BD2D6    0F85 A0000000       jnz   741BD37C
741BD2DC    8B47 0C             mov   eax, dword ptr
741BD2DF    8945 A4             mov   dword ptr , eax
741BD2E2    8D45 A4             lea   eax, dword ptr
741BD2E5    8947 0C             mov   dword ptr , eax
741BD2E8    8B47 14             mov   eax, dword ptr
741BD2EB    8945 F8             mov   dword ptr , eax
741BD2EE    8D45 D8             lea   eax, dword ptr
741BD2F1    8947 14             mov   dword ptr , eax
741BD2F4    BE 01000000         mov   esi, 1
741BD2F9    8D4D D8             lea   ecx, dword ptr
741BD2FC    C741 24 00000000    mov   dword ptr , 0
741BD303    51                  push    ecx
741BD304    8B4D 94             mov   ecx, dword ptr
741BD307    E8 5E2F0000         call    741C026A
741BD30C    0FB773 08         movzx   esi, word ptr          ; word,取函数代码的长度
741BD310    F7DE                neg   esi
741BD312    03F3                add   esi, ebx                        ; 计算得到函数开始地址,esi指向函数第1条指令
741BD314    8975 A8             mov   dword ptr , esi         ; CyberBla.0040E26C
741BD317    8975 EC             mov   dword ptr , esi
741BD31A    33C0                xor   eax, eax
741BD31C    8A06                mov   al, byte ptr             ; 取出第1条指令
741BD31E    46                  inc   esi
741BD31F    FF2485 94ED1B74   jmp   dword ptr       ; 去执行指令

下面是函数信息数据,上面的 Stub 通过这个数据块来调用 p-code 代码:
;; 事件信息块
0040E68074 2A 40 00 04 00 F4 00 14 04 3C 00 00 00 00 00t*@..?<.....
0040E69000 00 00 00 00 00 00 00 24 00 00 00 00 00 06 00........$......


通过以上分析,可以看出,人为制作一个函数信息块,再写一个 p-code 代码的函数,也可以新加事件,只是难度比原生代码的高一些!!!


p-code例子就不做了。

分析完毕!!!



后面的图片是不需要的,没地方删除,请跳过!!!




solly 发表于 2019-7-31 18:50

多出的图怎么没地方删掉了呀?

ggsq 发表于 2019-7-31 18:59

感谢分享。。。。。。。。。。。。

gaosld 发表于 2019-7-31 21:25

谢谢分享,学习楼主的坚持

Deschanel 发表于 2019-7-31 21:30

谢谢大佬,学习了

daitoudage 发表于 2019-7-31 22:02

谢谢楼主的分享{:1_893:}{:1_893:}

sjilies 发表于 2019-7-31 22:55

谢谢楼主的分享

mazin 发表于 2019-7-31 23:43

先回复,再学习

feiyao32 发表于 2019-8-2 10:20

多图眼花缭乱的,相当精彩!

byh3025 发表于 2019-8-3 08:23

好详细的分析,谢谢啦
页: [1] 2
查看完整版本: 160 个 CrackMe 之 101 - Acid_Cool_178.4(VB6 Native)VB事件处理的分析和增删改!