【逆向】某吉他调音APP存在支付漏洞可¥0.01拿下永久会员等严重漏洞
想想还是发自己网站舒服,想怎么写就怎么写,某个社区认为这篇文章在鼓励使用网站漏洞不给予参加写作计划。发在社区里那篇的我甚至都做了完整打码,Hook代码也没贴。
就在今天,我吉他调音器不小心摔坏了,想到现在有调音器app,所以到小米应用市场搜了一下下载下来,但是调吉他一弦和六弦竟然是收费的

然后看了一眼这个app是没有加固的,也不知道为什么,看到没加固我就想反编译。不看不知道,一看吓一跳。整个分析过程,就像老奶奶钻被窝,给爷整笑了。
槽点1:代码内置VIP账户
使用jadx反编译代码,通过app内的Toast提示词定位到判断vip的方法,这个方法硬编码了一个手机号,只要是这个手机号,就直接给VIP。可能是开发人员的,也可能是老板的。

槽点2:登录不管是否成功,都返回账户的正确密码
我原本是想测下这个登录是否有漏洞点,结果输入错误密码后,接口竟然返回了明文的正确密码。

等等,那根据前面逆向得到的硬编码的账户,我是不是可以拿到永久VIP账户?
答案不言而喻

槽点3:购买会员无校验
从点击弹出优惠页面,到点购买跳转到支付宝,一路回溯到支付代码。发现参数异常简单,于是试着Hook该支付方法,在调用支付SDK之前,把金额修改为¥0.01,写成了xposed模块放到手机上试下,结果如图


槽点4:会员传染
当你购买了会员后,退出登录再登录任意非会员账户,此时非会员账户会成为会员,且被记录到云端(换手机登录也是VIP,是真的持久化)
逆向代码可以看到几个问题
1、因为购买完成后需要把购买成功消息通知服务器,所以代码里总是优先取本地的VIP状态,然后发送给服务器(服务器才知道有个用户购买成功了,要记录下来)
2、代码中VIP等级+过期时间是全局变量,并且在退出登录时不销毁
3、因为1和2,任意非会员账户登录,app就会认为他购买了会员并通知服务器记录
4、此种情况持续到app被关闭才会消失

总结
这个app在用户认证、支付安全、状态管理等方面存在严重设计缺陷,事实上问题远不止我列出来的这些。
相关Hook代码
package com.sumver.fdtune;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
import android.content.Context;
public class hackvip implements IXposedHookLoadPackage {
private static final String TAG = "HackVip";
@Override
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.fd.tune")) {
return;
}
XposedBridge.log(TAG + ": 找到吉他调音器+");
try {
XposedHelpers.findAndHookMethod(
"com.fd.uservip.activity.VipBvActivity",
lpparam.classLoader,
"m",
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Object activityInstance = param.thisObject;
// 获取当前 VIP 类型b
int currentVipType = (int) XposedHelpers.getObjectField(activityInstance, "B");
XposedBridge.log(TAG + ": Hook m(): Current VIP Type (B) is: " + currentVipType);
// 检查是否是永久会员 (B == 3)
if (currentVipType == 3) {
// 获取当前价格c
double currentPrice = (double) XposedHelpers.getObjectField(activityInstance, "C");
// 修改价格为 0.01
XposedHelpers.setObjectField(activityInstance, "C", 0.01);
}
}
}
);
} catch (NoSuchMethodError e) {
XposedBridge.log(TAG + ": NoSuchMethodError: " + e.getMessage());
} catch (XposedHelpers.ClassNotFoundError e) {
XposedBridge.log(TAG + ": ClassNotFoundError: " + e.getMessage());
} catch (Exception e) {
XposedBridge.log(TAG + ": Hook 过程中发生异常: " + e.getMessage());
e.printStackTrace();
}
}
}
这只是刚好挖到的漏洞,事实上要解锁会员功能,都不用修改支付相关函数,直接Hook判断VIP的函数,让他始终返回为true就行了
try {
// Hook 关键的 VIP 检查方法: c.w(Context)
XposedHelpers.findAndHookMethod(
"o4.c",
lpparam.classLoader,
"w",
Context.class,
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
param.setResult(true); // 将返回值设为 true,表示用户始终是 VIP
XposedBridge.log(TAG + ": VIP 检查被绕过!方法 c.w() 被强制返回 true。");
}
}
);
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭