吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 72439|回复: 170
收起左侧

[Android 原创] 《同声翻译超级版》支付宝内购破解之思路分析及图文教程

    [复制链接]
pk196371 发表于 2015-8-8 13:33

        前言:由于繁华大大丢了个apk出来给大伙练手,所以一时兴起就想自己写一篇破文。首先,必须膜拜一下繁华大大的脱壳技能,这个脱壳大难题我真的是搞不定了。其次,希望一些思路可以给大家带来一点启发,并且能够帮助大家举一反三。最后,这是我第一次分析整理破解思路,如有瑕疵之处还请大家见谅。

繁华帖子:
http://www.52pojie.cn/thread-395983-1-1.html

应用名称:
同声翻译超级版

破解方式:
1. 购买时取消之后支付成功
2. 点击立即升级即购买成功
3. 打开应用就已经是注册版

使用工具:
AndroidKiller v1.2 (或其他反编译分析工具,如:ApkIDE v3.2、Apkdb v1.92等)
Droid4X v0.8.4 (即海马玩安卓模拟器,或其他类似模拟器,如:天天、夜神、文卓爷等)



Level-1:购买时取消之后支付成功

先把apk丢进AndroidKiller进行反编译就不在此多说了,接下来通过查阅支付宝钱包支付接口开发文档,我们知道了支付状态或结果的返回代码,这个类似于网页上的404、500等。

alipay_error_code.png

如上图,当返回9000时表示支付成功,而返回4000则是支付失败,同时看到当用户中途取消时会返回6001错误代码。那么,我们就可以在取消支付时跳转到支付成功来实现内购的破解了。

9000转化为16进制得到0x2328,然后对整个项目进行搜索,从得到的搜索结果来看,我们打开第一个smali文件:

20150808110506.png

20150808110543.png

20150808111100.png

显然,我们只要把0x1771 -> :sswitch_1修改为0x1771 -> :sswitch_0即可实现破解。保存修改结果并编译成apk,安装到模拟器运行测试一下:恭喜,您已成为会员!

Screenshot_2015-08-07-17-47-08.png

Screenshot_2015-08-07-17-48-37.png



Level-2:点击立即升级即购买成功

如果想点击立即升级即实现支付成功,就应该要跳过支付购买这个步骤,我们运行程序看一下流程是怎样的:首先提示“正在获取会员信息”,接着弹出快捷支付窗口,取消返回后提示“支付失败”。

Screenshot_2015-08-07-17-46-48.png

Screenshot_2015-08-07-17-47-12.png

现在我们来搜索一下“正在获取会员信息”,记得要先转换成Unicode编码,结果显示这个字符串在PayActivity.smali文件,接着我们查看一下当前文件的Java源码:

20150808114707.png

20150808115210.png

20150808115425.png

从以上源码中,我们发现当点击立即升级时,程序执行到了do...while函数,并且利用start()方法启动了co线程。同时,我们还看到上面有个if判断函数,当条件不满足时才会执行下面的do...while等。所以,我们可以修改if判断语句,即if-nez v2, :cond_1改为if-eqz v2, :cond_1,让其直接执行函数内的方法,这样就可以跳过支付流程了。运行测试:升级成功!

20150808120747.png



Level-3:打开应用就已经是注册版

通过上面的步骤应用就已经升级为会员了,利用RE管理器查看/data/data/android.translate.xuedianba/shared_prefs目录下的存档文件,我们可以发现<int name="vip_grade" value="1" />就是会员的记录标志,当vip_grade为1表示已升级会员,否则为0就表示非会员。那么,我们可以在应用启动时,就将vip_grade赋值为1,并写入存档文件中,这样就能实现打开程序即已成为会员了。

Screenshot_2015-08-07-17-49-23.png

我们搜索一下“vip_grade”这个字符串,结果搜索出来了很多文件,但很明显我们需要的是MainActivity.smali文件,查看一下Java源码,找到onCreate()方法,里面有一句代码:this.mVipgrade = this.L.getInt("vip_grade", 0); 其表示先读取存档文件中vip_grade的值,然后赋值给mVipgrade变量。

20150808130416.png

20150808130432.png

我们在读取vip_grade的值之前,先把vip_grade赋值为1,并写入存档文件中,其修改代码如下:

20150808130909.png

20150808131047.png

最后,我们编译测试一下,结果就是完美破解!

点评

我完全赞成没啥技术含量这个观点  发表于 2015-9-2 15:42

免费评分

参与人数 42威望 +2 吾爱币 +9 热心值 +42 收起 理由
stars-one + 1 + 1 谢谢@Thanks!
木子汐 + 1 + 1 已答复!
zhiyi1120 + 1 + 1 谢谢@Thanks!
天道勤酬 + 1 + 1 热心回复!
blockke + 1 + 1 热心回复!
17189926689 + 1 + 1 热心回复!
呵Eric呵 + 1 + 1 热心回复!
52_poj + 1 + 1 我很赞同!
chaser1 + 1 我很赞同!
hehe408 + 1 + 1 热心回复!
supperlitt + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Czkusers + 1 谢谢@Thanks!
小佐yo + 1 我很赞同!
bitssly + 1 用心讨论,共获提升!
x020413 + 1 谢谢@Thanks!
刘统宝 + 1 谢谢@Thanks!
yt753302 + 1 对我来说是天书啊
赚1649616497 + 1 给赞,正好用到
仿佛是我 + 1 谢谢@Thanks!
zoglag + 1 谢谢@Thanks!
learndozen + 1 学习思路~~~
寒号.鸟 + 1 受益匪浅 但是我打开绝大多数APK都是乱码
970883246 + 1 谢谢@Thanks!
fenghaoda + 1 我很赞同!
UUY + 1 我很赞同!
tzxinqing + 1 感谢您的宝贵建议,我们会努力争取做得更好.
Amor_Liu + 1 谢谢@Thanks!
夜之零落兮 + 1 谢谢 受教了
136108880 + 1 我很赞同!
Tortoise + 1 谢谢@Thanks!
Poetry + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
469164323 + 1 热心回复!
Jacve + 1 楼主可否分享下 查询错误代码 具体链接
潇潇风 + 1 谢谢@Thanks!
alccc + 1 谢谢@Thanks!
84420988 + 1 谢谢大神
bxxb555 + 1
长存 + 1 大神请收下我的膝盖
Ericky + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
spguangz + 1 很详细
逍遥枷锁 + 1 谢谢@Thanks!
欧盆饭 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

lqb654 发表于 2015-11-19 19:59
new-instance v0 Ljava/lang/StringBuilder;
invoke-direct {v0} Ljava/lang/StringBuilder;-><init>()V
const-string v1 "msg.obj------>"
invoke-virtual {v0,v1} Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
iget-object v1 v4 Landroid/os/Message;->obj:Ljava/lang/Object;
invoke-virtual {v1} Ljava/lang/Object;->toString()Ljava/lang/String;
move-result-object v1
invoke-virtual {v0,v1} Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0} Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v0
invoke-static {v0} Lcn/douwan/sdk/util/Logger;->d(Ljava/lang/Object;)V
iget-object v0 v3 Lcn/douwan/sdk/b;->a:Lcn/douwan/sdk/a;
invoke-static {v0} Lcn/douwan/sdk/a;->a(Lcn/douwan/sdk/a;)Lcn/douwan/sdk/e/p;
move-result-object v1
iget-object v0 v4 Landroid/os/Message;->obj:Ljava/lang/Object;
check-cast v0 Ljava/lang/String;
iput-object v0 v1 Lcn/douwan/sdk/e/p;->d:Ljava/lang/String;
iget-object v0 v3 Lcn/douwan/sdk/b;->a:Lcn/douwan/sdk/a;
invoke-static {v0} Lcn/douwan/sdk/a;->a(Lcn/douwan/sdk/a;)Lcn/douwan/sdk/e/p;
move-result-object v0
iget-object v0 v0 Lcn/douwan/sdk/e/p;->b:Ljava/lang/String;
invoke-static {v0} Lcn/douwan/sdk/util/y;->a(Ljava/lang/String;)Z
move-result v0
if-nez v0 :label_74
new-instance v0 Lcn/douwan/sdk/bu;
iget-object v1 v3 Lcn/douwan/sdk/b;->a:Lcn/douwan/sdk/a;
invoke-static {v1} Lcn/douwan/sdk/a;->b(Lcn/douwan/sdk/a;)Landroid/app/Activity;
move-result-object v1
iget-object v2 v3 Lcn/douwan/sdk/b;->a:Lcn/douwan/sdk/a;
invoke-static {v2} Lcn/douwan/sdk/a;->a(Lcn/douwan/sdk/a;)Lcn/douwan/sdk/e/p;
move-result-object v2
invoke-direct {v0,v1,v2} Lcn/douwan/sdk/bu;-><init>(Landroid/content/Context;Lcn/douwan/sdk/e/p;)V
invoke-virtual {v0} Lcn/douwan/sdk/bu;->start()V
label_74:
const-string v0 "resultStatus={"
iget-object v1 v3 Lcn/douwan/sdk/b;->a:Lcn/douwan/sdk/a;
invoke-static {v1} Lcn/douwan/sdk/a;->a(Lcn/douwan/sdk/a;)Lcn/douwan/sdk/e/p;
move-result-object v1
iget-object v1 v1 Lcn/douwan/sdk/e/p;->d:Ljava/lang/String;
const-string v2 "resultStatus="
invoke-virtual {v1,v2} Ljava/lang/String;->indexOf(Ljava/lang/String;)I
move-result v1
invoke-virtual {v0} Ljava/lang/String;->length()I
move-result v0
add-int/2addr v0 v1
iget-object v1 v3 Lcn/douwan/sdk/b;->a:Lcn/douwan/sdk/a;
invoke-static {v1} Lcn/douwan/sdk/a;->a(Lcn/douwan/sdk/a;)Lcn/douwan/sdk/e/p;
move-result-object v1
iget-object v1 v1 Lcn/douwan/sdk/e/p;->d:Ljava/lang/String;
const-string v2 "};memo="
invoke-virtual {v1,v2} Ljava/lang/String;->indexOf(Ljava/lang/String;)I
move-result v1
iget-object v2 v3 Lcn/douwan/sdk/b;->a:Lcn/douwan/sdk/a;
invoke-static {v2} Lcn/douwan/sdk/a;->a(Lcn/douwan/sdk/a;)Lcn/douwan/sdk/e/p;
move-result-object v2
iget-object v2 v2 Lcn/douwan/sdk/e/p;->d:Ljava/lang/String;
invoke-virtual {v2,v0,v1} Ljava/lang/String;->substring(II)Ljava/lang/String;
move-result-object v0
new-instance v1 Ljava/lang/StringBuilder;
invoke-direct {v1} Ljava/lang/StringBuilder;-><init>()V
const-string v2 "tradeStatus---->"
invoke-virtual {v1,v2} Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v1
invoke-virtual {v1,v0} 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 {v1} Lcn/douwan/sdk/util/Logger;->d(Ljava/lang/Object;)V
const-string v1 ""
invoke-virtual {v1,v0} Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v1
if-nez v1 :label_168
const-string v1 "9000"
invoke-virtual {v1,v0} Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v0
if-eqz v0 :label_168
iget-object v0 v3 Lcn/douwan/sdk/b;->a:Lcn/douwan/sdk/a;
invoke-static {v0} Lcn/douwan/sdk/a;->b(Lcn/douwan/sdk/a;)Landroid/app/Activity;
move-result-object v0
invoke-static {v0} Lcn/douwan/ui/ay;->a(Landroid/app/Activity;)V
label_168:
return-void
label_169:
move-exception v0
goto :label_168


#Handler Exceptions

.catch Ljava/lang/Exception;
    start : label_74
    end : label_168
    handler : label_169
.end catch

这个咱们修改?
Shirley 发表于 2015-8-8 13:38
1347857701 发表于 2015-8-8 14:20
不是呵呵 发表于 2015-8-8 15:53
为什么要直接搜索十六进制0x2328,而不是十进制的9000
不是呵呵 发表于 2015-8-8 16:11
这个错误代码不是显示出来的么“9000”
吸引力9933 发表于 2015-8-8 16:43 来自手机
用re管理器就能搞定?
ssyygg 发表于 2015-8-8 22:12 来自手机
我用mt管理器改完并不成功呢?
timeles 发表于 2015-8-8 22:18
可以去不用钱充话费了吗
wefgod 发表于 2015-8-8 22:19
不错,APK破解的好方法啊
hxyyyssc 发表于 2015-8-8 22:45
为何没见软件呢 对吧
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 11:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表