吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2890|回复: 67
上一主题 下一主题
收起左侧

[原创] MybatisCodeHelperPro 3.3.5 注册流程逆向分析

  [复制链接]
跳转到指定楼层
楼主
lvbuqing 发表于 2024-9-24 17:59 回帖奖励

首先感谢大佬提供的图床工具,好用的一批,原帖地址:
https://www.52pojie.cn/thread-1965983-1-1.html

正文开始

插件介绍:

阅读完之后你会得到什么:

步骤1:
尝试假激活码,查看报错堆栈:

可疑的地方:

注意看有个doOKAction方法,从字面意思都可以猜出是执行验证OK的动作。

jdax 启动!!

相关代码:

if (this.f1772a.getSelectedComponent() == this.f1776d) {
            if (StringUtils.isNotBlank(this.f1769a.getText())) {
                C0392c c0392c = new C0392c();
                String trim = this.f1769a.getText().trim();
                c0392c.m2039a(trim);
                c0392c.m2042c(C0385a.f1268a);
                String m1880a = C0375s.m1880a();
                c0392c.m2041b(m1880a);
                if (C0626a.m2753a().getInvalidOffLineKey().contains(trim)) {
                    Messages.showErrorDialog(this.f1789a, "激活码不正经", "失败");
                    return;
                }
                try {
                    boolean m2020a = C0389c.m2020a(c0392c);
                    c0392c.m2041b(C0375s.m1881b());
                    boolean m2020a2 = C0389c.m2020a(c0392c);
                    c0392c.m2041b(this.f1767b.getText());
                    boolean m2020a3 = C0389c.m2020a(c0392c);
                    if (m2020a || m2020a2 || m2020a3) {
                        C0626a.m2753a().setValid(true);
                        C0626a.m2753a().setUseFreeVersion(false);
                        Messages.showInfoMessage(this.f1789a, "激活成功", "成功");
                        C0337Q.m1558a();
                        m2641a();
                    } else {
                        Messages.showErrorDialog(this.f1789a, "激活码错误, 激活码为" + trim + "\n 唯一码为:" + m1880a + " 请将信息复制发送给作者", "失败");
                    }
                    return;
                } catch (Exception e) {
                    Messages.showErrorDialog(this.f1789a, "激活码不正常" + ExceptionUtils.getStackTrace(e), "失败");
                    return;
                }
            }
            return;
        }

需要到达 “激活成功” 需要经过的步骤:

1.如图 206 行,得填写激活码

  1. 214行 激活码不正经,激活码格式要正确
  2. 需要满足其中任意条件,m2020a ,m2020a2,m2020a3
boolean m2020a = C0389c.m2020a(c0392c);
c0392c.m2041b(C0375s.m1881b());
boolean m2020a2 = C0389c.m2020a(c0392c);
c0392c.m2041b(this.f1767b.getText());
boolean m2020a3 = C0389c.m2020a(c0392c);
// if (m2020a || m2020a2 || m2020a3)

这里校验都是走的 m2020a ,所以重点分析这个函数。

  1. m2020a 方法函数:

    没啥好看的,重点分析mo1993a

  2. mo1993a 方法函数:


public static C0400f m2156a(String str) {
        byte[] m2154b;
        try {
            m2154b = C0411d.m2154b(C0411d.m2148a(new String(Base64.getDecoder().decode("aaaaaaaaaaaa"), Charsets.UTF_8)), Base64.getDecoder().decode(str));
        } catch (C0409b e) {
            m2154b = C0411d.m2154b(new C0410c(), Base64.getDecoder().decode(str));
        }
        try {
            String str2 = new String(m2154b, "UTF-8");
            try {
                return (C0400f) f1356a.fromJson(str2, C0400f.class);
            } catch (Exception e2) {
                throw new RuntimeException("gson catch exception, the json string is" + str2, e2);
            }
        } catch (UnsupportedEncodingException e3) {
            throw new RuntimeException(e3);
        }
    }

可以看到,取 c0392c 的 值都是通过  m2156a 去校验。而 m2156a
来自: C0412e.m2156a(m2035a);
这里需要分析 m2156a 这个方法

  1. m2156a 方法函数:

看返回出: return (C0400f) f1356a.fromJson(str2, C0400f.class);
这里返回的是一个json序列化转为 C0400f 对象,而C0400f如图:

大概这个就是离线验证后的要校验的数据类了。

回到m2156a 一看能够看出这是一个数据解密字符串的操作,而返回的数据是 m2154b ,

好巧不巧,m2154b 都是通过 C0411d.m2154b 函数返回的

正好 第 17 行  可以看出他加载的一个很长的字符串,盲猜就是解密数据相关的东西了。

  1. m2154b 方法函数:

可知,采用 RSA 的加密方式,图中所示为 公钥解密操作。
由步骤五 可以逆推出 加密过程。

还原加密代码流程:

  1. 构建自己的RSA 公私钥
  2. 由步骤五 可知,传入的 公钥需要经过base64 编码 。
  3. 构建 需要加密的json串,大致结构为:{"paidKey":"","valid":true,"userMac":"","validTo":}
    其中,根据字面意思可知,paidKey为购买的激活码,valid验证的结果,userMac机器码,validTo到期时间
  4. 私钥加密json串

完整代码:

package org.example;

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
public class Main2 {
    public static void main(String[] args) {
        String json = "{\"paidKey\":\"lvbuqing@52pojie.cn\",\"valid\":true,\"userMac\":\"实际的机器码\",\"validTo\":4092566400000}";

        RSA rsa = SecureUtil.rsa( "私钥", "公钥");
        String privateKeyBase64 = rsa.getPrivateKeyBase64();
        String publicKeyBase64 = rsa.getPublicKeyBase64();
        System.out.println("privateKeyBase64: " + privateKeyBase64);
        System.out.println("publicKeyBase64: " + publicKeyBase64);

        String encode1 = Base64.encode(publicKeyBase64);
        System.out.println("公钥的base64编码: " + encode1);
                        /**
                         * 私钥加密
                         */
        String encryptBase64 = rsa.encryptBase64(json, KeyType.PrivateKey);
        System.out.println("私钥加密: " + encryptBase64);
        /**
         * 公钥解密
         */
        String decryptStr = rsa.decryptStr(encryptBase64, KeyType.PublicKey);
        System.out.println("公钥解密: " + decryptStr);
    }
}

运行结果:

将 公钥的base64编码 放到程序包里面,将 私钥加密 的数据在程序内激活

最重要:

当然是替换插件包里面的 被加密的公钥啦,换成我们自己的。

jclasslib bytecode viewer  启动!!

了解classfile 文件结构的同学都知道,像这种写死的字符串,一般都在常量池初始化,如图

这里是引用类型,需要跳转到 索引第78号的位置,
然后,就可以了执行如图所示操作:

当然,我这边已经修改好了,
下载:[backcolor=rgb(238">https://lvbuqing.lanzouw.com/iBe3X2ar9k3c[backcolor=rgb(238, 238, 238)] 密码:hgnb
至于激活,我得需要知道你的机器码才能帮你激活
ps:
我用的公私钥:
privateKeyBase64: MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ7XwlkJ1om75Abw55NiFfqwA+MR9UBhfKAr/EF/jdei219PMWc0AQDYfiCrjunIOdRXkTXXbbwMfH3pD4gv38nmDFrQ89rOD9aW964vzX05zMEbi35PRFQ+TS5wKvXeOGzn1CEvOwbiqVvzty1wRfydfXv1XyqVMWoAdXySL+MFAgMBAAECgYACVYNKkaVwYq1oGLQea0uNYna8KHBlIMmXBO5w+/HWoFL+5IgCTzZQj93SlxLDhqiq4RqGIwM+xyQxKXKL+sAcDmrFNt9vPMfa1mWLckoWquZEknj36MgC3apFCkfGUG+VGr0LOsubj0qSJ6M6YA9sXfk+zOV555dgoSUS8YNmwQJBAOAPY0RnuDFAHLSl0zL6E8fxwUnDsHrOSv5xqJQOTpBjvm1UDpqMRLTO9mFoQW6r1qa+0sXjTnPwzd7Q8HN7cPUCQQC1fGZ/WVTMXxz5WIsD3HY1QxTjtrBjgH9d3GYUQKYvSYF3iWKj4Og4c6peGkhwxm3mXbDbZ/mepuXlHGp37x/RAkA2AB9pliHTZONGOo0LRTBNSRvPnmVDQ8LZTiVWAZi3vgJgMRkP8GyCszq4QTs75Bhouabs4JrA4LGNWQgKnR6dAkBdLEa67rPYUKRhZxHHo7GUWqIo3ivkiZ3aJELL9vzanhQ3uHLJy7es88TtlvTF4Tme4U7g9Zpz1x+D5njKphthAkALsHi9VlzWO1mao3m1H5LvZUy+uu2tsuCOhnU7VsewG5ETd84btS5zpaU4ugLdO4Smeka+37AG/KHx3bVXMrwh
publicKeyBase64: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCe18JZCdaJu+QG8OeTYhX6sAPjEfVAYXygK/xBf43XottfTzFnNAEA2H4gq47pyDnUV5E11228DHx96Q+IL9/J5gxa0PPazg/WlveuL819OczBG4t+T0RUPk0ucCr13jhs59QhLzsG4qlb87ctcEX8nX179V8qlTFqAHV8ki/jBQIDAQAB

完结,撒花!!{:301_987:}

==================================

2024年9月26日19:50:50

接着分析:

有人反馈,生成代码后闪退,

具体问题原因为:

这里判断成功后会直接弹窗后关闭 IDEA  ,
其实不难发现 是在取值 getIfUseNewMapping 后判断 是否大于100。然后后面的代码才会执行。
我们只需要把修改getIfUseNewMapping 函数,让他的值返回小于100以内就可以。

怎么做呢?

使用工具:javassist

具体代码:

    public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath("instrumented-MyBatisCodeHelper-Pro241-3.3.5+2321.jar");

        CtClass driverclass = pool.get("com.ccnode.codegenerator.myconfigurable.Profile");

        driverclass.getDeclaredMethod("getIfUseNewMapping").setBody("{return 1;}");
        driverclass.writeFile("javassistout");
    }

然后替换 Profile.class 文件就可以啦!!

效果图:

这样就OK啦!!

https://lvbuqing.lanzouw.com/iizzI2ax8pmb

密码:52pj

免费评分

参与人数 13吾爱币 +12 热心值 +11 收起 理由
9324 + 1 热心回复!
Coocle + 1 谢谢@Thanks!
梦毁他城 + 1 + 1 用心讨论,共获提升!
water201 + 1 热心回复!
不知道改成啥 + 3 + 1 感谢大佬激活成功了
Issacclark1 + 1 谢谢@Thanks!
1783780690 + 1 + 1 热心回复!
tutu2 + 1 + 1 虽然已经不做开发了 但是还是谢谢你的辛勤付出
novice11 + 1 谢谢@Thanks!
夜莺高歌 + 1 + 1 我很赞同!
Carinx + 1 + 1 谢谢@Thanks!
孤狼微博 + 1 + 1 谢谢@Thanks!
3yu3 + 1 + 1 用心讨论,共获提升!

查看全部评分

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

来自 32#
 楼主| lvbuqing 发表于 2024-9-26 14:27 |楼主
本帖最后由 lvbuqing 于 2024-9-26 20:24 编辑


目前有这个问题,晚点修复,

# 已修复,请下载最新的
推荐
sunlong0717 发表于 2024-10-5 20:16
wyakuan 发表于 2024-9-28 03:21
离线激活的话还有个方案,就是改解码的方法

然后再修改Profile.java的getIfUseNewMapping方法

我也是用这种方案处理的,很方便
推荐
tokenian 发表于 2024-10-2 12:54
我这里有个疑问,既然能够替换人家的class文件。那直接修改验证逻辑。把验证方法里多余的改成
                        C0626a.m2753a().setValid(true);
                        C0626a.m2753a().setUseFreeVersion(false);
                        Messages.showInfoMessage(this.f1789a, "激活成功", "成功");
                        C0337Q.m1558a();
                        m2641a();
其他的直接删掉。常见的hook方法,不知道这样子行不?公私钥得自己构造,多麻烦。望楼主解惑
沙发
孤狼微博 发表于 2024-9-24 18:41
文件是俩apk正确吗
3#
water201 发表于 2024-9-24 18:43
文件是2个apk包,时间还是2019,是不是上传错误了?
4#
孤狼微博 发表于 2024-9-24 18:49
uniqueCode:74-4C-A1-DF-C8-57,email:i@batcd.com 求大佬
5#
lhfcsm 发表于 2024-9-24 20:19
呵呵,正在使用中
6#
XD001 发表于 2024-9-24 20:42
试试看 也可以
7#
 楼主| lvbuqing 发表于 2024-9-24 20:45 |楼主

不好意思填错了链接,已经修改了
8#
 楼主| lvbuqing 发表于 2024-9-24 20:45 |楼主

对不起,大佬,已经改了,链接已修正
9#
 楼主| lvbuqing 发表于 2024-9-24 20:47 |楼主
孤狼微博 发表于 2024-9-24 18:49
uniqueCode:74-4C-A1-DF-C8-57,email:i@batcd.com 求大佬

明天给您弄,今天下班了
10#
lyzh 发表于 2024-9-24 21:29
感谢大佬分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

快速回复 收藏帖子 返回列表 搜索

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

GMT+8, 2024-10-7 14:07

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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