0x00 前言

看这个吧

https://bbs.ichunqiu.com/thread-34304-1-1.html

前置

感谢蛋总栽培,此文章首发I春秋,非本人同意禁止转载。

说明

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

时间

2018年2月11日23:05:33大概写一会儿就去睡觉了

导航

由于本人为了节省时间,不想贴太多的代码,所以总结了一个导航栏目。并且在栏目中有内容的说明。帮助了解。希望一起进步。
博客系列导航
为了练习方便,顺便把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()

支付宝总结

支付失败
9000
ResultStaus

0x03 咪咕游戏破解实例

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

实例是我刚找的。

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

实例分析(1)

暂停:2018年2月12日00:34:05
原因:吵到我爸睡觉了。

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

第一步:试玩。

自己玩

第二步:反编译,搜索关键字。

1.搜索“成功”
这里搜索到了三条数据

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

.method public static d()V.locals 4const/4 v3, 0x1const/4 v2, 0x0sget v0, Lcom/xy/kom/d/bk;->i:Iinvoke-static {v0}, Lcom/xy/kom/g/p;->b(I)Zsget v0, Lcom/xy/kom/d/bk;->h:Iinvoke-static {v0}, Lcom/xy/kom/g/p;->c(I)Zsget-boolean v0, Lcom/xy/kom/d/bk;->G:Zif-eqz v0, :cond_4sget-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 v0invoke-static {}, Lcom/xy/kom/g/f;->l()Lcom/xy/kom/g/f;move-result-object v1invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z:goto_0sget-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()Vsget-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_0sget-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_0sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;const/4 v1, 0x6invoke-virtual {v0, v1}, Lcom/xy/kom/GameActivity;->a(I)Vinvoke-static {}, Lcom/xy/kom/d/bk;->h()Vsget-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 v0invoke-virtual {v0}, Landroid/widget/Toast;->show()Vsget-object v0, Lcom/xy/kom/GameActivity;->N:Lcom/xy/kom/e/a;invoke-virtual {v0, v3}, Lcom/xy/kom/e/a;->a(I)Vsput-boolean v3, Lcom/xy/kom/GameActivity;->M:Zinvoke-static {}, Lcom/xy/kom/a/h;->f()Imove-result v0const/16 v1, 0xdif-ne v0, v1, :cond_2sget v0, Lcom/xy/kom/GameActivity;->h:Iconst/4 v1, 0x2if-ne v0, v1, :cond_2sget-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 v0invoke-interface {v0}, Ljava/util/List;->size()Imove-result v1sget-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()Imove-result v2if-ne v1, v2, :cond_1sget-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()Imove-result v2add-int/lit8 v2, v2, -0x1invoke-interface {v0, v2}, Ljava/util/List;->get(I)Ljava/lang/Object;move-result-object v0check-cast v0, Lcom/xy/kom/g/f;invoke-virtual {v1, v0}, Lcom/xy/kom/d/ei;->b(Lcom/xy/kom/g/f;)V:cond_1sget-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;)Vinvoke-static {}, Lcom/xy/kom/d/bk;->m()V:cond_2sget-boolean v0, Lcom/xy/kom/d/bk;->G:Zif-nez v0, :cond_3const/4 v0, 0x0sput-object v0, Lcom/xy/kom/d/bk;->d:Lcom/xy/kom/g/f;:cond_3return-void:cond_4sget-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 v0sget-object v1, Lcom/xy/kom/d/bk;->d:Lcom/xy/kom/g/f;invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Zgoto/16 :goto_0
.end method

看到了方法名,就知道是被混淆过的。所以一些东西都不管用。
直接右键查看引用。

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

这里发现还有一个支付失败的提示。
恩,怎么说呢,这个游戏一点保护措施都没有,好歹加密一下字符串什么的。然后解密。至少可以把安全提高一个层次吧。
不理她。
发现这是一个switch逻辑。

解决方法:
(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;.prologuegoto :pswitch_0.line 26packed-switch p1, :pswitch_data_0.line 37const-string v0, "Unity"new-instance v1, Ljava/lang/StringBuilder;const-string v2, "\u8d2d\u4e70\u9053\u5177\uff1a["invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)Vinvoke-virtual {v1, p2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;move-result-object v1const-string v2, "]\u53d6\u6d88\uff01"invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;move-result-object v1invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;move-result-object v1invoke-static {v0, v1}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I.line 38invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$0()Ljava/lang/String;move-result-object v0invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$1()Ljava/lang/String;move-result-object v1const-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_0return-void.line 29:pswitch_0const-string v0, "Unity"new-instance v1, Ljava/lang/StringBuilder;const-string v2, "\u8d2d\u4e70\u9053\u5177\uff1a["invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)Vinvoke-virtual {v1, p2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;move-result-object v1const-string v2, "]  \u6210\u529f\uff01"invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;move-result-object v1invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;move-result-object v1invoke-static {v0, v1}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I.line 30invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$0()Ljava/lang/String;move-result-object v0invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$1()Ljava/lang/String;move-result-object v1const-string v2, "success"invoke-static {v0, v1, v2}, Lcom/unity3d/player/UnityPlayer;->UnitySendMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Vgoto :goto_0.line 33:pswitch_1const-string v0, "Unity"new-instance v1, Ljava/lang/StringBuilder;const-string v2, "\u8d2d\u4e70\u9053\u5177\uff1a["invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)Vinvoke-virtual {v1, p2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;move-result-object v1const-string v2, "] \u5931\u8d25\uff01"invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;move-result-object v1invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;move-result-object v1invoke-static {v0, v1}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I.line 34invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$0()Ljava/lang/String;move-result-object v0invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$1()Ljava/lang/String;move-result-object v1const-string v2, "fail"invoke-static {v0, v1, v2}, Lcom/unity3d/player/UnityPlayer;->UnitySendMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Vgoto :goto_0.line 26nop:pswitch_data_0.packed-switch 0x1:pswitch_0:pswitch_1.end packed-switch
.end method

之前还有一个细节不知道有没有发现。

这里是白的,为什么是白的,很有可能就是被隐藏起来的。

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

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

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

测试

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

总结

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

0x04 结束语

说明

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

完成时间

2018年2月12日20:34:20

以上。

Android逆向-Android基础逆向7(内购干货集合)相关推荐

  1. 安卓逆向010之实战破解内购(斗地主)

    文章目录 快速定位关键代码 实例分析 ~Jadx分析 ~AndroidKiller分析 关键点分析 附带常见方法名: 快速定位关键代码 1. 分析流程 搜索特征字符串搜索关键api通过方法名来判断方法 ...

  2. 安卓逆向_14 --- 单机和弱联网游戏内购 突破口 和 思路

    From:https://www.bilibili.com/video/BV1UE411A7rW?p=41 Android 逆向资源收集( apk ):https://blog.csdn.net/qq ...

  3. 傻瓜式IOS发布教程(一)iTunes Connect创建应用以及内购

    使用U3D进行手机游戏开发已经1年多了,由于工作原因,之后可能将长期不会接触U3D,将目标投向Cocos2d-x.目前涉及一些U3D方面的工作交接问题,突然发现如果自己一开始就有总结写博的习惯,现在会 ...

  4. Google 内购总结

    Google 内购坑之总结 最近项目中增加了 Google 内购的内容,接入并不难,在这里总结下接入过程中的细节和坑的地方. 内购接入过程 如何接入官方的教程写的很详细(传送门),并且官方也提供了一个 ...

  5. Android逆向之旅--疯狂兔子无敌跑跑 内购破解教程

    感谢「一块硬币」同学投稿,也热烈欢迎其他同学来投稿,分析是一种快乐,也是一种精神! 今日偶然看到一个还算热门的游戏,看到里面有内购的方法.尝试破解一下 1.拖入AK后重打包,一切顺利安装到手机上后发现 ...

  6. Android逆向笔记-大部分内购游戏破解思路

    最近出了几个Android逆向的笔记,CSDN审核不通过,在此不再做详细的笔记,仅是记录下思路,免得CSDN审核不通过. 这里以单机游戏为例,大部分是单机内购游戏. 2020-07-05 10:35: ...

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

    安卓逆向之二__<全民捕鱼>游戏内购破解 环境简介 系统:Android 4.4 工具:Windows 10 64bit 夜神模拟器         Android Killer Java ...

  8. Android逆向实例笔记—手游中的内购破解(火柴人联盟最新版1.9.2 BB弹 )

    最近学到了一些内购的破解方式,就来试试手.然后找个了比较火爆的游戏BB弹,找个个没壳的就来练习. 这些东西都是大神写烂了的东西了,我这里只是写出我自己找不到方法的时候的思路.勿笑. 一.BB弹 BB弹 ...

  9. Android逆向笔记-某水果大作战内购破解思路

    思路一: 在游戏中,我们点下支付或购买,弹出一个框,我们点返回,就购买成功: 将成功转Unicode进行搜索后: 定位在此,发现payResultSuccess()为购买成功,payResultCan ...

最新文章

  1. 无法复制winevt中的文件_u盘文件无法复制怎么解决 u盘文件无法复制解决方法【详细步骤】...
  2. 2019 年编写现代 JavaScript 代码的5个小技巧
  3. 关于properties.load()出现的空指针异常
  4. rsync替换cp命令显示速度和进度
  5. TOGAF 10 正式发布
  6. 阿里巴巴Java开发手册(2018-2021泰山版整理)
  7. 计算机网络技术发展四个阶段,计算机网络的发展分哪四个阶段,特点?
  8. ARP缓存表过期问题
  9. Jenkins - 札记 - 无法连接仓库:Command “git ls-remote -h -- http://git.govmade.cn/shanghai/demo.git HEAD“...
  10. Python判断指定日期是不是法定节假日
  11. JNDI注入学习(看不懂直接喷,别忍着!)
  12. 骨传导蓝牙耳机哪个好,五款热门骨传导蓝牙耳机推荐
  13. hosts.allow和hosts.deny
  14. 英飞凌SP370方案胎压监测器-入门级视频课程-朱有鹏-专题视频课程
  15. 人事信息管理系统part1
  16. 学习「线性代数」看哪篇?推荐这篇,超级棒!
  17. PbootCms微信小程序官网模版
  18. Cocos2d-x虚拟摇杆控制精灵上下左右运动----之游戏开发《赵云要格斗》(1)
  19. 真正的十大暴利商品 成本曝光
  20. 耐克空军一号AF1 一双多少钱

热门文章

  1. Win7系统DIY工具 v 1.0
  2. AIDL for HALs实战
  3. 对比X家互联网公司,哪家月饼最小气
  4. argc argv
  5. datatables html定义,DataTables表格插件使用说明
  6. GPU+windows 10+vs2013+cuda7.5环境下配置caffe框架
  7. 关于安卓APP加固基础的总结
  8. 牛客网面经题题目及答案总结-数据库篇
  9. 用计算机算霍林格指数,【P_Patterson】[翻译团]霍林格:NBA替补战力排行榜
  10. 深度 | 阿里巴巴的2015-2017:透明“经济体”的诞生