吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6091|回复: 44
收起左侧

[Android 原创] 某麦演出app分析(一)---倒计时去除

  [复制链接]
6yanfeibiao 发表于 2023-8-7 18:06
第一次发帖,多多包涵

起因

疫情开放第一年的演出市场彻底疯掉,五月天北京鸟巢完全抢不到,黄牛猖狂加价,恶心羞辱真五迷,气愤无奈情绪无从发泄。
一气之下决定研究一下某麦app接口。

逆向信息

平台:Android
app版本:8.4.5
工具:jadx,frida

思路

其实想法很简单,一共两个方向

  1. 在app中,等待开票提前进入选择界面或者付款界面,这样可以一定程度上比普通用户快一掉掉
  2. 实现程序call api生成订单,这是最终目的

<!--more-->

APP源码分析

倒计时去除

从界面上看,待开售的页面和立即购买页面是的却别是开售倒计时,从开发估计一定是会通过api获取开售时间,在前端进行倒计时。
GIF 2023-7-27 11-38-13.gif

通过抓包得知获取详情的api是:

https://acs.m.taobao.com/gw/mtop.alibaba.damai.detail.getdetail/1.2/

返回结构:

{
    "api": "mtop.alibaba.damai.detail.getdetail",
    "data": {
        "result": "......"
    },
    "ret": [
        "SUCCESS::调用成功"
    ],
    "v": "1.2"
}

其中data.result就是演出的detail数据:
image-20230718150401539.png

猜测sellStartTime就是开始时间,用countDown作倒计时.尝试在APP源码中查找

image-20230718150535376.png

找到一个叫做ProjectItemDataBean的类,看一下这个DataBean用来做什么
image-20230718150750719.png

继续查找countDown的用例image-20230718153559468.png

发现了ProjectDetailItemMainFragment,应该是View层了,查看是怎么使用image-20230718153703758.png

从api 返回知道countdown返回的值是591614, 估计是秒数,所以hook一下测试:

let ProjectItemDataBean = Java.use(
  "cn.damai.trade.newtradeorder.ui.projectdetail.projectdetailitem.bean.ProjectItemDataBean"
);

ProjectItemDataBean["setCountDown"].implementation = function (j) {
  console.log(`ProjectItemDataBean.setCountDown is called: j=${j}`);
  if (j > 1) {
    this["setCountDown"](5);
  } else {
    this["setCountDown"](0);
  }
};

直接把countDown设成5秒以内,效果是成功的
GIF 2023-7-20 17-49-16.gif

但是即便是倒计时小时了显示立即购买,点击立即购买按钮依然是没办法进入选择价钱页面,为什么呢?

于是我尝试查找倒计时结束之后的逻辑,在View层有一个TimeCountDownListener

image-20230718160619416.png

这里是更新了BuyBtnText,还更新了this.mProjectItemStatusHelper.m45526u(this.mProjectItemDataBean);,所以估计在点击立即购买按钮还有其他数据的判断.
image-20230718160657553.png

这是通过阅读代码发现有一个类叫做ProjectItemStatusHelper.OnBottomViewClickListener,里面的函数:

    public interface OnBottomViewClickListener {
        void onBuyRightNow(int i);

        void onNeedPrivilege(int i);

        void onRegister(int i);

        void onSelectSeat();

        void onSoldOut();

        void onTimingCountDown();
    }

ProjectDetailitemMainFragment中的实现是:

public class C4295e0 implements ProjectItemStatusHelper.OnBottomViewClickListener {
        private static transient /* synthetic */ IpChange $ipChange;

        C4295e0() {
            ProjectDetailItemMainFragment.this = r1;
        }
        ...
        ...
        ...
        @Override // 
        public void onTimingCountDown() {
            IpChange ipChange = $ipChange;
            if (AndroidInstantRuntime.support(ipChange, "-926618722")) {
                ipChange.ipc$dispatch("-926618722", new Object[]{this});
            } else {
                ProjectDetailItemMainFragment.this.processTimeCountDownClick();
            }
        }
    }

通过分析processTimeCountDownClick可知道:

processTimeCountDownClick()->processClickNotRefreshAfterCountDown()->getSubProjectDectailCheckData()

最终调用skuRequest再次call api获取数据:
image-20230718164524955.png

ProjectDetailItemMainFragment.onReturnSkuBeanDataSuccess()中可以看到,原来点击按钮之后会再次获取skuBean,然后判断里面的itemBuyBtnBean.btnStatus是否等于106和倒计时是否等于0,最终运行popupSkuByPerformInfo()

public void onReturnSkuBeanDataSuccess(SkuBean skuBean) {
        long j;
        ...
        ...
        int i = itemBuyBtnBean.btnStatus;
        if (i != 230 && i != 231) {
            this.mSkuBean = skuBean;
        } else {
            this.mSkuBean = null;
        }
        ...
        ...
        if (itemBuyBtnBean.btnStatus == 106) {
            ...
            ...
        }
        updateCountDownVisibility(false, false);
        updateMemberPromptCountDownVisibility(false, false);
        ProjectItemStatusHelper projectItemStatusHelper2 = this.mProjectItemStatusHelper;
        if (projectItemStatusHelper2 != null) {
            projectItemStatusHelper2.m45526u(this.mProjectItemDataBean);
            updatePageUT();
            if (!this.mProjectItemStatusHelper.m45535l()) {
                cancelCountDown();
                displayProjectNotExistPage();
                return;
            }
            this.mPurchaseType = -1;
            popupSkuByPerformInfo();
        }
    }

通过其他正常可购买的api返回得知,"立即购买"的status204,所以,我们可以通过抓包或者hook修改skubeanitemBuyBtnBean.btnStatus204.

我是通过Hook修改:

C42703["onSuccess"].overload(
  "cn.damai.commonbusiness.seatbiz.sku.qilin.bean.SkuBean"
).implementation = function (skubean) {
  var result = updateSkuBean(skubean);
  this["onSuccess"](result);
};
function updateSkuBean(skubean) {
  var json = Java.use("com.alibaba.fastjson.JSON");
  var a = JSON.parse(json["toJSONString"](skubean));
  a.itemBuyBtn.btnStatus = 204;
  var result = json["parseObject"](JSON.stringify(a), skubean.getClass());
  return result;
}

如果一切正常最后会运行openSkuActivity()进入到下一个选购界面
GIF 2023-7-27 11-51-59.gif
然而进入了选择场次票档界面,底部的按钮依然是"提交开售提醒",不是立即购买.

后续

这里继续看下有无办法Hook一下,去显示购买按钮

<!--MyCopyright-->

免费评分

参与人数 9吾爱币 +8 热心值 +8 收起 理由
xuna2009 + 1 + 1 热心回复!
wxxbc + 1 + 1 谢谢@Thanks!
fengchuan + 1 用心讨论,共获提升!
soyadokio + 1 谢谢@Thanks!
iou99vip + 1 + 1 我很赞同!
开心熊猫741 + 1 + 1 我很赞同!
random1 + 1 + 1 用心讨论,共获提升!
lingyun011 + 1 + 1 热心回复!
woaidigua1 + 1 + 1 我很赞同!

查看全部评分

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

白水饮 发表于 2023-8-8 14:54
提示下,将renderingType的值由2改为1即可
fryant 发表于 2023-8-8 23:28
liuhy 发表于 2023-8-8 13:02
liuhy 发表于 2023-8-8 13:05
进入提交订单页面,不是可以直接使用bp链接吗
restartxie 发表于 2023-8-8 13:13
这个有办法破除黑号机制吗
huangnzd 发表于 2023-8-8 14:21
加油,演唱会票靠你了
ChangHJ 发表于 2023-8-8 14:50
看着就很刑呀,比黄牛还刑
ikun20230721 发表于 2023-8-8 15:57
感谢,试一试
lv3389 发表于 2023-8-8 16:15
怎么样,成功了吗
qinshuaizhi 发表于 2023-8-8 16:20
很刑,的确很刑,哈哈
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-28 03:19

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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