yodo1偶滴神(最SB塔防)Android内购破解

—Creaked by B.S. 6/14/2017 2:10:58 PM

无聊练手,当作学习Android优秀源码的笔记

仅供学习研究,请勿用作商业用途,如若喜欢请支持正版!

原程序:(貌似android 5.x 以上版本运行不起来)

百度下载

游道易官网: http://www.yodo1.cn/archives/omg-td.html

B.S.内购破解版:

百度下载

也可以去各大安卓市场搜索下载最新版本:(推荐支付接口比较熟悉的移动,咪咕游戏,爱游戏)

爱游戏: http://www.play.cn/

咪咕游戏: http://g.10086.cn/

中国移动应用商城: http://mm.10086.cn/android

腾讯应用宝: http://android.myapp.com/

360手机助手: http://zhushou.360.cn/

百度旗下安卓市场: http://apk.hiapk.com/

安智市场: http://www.anzhi.com/

有图有真相,动画演示:

破解了移动接口的动画演示

无限内购B.S.破解版

1. 找到支付相关的sdk类的关键破解点在”onResult”Method中

public void onResult(int arg0, String arg1, Object arg2)

1
2
3
4
5
6
7
8
9
10
.method public onResult(ILjava/lang/String;Ljava/lang/Object;)V
.locals 3
.param p1, "arg0" # I
.param p2, "arg1" # Ljava/lang/String;
.param p3, "arg2" # Ljava/lang/Object;
.prologue #此处省略Java汇编smali代码若干
.end method

2. android killer出马java反编译后到路径

package com.yodo1.sdk.game.smspay;

移动咪咕和支付接口,相关源码,直接上图.当然还有电信,联通的
关键在这个switch里,使他总是走case 1:支付成功.有时候需要向上层调用回溯才能定位到他支付校验的代码,让他支付校验的代码总是返回真即可.可以在最后的smali汇编代码里修该为这个样子.
秒杀所有smspay支付

.class Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterCMCC$1;

.super Ljava/lang/Object;

.source “YgSmsPayAdapterCMCC.java”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.line 46
.local v0, "result":Ljava/lang/String;
goto :pswitch_0 #这里添加一句代码直接跳到支付成功witch等于0
packed-switch p1, :pswitch_data_0
goto :goto_0
.line 46
:pswitch_data_0
.packed-switch 0x1
:pswitch_0 #全部调到:pswitch_0 支付成功分支 #:pswitch_0 #成功
:pswitch_0 #全部调到:pswitch_0 支付成功分支 #:pswitch_1 #失败
:pswitch_0 #全部调到:pswitch_0 支付成功分支 #:pswitch_2 #取消
.end packed-switch
.end method

smspay

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public void onResult(int arg0, String arg1, Object arg2) {
String result = HttpNet.URL;
switch (arg0) {
case 1:
if (!isRepeat) {
YgSmsPayAdapterBase.setPaid(activity2, str);
}
if (yodo14GameSmsPayListener != null) {
yodo14GameSmsPayListener.onSuccess();
}
result = "支付成功";
break;
case 2:
if (yodo14GameSmsPayListener != null) {
yodo14GameSmsPayListener.onFailed();
}
result = "支付失败";
break;
case 3:
if (yodo14GameSmsPayListener != null) {
yodo14GameSmsPayListener.onCanceled();
break;
}
break;
default:
if (yodo14GameSmsPayListener != null) {
yodo14GameSmsPayListener.onFailed();
break;
}
break;
}
if (result != null && result.length() > 0) {
Toast.makeText(activity2, result, 0).show();
}
}

3. 破解修改的另一处更简单的地方:

也可以试试修改这里
通过logcat定位到的字符串所在的类一个内部类或者嵌套类里

successMessage or failedMessage is null

android killer 找到下面这个类的smali文件

.class Lcom/yodo1/sdk/game/Yodo14GameSmsPay$2;

.super Ljava/lang/Object;

.source “Yodo14GameSmsPay.java”

删掉原来的.method public onCanceled()V方法实现,用下面的.method public onSuccess()V里的代码来替换.

1
2
3
4
.method public onCanceled()V
#这里的原先的代码块全删掉,用下面.method public onSuccess()V里的代码块填入这里
#这样点取消,或者返回支付,就会走支付成功的流程.
.end method

改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
.method public onCanceled()V
.locals 2
.prologue
.line 180
iget-object v0, p0, Lcom/yodo1/sdk/game/Yodo14GameSmsPay$2;->val$activity:Landroid/app/Activity;
iget-object v1, p0, Lcom/yodo1/sdk/game/Yodo14GameSmsPay$2;->val$productId:Ljava/lang/String;
invoke-static {v0, v1}, Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterBase;->setPaid(Landroid/content/Context;Ljava/lang/String;)V
.line 182
iget-object v0, p0, Lcom/yodo1/sdk/game/Yodo14GameSmsPay$2;->val$listener:Lcom/yodo1/sdk/game/Yodo14GameSmsPayListener;
if-eqz v0, :cond_0
.line 183
iget-object v0, p0, Lcom/yodo1/sdk/game/Yodo14GameSmsPay$2;->val$listener:Lcom/yodo1/sdk/game/Yodo14GameSmsPayListener;
invoke-interface {v0}, Lcom/yodo1/sdk/game/Yodo14GameSmsPayListener;->onSuccess()V
.line 185
:cond_0
invoke-static {}, Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterBase;->getBillingSuccessMessageKey()Ljava/lang/String;
move-result-object v0
invoke-direct {p0, v0}, Lcom/yodo1/sdk/game/Yodo14GameSmsPay$2;->showDialog(Ljava/lang/String;)V
.line 188
iget-object v0, p0, Lcom/yodo1/sdk/game/Yodo14GameSmsPay$2;->val$smsPayAdapter:Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterBase;
iget-object v1, p0, Lcom/yodo1/sdk/game/Yodo14GameSmsPay$2;->val$productId:Ljava/lang/String;
invoke-virtual {v0, v1}, Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterBase;->onPayFinish(Ljava/lang/String;)V
.line 189
return-void
.end method

这几个函数接口原来的源码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public void onCanceled()
{
if (this.val$listener != null) {
this.val$listener.onCanceled();
}
this.val$smsPayAdapter.onPayFinish(this.val$productId);
}
public void onFailed()
{
if (this.val$listener != null) {
this.val$listener.onFailed();
}
showDialog(YgSmsPayAdapterBase.getBillingFailedMessageKey());
this.val$smsPayAdapter.onPayFinish(this.val$productId);
}
public void onSuccess()
{
YgSmsPayAdapterBase.setPaid(this.val$activity, this.val$productId);
if (this.val$listener != null) {
this.val$listener.onSuccess();
}
showDialog(YgSmsPayAdapterBase.getBillingSuccessMessageKey());
this.val$smsPayAdapter.onPayFinish(this.val$productId);
}

4. 后记(一点总结和补充):

先破解电信支付(不弹窗支付窗口的,不弹消息的购买成功的修改方法有很多种),然后把联通和移动的接口强制改为电信接口.

破解电信支付:

.class Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterTelsub$1;

.super Ljava/lang/Object;

.source “YgSmsPayAdapterTelsub.java”

用onSuccess函数,替换掉onCanceled,onFailed函数.修改smali汇编代码,变为下面这个样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
.method public payCancel(Ljava/lang/String;)V
#替换为paySuccess函数体代码
.locals 2
.param p1, "arg0" # Ljava/lang/String;
.prologue
.line 44
iget-object v0, p0, Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterTelsub$1;->val$listener:Lcom/yodo1/sdk/game/Yodo14GameSmsPayListener;
if-eqz v0, :cond_0
.line 45
iget-object v0, p0, Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterTelsub$1;->val$listener:Lcom/yodo1/sdk/game/Yodo14GameSmsPayListener;
invoke-interface {v0}, Lcom/yodo1/sdk/game/Yodo14GameSmsPayListener;->onSuccess()V
.line 46
iget-boolean v0, p0, Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterTelsub$1;->val$isRepeated:Z
if-nez v0, :cond_0
.line 47
iget-object v0, p0, Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterTelsub$1;->val$activity:Landroid/app/Activity;
iget-object v1, p0, Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterTelsub$1;->val$productId:Ljava/lang/String;
invoke-static {v0, v1}, Lcom/yodo1/sdk/game/smspay/YgSmsPayAdapterBase;->setPaid(Landroid/content/Context;Ljava/lang/String;)V
.line 50
:cond_0
return-void
.end method
统一接口,强制改为电信的支付接口:

.class public Lcom/talaya/share/utils/OperatorUtils;

.super Ljava/lang/Object;

.source “OperatorUtils.java”

修改getOperatorChannelId让其所有条件下的返回值全部返回为2;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
.method public static getOperatorChannelId(Landroid/content/Context;)I
.locals 5
.param p0, "context" # Landroid/content/Context;
.prologue
const/4 v2, 0x2 #const/4 v2, 0x0 #默认分支 返回为0,初始赋值变量v2
const/4 v3, 0x2 #const/4 v3, 0x1 #移动分支 返回为1,初始赋值变量v3
.line 26
const-string v4, "phone"
invoke-virtual {p0, v4}, Landroid/content/Context;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
move-result-object v1
check-cast v1, Landroid/telephony/TelephonyManager;
.line 27
.local v1, "phoneManager":Landroid/telephony/TelephonyManager;
invoke-virtual {v1}, Landroid/telephony/TelephonyManager;->getSimOperator()Ljava/lang/String;
move-result-object v0
.line 28
.local v0, "operator":Ljava/lang/String;
if-eqz v0, :cond_0
invoke-virtual {v0}, Ljava/lang/String;->length()I
move-result v4
if-lt v4, v3, :cond_0
invoke-virtual {v1}, Landroid/telephony/TelephonyManager;->getSimState()I
move-result v4
if-ne v4, v3, :cond_1
.line 41
:cond_0
:goto_0
return v2 #默认分支 返回为0,前面初始赋值过变量v2
.line 31
:cond_1
const-string v4, "46000" #中国移动分支
invoke-virtual {v0, v4}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z
move-result v4
if-nez v4, :cond_2
const-string v4, "46002" #中国移动分支
invoke-virtual {v0, v4}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z
move-result v4
if-nez v4, :cond_2
const-string v4, "46007" #中国移动分支
invoke-virtual {v0, v4}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z
move-result v4
if-eqz v4, :cond_3
:cond_2
const/4 v2, 0x2 #0x2代表电信 #move v2, v3 #移动分支 返回为1,前面初始赋值过变量v3
.line 32
goto :goto_0
.line 34
:cond_3
const-string v3, "46001" #中国联通分支
invoke-virtual {v0, v3}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z
move-result v3
if-eqz v3, :cond_4
.line 35
const/4 v2, 0x2 #0x2代表电信 #const/4 v2, 0x4
goto :goto_0
.line 37
:cond_4
const-string v3, "46003" #中国电信分支
invoke-virtual {v0, v3}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z
move-result v3
if-eqz v3, :cond_0 #默认分支
.line 38
const/4 v2, 0x2 #0x2代表电信
goto :goto_0
.end method

所以,以后遇到热门的支付的游戏,简单的破解步骤就是:

先搜索”46003”,修改代码让它getOperatorChannelId全部返回2,即:中国电信,的接口;
然后用onSuccess函数,替换掉onCanceled,onFailed函数.也就是说,只要将对应的方法在Smali代码中全部替换成”???Success”的代码即到达在支付界面,无论点击“返回”或者“关闭”都能到达破解成功的效果。为了以防万一,还要可以将AndroidManifest.xml文件中的发送短信权限“android.permission.SEND_SMS”删除。

可以尝试搜索的关键词:

1、”Succeed”、”Fail”、”Cancel”、”Success”、”Failure”相应的关键词有“paySucceed””payFailed”、”payCanceled”和
有“onSucceed””onFailed”、”onCanceled”等等

2、”purchase”、”purchaseCode”、”pay”、”payCode”、”resultCode”、“onBillingFinish”等

运营商网络 特征码 备注
中国移动 46000、46002、46007
中国联通 46001、46006、46010
中国电信 46003、46005、46011
中国铁通 46020、 归属移动

顺便说一句,保存软件数据和缓存配置卸载app的方法,相当于adb uninstall [-k] .
可以直接在手机/data/app/文件夹里删掉类似com.yodo1.olympus.QIHU36001-1.apk文件.格式: [package包名]-x.apk的文件,x为1-N的数字.

您觉得好,您就随意打赏点吧(*^__^*)您的鼓励,是我坚持的动力!