记某app内购破解 – 安卓逆向菜鸟的初体验

摘要:
我搜索了网上相关的帖子,发现这个apk的破解都是讲了关键点都在哪里,没有具体的关键点查找思路,所以我重新自己破解了一次,中间多次误入歧途,我把自己的详细思路发在这里,与所有的菜鸟共勉。这是意外的惊喜。至此,成功破解了这个app的内功功能。我称之为“漏洞”,通过这个“漏洞”可以定位到支付功能必须执行的某些代码。
前言

因为某个机缘,我拿到一个赛车app,玩了一会想买个装备,居然要我掏钱包,作为一名cracker,我觉得我的尊严受到了严重的蔑视(无奈钱包空空),我觉得要捍卫我那脆弱的玻璃心(钱包),所以,开干吧。我搜索了网上相关的帖子,发现这个apk的破解都是讲了关键点都在哪里,没有具体的关键点查找思路,所以我重新自己破解了一次,中间多次误入歧途,我把自己的详细思路发在这里,与所有的菜鸟共勉。

工具

Android killer v1.3.1.0 -- 用于搜索字符串和重打包,下文使用缩写AK

Apktool Box v1.6.4 – 用于获取调试启动命令,下文使用缩写AB

小米5 MIUI9.5.1.0 android7.0 – 用于运行apk

Android Studio 2.3.3(安装 smalidea-0.0.5插件) – 用于调试smali源码,下文使用缩写AS

Jadx-gui 0.7.1 – 用于查看smali反编译源码,其实AK也有反编译功能,但是AK的反编译有的地方没有jadx好看,我发现switchcase结构AK总是翻译成ifelse结构。

搭建调试环境

重打包生成可调式APK

使用AS调试smali需要apk设置调试标识(不然AS会显示错误:Unable to open debugger port (localhost:7800): java.net.SocketException "connection reset"),用AK打开apk,从工程管理器栏打开文件androidmanifest.xml,在application项添加如下代码:

1
android:debuggable="true"

如下图:

记某app内购破解 – 安卓逆向菜鸟的初体验第1张

然后选择菜单android->编译,重打包APK。并安装到米5里面。

调试启动apk

使用AB打开apk,点击启动命令按钮生成调试启动命令,

记某app内购破解 – 安卓逆向菜鸟的初体验第2张

将上图中下面的命令拷贝到cmd中,启动apk,手机中apk会停在调试启动界面。然后查看apk的进程PID,

记某app内购破解 – 安卓逆向菜鸟的初体验第3张

然后使用adb命令转发调试到tcp端口8700,如下:

记某app内购破解 – 安卓逆向菜鸟的初体验第4张

接下来,使用AS建立smali源码的工程,并配置调试端口,这部分内容网上有现成的教程,这里就不多说了,建立完了之后,点击调试按钮,AS下面显示日志如下表示启动调试成功:

记某app内购破解 – 安卓逆向菜鸟的初体验第5张

到此,调试环境搭建成功,下面开始破解。

破解过程

思路一:错误信息提示

老思路,先是试用一下。点击游戏的购买,会弹出一个购买的框,需要输入手机号和验证码,这里随便输入一个手机号和验证码,点击确认支付,不出意外会失败,并弹出一个提示框:

记某app内购破解 – 安卓逆向菜鸟的初体验第6张

好了,这是我的第一个第一个失败点。我的思路是,既然它给了这个错误提示,那么显示这个错误的地方肯定有支付成功和失败的逻辑,那么我修改了这个逻辑,就可以了。OK,下面就是如何找到这个判断的逻辑。没错,字符串查找,最传统的方法,在android里面搜字符串,不能直接搜汉字,需要将它转为unicode码,然后将“短信验证码验证失败”转换为unicode码,则为“u77edu4fe1u9a8cu8bc1u7801u9a8cu8bc1u5931u8d25 ”,结果没有找到,好吧,是不是字符串拼接出来的呢,短一点,搜“短信验证码”,然后有了搜索结果

记某app内购破解 – 安卓逆向菜鸟的初体验第7张

不好意思,我是小菜看不懂smali,将其转换为java源代码,

记某app内购破解 – 安卓逆向菜鸟的初体验第8张

原函数太大了,这里只贴了一部分,看着逻辑真不像,那么到底是不是这个逻辑呢?验证的办法很简单,在这里下个断点,然后,没有断下来。那么在函数入口下个断点,还是没有来。好吧,这个思路以失败告终。后来跟踪代码我才知道这个支付框是从so里面弹出来的。呜呜。。

思路二:网络帖子借鉴

之前搜过类似的帖子,帖子说是搜字符串“支付成功”,所以我将字符串转化为unicode码,到AK里面去搜索,然后搜索到三个结果:

记某app内购破解 – 安卓逆向菜鸟的初体验第9张

同样,验证这里是不是判断是否支付成功的逻辑代码,在每个字符串所在的函数头部设置断点,这里没有在字符串所在的位置设置断点是因为我是不会掏钱包的,所有的操作都是支付失败的操作,支付成功的代码逻辑肯定是不会来的,所以在函数头部设置断点,然后,点击确认支付没有断下来,但是当我点击关闭按钮时,却成功的断在了第一个函数中。这是意外的惊喜。然后使用jadx查看这个函数的逻辑:

记某app内购破解 – 安卓逆向菜鸟的初体验第10张

代码的逻辑很清晰,检查参数resultCode的值,然后判断是否支付成功,所以这里很有可能就是我要的关键代码逻辑。验证一下,把所有的switch结构都改成到case1分支。Smali代码的语法是把所有的case放到一块,如下

记某app内购破解 – 安卓逆向菜鸟的初体验第11张

上面代码的意思是将switch里面的值与1比较,结果为0则跳转到pswitch_0标号,结果为1则跳转到pswitch_1执行,所以这里把所有的标号都改为pwtich_0,并在下面添加一行,这样默认情况也会跳转到pswtich_0,即三种不管resultCode为何值,都会跳转到成功的分支,如下:

记某app内购破解 – 安卓逆向菜鸟的初体验第12张

最后,编译重打包,安装测试,成功,OK。至此,成功破解了这个app的内功功能。

其实,当初我并没有按下支付框的关闭按钮,所以我走的是另一条思路,如果看到这里你还有耐心,可以看下我的弯路,哈哈。

思路三:我的弯路

当在三个“支付成功”字符串所在的函数设置断点,点击手机上确认支付按钮时,三个断点都没有来。然后我换了搜所的字符串为“支付失败”,然后搜到6个结果

记某app内购破解 – 安卓逆向菜鸟的初体验第13张

我在6个结果的字符串所在的函数头部设置断点,点击确认支付按钮,结果所有的断点都没有来。后来我就去网上搜帖子,见到有帖子说“支付失败”所在的一个函数checkPayResultTest的调用者在用户点击购买时被调用。所以我转变了思路,放弃了直接查找判断是否支付成功的代码,而是查找能在支付过程中会被执行到的函数,然后我可以从这个函数跟踪到判断支付的代码。使用jadx打开apk,定位到函数checkPayResultTest,右键find usage,

记某app内购破解 – 安卓逆向菜鸟的初体验第14张

然后查看其调用函数,

记某app内购破解 – 安卓逆向菜鸟的初体验第15张

在此函数的头部设置断点,当我点击购买时,程序断在了这里。这是个喜讯。此时,我发现手机上的支付框还没有弹出来,所以我想,我可以从这里跟踪下去知道支付框弹出,然后找到确认支付按钮的回调。于是我一路F7单步步入跟进去,当调试跟踪到下图中的红线标识部分时我跟不进去了:

记某app内购破解 – 安卓逆向菜鸟的初体验第16张

通过查资料我才知道,这是jni调用,我这才知道了,为什么我之前设置的失败断点都没有来,原因最后掉用到so库里了。那怎么办,难道我要算调试so文件么?然后我仔细观察了这个函数调用,发现这里有个回调,于是我找到回调定义的地方,

记某app内购破解 – 安卓逆向菜鸟的初体验第17张

哈哈,是不是很眼熟,在回调里面设置断点,然后这次我鬼使神差的点击了支付框的关闭按钮,然后断下来了。哈哈。再然后的操作就如同上个思路一样了。这就是我的弯路了。

思路四:程序的“漏洞”

这里怎么说呢,其实也不算是程序的漏洞,而是程序员的一种编程习惯。我称之为“漏洞”,通过这个“漏洞”可以定位到支付功能必须执行的某些代码。思路是这样的,我发现在程序的代码中有很多调试日志输出,我如果能修改程序输出日志,那么当我使用支付功能的时候,相关代码会输出相关调试信息,然后我搜索输出的字符串,不就可以定位到支付功能一定会调用的代码吗!

首先,随便找一段代码,看看它是如何输出的,

记某app内购破解 – 安卓逆向菜鸟的初体验第18张

从上图可以看出,调试信息的输出是通过一个叫LogUil.iT函数实现的,找到这个函数:

记某app内购破解 – 安卓逆向菜鸟的初体验第19张

这里会看到,代码中有个DEBUG标志,如果此标志为真则输出调试信息,然后找到这个标志赋值的位置:

记某app内购破解 – 安卓逆向菜鸟的初体验第20张

本来以为这个标志是会在构造里面赋值的,没想到居然是判断sdcard路径下有没有alg,哈哈,那就更简单了,我在手机的sdcard下面放了一个alg文件,

记某app内购破解 – 安卓逆向菜鸟的初体验第21张

然后打开DDMS,启动程序,点击购买,DDMS日志视图里面发现如下信息:

记某app内购破解 – 安卓逆向菜鸟的初体验第22张

到AK里面去搜索字符串“支付接口被游戏调用”,哈哈,有一条结果:

记某app内购破解 – 安卓逆向菜鸟的初体验第23张

转到java源代码:

记某app内购破解 – 安卓逆向菜鸟的初体验第24张

在AS中对应位置下断点,程序成功断下来啦。哈哈。

总结

虽然走了很多的弯路,但是也发现了很多有趣的东西。例如通过日志来定位代码,so中弹出对话框是无法在java中找到关键点的,要多试几种别的操作。

其它

附件太大,这里给个链接吧:https://pan.baidu.com/s/1P40TZLvJXV727-mlJLNIdA

本帖子如果引起任何其它负面的影响,请版主直接删帖即可。

如果转载,请声明来自看雪。

免责声明:文章转载自《记某app内购破解 – 安卓逆向菜鸟的初体验》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇canal 配置 多个监听 推送到不同mqcentos7 nodejs正确的安装方式下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Debug与Release版本的区别

  Debug 和 Release 并没有本质的区别,他们只是VC预定义提供的两组编译选项的集合,编译器只是按照预定的选项行动。如果我们愿意,我们完全可以把Debug和Release的行为完全颠倒过来。当然也可以提供其他的模式,例如自己定义一组编译选项,然后命名为MY_ABC等。习惯上,我们仍然更愿意使用VC已经定义好的名称。    Debug版本包括调试...

抓apk中的https包(​含破解https的SSL Pinning)

一般来说,http请求的包都可以通过fiddler来抓包(http2.0不支持)。 https抓包的原理是利用中间人攻击,向客户端伪装成服务端,向服务端伪装成客户端,从而可以抓包,但是有部分https的包是抓取不了的。 其中可能用到了SSL Pinning(证书绑定或SSL证书绑定)技术。 然而道高一尺魔高一丈,下面通过一种简单的办法来修改apk的配置,允...

对 Android APK 安装包进行反编译并修改再打包

1、确认系统中已安装 JRE、JDK(需要 1.8 以上版本:https://www.oracle.com/cn/java/technologies/javase-downloads.html) 检查命令:java -version 2、JRE、JDK 的路径已配置在系统环境变量 PATH 中: 如:C:Program FilesJavajdk1.8.0_...

第二章排错的工具:调试器Windbg(上)

感谢博主 http://book.51cto.com/art/200711/59731.htm 《Windows用户态程序高效排错》第二章主要介绍用户态调试相关的知识和工具。本文主要讲了排错的工具:调试器Windbg。   第二章 汇编、异常、内存、同步和调试器——重要的知识点和神兵利器 这一部分主要介绍用户态调试相关的知识和工具。包括:汇编、异常(ex...

android 系统重启与关机:java 代码实现

在应用层如何通过代码实现 android 系统的重启,分享给大家。 这篇博客是在 android 系统开发的基础之上进行实践的,所以如果你是纯粹的 app 开发,可能要让你失望了。 该代码在真机上测试成功,在模拟器上面测试失败。 在 linux 下面,重启 pc,非 root 用户需要执行 sudo reboot,所以在 android 下重启机器也需...

GDB如何调试没有符号表(未加-g选项的编译)的程序

/********************************************************************* * Author  : Samson * Date    : 01/30/2015 * Test platform: *              3.13.0-24-generic *              G...