安卓逆向(Android)之二__《全民捕鱼》游戏内购破解

安卓逆向之二__《全民捕鱼》游戏内购破解

 

环境简介

系统:Android 4.4
工具:Windows 10 64bit 夜神模拟器
        Android Killer

        Java Decompiler

 

全民捕鱼游戏简介

游戏名称:全民捕鱼
游戏类型:休闲益智
游戏版本:1.7

游戏界面如下:

 

逆向分析

首先我们进入商城点击付费金币的购买,弹出"购买失败"的Toast(吐司)

根据这个提示我们使用AndroidKiller分析这个APK.看到入口函数为LogoActivity很简单.

直接使用特征Toast字符串搜索,没有搜到.

再次测试把字符串转换为UniCode形式(下边的小a大A按钮),再次搜索,找到一个字符串结果

双击到使用处的语句,查看源码发现此处有购买成功失败函数的选择调用语句

我们通过这几个函数继续查找对比,最后在搜索payFail的最后一个结果,发现重要函数所在

支付失败,与支付成功函数离得很近,分析发现,函数参数也相似

所以我们使用的破解内购的办法可以是,把支付成功函数的函数体,整个复制到支付失败函数里边去,让支付永远成功.

两个函数smali代码

.method public payFailed(Ljava/util/Map;I)V
    .locals 5
    .param p1, "params"    # Ljava/util/Map;
    .param p2, "arg1"    # I

    .prologue
    .line 208
    const-string v0, "cocos2d-x debug info"

    new-instance v1, Ljava/lang/StringBuilder;

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

    const-string v2, "Failed DX_payCode2 == "

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

    move-result-object v1

    sget-object v2, Lcom/payCom/org/IAPListener;->DX_PAYCODES:[Ljava/lang/String;

    iget-object v3, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;

    iget v3, v3, Lcom/payCom/org/IAPListener;->curPayIndex:I

    aget-object v2, v2, v3

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

    move-result-object v1

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

    move-result-object v1

    invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    .line 209
    const-string v0, "cocos2d-x debug info"

    new-instance v1, Ljava/lang/StringBuilder;

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

    const-string v2, "FaildCode == "

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

    move-result-object v1

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

    move-result-object v1

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

    move-result-object v1

    invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    .line 210
    iget-object v0, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;

    iget v0, v0, Lcom/payCom/org/IAPListener;->curPayIndex:I

    const/4 v1, 0x0

    invoke-static {v0, v1}, Lcom/payCom/org/GameJni;->OderFinish(II)V

    .line 211
    sget-object v0, Lcom/payCom/org/IAPListener;->iapHandler:Lcom/payCom/org/IAPHandler;

    sget-object v1, Lcom/payCom/org/IAPListener;->iapHandler:Lcom/payCom/org/IAPHandler;

    const/16 v2, 0x2715

    sget-object v3, Lcom/payCom/org/IAPListener;->DX_PAYCODES:[Ljava/lang/String;

    iget-object v4, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;

    iget v4, v4, Lcom/payCom/org/IAPListener;->curPayIndex:I

    aget-object v3, v3, v4

    invoke-static {v1, v2, v3}, Landroid/os/Message;->obtain(Landroid/os/Handler;ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    invoke-virtual {v0, v1}, Lcom/payCom/org/IAPHandler;->sendMessage(Landroid/os/Message;)Z

    .line 212
    return-void
.end method

.method public paySuccess(Ljava/util/Map;)V
    .locals 5
    .param p1, "params"    # Ljava/util/Map;

    .prologue
    .line 202
    const-string v0, "cocos2d-x debug info"

    new-instance v1, Ljava/lang/StringBuilder;

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

    const-string v2, "Success DX_payCode1"

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

    move-result-object v1

    sget-object v2, Lcom/payCom/org/IAPListener;->DX_PAYCODES:[Ljava/lang/String;

    iget-object v3, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;

    iget v3, v3, Lcom/payCom/org/IAPListener;->curPayIndex:I

    aget-object v2, v2, v3

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

    move-result-object v1

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

    move-result-object v1

    invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    .line 203
    iget-object v0, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;

    iget v0, v0, Lcom/payCom/org/IAPListener;->curPayIndex:I

    const/4 v1, 0x1

    invoke-static {v0, v1}, Lcom/payCom/org/GameJni;->OderFinish(II)V

    .line 204
    sget-object v0, Lcom/payCom/org/IAPListener;->iapHandler:Lcom/payCom/org/IAPHandler;

    sget-object v1, Lcom/payCom/org/IAPListener;->iapHandler:Lcom/payCom/org/IAPHandler;

    const/16 v2, 0x271a

    sget-object v3, Lcom/payCom/org/IAPListener;->DX_PAYCODES:[Ljava/lang/String;

    iget-object v4, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;

    iget v4, v4, Lcom/payCom/org/IAPListener;->curPayIndex:I

    aget-object v3, v3, v4

    invoke-static {v1, v2, v3}, Landroid/os/Message;->obtain(Landroid/os/Handler;ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    invoke-virtual {v0, v1}, Lcom/payCom/org/IAPHandler;->sendMessage(Landroid/os/Message;)Z

    .line 205
    return-void
.end method

修改完成后,保存,并重新编译

在夜神模拟器上卸载之前的原版游戏,安装破解后的游戏,实现了商城内购破解

 

添加个人信息的破解

为了更有趣一点,我们在购买成功的提示上添加自己的个人信息

我们再次搜索到"购买成功"提示,在字符串之前加入"Hades破解:",如下,最后再次编译,安装测试

完成破解:

总结:

安卓游戏内购的破解简单的思路都是大同小异,也可以更改调用的函数参数等.smail代码与伪Java代码很接近自然语言逻辑思路,在没有安卓加固(壳)的游戏上做一些内购破解还是很简单的.去网上Download几个游戏练习一下破解就很有成就感.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章