本文通过逆向分析Flappy Bird安卓版,最后达到修改分数,取消水管碰撞检测,取消落地检测的效果。

目标APK:Flappy Bird安卓版
使用工具:APK改之理
目的:修改每过一关的增长分数、取消水管碰撞检测、取消落地检测

  • 修改每过一关的增长分数
    反编译的步骤就不介绍了,我们直接来看反编译得到的文件夹:
    1
    方法1:在smali目录下,我们看到org/andengine/,可以知晓游戏是由andengine引擎开发的。打开/res/raw/atlas.txt文件,找到如下信息:
    2
    我们直接把number_score_00 01….08的坐标值全部修改为number_score_09的坐标值,重新打包并签名apk,运行测试,0-9关分数一直为9分,10-99关分数一直为99分。
    方法2:打开string.xml,没有找到有用的信息,由于代码是被混淆过的,无法直接根据类名找关键代码。我们换另一种方式,查找string变量,用工具apk改之理打开apk文件,选中smali/com/dotgears/文件夹,在软件右侧面板,按如下操作:
    3
    在搜索结果中,有这样一条记录:

    const-string v0, "0123456789"
    

    我们不妨猜测该字符串是用来获取分数的,双击来到所在文件,\com\dotgears\h.smali。关键代码如下:

    # direct methods   
    .method static constructor <clinit>()V    
    .locals 1
    const-string v0, "0123456789"
    sput-object v0, Lcom/dotgears/h;->l:Ljava/lang/String;
    return-void   
    .end method
    

    为了测试我们的猜测,直接将“0123456789”修改为“9999999999”,打包签名安装,运行测试,0-9关分数一直为9分,10-99关分数一直为99分。猜测正确。

    sput-object v0, Lcom/dotgears/h;->l:Ljava/lang/String  //将string类型的变量I赋值为“0123456789”
    

    我们在当前文件查找l:Ljava/lang/String, 在方法.method public a(II)V中发现调用,部分代码为:

    sget-object v5, Lcom/dotgears/h;->l:Ljava/lang/String;
    invoke-virtual {v5, v2}, Ljava/lang/String;->charAt(I)C
    

    我们转到反编译出的java代码来仔细看下该方法:

    public void a(int paramInt1, int paramInt2)
    {
        this.k = 0;
        int m = paramInt1;
        if (paramInt2 <= 0);
        for (int i1 = 0; ; i1++)
        {
          if (i1 >= this.k)
          {
            if (this.k == 0)
            {
              this.i[0] = '0';
              this.k = 1;
            }
            return;
            if (m <= 0);
            while (true)
            {
              paramInt2--;
              break;
              int n = m % 10;
              m /= 10;
              this.j[this.k] = l.charAt(n);
              this.k = (1 + this.k);
            }
          }
          this.i[i1] = this.j[(-1 + (this.k - i1))];
        }
    }
    

    参数paramInt1为所得分数,paramInt2为所得分数位数

    int n = m % 10; //获取分数低位
    m /= 10; //获取分数高位
    this.j[this.k] = l.charAt(n); //取分数
    

    验证:我们直接在该方法中对参数进行赋值,然后打包签名,安装测试即可。事实上,该方法的作用是实时更新界面上方的显示的分数。
    通过修改此处的参数paramInt1的值,我们就可以修改上方显示的分数,但是最终记录的分数仍然未改变,为此我们必须找到该方法在哪里被程序调用,以及参数paramInt1是如何得来的。
    利用ida或者jeb定位到上层调用方法:

    this.an.a(this.y, 20);
    

    即参数paramInt1为this.y,参数paramInt2固定取20。
    继续往上搜索变量this.y,来到此处:

    if ((this.ao > 0) && (this.ak <= 0) && ((this.ag == this.J.b) || (this.ag == -1 + this.J.b)))
    {
        this.y = (1 + this.y);
        c(9, 0);
    }
    

    this.y在前面已被初始化为0,此处,if循环应为判断是否得分的条件,如果为真,则分数加1。显然,我们直接将1修改为我们所希望的增长分数即可。打开对应的smali文件:/dotgears/flappy/c.smali,修改第489行代码:

    add-int/lit8 v0, v0, 0x1 -> add-int/lit8 v0, v0, 0x*  //*为你所希望的增长分数(16进制)
    

    重新打包,签名安装,测试通过。

  • 取消水管碰撞检测
    修改文件:/com/dotgears/flappy/c.smali
    修改前后对比(这个方法就是水管的碰撞检测,直接使返回值固定为0即可):
    4
    5

  • 取消落地检测
    修改文件:/com/dotgears/flappy/c.smali
    修改方法.method public b(F)V中部分代码,修改前后对比(取消落地检测判断,无条件跳转):
    6
    7

工具下载地址:http://pan.baidu.com/s/1ntyk1uT
原始apk:http://pan.baidu.com/s/1jGsQTfS