Android逆向笔记

「 50层魔塔 」smali修改初始化金币和插入Toast提示

2018-06-08  本文已影响104人  h080294

今天无意翻出来一款我认为非常经典的游戏 -- 50层魔塔。回想起在flash时代,操作着键盘的上下左右键,仔细的拿纸计算着攻击防御和血量。甚至还能依稀地体会到经历无数次失败后最终通关的那种喜悦。

flash版本的50层魔塔

魔塔故事背景(摘选自百科)

一个实力高强的魔王,想要找一位拥有足够力量支配神圣剑的人,与他合作,使黑暗降临世界。所以,魔王就以一个洋娃娃公主为诱饵,引诱了一位勇士(就是你)进入了魔塔。在魔塔中,魔王装扮成小偷,在游戏过程中不断为勇士提供帮助。勇士到达塔顶,与魔王对话,在对话中得知魔王想让黑暗降临在这个世界,并且想要勇士交出神圣剑,配合魔王的智慧权杖,与魔王一起使黑暗降临世界,勇士当然不会同意,就杀死了魔王。最终,勇士拯救了世界。

smali逆向修改

不同于之前的高难度,在这款Android 50层魔塔游戏中,原作者增加了商店,可以通过支付宝购买魔塔币,然后用魔塔币购买道具或人物属性等。

想要获取更多的魔塔币,我们可以修改购买回调的逻辑,让支付失败的逻辑变成支付成功。对于这种单机校验性不强的游戏,通常还可以修改其初始化值,游戏初始化的魔塔币的值。在此过程中,介绍一些非常简单但实用适合新手的小方法。

1、定位到当前的页面

通常,字符串都是我们第一考虑下手的对象,搜索充值魔塔币或者当前魔塔币字符串。可以看到字符串出现在activity_ext.xml布局文件中。

接下来继续搜索谁引用了activity_ext.xml,记录下id:0x7f030000

搜索id值,找到相关的调用,发现是在com/cyanflxy/game/ext/ExtActivity中进行了初始化。

这样就知道了当前页面为com.cyanflxy.game.ext.ExtActivity。当然我们还可以通过adb命令,获取当前焦点页面的信息。

$ adb shell dumpsys activity | grep "mFocusedActivity"
  mFocusedActivity: ActivityRecord{fd18f29 u0 com.itwonder.mota50g/com.cyanflxy.game.ext.ExtActivity t489}

2、查找金币金额初始化的地方

前面做了textview的初始化,后面调用了一个g方法。

    .line 57
    const/high16 v0, 0x7f090000

    invoke-virtual {p0, v0}, Lcom/cyanflxy/game/ext/ExtActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/TextView;

    iput-object v0, p0, Lcom/cyanflxy/game/ext/ExtActivity;->m:Landroid/widget/TextView;

    .line 59
    invoke-static {}, Lcom/cyanflxy/game/b/a;->getInstance()Lcom/cyanflxy/game/b/a;

    move-result-object v0

    iput-object v0, p0, Lcom/cyanflxy/game/ext/ExtActivity;->i:Lcom/cyanflxy/game/b/a;

    .line 60
    invoke-direct {p0}, Lcom/cyanflxy/game/ext/ExtActivity;->g()V

    .line 61
    return-void

下面看一下g方法,先是调用了com/cyanflxy/game/a/a中的k方法,获得一个值,然后通过setText方法将值(金币)展示出来。

.method private g()V
    .locals 4

    .prologue
    .line 298
    invoke-static {}, Lcom/cyanflxy/game/a/a;->k()I

    move-result v0

    .line 299
    iget-object v1, p0, Lcom/cyanflxy/game/ext/ExtActivity;->m:Landroid/widget/TextView;

    new-instance v2, Ljava/lang/StringBuilder;

    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V

    const-string v3, ""

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v0

    invoke-virtual {v1, v0}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 300
    return-void
.end method

最后看下com/cyanflxy/game/a/a中的k方法,该方法从SharedPreferences中去一个叫user_balance的值,默认值是0x64,也就是十进制的100。这里我们可以修改这个默认值,比如一百万。需要注意的是,源代码使用了const/16,也就是位数上做了限制,最大值是0xFFFF。为了让值能更大些,我们直接使用const v3, 0x989680就可以了(0x989680 = 一千万)。

.method public static declared-synchronized k()I
    .locals 4

    .prologue
    .line 173
    const-class v1, Lcom/cyanflxy/game/a/a;

    monitor-enter v1

    :try_start_0
    sget-object v0, Lcom/cyanflxy/game/a/a;->a:Landroid/content/SharedPreferences;

    const-string v2, "user_balance"

    const/16 v3, 0x64

    invoke-interface {v0, v2, v3}, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I
    :try_end_0
    .catchall {:try_start_0 .. :try_end_0} :catchall_0

    move-result v0

    monitor-exit v1

    return v0

    :catchall_0
    move-exception v0

    monitor-exit v1

    throw v0
.end method

3、插入启动Toast

我们修改完了,想要标识一下是谁对游戏动了手脚,就需要在游戏启动的时候,弹一个Toast提示。

代码很简单,从androidManifest文件中,找到游戏的入口。这里我们可以很明显的看到游戏的入口为com.cyanflxy.magictower.MainActivity。

        <activity android:name="com.cyanflxy.magictower.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

那么接下来,在Oncreat方法中,插入toast代码即可。由于我们需要额外的寄存器来存储我们的变量,因此在方法开始的地方,不要忘了增加.locals的数量。

    const v4, 0x1
    ...(省略)
    .line 37
    const-string v0, "\u7834\u89e3\u0020\u0042\u0079\u0020\u004a\u006f\u0068\u006e\u0020\u0048\u0061\u006f\u0020\u002d\u002d\u0020\u0035\u0032\u0070\u006f\u006a\u0069\u0065"

    invoke-static {p0, v0, v4}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object v0

    invoke-virtual {v0}, Landroid/widget/Toast;->show()V

打包重新运行,在开始的界面就能看到我们自己特有的Toast提示了。

4、禁用购买的响应事件

画蛇添足的取消了购买的响应事件,替换了对应的文案为为保证游戏平衡谨慎购买,也就是不能再去支付宝了。

链接: https://pan.baidu.com/s/1j7eSdcTaNgN92-o_7gbp_w
密码: 37qk

关注获取更多
上一篇下一篇

猜你喜欢

热点阅读