吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4852|回复: 17
收起左侧

[原创] 某数据库管理软件注册分析

[复制链接]
gzzchh 发表于 2020-2-16 23:50
本帖最后由 gzzchh 于 2020-2-16 23:50 编辑

最近为了准备把开发环境搬到Linux上去. 对一些开发工具进行了挑选. 我发现DBeaver-EE效果不错. 于是尝试逆向分析之.本文原文在B站的链接是 https://www.bilibili.com/read/cv4538717
0x01 搜索
在 plugins 文件夹找一些文件名比较奇特的JAR文件,丢进反编译器看结果.
一般来说,包名为org.apache org.eclipse 之类的一看就跟程序本身无关的第三方库就可以跳过去了.
最后发现所有带有关键字 lm 的包都与许可有关(LicenseManager)
image.png
0x02 反编译
我用的是Bytecode-Viewer,可以开两种(最多三种)不同的反编译器相互比较.
如果要跟踪上下关系就得用IDEA进行反编译.
Bytecode-Viewer中我们看到了导入许可相关的类

导入

导入

跟踪之~

获取解密密钥

获取解密密钥

若要解密则必须获取解密Key

从JAR获取

从JAR获取

密钥源自JAR中

读加密字符串

读加密字符串

要读出来

自定义读取方法

自定义读取方法

用自己的方法读

此时完成密钥读取.回到之前的位置,开始解密
解密方法如下

解密

解密

这就是标准的RSA解密.
解密方法:读取导入的字符串->Base64解密->用JAR内置Key进行RSA解密(方法RSA/ECB/PKCS1Padding)
解密完成后,得到的字节数组便是密钥.
其格式如下,先贴出读取代码
public LMLicense(@NotNull byte[] encryptedData, @NotNull Key key) throws LMException {
        this.encoded = encryptedData;
        byte[] data = LMEncryption.decrypt((byte[])encryptedData, (Key)key);
        int offset = 0;
        this.licenseFormat = LMLicenseFormat.STANDARD;
        try {
            this.licenseFormat = LMLicenseFormat.valueOf((byte)data[offset]);
        }
        catch (Exception exception) {
            log.warning("Unsupported license format: " + data[offset]);
        }
        ++offset;
        if (data.length != this.licenseFormat.getEncryptedLength()) {
            throw new LMException("Bad " + (Object)this.licenseFormat + " license length (" + data.length + ")");
        }
        this.licenseId = new String(data, offset, 16).trim();
        this.licenseType = LMLicenseType.valueOf((byte)data[offset += 16]);
        this.licenseIssueTime = LMUtils.getDateFromBytes((byte[])data, (int)(++offset));
        this.licenseStartTime = LMUtils.getDateFromBytes((byte[])data, (int)(offset += 8));
        this.licenseEndTime = LMUtils.getDateFromBytes((byte[])data, (int)(offset += 8));
        this.flags = LMUtils.bytesToLong((byte[])data, (int)(offset += 8));
        this.productId = new String(data, offset += 8, 16).trim();
        this.productVersion = new String(data, offset += 16, 8).trim();
        this.ownerId = new String(data, offset += 8, 16).trim();
        this.ownerCompany = new String(data, offset += 16, 64).trim();
        offset += 64;
        if (this.licenseFormat == LMLicenseFormat.STANDARD) {
            this.ownerName = new String(data, offset, 64).trim();
            offset += 64;
            return;
        }
        this.ownerName = new String(data, offset, 32).trim();
        this.ownerEmail = new String(data, offset += 32, 48).trim();
        offset += 48;
        this.yearsNumber = data[offset++];
        if (this.yearsNumber <= 0) {
            this.yearsNumber = 1;
        }
        this.reserved1 = data[offset++];
        this.usersNumber = LMUtils.bytesToShort((byte[])data, (int)offset);
        if (this.usersNumber <= 0) {
            this.usersNumber = 1;
        }
        offset += 2;
    }

原文中使用FernFlower反编译,我写这篇文章的时候用的是CFR(懒得开IDEA) 所以有一些不一样
我整理了一下这段字节数组中,哪些部分是什么意思,如下

格式分析

偏移量 项目 类型 长度 注解
0 LMLicenseFormat 枚举 1 见下文
1 licenseId String 16
17 licenseType LMLicenseType 1
18 licenseIssueTime Date 8
26 licenseStartTime Date 8
34 licenseEndTime Date 8
42 flags Long 8
50 productId String 16
66 productVersion String 8
74 ownerId String 16
90 ownerCompany String 64

若许可类型是STANDARD

偏移量 项目 类型 长度 注解
154 ownerName String 64

否则

偏移量 项目 类型 长度 注解
154 ownerName String 32
186 ownerEmail String 48
234 yearsNumber Byte(直接取数组) 1 见下文
235 reserved1 Byte(直接取数组) 1 保留位,未知
236 usersNumber Short 1 见下文

最后偏移量再+2

LicenseFormat

许可类型 说明 加密长度
0 STANDARD 初始许可格式 238
1 EXTENDED 带有所有者邮箱的扩展格式 218

yearsNumber

看上去貌似是直接取了所在下标的值.
若小于等于0,则设定该变量为1

usersNumber

yearsNumber但需要进行转换,从Byte转换到Short
判定规则相同



以上内容来自我自己的笔记程序
简单来说就是把字节数组一部分一部分读出来并进行类型转换.获取许可信息
关于注册原理分析就到此结束了. DBeaver-EE可以说是一款很良心的数据库管理软件了.
如果有dalao想要白嫖EE版,想办法换了JAR的key然后照着上面的原理写一份Keygen就可以了.
至于数组转换 这些方法位于 org.jkiss.lm.LMUtils 包内 文件名是 org.jkiss.lm_xxxxx.jar
最后放上研究手记和一些代码 : https://github.com/gzzchh/DBE-Agent
疫情在家好无聊QAQ~

免费评分

参与人数 5威望 +1 吾爱币 +24 热心值 +2 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
solly + 1 + 1 我很赞同!
wzw666 + 1 我很赞同!
WarWolf + 1 我很赞同!
为往圣继绝学 + 1 热心回复!

查看全部评分

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

 楼主| gzzchh 发表于 2020-3-3 01:18
a5228172 发表于 2020-3-2 09:11
""用JAR内置Key进行RSA解密(方法RSA/ECB/PKCS1Padding)      ""  这个用什么软件可以

自己写一段Java代码来实现

免费评分

参与人数 1吾爱币 +1 收起 理由
a5228172 + 1 热心回复!

查看全部评分

绫织梦 发表于 2020-2-17 00:37
acersnow 发表于 2020-2-17 01:05
ufozoupan 发表于 2020-2-17 01:35
感谢分享,谢谢楼主
头像被屏蔽
tlf 发表于 2020-2-17 07:36
提示: 作者被禁止或删除 内容自动屏蔽
小若离 发表于 2020-2-17 07:57
膜拜大佬,学习学习
setycyas 发表于 2020-2-17 08:30
感谢楼主的分析。学习一下
mongerwjb 发表于 2020-2-17 09:55
感谢楼主分享,学习了。
zhanget3 发表于 2020-2-17 10:23
厉害,大神啊
toney 发表于 2020-2-17 12:12

感谢楼主的分析。学习一下。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-16 14:42

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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