Android逆向

Android逆向

本文作者:MSTLab-EvilChen

0x00 前言首先,本来想写NDK的,但是还是先把这个流程过一遍吧,这个流程是必不可少的。其次,RMB真的是一个好东西。

导航由于本人为了节省时间,不想贴太多的代码,所以总结了一个导航栏目。并且在栏目中有内容的说明。帮助了解。希望一起进步。博客系列导航为了练习方便,顺便把apk进行了一个整理。练习传送门

内容1.内购基础

0x01 内购知识基本知识什么是内购?内购就是游戏内部购买。

SDK厂商1.移动2.电信3.联通4.支付宝5.微信6.其他

其他破解拇指玩网侠手机站7723爱吾7yw趣游软天空西西软件园葫芦侠三楼

游戏平台1.某咕游戏

0x02 经验总结关键点通用总结通用1最古老的方法就是搜索关键字:“成功““失败”

绕过通用switch(1)覆盖switch失败转为成功。(2)更改switch跳转(3)最后一种我最喜欢作用,思路最明确,使用goto进行跳转。跳转到成功即可。

某咕游戏总结方法 :onResult

移动总结onbillingfinish()dobilling()onresult()

联通总结payCallback()PayResult()

电信总结paySuccess()

支付宝总结支付失败9000ResultStaus

0x03 某咕游戏破解实例也不能说是因为篇幅问题吧,就是有点犯懒,不想截取一些简单的步骤。所以能简写就简写,这样能多分析几个实例。

实例是我刚找的。

原版apk:练习传送门在这里找,编号:2001

实例分析(1)暂停:2018年2月12日00:34:05原因:吵到我爸睡觉了。

开始时间: 2018年2月12日14:58:17

第一步:试玩。自己玩

第二步:反编译,搜索关键字。1.搜索“成功”

这里搜索到了三条数据

点进去之后是这样一个方法:

.method public static d()V

.locals 4

const/4 v3, 0x1

const/4 v2, 0x0

sget v0, Lcom/xy/kom/d/bk;->i:I

invoke-static {v0}, Lcom/xy/kom/g/p;->b(I)Z

sget v0, Lcom/xy/kom/d/bk;->h:I

invoke-static {v0}, Lcom/xy/kom/g/p;->c(I)Z

sget-boolean v0, Lcom/xy/kom/d/bk;->G:Z

if-eqz v0, :cond_4

sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;

iget-object v0, v0, Lcom/xy/kom/GameActivity;->m:Lcom/xy/kom/g/p;

invoke-virtual {v0}, Lcom/xy/kom/g/p;->x()Ljava/util/ArrayList;

move-result-object v0

invoke-static {}, Lcom/xy/kom/g/f;->l()Lcom/xy/kom/g/f;

move-result-object v1

invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z

:goto_0

sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;

iget-object v0, v0, Lcom/xy/kom/GameActivity;->m:Lcom/xy/kom/g/p;

invoke-virtual {v0}, Lcom/xy/kom/g/p;->t()V

sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;

iget-object v0, v0, Lcom/xy/kom/GameActivity;->r:Lcom/xy/kom/d/ei;

if-eqz v0, :cond_0

sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;

iget-object v0, v0, Lcom/xy/kom/GameActivity;->r:Lcom/xy/kom/d/ei;

invoke-virtual {v0, v2}, Lcom/xy/kom/d/ei;->a(I)V

:cond_0

sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;

const/4 v1, 0x6

invoke-virtual {v0, v1}, Lcom/xy/kom/GameActivity;->a(I)V

invoke-static {}, Lcom/xy/kom/d/bk;->h()V

sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;

const-string v1, "\u8d2d\u4e70\u6210\u529f\uff01\u9053\u5177\u5df2\u53d1\u653e"

invoke-static {v0, v1, v2}, 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

sget-object v0, Lcom/xy/kom/GameActivity;->N:Lcom/xy/kom/e/a;

invoke-virtual {v0, v3}, Lcom/xy/kom/e/a;->a(I)V

sput-boolean v3, Lcom/xy/kom/GameActivity;->M:Z

invoke-static {}, Lcom/xy/kom/a/h;->f()I

move-result v0

const/16 v1, 0xd

if-ne v0, v1, :cond_2

sget v0, Lcom/xy/kom/GameActivity;->h:I

const/4 v1, 0x2

if-ne v0, v1, :cond_2

sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;

iget-object v0, v0, Lcom/xy/kom/GameActivity;->m:Lcom/xy/kom/g/p;

invoke-virtual {v0}, Lcom/xy/kom/g/p;->w()Ljava/util/ArrayList;

move-result-object v0

invoke-interface {v0}, Ljava/util/List;->size()I

move-result v1

sget-object v2, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;

iget-object v2, v2, Lcom/xy/kom/GameActivity;->m:Lcom/xy/kom/g/p;

invoke-virtual {v2}, Lcom/xy/kom/g/p;->l()I

move-result v2

if-ne v1, v2, :cond_1

sget-object v1, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;

iget-object v1, v1, Lcom/xy/kom/GameActivity;->r:Lcom/xy/kom/d/ei;

invoke-interface {v0}, Ljava/util/List;->size()I

move-result v2

add-int/lit8 v2, v2, -0x1

invoke-interface {v0, v2}, Ljava/util/List;->get(I)Ljava/lang/Object;

move-result-object v0

check-cast v0, Lcom/xy/kom/g/f;

invoke-virtual {v1, v0}, Lcom/xy/kom/d/ei;->b(Lcom/xy/kom/g/f;)V

:cond_1

sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;

iget-object v0, v0, Lcom/xy/kom/GameActivity;->r:Lcom/xy/kom/d/ei;

sget-object v1, Lcom/xy/kom/d/bk;->d:Lcom/xy/kom/g/f;

invoke-virtual {v0, v1}, Lcom/xy/kom/d/ei;->a(Lcom/xy/kom/g/f;)V

invoke-static {}, Lcom/xy/kom/d/bk;->m()V

:cond_2

sget-boolean v0, Lcom/xy/kom/d/bk;->G:Z

if-nez v0, :cond_3

const/4 v0, 0x0

sput-object v0, Lcom/xy/kom/d/bk;->d:Lcom/xy/kom/g/f;

:cond_3

return-void

:cond_4

sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;

iget-object v0, v0, Lcom/xy/kom/GameActivity;->m:Lcom/xy/kom/g/p;

invoke-virtual {v0}, Lcom/xy/kom/g/p;->x()Ljava/util/ArrayList;

move-result-object v0

sget-object v1, Lcom/xy/kom/d/bk;->d:Lcom/xy/kom/g/f;

invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z

goto/16 :goto_0

.end method

这里找到一个调用成功的方法。我们继续溯源查看。

发现是一个onResult方法。

解决方法:(1)覆盖switch失败转为成功。(2)更改switch跳转(3)最后一种我最喜欢作用,思路最明确,使用goto进行跳转。跳转到成功即可。

恩,改完之后汇编,整个游戏就破解好了。没什么好说的。

测试成果。是成功的,懒的玩。不想发图,自己测试吧,有疑问可以找我。

实例分析(2)之前没有找好,现在去找找。找练习的APK的时候主要注意三点。(1)最好是单机(2)选择大小的时候选小一点的,恩,反编译快。我们的目的是为了练习。(3)无壳,现阶段可定脱不了壳。

找到了一个什么酷跑什么的游戏。三步走

第一步 试玩原版apk:练习传送门在这里找,编号:2002

拿到游戏,首先就要玩一下是不,人家怎么购买的你总要知道吧。说不定会有新的发现。

反编译破解搜索关键字“成功失败”

点开之后进去,发现,原来还是一个onResult。

.method public onResult(ILjava/lang/String;Ljava/lang/Object;)V

.locals 3

.param p1, "paramAnonymousInt" # I

.param p2, "paramAnonymousString" # Ljava/lang/String;

.param p3, "paramAnonymousObject" # Ljava/lang/Object;

.prologue

goto :pswitch_0

.line 26

packed-switch p1, :pswitch_data_0

.line 37

const-string v0, "Unity"

new-instance v1, Ljava/lang/StringBuilder;

const-string v2, "\u8d2d\u4e70\u9053\u5177\uff1a["

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

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

move-result-object v1

const-string v2, "]\u53d6\u6d88\uff01"

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;->v(Ljava/lang/String;Ljava/lang/String;)I

.line 38

invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$0()Ljava/lang/String;

move-result-object v0

invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$1()Ljava/lang/String;

move-result-object v1

const-string v2, "cancel"

invoke-static {v0, v1, v2}, Lcom/unity3d/player/UnityPlayer;->UnitySendMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V

.line 41

:goto_0

return-void

.line 29

:pswitch_0

const-string v0, "Unity"

new-instance v1, Ljava/lang/StringBuilder;

const-string v2, "\u8d2d\u4e70\u9053\u5177\uff1a["

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

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

move-result-object v1

const-string v2, "] \u6210\u529f\uff01"

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;->v(Ljava/lang/String;Ljava/lang/String;)I

.line 30

invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$0()Ljava/lang/String;

move-result-object v0

invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$1()Ljava/lang/String;

move-result-object v1

const-string v2, "success"

invoke-static {v0, v1, v2}, Lcom/unity3d/player/UnityPlayer;->UnitySendMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V

goto :goto_0

.line 33

:pswitch_1

const-string v0, "Unity"

new-instance v1, Ljava/lang/StringBuilder;

const-string v2, "\u8d2d\u4e70\u9053\u5177\uff1a["

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

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

move-result-object v1

const-string v2, "] \u5931\u8d25\uff01"

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;->v(Ljava/lang/String;Ljava/lang/String;)I

.line 34

invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$0()Ljava/lang/String;

move-result-object v0

invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$1()Ljava/lang/String;

move-result-object v1

const-string v2, "fail"

invoke-static {v0, v1, v2}, Lcom/unity3d/player/UnityPlayer;->UnitySendMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V

goto :goto_0

.line 26

nop

:pswitch_data_0

.packed-switch 0x1

:pswitch_0

:pswitch_1

.end packed-switch

.end method

咪咕整个支付流程大概就是这个样子。(我猜的)

原本游戏(隐藏不可见)—咪咕支付接口(可见)——咪咕支付处理(不可见)——返回结果(可见)——回馈给原本游戏(不可见)

我们搞的其实就是在返回结果上动手脚。

测试测试我做了,但是截图不了,有兴趣的可以自己去做下尝试。

总结咪咕游戏最明显的一个特征就是 onResult()这个方法,只要改了这个方法,那么就可以轻松搞定了。当然你也可以通过其他手段找到它的特征。不过经验是可以提高效率哒嘛。

0x04 结束语说明这些只是对方法的一个总结,在总结的时候,可能没有时间整理实例了,但是在之后有时间或者遇到的话,那么我们就可以从这里找到方法去破解内购等。当然也包括了二次破解等说明。之后如果需要则进行补充。

🌈 相关推荐

为什么蟋蟀沾水就死
博大365

为什么蟋蟀沾水就死

📅 09-15 👁️ 6755
迷你辣椒蟹吃什么食物好养活
博大365

迷你辣椒蟹吃什么食物好养活

📅 08-07 👁️ 4272