逆向工程第005篇:跨越CM4验证机制的鸿沟(上)

一、前言

《冠军足球经理》系列作为一款拟真度极高的足球经营类游戏,赢得过无数赞誉,而CM4可以说是这个传奇的起点。但是在游戏安装过程中,当用户输入完序列号之后,程序并不会对用户的输入进行真伪判断,只有等到安装完毕,进入游戏之后,通过游戏是否正常显示才能够得知。而如果遇到用户不小心输入错误的情况,那么只能卸载游戏重新安装,这就会造成很大的麻烦。

为解决这个问题,这次的研究会以两篇文章的篇幅通过两种方式对这个游戏进行逆向分析,一种是采用常见的“爆破”手段,也就是本文所讨论的方法;而另一种则是编写出CM4的注册码生成器,这会在下一篇文章中进行讨论。后者需要依据反汇编代码分析出游戏的验证机制,这可以说是任何逆向研究的最终目标,也是本次研究的最终目标。

图1 CM4游戏封面

 

二、尝试在没有序列号的前提下安装并进入游戏

CM4这款游戏在游戏安装的过程中,会要求用户输入序列号,这个序列号由数字加字母组成,一共16位,每4位为一组。

图2 CM4安装程序的序列号输入界面

而在本研究的过程中,我尝试将序列号输入为“0123456789ABCDEF”,每一位输入不同的字符,这样便于后面的逆向跟踪。这种方式往往也运用于缓冲区溢出的检测(可见《反病毒攻防研究第003篇:简单程序漏洞的利用》)。当游戏安装完毕后,进入游戏。程序会先进行序列号的验证,如果之前的序列号输入错误,那么就会出现错误提示对话框。

图3 进入游戏之前提示的错误信息

这里当我们单击“确定”之后,依然能够进入游戏,但是游戏却无法正常显示,在我的电脑中,凡是出现文字的部分,均会以乱码显示。虽然说对于老玩家而言,依然可以通过各个按钮的位置来确定每个按钮的功能,但是依然会造成很大的麻烦,所以在此很有必要对这一问题进行逆向研究。

图4 进入游戏中的乱码显示

三、寻找软件的CDKEY检查对话框位置

一般来说,想要找到软件的验证语句的位置,则需要运用动态或者静态反汇编工具,得到它的反汇编代码,分析该软件的运行机理,一步一步跟踪执行,直至弹出如图3所示的“CDKEY检查”对话框。这个对话框一定是由一个CALL语句调用出来的,那么这个CALL语句必然包含了相应的验证机制,就有必要进入这个CALL语句,进一步分析。

对于这次的研究对象——CM4来说同样如此,根据惯例,我们有必要先对这款软件进行查壳的操作,这是一切逆向工作的起始,毕竟有壳的软件是必要进行脱壳之后才能进一步分析的。这里我使用的是PEiD:

图5 对CM4进行查壳操作

根据查壳的结果可以看到,本软件是采用Microsoft Visual C++ 8.0编写的Debug版本,并没有加壳,那么接下来就可以按照上述思想开始分析了。直接单步运行进行检查,很快就可以定位到调用错误提示对话框的CALL语句,其相对地址为0x0041495C(当然真正调用MessageBox()语句的 CALL还在这个CALL的内部)。

图6 找到CDKEY检查的CALL

按F7进入这个CALL之后,继续单步执行,来到相对地址为0x00411E3C位置处的语句,由于经过上一步(test eax,eax)的验证后ZF标志位为1(两个eax的值相等),于是跳转实现,会直接跳转到0x00411F26的位置。

图7 跳转至对话框的语句

经过观察可以发现,所跳转到的0x00411F26的位置就是调用MessageBox()函数的位置,而它也正是“CDKEY检查”对话框。

图8 对话框调用函数位置

分析至此,就可以采取相应的手段来避开这个对话框,使游戏正常运行。

 

四、采取“爆破”方式来正常进入游戏

“爆破”最常用的方式是修改关键跳,对于本软件来说,就是上面分析出来的相对地址为0x00411E3C位置(图7)处的“je00411F26”(相等则跳转)语句。正是由于这个跳转实现,使得CDKEY检查对话框(图3)弹出。依据这个就可以进行修改了。

在此情况下通常有两种方式可以达到目的。一种是可以考虑改变条件跳转语句的条件。可以将je修改为jnz(不等于0则跳转),这样程序可以顺序执行下去,而不会跳转到错误提示窗口。

图9 修改跳转语句的条件

另一种是可以直接将跳转语句删除,用nop予以取代,也可以达到避免产生跳转的效果。(注意:将反汇编代码修改为nop并不是对所有程序都有效,其目的只是避免跳转,从而继续下一条语句执行。具体情况需要具体分析)。

图10 nop掉跳转语句

采用上述任何一种方式修改之后,进入游戏,可以发现错误提示窗口不再显示,并且游戏中的文字也正常了。

图11 修改后进入游戏

当然,“爆破”的手段五花八门,可供修改的位置以及方式多种多样,在此也就不再赘述。但是有一点在此需要强调,在一般的软件逆向分析中,有一种去除NAG窗口的方式是把MessageBox()函数的第一个参数(在反汇编代码中是第四个参数)的值修改为一个无意义的值,比如1,这样就会导致消息窗口创建失败,从而也就不会显示MessageBox了。

图12  修改MessageBox的hWnd参数的值

但是在本软件中,采用这种方式虽然能够去除错误窗口,但是进入游戏后依旧显示乱码(如图4所示),可见,此时虽然不再提示CDKEY检查错误对话框,但是验证依旧失败,说明验证流程已经执行了。因此在本程序中,仅仅修改hWnd这个参数是无法达到目的的。

 

五、进一步分析CM4序列号验证机理

采取“爆破”手段虽然能够解决问题,但是却修改了程序的源代码,因此并不是高明的手段。而类似于这种软件的逆向分析的最高目标,就是通过分析其序列号的验证机制,从而编写出序列号生成器,这样不会破坏程序的原始代码,也对程序有了比较深刻的理解。当然关于序列号验证算法的逆向分析与序列号生成器的程序编写,会放到下一篇文章中讨论,这里只是去寻找验证机制的反汇编代码位置。

首先可以肯定的是,序列号验证模块的入口代码一定是一个CALL语句,而且它必然在判断是否执行错误提示窗口代码(图7)的上方(可能在上方很远处)。对于本程序来说,这个CALL的返回值保存在eax中,而这个eax正好就在弹出“CDKEY检查”窗口反汇编代码的正上方:

图13 序列号验证返回值判断

一般来说,序列号的验证就是通过一系列的算法对序列号进行检验,验证结束以后,接下来的语句就可以通过返回值,也就是保存在eax中的值的情况进行判断,以决定程序接下来的走向。有些不一样的是,本程序并不是对eax中的内容直接进行判断,而是将[ebp-19d]中的值经填充后再赋给eax进行验证,那么有理由相信,用于验证的CALL语句的真正返回值会保存在[ebp-19d]中,它才是最为关键的位置。逆向分析时就需要时刻留意这个位置的值如何发生变化。换算成相对地址,也就是0x0012FCEB。

不断向上回溯查找可以发现,整个流程中会出现非常多的CALL,但是不必每一个CALL都要跟进查看,只要留意该CALL语句执行完毕后是否改变了0x0012FCEB位置的值即可。可以紧盯数据窗口中的0x0012FCEB位置,看其究竟是受到哪个CALL的影响由断点“CC”变成了非零值(关于断点“CC”的说明,可查看《技术面试问题汇总第001篇:猎豹移动反病毒工程师part1》中问题1末尾处的补充知识)。按照这种思想,很快就可以找到关键CALL:

图14 影响返回值的关键CALL

相对地址为0x0041DB3的CALL语句执行后,其返回值赋给了[ebp-19d],将该位置的值由CC变成了00。

图15  数据窗口中查看0x0012FCEB

这样一来,接下来的工作就是进入相对地址为0x0041DB3的CALL语句中进行分析了。对于这个CALL内部原理的分析,我会放在下一篇文章中。

六、小结

对软件进行逆向分析是一件非常耗时的工作,需要耐心与恒心。但是一旦成功,喜悦是不言而喻的。OllyDbg是我们反汇编工作中的利器,希望大家能够熟练掌握,还是那句话,希望各位读者能够勤加练习,才能在实际的运用中,少走弯路。

时间: 2024-12-22 02:01:03

逆向工程第005篇:跨越CM4验证机制的鸿沟(上)的相关文章

黑客攻防技术宝典web实战篇:攻击验证机制习题

猫宁!!! 参考链接:http://www.ituring.com.cn/book/885 随书答案. 1. 在测试一个使用joe和pass证书登录的Web应用程序的过程中,在登录阶段,在拦截代理服务器上看到一个要求访问以下 URL 的请求:http://www.wahh-app.com/app?action=login&uname=joe&password=pass如果不再进行其他探测,可以确定哪 3 种漏洞? (a) 由于证书在该 URL 的查询字符串中传送,因此,这些证书将面临通过浏

通过扩展改善ASP.NET MVC的验证机制[使用篇]

原文:通过扩展改善ASP.NET MVC的验证机制[使用篇] ASP.NET MVC提供一种基于元数据的验证方式是我们可以将相应的验证特性应用到作为Model实体的类型或者属性/字段上,但是这依然具有很多的不足.在这篇文章中,我结合EntLib的VAB(Validation Application Block)的一些思想通过扩展为ASP.NET MVC提供一种更为完善的验证机制.[源代码从这里下载] 目录: 一.扩展旨在解决怎样的验证问题 二.一个简单的消息维护组件 三.多语言的支持 四.基于某

通过扩展改善ASP.NET MVC的验证机制[实现篇]

原文:通过扩展改善ASP.NET MVC的验证机制[实现篇] 在<使用篇>中我们谈到扩展的验证编程方式,并且演示了本解决方案的三大特性:消息提供机制的分离.多语言的支持和多验证规则的支持,我们现在来看看这样的验证解决方案最终是如何实现的. 目录: 一.为验证创建一个上下文:ValidatorContext 二.通过自定义ActionInvoker在进行操作执行之前初始化上下文 三.为Validator创建基类:ValidatorBaseAttribute 四.通过自定义ModelValidat

ASP.NET 身份验证机制

ASP.NET提供了3种认证方式:windows身份验证:IIS根据应用程序的设置执行身份验证.要使用这种验证方式,在IIS中必须禁用匿名访问.Forms验证          :用Cookie来保存用户凭证,并将未经身份验证的用户重定向到自定义的登录页.Passport验证      :通过Microsoft的集中身份验证服务执行的,他为成员站点提供单独登录和核心配置文件服务. 关于这三种验证方式的配置,推荐一篇博文:http://www.cnblogs.com/chenqingwei/arc

HTML5 number类型文本框step属性的验证机制——张鑫旭

我在下一盘很大的棋,本文只是其中的一个棋子. 需要提前知道的: 目前而言,对step雄起的浏览器为IE10+, Chrome以及Opera浏览器. 需要预先知道number类型input的一些基本知识. HTML5 step的验证机制可以应用在不支持的浏览器上. 问题引导,威逼利诱 如下一小段含step属性的HTML代码: <input type="number" step="2.1" min="1" /> 在Chrome浏览器下长相

Oracle基础学习2--Oracle登录与三种验证机制

首先,Oracle安装完毕有三个默认用户 ?  Sys:数据库对象的拥有者.权限最高.password在安装的时候(口令管理)能够改变 ?  System:数据库管理员,password为manager ?  Scott:一个普通用户,password为tiger 再看连接Oracle的三种验证机制 ?  操作系统验证(具体解释见以下) ?  password文件验证 ?  数据库验证 注:前两者适用于系统用户,比方:Sys.System等:最后一个适用于普通用户.比方:Scott. 再看Ora

定制Asp.NET 5 MVC内建身份验证机制 - 基于自建SQL Server用户/角色数据表的表单身份验证

背景 在需要进行表单认证的Asp.NET 5 MVC项目被创建后,往往需要根据项目的实际需求做一系列的工作对MVC 5内建的身份验证机制(Asp.NET Identity)进行扩展和定制: Asp.NET内建的身份验证机制会使用Local DB(本地数据库)读写用户相关的信息,而在数据库驱动的项目中,管理业务信息的数据库通常是特定的数据库环境,比如远程SQL Server数据库实例或Access数据库等等,业务数据库中保存着一系列针对业务需求的数据表,因此需要定制MVC 5内建身份验证,使其操作

tornado 学习之 cookie 验证机制详解

本文和大家分享的主要是tornado中cookie 验证机制相关内容,一起来看看吧,希望对大家 学习tornado有所帮助. 处理过程简单来说就是验证密码之后服务器端(tornado) 返回带有  cookie  信息的  Set-Cookie header 给客户端 ,  之后客户端发起请求时会把此  cookie  放入  Cookie header  中发给服务器端. tornado 设置 cookie 首先是对 cookie  的变量进行设置 , Morsel  是含有几个特殊  key

ASP.NET MVC- 数据验证机制

ASP.NET MVC的数据验证机制,比起ASP.NET WEBFORM那种高效很多.下面记录以下两个示例,以便日后方便查阅. 方式一:在Controller里通过AddModelError方法返回错误的验证信息,看一下代码示例: Controller里的,注意看一下,他Add的时候提交是HTTPPOST,并且传参是传一个MODEL进来. public ActionResult Add() { return View(); } [HttpPost] public ActionResult Add