跳至主要内容

安卓逆向练手项目:《全民捕鱼》内购破解

http://ift.tt/2E0p5EC

声明信息

此游戏已经下线,所以比较适合用来做来做练手的项目
保证虚拟机处于无网状态,因为已经下线了,所有联网内购功能都失效了

开干

开始破解


可以看到我们要破解的就是这个内购,在点击确定之后,会弹出一个Toast

一般有文字的是最好的了,可以用这个字符串作为突破口

字符串搜索

可以使用AndroidKiller或者jeb打开apk,这里因为AndroidKiller回编译比较方便,就用它了,不过他内置的源码查看真是不如jeb的

但是天不如人愿,搜了各种字符串都没有搜到

因此不得不换一个思路

日志分析

在软件开发中都需要打印日志来分析软件运行状态,游戏更甚,因此,可以尝试分析一下日志,看是否有什么苗头

首先,使用AndroidKiller附加到虚拟机上

然后打开日志窗口,选择游戏进程,开始监听日志

然后在点击按钮看看是否有日志

通过实验,在点击图标的时候,就有日志打印
但是经过正常的逻辑可知,肯定是点击“确定“之后才回触发购买,也就说在点击”确定“之后才回触发各种购买的函数,因此去看一下点击确定之后的日志,跟钱有关的,肯定会有日志的 :)


在点击了之后,发现日志有几处格外引人注目,跟pay相关的字眼总是惹人注目,我们有理由怀疑这个字符串很可能跟购买的函数有关,因此我们尝试搜索一下
先列出怀疑的日志如下:

Failed DX_payCode2 == 5125375
FaildCode == 1211
orderFinish code = 3 result= 0
orderFinish code = 3 result= 0

先一下DX_payCode2这个字符串试一下


通过搜索可以发现,可以搜索到一条内容,这个太好了 ,可以减轻分析的负担
双击进去之后,点击上面的下拉框,发现这个几个函数名,完完全全就是见名知意啊,填好了
payFailed,使用源码查看器jd-gui查看,因为不可能购买成功,所以看看失败的,然后跟成功的对比一下有什么不同,看看能不能改


经过对比,发现主要有上图几处不同
主要是oderFinish这个函数,成功的参数是1,而失败的参数是0,很让人怀疑,因此,从这个地方试一下,看看把失败的也改成1会怎么样

更改源码,破解内购


通过搜索发现有3处,这里要注意看函数的名称,因为要改的是payFailed的,所以不要找错了


直接改成1,回编译然后安装,看是有没有效果

点击编译按钮

这个时候发现已经编译完成了,安装到虚拟机中,看看能不能破解内购


虽然还是提示购买失败,单机点击之后发现

已经通过了验证,购买成功了

去掉购买提示框

现在虽然购买成功了,但是只要一点击,还是有购买的提示框弹出来,很是烦人,因此,现在要把提示框去除

分析

提示框是在点击的时候弹出来的,因此现在去看看点击的一瞬间的日志有没有可以参考的数据

这是点击瞬间弹窗的日志,没有看出明显的具有参考价值的字符串(比如跟想象中的显示窗口相关的),好在日志不是很多,一个一个的去看吧

event_id=buyMoney, label=1000
GameJni order payCode = 3 num= 1
order = 5125375
GamePay sendOrder payCode = 5125375
context.payType = 1
payCode = 5125375
DX payCode in DXSend == 5125375


buyMoney这个搜出来实在是太多了,先放一下看看后面

搜索order payCode发现只有两条,而且会很明显的发现,其实要找的只有一条,这个就好分析多了,先去分析一下这一条是不是在线上

查看源码

发现调用的是一个叫GamePay的对象调用的mlistener.sendoder的方法,跟进去这个类看看

首先我们发现了sendOder函数,但是可以看到在Order中,又调用了mListener自己类中的sendOrder,因此需要看一下这个mListener是怎么构成,正好setContext这个函数对mListen进行了赋值,跟进去看看吧


进入这个叫IAPListener这个类中,首先发现了其构造函数,并且有一个叫做IAPHandler类型额参数进行赋值,并且在这个类型还有一个静态的IAPHandler的对象,可以进去看一下这个类有大体有什么作用

一进这个类就发现其内部的几个字符串非常的显眼

而且在分发信息的函数中,发现了之前分析的时候看到过的代码
在之前的分析中,发想过购买失败是1005,成功是10010
也就是说这里可以改掉购买的时候Toast的字符串,阴差阳错,那就改一下吧

改掉Toast,替自己加个广告


通过搜索,可以确定其在smali汇编中的位置,然后把unicode改成自己的

我改成了字符串破解由cole.science提供,等会在编译吧,看看能不能出现,现在继续去找弹窗的位置

去掉弹窗

已经看过了IAPHandler 这个类了,大体知道了什么意思,但是好像目前来看跟弹窗的主要逻辑没什么太大的关系,回到IAPListener这个类中,在上面的类中,我们分析了实在oder这个函数中,带动了mlistener的Order,那正好去看一下这里面干了什么

因此去看一下这个order中干了什么

发现这个函数是一系列消息处理的开端,通过iapHander.sendMessage然后调用了mListener.sender来判断购买是否成功,因此这个就是最初传递消息的函数,可以想办法改一下整理的源码,在判断之前就把消息改掉,然后付款完成,就应该可以跳过那个Dialog了



这里它的程序员写的代码有问题,本来还想直接添加代码来着,发现最后正好有一个orderFinish,干脆直接跳过去

回编译,安装尝试

这里发现购买提示的弹窗,直接就购买成功了,但是发现Toast没有出现,原因是直接阿泰国了iapHandle方法,没有sendMessag

The post 安卓逆向练手项目:《全民捕鱼》内购破解 appeared first on cole.

http://ift.tt/2DrTavD Android Reverse Engineering, 破解 January 23, 2018 at 09:23PM

评论

此博客中的热门博文

反Hook 之自己实现GetProcAddress和LoadLibraryA(c++ version)

http://ift.tt/2AocAD0 // 课上练习.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> //要实现的功能: /* 自己实现GerProcAddress LoadLibraryA */ //思路: /* GerProcAddress和LoadLibraryA都是在Kernel32.dll中的 首要的任务就是找到Kernel32.dll,然后遍历IAT就能找到这两个函数 现在首要的难点就是如何找到kernel32.dll() 通过dll的加载顺序可以找到,而且虽然需要使用未文档化的API,但是好在windgb可以直接看,而且用到的也并不是很多 懒得去晚上搜了,直接自己实现一个得了,作为演示,能用就行(最好还是搜一个正规的结构体) */ /* 0: kd> dt _TEB /a nt!_TEB +0x000 NtTib : _NT_TIB +0x01c EnvironmentPointer : Ptr32 Void +0x020 ClientId : _CLIENT_ID +0x028 ActiveRpcHandle : Ptr32 Void +0x02c ThreadLocalStoragePointer : Ptr32 Void +0x030 ProcessEnvironmentBlock : Ptr32 _PEB //首先实现部分TEB结构体,因为只需要用的PEB的部分,所以实现到这就ok了 */ //构建 TEB typedef struct _TEB { //保证0x30是peb的结构体就ok了 struct _tem { DWORD a1; DWORD a2; DWORD a3; DWORD a4; DWORD a5; DWORD a6; DWORD a7; DWORD a8; DWORD a9; DWORD a10; ...

IDA动态调试ELF中遇到的问题(1)

https://ift.tt/2Gxnf2F 遇到 got SIGCHLD singal(child status has changed)...这种提示 singal fork了子进程 直接点yes,然后继续单步执行,出来提示 pass to application就行了 内存查看 用od习惯了之后,凡事都想右键看一下内存,但是IDA中好像没有那么如意, 目前只是在栈中右键发现有查看hex的选项 动态调试的时候的nop ida保存动态调试的时候修改的数据 方法一:在程序运行的时候保存 The post IDA动态调试ELF中遇到的问题(1) appeared first on cole . https://ift.tt/2q9Qf5g WHATEVER April 05, 2018 at 09:44AM

数据库(MySQL)编程之数据库和表的基本操作

http://ift.tt/2gOXg6X     数据库和表的基本操作 操作前的基本知识 基本 sql语句不区分大小写(关键字建议用大小写),但字符串常量区分大小写 sql语句可单行或多行书写,以; 结尾 关键字不能跨行或简写 可以用空格或者缩进来提高可读性 注释 sql标准 /**/ : 多行注释 "--":单行注释 mysql 标准: "#":单行注释 "COMMENT":为字段或列添加注释 创建和查看数据库 创建数据库 模板 CREATE DATABASE [IF NOT EXISTS ] db_name create_specification: IF NOT EXITSTS : 检查数据库是否存在,如果存在就不创建 creat_specification :创建条件 CHARACTER SET: 制定数据聚采用的字符集 COLLATE :制定数据库字符集的比较方式 DEFAULT :表示默认内容,即使没有制定该项,也有默认的值 # 创建数据库使用字符集为 UTF-8 ,使用规则为 uftf_bin CREATE DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE uft8_bin; 一般默认的数据库就是utf8 和utf8_bin的比较方式,因此一般创建数据库的时候都用 CREATE DATABASE db_name mysql> create database testdb; Query OK, 1 row affected (0.02 sec) 查看数据库 命令 SHOW DATABASES     mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sakila | | sys | | testdb | |...