前言在游戏中要想玩的畅快,免不了装备的购买,而前提是要有足够的点券支撑。本文将对某游戏,实现0元购买648元点券,仅供学习使用。 购买点券点券购买界面如图所示。[![](htt…
前言
在游戏中要想玩的畅快,免不了装备的购买,而前提是要有足够的点券支撑。本文将对某游戏,实现0元购买648元点券,仅供学习使用。
购买点券
点券购买界面如图所示。
查看程序log信息
利用工具Android Device Monitor查看程序log信息。
选中包名,并在过滤器添加包名进行过滤。
点击进入充值60点券页面后,查看日志。
发现返回的都是json数据,而json数据是通过网络返回的,并没有硬编码在smali代码里面。所以这些并不是我们想要的。
点击返回键后,再次查看日志。
发现日志中有一个很明显的"取消支付操作"字符串,但这个字符串同样是json格式,很大概率来自于网络。
在Android Killer中进行反编译,然后在工程搜索中将"取消支付操作"转换为Unicode后进行搜索。
果然并未搜索到任何结果。在log日志中,还有一处硬编码字符串为"4399充值返回:6001"。
同样,将"4399充值返回:6001"转换为Unicode后进行搜索。
仍然没有搜索到任何结果,尝试将返回码6001去除,只将字符串"4399充值返回:"转换为Unicode后进行搜索。
成功在smali.com.leiting.sdk.channel.m4399.M4399SdkUser$4.smali处搜索到结果。
方法剖析
将APK拖入到jadx-gui工具中进行反编译,以便于更方便的查看smali对应的java代码。
找到smali.com.leiting.sdk.channel.m4399.M4399SdkUser$4.smali处,对应Java代码如下:
private OperateCenter.OnRechargeFinishedListener mPayListener = new OperateCenter.OnRechargeFinishedListener() {
/* class com.leiting.sdk.channel.m4399.M4399SdkUser.AnonymousClass4 */
@Override // cn.m4399.operate.OperateCenter.OnRechargeFinishedListener
public void onRechargeFinished(boolean z, int i, String str) {
Message obtainMessage = M4399SdkUser.this.mHandler.obtainMessage();
String str2 = ConstantUtil.TAG;
BaseUtil.logDebugMsg(str2, "4399充值返回:" + i);
if (!z || i != 9000) {
Bundle bundle = new Bundle();
bundle.putString("resultMsg", str);
obtainMessage.what = 6;
obtainMessage.setData(bundle);
} else {
obtainMessage.what = 5;
}
M4399SdkUser.this.mHandler.sendMessage(obtainMessage);
}
};
通过代码分析得出,返回的字符串是"4399充值返回:"加上传入的参数i。
而我们通过日志收集到的信息为"4399充值返回:6001"。
所以推测,进入if (!z || i != 9000)
分支语句后,则充值不成功。
进入else
分支语句后,充值成功。
根据逻辑得出,else与if是相对的,所以只要满足 z && i == 9000 即可充值成功。
所以首先要找到参数z和i的值。
利用工具Android Device Monitor进行方法剖析。
点击start Method Profiling,然后在支付页面点击返回,捕捉这段时间的方法都执行了哪些方法。
因为在返回过程中一定调用了onRechargeFinished方法,所以在Find中搜索onRechargeFinished。
其中Parents表示调用它的方法,Children表示它调用的方法,依次类推找出调用关系为:
cn.m4399.recharge.ui.activity.RechargeActivity.d()
↓
cn.m4399.operate.x0$d.a
↓
com.leiting.sdk.channel.m4399.M4399SdkUser$4.onRechargeFinished
修改smali
通过方法剖析找到最初的代码调用位置为:cn.m4399.recharge.ui.activity.RechargeActivity.d()。
对应java代码为:
private void d() {
if (!b4.g() && a3.e != null) {
a3.e.a(false, 6001, PayResult.a(6001));
}
}
继续往下跟踪,找到cn.m4399.operate.x0$d.a对的Java代码为:
public class d implements a3.g {
d() {
}
@Override // cn.m4399.operate.a3.g
public void a(boolean z, int i, String str) {
x0.this.e.onRechargeFinished(z, i, str);
}
}
因为只有前两个参数对充值结果有影响,所以第三个参数不做研究。前两个参数中,z为false,i为6001。
而想要充值结果成功,需要满足:z为true,并且,i==9000。
z是第一个参数,所以在判断p1是否等于0之前,将1赋值给p1。
由于增加了代码,令p1=1,所以继续执行第75行代码。
第75行代码,令p1=0x2328。将0x2328换算成十进制为9000。
然后执行第77行代码,如果p2不等于p1就会跳转到:cond_0处。
已知i是第二个参数,p2的值是6001,而p1的值是9000。所以一定是不相等的。
而只有p2和p1相等的时候,才会充值成功。所以将6001转换为十六进制后赋值给p1。
成功内购
修改之后保存,进行回编译。安装后登入游戏,选择价值648元的点券购买,然后返回即可购买成功。
总结
利用Android Device Monitor工具查看程序每一步执行时打印的log信息,通过搜集到最有可能存在的硬编码信息进行逐一尝试,摸清代码编写方式。再通过方法剖析的方式,分析出各个方法之间的调用关系,最后通过读smali代码的逻辑找到关键语句处进行添加和修改。完成0元可购买任何点券。
- 本文作者: bmstd
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/951
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!