软件VIP破解的基本思路 - APP逆向论坛 - 主版块 - 奋斗资源网

软件VIP破解的基本思路

确保它没有加固,如果有加固的话还是360加固,那也没有关系,之后我会用hook方式来破解,但这仅限root,这篇文章只做最基本的软件会员破解,我会全程详细讲解,每一个步骤所有的含义包括这串代码,在软件中起什么作用图中软件仅用作演示,不提供破解后的安装包

20250218165919764-IMG_20250218_165854

先点开软件

20250218170215312-Screenshot_2025-02-18-17-02-09-66_9e8df3d0c7c1f50248b6ee043a653d26

20250218170216869-Screenshot_2025-02-18-17-02-12-14_9e8df3d0c7c1f50248b6ee043a653d26

随便点一个dex文件, dex编辑器++

20250218170303661-Screenshot_2025-02-18-17-03-04-38_9e8df3d0c7c1f50248b6ee043a653d26

进到这个界面后,我们直接点击常量,因为用搜索搜isvip或者是getvip,vip这类字眼往往一般会搜不到或者被软件厂商换种叫法,或者是有其他问题,常量搜索会员

20250218170548734-Screenshot_2025-02-18-17-05-43-42_9e8df3d0c7c1f50248b6ee043a653d26

20250218170549580-Screenshot_2025-02-18-17-05-46-78_9e8df3d0c7c1f50248b6ee043a653d26

这里也是轻松找到了永久会员,这个文字直接点击搜索

20250218170826190-Screenshot_2025-02-18-17-08-11-81_9e8df3d0c7c1f50248b6ee043a653d26

这里也是搜到了三种结果,有些小白就会慌了,不知道选哪个,那么我们一个一个开始排查

先点开第1个

20250218171021601-Screenshot_2025-02-18-17-09-52-49_9e8df3d0c7c1f50248b6ee043a653d26

右上角三个点转成Java代码,找不到会员就直接搜索会员,可以发现刚才搜索到的永久会员,他跟实际没有任何关系,他是充值页面上的文字,也就是价格这些跟有没有vip没关系,所以第1个可以直接排除

那么来看第3个

同样转成Java代码

20250218171301702-Screenshot_2025-02-18-17-12-04-74_9e8df3d0c7c1f50248b6ee043a653d26

看到这可能会懵了,那么我们直接来一串高亮代码解释一下

public final String x2(String str) {
    switch (str.hashCode()) { // 根据字符串的哈希值进行分支判断
        case -968291847: // 哈希值为 -968291847 的情况
            return !str.equals("vipMonthlyPrice") ? "" : "月度会员"; // 如果字符串是 "vipMonthlyPrice",返回 "月度会员",否则返回空字符串
        case -673972369: // 哈希值为 -673972369 的情况
            if (str.equals("vipYearPrice")) { // 如果字符串是 "vipYearPrice"
                return "年度会员"; // 返回 "年度会员"
            }
            break; // 如果不匹配,跳出分支
        case 852904651: // 哈希值为 852904651 的情况
            if (str.equals("lifeDays1Price")) { // 如果字符串是 "lifeDays1Price"
                return "永久会员-生命周期1"; // 返回 "永久会员-生命周期1"
            }
            break; // 如果不匹配,跳出分支
        case 881533802: // 哈希值为 881533802 的情况
            if (str.equals("lifeDays2Price")) { // 如果字符串是 "lifeDays2Price"
                return "永久会员-生命周期2"; // 返回 "永久会员-生命周期2"
            }
            break; // 如果不匹配,跳出分支
        case 1261029048: // 哈希值为 1261029048 的情况
            if (str.equals("vipPermanentPrice")) { // 如果字符串是 "vipPermanentPrice"
                return "永久会员"; // 返回 "永久会员"
            }
            break; // 如果不匹配,跳出分支
    }
    return ""; // 默认返回空字符串
}

很显然,这三个还不是,那只剩第2个了

20250218171615743-Screenshot_2025-02-18-17-16-15-06_9e8df3d0c7c1f50248b6ee043a653d26

看到这儿看不懂没关系,我也看不懂,转成Java再看一遍

20250218171721664-Screenshot_2025-02-18-17-17-18-28_9e8df3d0c7c1f50248b6ee043a653d26

到这儿就通俗易懂了

20250218173010940-IMG_20250218_172935

因为屏幕局限的原因写不了太多文字,我就直接用高亮代码写出来了

// 如果用户信息对象 userInfoBean3 不为空
if (userInfoBean3 != null) {
    // 获取用户的 VIP 等级状态(i3)
    i3 = userInfoBean3.getVIP();
}

// 如果 VIP 等级大于 0(表示有会员状态)
if (i3 > 0) {
    UserInfoBean userInfoBean4 = this.s; // 从类成员变量获取用户信息
    Long membersEndDateMs = null; // 初始化会员结束时间
    
    // 如果 userInfoBean4 存在且能获取到会员结束时间
    if (userInfoBean4 != null && (membersEndDateMs = userInfoBean4.getMembersEndDateMs()) != null) {
        // 通过 xf9.a1 方法处理时间(可能是时间格式转换)
        l2 = xf9.a1(membersEndDateMs);
    }

    // 判断会员是否有效:
    if (
        (l2 != null && l2.longValue() >= System.currentTimeMillis()) || // 结束时间未过期
        l2 == null // 或没有结束时间(永久会员)
    ) {
        if (l2 == null) {
            pbVar2.E("vipstatus", "永久会员"); // 标记为永久会员
            return;
        } else {
            pbVar2.E("vipstatus", "订阅会员"); // 标记为订阅会员
            return;
        }
    }
    
    // 如果会员已过期
    pbVar2.E("vipstatus", "过期会员");
    return;
}

// 非会员状态
pbVar2.E("vipstatus", "非会员");
return;

根据上述我们可知i3 = userInfoBean3.getVIP();才是是否为vip的关键

一般情况下我们只看小数点后面的,getVIP()

   这是 userInfoBean3对象的一个方法,用于获取用户的 VIP 等级或状态。

   所以我们只需要给getvip赋值就行了

20250218173929349-IMG_20250218_173917

20250218174743327-IMG_20250218_174736

想必知道的人应该怎么做了,我详细讲解一下每层含义吧

.method public final getVIP()I

声明一个公开的 (public) 不可重写的 (final) 方法,方法名为 getVIP,返回类型为 int (对应 I)。

寄存器数量

.registers 2

表示该方法共使用 2 个寄存器(p0 和 v0)。

p0 是隐式的 this 指针(非静态方法的第一个参数)。

v0 用于临时存储字段值。

字段读取

iget v0, p0, Lcom/app/modelintegral/data/bean/UserInfoBean;->VIP:I

iget 指令从实例中读取字段值。

v0: 目标寄存器,存储读取到的值。

p0: 当前对象 (this),即 UserInfoBean 实例。

VIP:I: 字段标识符,表示 UserInfoBean 类中的 int 类型字段 VIP

所以我们目标是给V0赋一个值

const/4 v0, 0x1

解释:const/4 v0, 0x1 将立即数值 1 存入寄存器 v0

20250218180637702-IMG_20250218_180629

保存完后一路返回

自动签名并更新

20250218180728235-IMG_20250218_175916

20250218180731424-IMG_20250218_175937

20250218180731306-IMG_20250218_175958

20250218180850545-IMG_20250218_180834

有问题的话评论底下留言

请登录后发表评论

    没有回复内容