zoukankan      html  css  js  c++  java
  • 逆向project第003篇:跨越CM4验证机制的鸿沟(上)

    一、前言

            《冠军足球经理》系列作为一款拟真度极高的足球经营类游戏。赢得过无数赞誉,而CM4可以说是这个传奇的起点。

    可是在游戏安装过程中。当用户输入完序列号之后。程序并不会对用户的输入进行真伪推断,仅仅有等到安装完成。进入游戏之后,通过游戏是否正常显示才可以得知。而假设遇到用户不小心输入错误的情况,那么仅仅能卸载游戏又一次安装。这就会造成非常大的麻烦。

            为解决问题,这次的研究会以两篇文章的篇幅通过两种方式对这个游戏进行逆向分析。一种是採用常见的“爆破”手段,也就是本文所讨论的方法;而还有一种则是编写出CM4的注冊码生成器。这会在下一篇文章中进行讨论。

    后者须要根据反汇编代码分析出游戏的验证机制,这能够说是不论什么逆向研究的终于目标。也是本次研究的终于目标。


    图1 CM4游戏封面

     

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

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


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

            而在本研究的过程中。我尝试将序列号输入为“0123456789ABCDEF”,每一位输入不同的字符,这样便于后面的逆向跟踪。

    这样的方式往往也运用于缓冲区溢出的检測(可见《反病毒攻防研究第003篇:简单程序漏洞的利用》)。当游戏安装完成后,进入游戏。程序会先进行序列号的验证,假设之前的序列号输入错误,那么就会出现错误提示对话框。


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

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



    图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篇:猎豹移动反病毒project师part1》中问题1末尾处的补充知识)。

    依照这样的思想,非常快就能够找到关键CALL: 


    图14 影响返回值的关键CALL

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


    图15  数据窗体中查看0x0012FCEB

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

    六、小结

            对软件进行逆向分析是一件很耗时的工作,须要耐心与恒心。可是一旦成功。喜悦是不言而喻的。OllyDbg是我们反汇编工作中的利器,希望大家可以熟练掌握,还是那句话,希望各位读者可以勤加练习。才干在实际的运用中,少走弯路。
  • 相关阅读:
    47种常见的浏览器兼容性问题大汇总
    201521123029《java程序设计》第2周学习总结
    201521123029《Java程序设计》第1周学习总结
    201521123022 《Java程序设计》 第一周学习总结
    201521123020《java程序设计》第1周学习总结
    Java程序设计第三周学习总结
    201521123021第二周Java学习总结
    201521123021《Java程序设计》第1周学习总结
    201521123017 《Java程序设计》第1周学习总结
    201521123028 《Java程序设计》第2周学习总结
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7064939.html
Copyright © 2011-2022 走看看