安卓游戏破解之分支跳转(修改分析)
本帖最后由 傲世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
傲世V雄哥720 发表于 2014-11-23 06:56
smali就不做教程了。
学习完ARM汇编就制作教程。
{:301_971:} 用APKIDE找关键字看的代码太复杂了, 有的改了不行有的改了还进不去游戏 =、= 现在很难找到教程什么的 愿大大 出个教程什么的谢谢!! 本帖最后由 傲世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 smail是什么,好难阅读啊 假如成功的源头是;switch_99298
因为它后面是5位数。goto/4不够用。所以用goto/16
赞一个 安卓破解初始阶段。。至今不会用IDA调戏so文件。。 好厉害,长知识了 APK代码很难懂的样子 学习了,刚刚学习很多需要慢慢研究。。 多谢楼主分享。 为什么看起来那么复杂 谢楼主分享
谢楼主分享