VB程序分析方法及修改例 (“万能分析断点”、启动form修改,form隐藏)

VB程序的分析一直较为麻烦。用OD打开VB程序后,光标停在程序入口点,如下所示:
00406BDC > $  68 20614600   push    00466120
00406BE1   .  E8 EEFFFFFF   call    <jmp.&MSVBVM60.#100>
按F8键也不能实现步进跟踪,程序直接进入程序界面。
进入程序界面后,对于按钮事件可设置按钮事件断点来确定按钮事件的入口点。但对于程序启动时的初始过程就难以跟踪,同时程序中除了一些按钮外,还有一些lable事件(即点一个label后,执行一段程序)很难用事件断点来断。
为了能跟踪程序启动时在formload中执行的一些初始化操作,以及对每一个动作(按钮动作、label点击动作)等全部进行跟踪,可以采用以下笨办法:

找到以下结构的跳转语句:注意,关键特征是在sub     dword ptr [esp+4],后有JMP,而且这种语句总是好多组在一起的。
00467600   .  816C24 04 37000000    sub     dword ptr [esp+4], 37
00467608   .  E9 03313B00           jmp     0081A710
0046760D   .  816C24 04 3B000000    sub     dword ptr [esp+4], 3B
00467615   .  E9 06323B00           jmp     0081A820
0046761A   .  816C24 04 4B000000    sub     dword ptr [esp+4], 4B
00467622   .  E9 E9323B00           jmp     0081A910
00467627   .  816C24 04 4F000000    sub     dword ptr [esp+4], 4F
0046762F   .  E9 2C413B00           jmp     0081B760
00467634   .  816C24 04 43000000    sub     dword ptr [esp+4], 43
0046763C   .  E9 DF413B00           jmp     0081B820
00467641   .  816C24 04 43000000    sub     dword ptr [esp+4], 43
00467649   .  E9 D25A3B00           jmp     0081D120
0046764E   .  816C24 04 47000000    sub     dword ptr [esp+4], 47
00467656   .  E9 755B3B00           jmp     0081D1D0

在程序开头部分,有不少这样的结构JMP,注意在不连续的地方可能都会找到这种结构的JMP(估计是一个FORM中的事件放在一起,不同的FORM就放在不同的地方了)。

接下来就是有点耐心,将这种结构跳转的JMP全部设置断点。

好了。接下F9吧。程序的每一步都在你的掌控中了。


实例1:改变程序启动时显示的FORM的顺序:

一个学习软件,启动时要先选择用户,然后才能进入学习。它设计的目的是这个软件在同一台电脑上可由不同的人用来学习,每人的学习记录分别保存。
但一般情况下,这台电脑也就是自己用这个软件来学习,因此,改造一下,让它启动后直接进入学习界面。

好,动手!

对每一个sub     dword ptr [esp+4], + JMP结构的JMP全部设置断点。
按下F9,一步一步跟踪,看那一步执行后显示用户选择界面,然后按下用户确定键后,程序停在那里:

.
46B2CD jmp 7A2156     在此按F9后,显示用户选择界面
.
.

46B2D8 jmp 7A2290     选择用户后,停在此处。在此按F9后,显示学习界面
.
.
就在这里下手:
将46B2CD jmp 7A2156     改为 jmp 7A2290

重新启动一下,哈哈,直接进入学习界面。

需要注意的是,这种修改启动form的方法不一定能全部成功,因为可能会跳过一些初始化过程,因而造成后面的程序不能正常运行。



实例2:让程序实现自己注册,你都不用输入什么,按注册键后,程序自己将正确的注册码写入注册文件

对上面说到的学习软件进行分析,发现它竟采用明码方式显示注册码的字符串。而且输入注册码后,不管注册码是否正确,都写入注册文件。

思路:在获得输入假码的地方,换为程序自己生成的真码。这样程序就自动将真码写入注册文件了。

动手:按“注册”后,程序停下,按F8跟踪:(注意这个“注册”按钮不是按钮,只是一个label,一般用按钮事件方法不能断下来)

00765F71   .  8B35 C4608900 mov     esi, [8960C4]
00765F77   .  8D4D CC       lea     ecx, [ebp-34]
00765F7A   .  51            push    ecx
00765F7B   .  56            push    esi
00765F7C   .  8B06          mov     eax, [esi]
00765F7E   .  FF90 04070000 call    [eax+704]       关键CALL,根据机器码生成注册码明码
00765F84   .  8B45 D4       mov     eax, [ebp-2C]   F8执行这一句后,EAX寄存器中显示出注册码了
00765F87   .  8945 E8       mov     [ebp-18], eax

好了,按F9,显示注册界面。
输入假码。
按“注册”按钮(这个是真的按钮了)。程序停下,按F8跟踪:


007E7919   .  FF15 6C104000 call    [<&MSVBVM60.__vbaHresultCheckObj>;  MSVBVM60.__vbaHresultCheckObj
007E791F   > \83EC 10       sub     esp, 10
007E7922   .  8B45 E8       mov     eax, [ebp-18]   F8执行这一句后,EAX寄存器中显示出办入的假码  这就是关键点了。
007E7925   .  8BD4          mov     edx, esp
007E7927   .  B9 08000000   mov     ecx, 8

哈哈,以上两段代码都是将注册码放入EAX!

动手:对007E791F处的代码修改如下:
007E7919   .  FF15 6C104000 call    [<&MSVBVM60.__vbaHresultCheckObj>;  MSVBVM60.__vbaHresultCheckObj
007E791F   >  E9 4CE60A00   jmp     00895F70    跳去新增的代码,生成真注册码
007E7924      90            nop
007E7925   >  8BD4          mov     edx, esp
007E7927   .  B9 08000000   mov     ecx, 8
.
.
.


在程序最后的空白处增加以下代码:
00895F70   > \56            push    esi
00895F71   .  8B35 C4608900 mov     esi, [8960C4]
00895F77   .  8D4D CC       lea     ecx, [ebp-34]
00895F7A   .  51            push    ecx
00895F7B   .  56            push    esi
00895F7C   .  8B06          mov     eax, [esi]
00895F7E   .  FF90 04070000 call    [eax+704]         调用注册码生成
00895F84   .  8B45 D4       mov     eax, [ebp-2C]     生成的真码放入EAX
00895F87   .  8945 E8       mov     [ebp-18], eax
00895F8A   .  5E            pop     esi
00895F8B   .  83EC 10       sub     esp, 10
00895F8E   .^ E9 9219F5FF   jmp     007E7925          返回原程序段,此时真码就已放入EAX了

嘿嘿!重新启动程序看看:是不是“未注册”已变为“已注册”,所有的限制已取消了。

注:这个软件的新版已不再采用生成明码注册码的方式了。这个老版留做记念。


实例3:改变程序启动form顺序,隐藏一些form(用VBExplorer配合)

还是前面的程序,增加自己注册功能后,想做成个专门的注册程序,不需要什么学习界面。
按实例1方法,在进入学习界面后,点“注册”,停在了下面:

46FF5D jmp 7F2BC2     在此按F9后,显示注册界面。

好了,按实例1中找到的启动画面显示处,进行修改: 

将:46B2CD jmp 7A2156   修改为 jmp  7F2BC2

不好,怎么启动程序后,不仅显示了注册界面,还显示了用户选择界面,想了多种跳转修改,还是要显示用户选择。
郁闷!

先是自己用VB做了两个FORM,一个是可显示的,一个的显示属性设置为隐藏。然后分析两个form的数据结构,发现隐藏的form数据结构中的数据多了几个数据。看来想修改用户选择界面form的隐藏属性是不太可能了(因为要增加数据项)。

这下动用VBExplorer了。
用VBExplorer打开程序,找到用户选择的form,查看它的属性,将top 设置为-5,left设置为-5,height设置为1,width设置为1,将窗口显示方式设置为manual,存盘。

再启动程序,嘿!这个用户选择界面终于消失了(它只是1*1大小,而且是放在了左上角显示器之外了,当然看不见了 ^D^)


附实例4:利用VBExplorer改变程序对像放置位置

奇迹智能英语用来背单词还是很优秀的,但原版程序有个BUG:一启动就将系统音量调整到最大。真是很烦人的。

这个好办,找到启动时设置音量的代码,nop就行了。
但剩下的问题还有:程序音量调整按钮的音量指示还在音量最大处,想调音量时,一点指示器,音量又调到最大了。看来需要将这个指示器的初始位置调整一下了:

用VBExplorer打开程序,找到用于音量指示的image,将其left属性调整到一个适当值即可。