傲世V雄哥720 发表于 2014-11-18 12:42

安卓游戏破解之分支跳转(修改分析)

本帖最后由 傲世V雄哥720 于 2014-11-20 16:27 编辑

【安卓smali破解之分支跳转(修改分析)】


终极冒险岛智能版。
存在箱底下很久了。



为什么会存在箱底很久无法破解。下面有原因的。

修改成功。下面是修改流程。
也就是今天要讲的;分支跳转修改方法。

首先;
测试游戏提示;
游戏卡死在发送中
所以直接搜;发送中。
看到如下代码;↓这就是它的整个方法的验证系统。

(Pswitch)


.method public logic_activate()V
    .locals 8

    const/4 v7, 0x2

    const/4 v6, 0x1

    const/high16 v5, 0x800

    const/4 v4, 0x0

    const/16 v3, 0x32

    sget v0, Lcom/FrameWork/Screen_Main;->activate:I

    goto/16 :goto_1    #【注释:这里就是添加的强制代码】

    packed-switch v0, :pswitch_data_0

    :cond_0
    :goto_0
    return-void

    :pswitch_0
    iget-boolean v0, p0, Lcom/FrameWork/Screen_Main;->b:Z

    if-nez v0, :cond_0

    iget v0, p0, Lcom/FrameWork/Screen_Main;->curPage:I

    packed-switch v0, :pswitch_data_1

    goto :goto_0

    :pswitch_1
    invoke-static {v5}, Lcom/FrameWork/GameScreen;->isInputDown(I)Z

    move-result v0

    if-eqz v0, :cond_1

    sget v0, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_X:I

    sget v1, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_WIDTH:I

    add-int/2addr v0, v1

    sub-int/2addr v0, v3

    sget v1, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_Y:I

    sget v2, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_HEIGHT:I

    add-int/2addr v1, v2

    sub-int/2addr v1, v3

    invoke-static {v0, v1, v3, v3}, Lcom/FrameWork/GameScreen;->touchLogic(IIII)Z

    move-result v0

    if-eqz v0, :cond_1

    invoke-static {v7}, Lcom/FrameWork/GameScreen;->changeSubScreen(I)V

    goto :goto_0

    :cond_1
    invoke-static {v5}, Lcom/FrameWork/GameScreen;->isInputDown(I)Z

    move-result v0

    if-eqz v0, :cond_0

    sget v0, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_X:I

    sget v1, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_Y:I

    sget v2, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_HEIGHT:I

    add-int/2addr v1, v2

    sub-int/2addr v1, v3

    invoke-static {v0, v1, v3, v3}, Lcom/FrameWork/GameScreen;->touchLogic(IIII)Z

    move-result v0

    if-eqz v0, :cond_0

    iput v6, p0, Lcom/FrameWork/Screen_Main;->curPage:I

    iget-object v0, p0, Lcom/FrameWork/Screen_Main;->activateBox:LhlLib/HLTextBox;

    const-string v1, ""是否确认购买正版验证?"

    invoke-virtual {v0, v1}, LhlLib/HLTextBox;->setText(Ljava/lang/String;)V

    goto :goto_0

    :pswitch_2
    invoke-static {v5}, Lcom/FrameWork/GameScreen;->isInputDown(I)Z

    move-result v0

    if-eqz v0, :cond_2

    sget v0, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_X:I

    sget v1, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_WIDTH:I

    add-int/2addr v0, v1

    sub-int/2addr v0, v3

    sget v1, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_Y:I

    sget v2, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_HEIGHT:I

    add-int/2addr v1, v2

    sub-int/2addr v1, v3

    invoke-static {v0, v1, v3, v3}, Lcom/FrameWork/GameScreen;->touchLogic(IIII)Z

    move-result v0

    if-eqz v0, :cond_2

    iput v4, p0, Lcom/FrameWork/Screen_Main;->curPage:I

    iget-object v0, p0, Lcom/FrameWork/Screen_Main;->activateBox:LhlLib/HLTextBox;

    const-string v1, "购买正版验证,可获得游戏后续关卡,信息费5元(不含通信费),通过短信代收,是否确认购买?"

    invoke-virtual {v0, v1}, LhlLib/HLTextBox;->setText(Ljava/lang/String;)V

    goto :goto_0

    :cond_2
    invoke-static {v5}, Lcom/FrameWork/GameScreen;->isInputDown(I)Z

    move-result v0

    if-eqz v0, :cond_0

    sget v0, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_X:I

    sget v1, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_Y:I

    sget v2, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_HEIGHT:I

    add-int/2addr v1, v2

    sub-int/2addr v1, v3

    invoke-static {v0, v1, v3, v3}, Lcom/FrameWork/GameScreen;->touchLogic(IIII)Z

    move-result v0

    if-eqz v0, :cond_0

    invoke-virtual {p0}, Lcom/FrameWork/Screen_Main;->sendMessage()V

    iput-boolean v6, p0, Lcom/FrameWork/Screen_Main;->b:Z

    iget-object v0, p0, Lcom/FrameWork/Screen_Main;->activateBox:LhlLib/HLTextBox;

    const-string v1, "发送中...."

    invoke-virtual {v0, v1}, LhlLib/HLTextBox;->setText(Ljava/lang/String;)V

    goto/16 :goto_0

    :pswitch_3
    sput v4, Lcom/FrameWork/Screen_Main;->activate:I

    goto/16 :goto_0

    :pswitch_4
    invoke-static {v7}, Lcom/FrameWork/GameScreen;->changeSubScreen(I)V

    sput v4, Lcom/FrameWork/Screen_Main;->activate:I

    sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;

    new-instance v1, Ljava/lang/StringBuilder;

    const-string v2, "ACTIVATE_CANCEL======"

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

    sget v2, Lcom/FrameWork/Screen_Main;->activate:I

    invoke-virtual {v1, v2}, 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-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

    const/4 v0, -0x1

    invoke-static {v4, v0}, Lcom/FrameWork/GameScreen;->setSaveGameInt(II)V

    const/16 v0, 0x8

    sget v1, Lcom/FrameWork/Screen_Main;->activate:I

    invoke-static {v0, v1}, Lcom/FrameWork/GameScreen;->setSaveGameInt(II)V

    invoke-static {v6}, Lcom/FrameWork/GameScreen;->saveSave(I)V

    goto/16 :goto_0

    :goto_1    【#注释:goto_1跳向了这里。成功】
    :pswitch_5
    iget-object v0, p0, Lcom/FrameWork/Screen_Main;->activateBox:LhlLib/HLTextBox;

    const-string v1, "游戏激活成功! "

    invoke-virtual {v0, v1}, LhlLib/HLTextBox;->setText(Ljava/lang/String;)V

    invoke-static {v5}, Lcom/FrameWork/GameScreen;->isInputDown(I)Z

    move-result v0

    if-eqz v0, :cond_0

    sget v0, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_X:I

    sget v1, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_WIDTH:I

    add-int/2addr v0, v1

    sub-int/2addr v0, v3

    sget v1, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_Y:I

    sget v2, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_HEIGHT:I

    add-int/2addr v1, v2

    sub-int/2addr v1, v3

    invoke-static {v0, v1, v3, v3}, Lcom/FrameWork/GameScreen;->touchLogic(IIII)Z

    move-result v0

    if-eqz v0, :cond_0

    sget v0, Lcom/FrameWork/Screen_Main;->curStageNumber:I

    add-int/lit8 v0, v0, 0x1

    invoke-direct {p0, v0}, Lcom/FrameWork/Screen_Main;->changeToSelectStage(I)V

    const/16 v0, 0x8

    sget v1, Lcom/FrameWork/Screen_Main;->activate:I

    invoke-static {v0, v1}, Lcom/FrameWork/GameScreen;->setSaveGameInt(II)V

    invoke-static {v6}, Lcom/FrameWork/GameScreen;->saveSave(I)V

    goto/16 :goto_0

    :pswitch_6
    sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;

    const-string v1, "ACTIVATE_ERROR"

    invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

    sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;

    new-instance v1, Ljava/lang/StringBuilder;

    const-string v2, "erroCode==="

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

    sget v2, Lcom/FrameWork/Screen_Main;->erroCode:I

    invoke-virtual {v1, v2}, 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-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

    sget v0, Lcom/FrameWork/Screen_Main;->erroCode:I

    packed-switch v0, :pswitch_data_2

    :goto_2
    invoke-static {v5}, Lcom/FrameWork/GameScreen;->isInputDown(I)Z

    move-result v0

    if-eqz v0, :cond_0

    sget v0, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_X:I

    sget v1, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_WIDTH:I

    add-int/2addr v0, v1

    sub-int/2addr v0, v3

    sget v1, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_OFFSET_Y:I

    sget v2, Lcom/FrameWork/Screen_Main;->LOGIC_SCREEN_HEIGHT:I

    add-int/2addr v1, v2

    sub-int/2addr v1, v3

    invoke-static {v0, v1, v3, v3}, Lcom/FrameWork/GameScreen;->touchLogic(IIII)Z

    move-result v0

    if-eqz v0, :cond_0

    invoke-static {v7}, Lcom/FrameWork/GameScreen;->changeSubScreen(I)V

    sput v4, Lcom/FrameWork/Screen_Main;->activate:I

    const/4 v0, -0x1

    invoke-static {v4, v0}, Lcom/FrameWork/GameScreen;->setSaveGameInt(II)V

    const/16 v0, 0x8

    sget v1, Lcom/FrameWork/Screen_Main;->activate:I

    invoke-static {v0, v1}, Lcom/FrameWork/GameScreen;->setSaveGameInt(II)V

    invoke-static {v6}, Lcom/FrameWork/GameScreen;->saveSave(I)V

    goto/16 :goto_0

    :pswitch_7
    iget-object v0, p0, Lcom/FrameWork/Screen_Main;->activateBox:LhlLib/HLTextBox;

    const-string v1, "发送短信失败后未使用联网计费。"

    invoke-virtual {v0, v1}, LhlLib/HLTextBox;->setText(Ljava/lang/String;)V

    goto :goto_2

    :pswitch_8
    iget-object v0, p0, Lcom/FrameWork/Screen_Main;->activateBox:LhlLib/HLTextBox;

    const-string v1, "联网失败,请查看网络设置。"

    invoke-virtual {v0, v1}, LhlLib/HLTextBox;->setText(Ljava/lang/String;)V

    goto :goto_2

    :pswitch_9
    iget-object v0, p0, Lcom/FrameWork/Screen_Main;->activateBox:LhlLib/HLTextBox;

    const-string v1, "Android手机未使用CMWAP计费"

    invoke-virtual {v0, v1}, LhlLib/HLTextBox;->setText(Ljava/lang/String;)V

    goto :goto_2

    nop

    :pswitch_data_0
    .packed-switch 0x0
      :pswitch_0
      :pswitch_3
      :pswitch_5
      :pswitch_4
      :pswitch_6
    .end packed-switch

    :pswitch_data_1
    .packed-switch 0x0
      :pswitch_1
      :pswitch_2
    .end packed-switch

    :pswitch_data_2
    .packed-switch 0x6
      :pswitch_7
      :pswitch_8
      :pswitch_9
    .end packed-switch
.end method



图上的代码是修改后的。

代码头的分支判断跳转;
    packed-switch v0, :pswitch_data_0

这一个分支判断。当游戏弹出购买→选择下一步的时候,它就会来到这里。

来到这里后,然后跳转到底部如下代码。

   :pswitch_data_0
    .packed-switch 0x0
      :pswitch_0
      :pswitch_3   (CANCEL)
      :pswitch_5(成功激活)
      :pswitch_4(失败)
      :pswitch_6    (联网错误)
    .end packed-switch




然后pswitch_data_0,判断;购买成功失败。返回结果如果是成功。
成功会来到 pswitch_5.

因为它的失败混淆了。没有;失败字样。
所以。我们在判断的前面
加上一个代码。

强制跳向成功。
成功的源头是;pswitch_5

所以在上面的代码;修改;

    goto/16 :goto_1

    packed-switch v0, :pswitch_data_0


goto/16 :goto_1
跳向了;pswitch_5(成功)
所以。购买→确定→直接成功。


总结一下吧。

分支判断的游戏(验证系统。)
修改方法;
在它判断的地方。前面加上goto进行强制跳转。跳向成功。

另外要注意;
goto的使用。
假如成功的源头是;switch_99298
因为它后面是5位数。goto/4不够用。所以用goto/16
也就是说改的时候。如果goto对应分支位数不足。那么就会出错。

【goto分为;goto    goto/4   goto/16   goto/32】
【goto在代码里的应用:无条件跳转(向)

分支跳转(pswitch)我研究了下。它不能和条件判断跳转(if-eqz)一样。删掉失败跳转。跳向成功。
分支只能强制goto跳转。
分支如果删掉的话。当代码来到这里的时候会卡死。无响应。




这个冒险岛改掉了。先上截图。然后发附件。

游戏个人感觉还不错。这次就把破解版的附件发上来吧。

游戏截图;






















说明;点击内购→直接如图中的;激活成功。点击返回。即可。
如果卡住。多点几次返回。

附件不是主要。我讲的主要是;分支判断如何去修改。破解。
如果各位有什么问题可以到本贴提问。

下载说明;
这有2个版的冒险岛。1版和2版。都放在压缩包里了。解压即可。

下载地址:


链接: http://pan.baidu.com/s/1hquy8kO

密码: ggkl








qwe1154323937 发表于 2014-11-24 21:38

傲世V雄哥720 发表于 2014-11-23 06:56
smali就不做教程了。

学习完ARM汇编就制作教程。

{:301_971:}   用APKIDE找关键字看的代码太复杂了, 有的改了不行有的改了还进不去游戏 =、=   现在很难找到教程什么的   愿大大 出个教程什么的谢谢!!

傲世V雄哥720 发表于 2014-11-18 19:16

本帖最后由 傲世V雄哥720 于 2014-11-18 19:17 编辑

mgsjh 发表于 2014-11-18 18:40
是直加
    goto/16 :goto_1    #【注释:这里就是添加的强制代码】


是吧。
smali代码是写一行空一行。

goto/16 :goto_1
这个是成功的源头是1
所以是goto_1

如果成功是
pswitch_5
那么goto就是
goto/16 :pswitch_5

lixingcong 发表于 2014-11-18 12:46

smail是什么,好难阅读啊

淡然出尘 发表于 2014-11-18 12:51

假如成功的源头是;switch_99298
因为它后面是5位数。goto/4不够用。所以用goto/16

赞一个

Avenshy 发表于 2014-11-18 13:09

安卓破解初始阶段。。至今不会用IDA调戏so文件。。

Taurus初心 发表于 2014-11-18 13:27

好厉害,长知识了

851518232 发表于 2014-11-18 13:33

APK代码很难懂的样子

Kesuen 发表于 2014-11-18 14:09

学习了,刚刚学习很多需要慢慢研究。。

JK52PJ 发表于 2014-11-18 14:16

多谢楼主分享。

hzgg676102014 发表于 2014-11-18 14:34

为什么看起来那么复杂

guanggao 发表于 2014-11-18 14:38

谢楼主分享
谢楼主分享
页: [1] 2 3 4 5 6
查看完整版本: 安卓游戏破解之分支跳转(修改分析)