<title></title>
网络硬盘:
http://wallimn.ys168.com
时间:2008-11-18
/***********本人原创,保留所有权利,欢迎转载,转载请保留本人信息*************/
引言
本文主要讲解使用OllyDBG(也有叫OllyICE,本文以下简称OD),启用(使能、Enable)应用程序中不可用(禁用、Disable)的菜单。以一个自已编写的例子(VC6.0)为主线,详细讲解OD的功能、用法,使您快速掌握强大的时下最为流行的逆向工程工具---OD。我尽量把过程写得详细一点,希望能给学习OD或者逆向工程的人以帮助。
逆向工程是几种知识的综合运用,包括Windows高级编程知识(最好能会一种高级语言,如VC)、Windows系统API函数、Windows32位汇编知识、PE文件结构,以及逆向工程工具:OllyDBG。阅读本文不要求您具备以上全部知识,但具备以上知识,才可以真正会用逆向工程技术解决实际问题;不然可能只会照搬照抄。
学习逆向工程,最好的资料就是看雪论坛出的《加密与解密》了,看雪论坛的离线知识库也非常的好。查API函数,可以使用微软的MSDN。如果有兴趣和精力,最好再看一下《Windows环境下32位汇编程序设计》,这本书对于汇编、Windows程序设计相关知识的讲解非常精彩,即使不打算学习汇编,看看也会有帮助。
一、基础知识及例子
在VC中,禁止应用程序的菜单有三种方式,一是直接使用API函数:EnableMenuItem;二是使用ON_UPDATE_COMMAND_UI消息映射(MFC经过一系列的封装,最后还是调用的API函数EnableMenuItem);三是在资源中直接对菜单的属性进行设置。本文的例子程序中包括了使用上述三种方法禁用的三个菜单。程序运行界面如图1所示。前两种技术,因为都会调用EnableMenuItem,所以我们就在这个函数上做文章。对于第三种情况,一般可以用exeScope或者ResHacker制定,实际应用中,这种情况也不是很多,就不介绍了。
在实际逆向工程中,对于VC两种连接MFC库的模式:动态链接及静态连接,处理起来有些不一样,下面依次为大家讲解。
另: VC有两种编译模式,Release为发行模式,生成应用程序小,效率高;而Debug模式为调试模式,包括很多用于调试的代码。使用OD,可以比较一下VC使用Debug模式、Release模式生成的应用程序的反汇编代码,你会发现Debug模式生成的程序有许多用于调试跟踪的垃圾代码,因此应用程序发布一定要使用Release模式。我见过有些软件交付时使用了Debug模式的,相当多的情况是因为作者写了一大堆的代码,最终发布的时候发现Release模式无法正常运行(当然也不排除有些菜鸟不知Release模式),只好使用Debug模式。
另: Debug模式对于逆向工程操作的时候,由于垃圾代码的存在,无形中会增加一点儿难度。
图1
二、破解
1 静态连接MFC库模式的VC应用程序
先来处理这种热热身,这种是比较容易的。有人把这种容易形容为“秒杀”。运行OD,打开例子程序,界面如图2所示。请注意其中的黄色区域,本文统一称为“命令查看窗口”,此时可以注意到,程序自动定位的例子程序的入口处。窗口内部的右侧,为注释区域,对一些API函数及一些高级程序的运行库函数进行注释。
小技巧: 如何你的程序中没有显示出相应的注释,或者注释显示为序号,可以选择“调试”菜单->“选择导入库”,将对应的动态库的导入库导入(.lib文件)
图2
在“命令提示窗口”,点击鼠标右键,在弹出的上下文菜单中选择“查找”->“当前模块中的名称”,会弹出“名称窗口”,在“名称窗口”中键入“EnableMenuItem”,键入前几个字母就会定位到USER32.EnableMenuItem这个函数,USER32表示动态库的名称,即系统的核心库之一USER32.dll。用鼠标高亮度选中这一行,按“回车”键。会出现图3所示窗口。
图3
该窗口提示程序中有两处引用EnableMenuItem开禁用菜单项。使用鼠标双击第一处(另一处即为另一种禁止菜单方式的执行代码,这里略过不讲),会切换到“命令查看窗口”,代码如下图4所示。
图4
小技巧: 可以使用Ctrl+Tab键,迅速切换到上一个窗口。
可以使用Exescope或者Rescrack等工具查看一下应用程序中菜单的ID,发现看到的ItemID=32774,正好是对应着使用直接使用API函数对应的菜单项,而Flags = MF_BYCOMMAND|3|MF_STRING这句呢,可以直观的看出这命令的作用,其中3,是MF_DISABLED与MF_GRAYED的结合,也就是不可用并且灰化。再查一下API的文档,MF_ENABLE对应着数值0,所示只要把push 3这句改成push 0就可以了,也可以把这四句改成相应字节数的nop命令(使用也不做的汇编命令,对应的汇编代码为90,这是个很有用很有用的命令)。我们以第一种方法来修改,在push 3(在这个命令文字区域上,不同位置双击会有不同的效果),上双击鼠标左键在弹出的对话框中,将3改为0。选择主菜单“调试”->“运行”(或者直接使用F9功能键),看一下应用程序的菜单是不是已经可用了。
此时的修改,仅是在内存中的修改,退出OD后,应用程序的菜单依然是不可用的,那么如何保存到应用程序中呢?方法很简单,高亮度选中等修改的代码,在“命令查看窗口”中点右键,在弹出菜单中选择“复制到可执行文件”,在子菜单中选“选择”或者“所有修改”都可以,意思大家应该猜得出吧。在弹出的窗口中点右键,在弹出菜单中选择“保存文件”,就将修改保存到了应用程序中,以后运行程序,菜单总是可用的了。
2、动态链接MFC库模式发布的VC应用程序
在这种情况下,使用上面的方法,“查找”->“当前模块中的名称”,你在惊奇的发现,没有EnableMenuItem。这是因为此时EnableMenuItem函数被封装在MFC的动态连接库中(mfc42.dll或者mfc42d.dll),也就是说,当前应用程序没有直接调用,所以在“当前模块中的名称”中找不到。
这时就要用到“命令窗口”了,使用方法,在如图5所示的“命令窗口”(位于主程序的左下角)中输入:“bp EnableMenuItem”(不带引号),然后回车。这个意思就是说,当应用程序调用EnableEmnuItem这个函数的时候中断程序。
图5
提示:“ 命令窗口”很有用,可以在帮助中看看。破解注册码时会用到bp GetWindowText或bp GetDlgItemText等,也可以使用命令窗口来下消息断点。。。。。
点击工具栏上的运行按钮(或者主菜单“调试”->“运行”),启动程序,程序会中断在程序入口处(也即应用程序代码的最开始执行处),再点一次运行,会发程序停在USER32模块,如下图6所示(注意看标题)。
图6
这时怎么办呢?注意看,主菜单“调试”菜单中有个“执行到返回”子菜单,热键是Ctrl+F9,这时多按几次这个组合热键,注意观察主程序的标题栏,当出现Test.exe模块(主程序模块)的时候停止(此时地址偏移量一般为00开头),如下图7所示高量度行所示。查看上面一句call语句,可以发现,在应用程序主模块中,调用的是CMenu::EnableMenuItem,最终这个函数调用API函数:EnableMenuItem。
提示: 由此我们推断,静态链接MFC的应用程序,执行效率应该好一点,但会大一点,当应用程序只有一个或很少的模块的时候,可以选用静态链接的方式;当应用程序模块很多,即有很多动态库,若使用静态链接,同样的MFC动态库中的代码会被重复多次复制到每个模块中,因此选用动态链接的方式为佳。
图7
向上找一点,又会发现push 3,向前面讲的一样,改成push 0就可以了,然后复制到可执行程序,就可以了。
对于使用ON_UPDATE_COMMAND_UI消息映射禁止菜单的情况,修改办法大致类似,运行应用程序,出现主界面后,点击一下“禁用的菜单”主菜单,OD会中断,然后按几次Ctrl+F9热键,回到主程序模块,此时程序中断处的代码与上面有所不同,如图8所示。
图8
这时注意那个标识的call语句,实际上调用的是:CCmdUI::Enable(FALSE),(可以通过运行程序(按F9),然后在这一行设断点,发现这个函数名字,然后查MSDN看到函数介绍)。前面的那个push 0,就是传递的Enable的参数,所以我们只要把push 0改成push 1就可以了。
三、结束语
这不是一篇高深的文章,只是供爱者学习OD入门之用,希望对朋友们有所帮助。
第一次写教程,不当之处敬请批评指证。由于先抓了图,后来又修改了测试用例,可实际操作的时候,地址偏移量不一定与图中相同。