提起VB编写的软件,相信许多学习破解的新手朋友都会感觉比较头疼,一是VB类的软件不容易查找字符串,二是代码比较繁琐,这是因为VB足解释性语言,所以在反汇编后就会看到很多对分析没用的垃圾代码,跟踪时就容易产生厌烦的情绪了。但是VB编写的软件也存在对破解有利的地方,比如容易查找按钮事件,函数的功能一目了然等。本文我们就总结一下这类软件的破解方法,主要是本地代码编译的破解,由于P-CODE编译的软件还需要了解P-CODE函数,所以就暂时不介绍了。
我自己使用VB编写了一个CM程序,这个程序的加密强度不高,算法也比较简单,下面我们就开始分析它。双击打开CM,什么也不输入,直接点击“注册”接钮,结果提示我们“用户名或注册码不能为空”。随便输入注册信息,比如用户名就填lonewolf2008,注册码就填123456789,点击“注册”后出现了消息框,提示“注册失败”,由此我们知道了它的提示信息和提示方式,这是软件提供给我们的有用的信息。
使用OD载入程序,首先要定位到关键代码,这时候我们来扩展一下思路,看看VB类的软件都有几种方法:1、字符串查找;2、F12暂停法;3、VB专用函数断点法:4、VBExplorer查找按钮事件地址法;5、万能断点法(通用指令816C24);6、VB按钮事件脚本法。
首先介绍查找字符串的方法,我们点右键,选择“超级字符串参考”一一“查找UNICODE”,结果没有找到“注册失败”这样有用的字符串,这是为什么呢?这是由于VB中的中文不能被反汇编工具和调试工具识别,而我们的提示信息却正好又是中文的,所以也就搜索不到了。那我们该怎么解决呢?常言道:上有政策,下有对策。既然调试工具只能搜索到英文字符,那我们就把中文信息都更改成对应的英文,不就可以搜索到了吗?
我们可以使用VBExplorer这款VB专用反编译工具,使用该软件打开程序后,选择菜单中的“查看”——“查看字符串”,结果看到了对我们有用的信息:“注册失败”、“注册成功”,因为都是中文的,所以在OD中查找不到。我们在“现字符串”中,将“注册失败”改为“fail”,将“注册成功”改为“succ”,修改的时候要注意字符长度,别溢出了。修改完毕后保存,然后重新使用OD载入程序,再次查找字符串,我们就会发现比刚才多出了“succ”和“fail”这两个字符串,也就是我们刚才修改的注册信息。直接双击就可以来到关键代码处,向上滚动就可以找到这段代码的首地址0x00402520。
下面来介绍F12暂停法,使用OD载入程序,按F9运行,随便输入用户名和注册码,出现了注册失败的提示,这时我们不要点“确定”,而是在OD里按下F12,或选择菜单中的“调试”一一“暂停”,此时程序就会暂停下来,然后我们按ALT+K,或是点击工具栏上的标有“K”的按钮,结果来到了重要的地方。在最后一行,我们看到程序调用了“rtcMsgBox”,我们点鼠标右键,选择“显示调用”,就可以来到程序注册的关键代码了,向上滚动,也可以找到首地址0x00402520。
第三种就是VB专用函数断点法,我们需要了解常用的VB专用函数,比较常用的有:rtcMsgBox,__vbaStrComp、__vbaStrCmp、__vbaSirCopy、__vbaStrMove。第一个是消息框专用函数,后两个是字符串比较函数,最后两个是字符串移动函数,这些函数在OD的API断点插件里都有。可能有些读者会发现在自己使用的0D的插件里没有,那么只需要在文件夹“plugin”下的“APIBreak.ini”里进行添加就行了,没有这些断点的,只需要覆盖OD中原来的文件就可以了。
我们使用OD载入程序,运行起来后,在插件里把rtcMsgBox这个函数勾选上,然后填写我们的注册信息,点击“注册”,此时就会断下来了,我们取消断点,按F8单步,就可以返回的注册关键代码了。
接下来介绍第四种方法,使用WBExplorer查找按钮事件。使用VBExplorer载人CM程序后,首先选择“注册”按钮的控件,然后单击那个像闪电一样的按钮,就会出现按钮单击事件的地址,0x402520就是按钮单击事件的地址,跟上面的方法找到的一样。
第五种方法是万能断点法,使用D载入CM程序后,点右键,选择“查找”——“二进制字符串”,在十六进制栏里输入“816C24”,点击确定后就来到了。这里的四个JMP都是事件的地址,我们都按F2下断。运行CM程序,输入注册信息,点击“注册”,就会在第一个JMP断下来了,按一下F8,就来到了0x00402520处,跟上面的地址一样。
第六种方法跟第五种的原理一样,只是更加方便。使用OD载入CM后,使用脚本插件,运行我们的脚本就会在上图中的四个JMP下断点,跟我们手工操作的结果是一样的。
通过上面六种方法我们都定位到了注册的关键代码处,在实际的破解过程中,我们要学会灵括运用,这样才能起到事半功倍的效果。
下面我们来分析关键代码,从首地址0x00402520开始。VB类软件在跟踪调试过程中,要时刻观察OD里的函数提示,通过函数中的英文单词的意思我们就可以把函数的功能猜个八九不离十。另外还要观察某些CALL前的PUSH指令,我们可以把CALL看做是一个函数,函数中的参数要在CALL之前通过PUSH指令人栈,因为函数的操作都是通过栈来处理数据的,所以在某个CALL之前人栈的基本就是这个函数的参数。通过观察参数和猜测函数功能,我们基本上就能知道某些CALL干了什么,而无需F7跟进了。
我把具体的分析和流程介绍一下,按F8从0x00402520单步到0x004025E5,出现了我们输入的用户名,接着出现了“__vbaStrMoVe”这个函数,“__vba”是VB函数的前缀,“str”代表字符串类型,“Move”是移动的意思,由此我们可以猜到是字符串移动的功能。继续单步到0x00402624,从这个地址到0x00402632处的代码在VB类软件中很常见,这是VB语言的特点,但对我们破解来说却是无用的指令,直接跳过就可以了。继续单步就会发现,假码出现并压入了堆栈,一块空内存区(代表空字符串)也入栈了,接着出现了“__vbaStrCmp”,“Cmp”表示比较,因此我们可以猜到这个函数是比较假码和空字符串,接着就是用户名入栈,再次与空字符串比较。
单步到0x0040267B后出现了一个条件跳转,通过观察可以发现,当用户名和假码都不为空时跳转实现(观察和猜测在软件分析中很关键,有些CALL我们无需跟进,通过观察参数的传入和传出就可以知道它的作用)。继续单步到0x004026F3后发现用户名入栈,出现了“__vbaLenBstr”函数,“LenB”是取Unicode长度的意思,可以猜到这个函数是取用户名的长度。再单步到0x0040276E,进入了一个循环,EAX存放的是递减计数器,从用户名长度开始递减,里面有一些数据类型的转换的指令。
我们单步走过,来到0x004027C4处,出现了“rtcMidCharVar”,“Mid”是从字符串中间取字符的意思,这个面数就是从用户名依次取字符,后面的“rtcAnsiValueBstr”是将字符转换为对应的ASCII数值,“rtcHexVarFromVar”函数的作用是将ASCII值转换为十六进制表示的字符串,接着的“__vbaVarAdd”将这些字符串连在一起。
单步到0x00402859后进入了下一次循环,再单步到0x0040289C时,就会出现上面的循环连在一起得到的字符串,这就是真码,后面就可以得到验证。接着真码和假码依次入栈,进入下面的CALL进行比较,如果相等就会注册成功,不相等就注册失败。整个流程就是这样的,爆破点很好找,注册码是用户名每个字符的十六进制ASCII值转化为字符串后连在一起,算法注册机编写起来也非常简单。
本文内容所提及均为本地测试或经过目标授权同意,旨在提供教育和研究信息,内容已去除关键敏感信息和代码,以防止被恶意利用。文章内提及的漏洞均已修复,作者不鼓励或支持任何形式的非法破解行为。