一元网络论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 85|回复: 0

获取DBeaver激活码和JaNetfilter规则的方法。

[复制链接]

2万

主题

2万

帖子

8万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
89580
发表于 2024-9-18 00:37:10 | 显示全部楼层 |阅读模式
声明:下面的代码没有一行是我写的。只在 dbeaver-ue-24.0.0-macos-x86_64.dmg 中测试通过。
已经有佬友用Python实现过了,帖子在DBeaver 使用ja-netfilter power插件激活。我只是一个Java CURD仔,Python代码看不太懂。又有佬友在帖子DBeaver Ultimate 激活方法分享提到了一个链接DBeaver Ultimate Edition License验证分析,拜读之,在24.0.0版本复现整个操作。在拜读和复现的过程中com.dbeaver.lm.api.LMMain类(com.dbeaver.lm.api_3.0.2.202404011634.jar 包)引起了我的注意,来看看它的main方法长什么样子
  public static void main(String[] args) throws Exception {
      System.out.println("LM 2.0");
      if (args.length > 0 && args[0].equals("gen-keys")) {
          System.out.println("Test key generation");
          generateKeyPair();
      } else if (args.length > 0 && args[0].equals("encrypt-license")) {
          System.out.println("Encrypt license");
          encryptLicense();
      } else if (args.length > 0 && args[0].equals("decrypt-license")) {
          System.out.println("Decrypt license");
          decryptLicense();
      } else if (args.length > 0 && args[0].equals("import-license")) {
          System.out.println("Import license");
          importLicense();
      } else {
          System.out.println("Test license generation");
          generateLicense();
      }
  }
这样的方法命名简直了,我愿称DBeaver也是大善人,直接告诉你怎么生成KEY,怎么生成License,结合狗群主的Janetfilter这是开卷考试啊,我们只需要把里面的代码抠出来组合一下不就成了么。
[/url]生成自定义的密钥对
生成密钥对的方法来自 LMMain#generateKeyPair 方法,DBeaver 密钥对的 keySize 为 2048,并且密钥对使用 Base64 编码后被按每行最多 76 个字符显示
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.util.Base64;
public class KeyGenerator {
    public static void main(String[] args) throws Exception {
        KeyPair keyPair = generateKeyPair(2048);
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();
        System.out.println("--- PUBLIC KEY ---");
        System.out.println(splitLines(Base64.getEncoder().encodeToString(publicKey.getEncoded()), 76));
        System.out.println("--- PRIVATE KEY ---");
        System.out.println(splitLines(Base64.getEncoder().encodeToString(privateKey.getEncoded()), 76));
    }
    public static KeyPair generateKeyPair(int keySize) throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        keyPairGenerator.initialize(keySize, secureRandom);
        return keyPairGenerator.generateKeyPair();
    }
    public static String splitLines(String bigString, int lineLength) {
        return bigString.replaceAll("(.{" + lineLength + "})", "$1\n");
    }
}
将生成的公钥和私钥分别保存到 user-public-key.txt 和 user-private-key.txt 文件中。
[url=#p-562541-dbeaver-2]
提取 DBeaver 公钥
找到com.dbeaver.app.ultimate_24.0.0.202404011634.jar包下的dbeaver-ue-public.key文件, 内容为
--- PUBLIC KEY ---
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk7ciFU/aUCIgH5flBbGD0t7B3KOmfL0l
BMf2ENuLA0w/T8A1RvteUYk2EQo3UrZ7kMZ8rK93nmDjituN7jlv/bsxGyAox87BbKYSs9oH5f9P
hYHAiTE0PxoMODnl4NgR+Bpc+Ath8wDLHMC+BzYkOy4JQo8EX/ff58TT9UYP8eoDeGdSxQmW3FJC
i82UiC5zIk75dx20Al9ql0fdxnzo31q/2MbnNCAfSchsqrKtzBtheex4JvvqZjxn98wk5Te1QgZz
Caz4ay9dkLVjSt79QYm5hKb8Jt3O5SxSUsrjmYVeG+k2bQlidw8dENwLZmvJkIJi8kb94yEwY/dq
lENDkQIDAQAB
将文件内容保存到 dbeaver-ue-public-key.txt 文件中。
[/url]生成 DBeaver 激活码
为了生成激活码我们需要几个辅助类,它们都来自 com.dbeaver.lm.api_3.0.2.202404011634.jar 包。
第一个是 LicenseType,它定义了各种 License 类型枚举
public enum LicenseType {
    STANDARD('S', "Yearly subscription", true, true),
    YEAR_UPDATE('Y', "Perpetual", false, false),
    YEAR_CORPORATE('C', "Corporate", false, false),
    ULTIMATE('U', "Ultimate", false, false),
    LIMITED('L', "Limited", true, true),
    PARTNER('P', "Technical partner", false, false),
    TRIAL('T', "Trial", true, true),
    ACADEMIC('A', "Academic", true, true),
    TEAM('M', "Yearly subscription (Team)", true, true),
    CUSTOM('X', "Custom", false, false);
    private final char id;
    private final String displayName;
    private boolean isExtendable;
    private boolean needsEndTime;
    private LicenseType(char id, String displayName, boolean isExtendable, boolean needsEndTime) {
        this.id = id;
        this.displayName = displayName;
        this.isExtendable = isExtendable;
        this.needsEndTime = needsEndTime;
    }
    public byte getId() {
        return (byte) this.id;
    }
    public String getDisplayName() {
        return this.displayName;
    }
    public boolean isExtendable() {
        return this.isExtendable;
    }
    public boolean needsEndTime() {
        return this.needsEndTime;
    }
}
第二个是 LicenseFormat,它定义了各种 License 格式枚举
public enum LicenseFormat {
    STANDARD((byte) 0, 218, "Initial basic license format"),
    EXTENDED((byte) 1, 238, "Extended format with owner email and corporate license info"),
    ADVANCED((byte) 2, 490, "Advanced format for role-based licenses");
    private final byte id;
    private final int encryptedLength;
    private final String description;
    private LicenseFormat(byte id, int encryptedLength, String description) {
        this.id = id;
        this.encryptedLength = encryptedLength;
        this.description = description;
    }
    public byte getId() {
        return this.id;
    }
    public String getDescription() {
        return this.description;
    }
    public int getEncryptedLength() {
        return this.encryptedLength;
    }
}
第三个是 License,它定义了 License 包含哪些内容
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Date;
public class License {
    public static final long FLAG_NONE = 0L;
    public static final long FLAG_ROLE_BASED = 1L;
    public static final long FLAG_CANCELED = 2L;
    public static final long FLAG_RESELLER = 4L;
    public static final long FLAG_SUBSCRIPTION = 8L;
    public static final long FLAG_LIMITED = 16L;
    public static final long FLAG_LIMITED_VERSION = 32L;
    public static final long FLAG_SERVER_LICENSE = 64L;
    public static final long FLAG_UNLIMITED_USERS = 256L;
    public static final long FLAG_UNLIMITED_TIME = 512L;
    public static final long FLAG_UNLIMITED_SERVERS = 1024L;
    public static final long FLAG_MULTI_INSTANCE = 2048L;
    private final String licenseId;
    private final LicenseType licenseType;
    private final Date licenseIssueTime;
    private final Date licenseStartTime;
    private final Date licenseEndTime;
    private long flags;
    private final String productId;
    private final String productVersion;
    private final String ownerId;
    private final String ownerCompany;
    private final String ownerName;
    private String ownerEmail;
    private byte yearsNumber;
    private byte reserved1;
    private short usersNumber;
    private LicenseFormat licenseFormat;
    public License(String licenseId, LicenseType licenseType, Date licenseIssueTime, Date licenseStartTime, Date licenseEndTime, long flags, String productId, String productVersion, String ownerId, String ownerCompany, String ownerName, String ownerEmail) {
        this.licenseFormat = (flags & 1L) != 0L ? LicenseFormat.ADVANCED : LicenseFormat.EXTENDED;
        this.licenseId = licenseId;
        this.licenseType = licenseType;
        this.licenseIssueTime = licenseIssueTime;
        this.licenseStartTime = licenseStartTime;
        this.licenseEndTime = licenseEndTime;
        this.flags = flags;
        this.productId = productId;
        this.productVersion = productVersion;
        this.ownerId = ownerId;
        this.ownerCompany = ownerCompany;
        this.ownerName = ownerName;
        this.ownerEmail = ownerEmail;
        this.yearsNumber = 1;
        this.reserved1 = 0;
        this.usersNumber = 1;
    }
    public byte[] getData() {
        ByteArrayOutputStream output = new ByteArrayOutputStream(this.licenseFormat.getEncryptedLength());
        output.write(this.licenseFormat.getId());
        writeStringToBuffer(output, this.licenseId, 16);
        output.write(this.licenseType.getId());
        writeDateToBuffer(output, this.licenseIssueTime);
        writeDateToBuffer(output, this.licenseStartTime);
        writeDateToBuffer(output, this.licenseEndTime);
        writeLongToBuffer(output, this.flags);
        writeStringToBuffer(output, this.productId, 16);
        writeStringToBuffer(output, this.productVersion, 8);
        writeStringToBuffer(output, this.ownerId, 16);
        writeStringToBuffer(output, this.ownerCompany, 64);
        if (this.licenseFormat == LicenseFormat.STANDARD) {
            writeStringToBuffer(output, this.ownerName, 64);
        } else {
            writeStringToBuffer(output, this.ownerName, 32);
            writeStringToBuffer(output, this.ownerEmail, 48);
            output.write(this.yearsNumber);
            output.write(this.reserved1);
            writeShortToBuffer(output, this.usersNumber);
        }
        return output.toByteArray();
    }
    public void writeStringToBuffer(ByteArrayOutputStream output, String value, int length) {
        output.writeBytes(getStringData(value, length));
    }
    public void writeDateToBuffer(ByteArrayOutputStream output, Date date) {
        long value = date == null ? 0L : date.getTime();
        writeLongToBuffer(output, value);
    }
    public byte[] getStringData(String value, int length) {
        byte[] bytes = value == null ? new byte[0] : value.getBytes(StandardCharsets.UTF_8);
        byte[] data = Arrays.copyOf(bytes, length);
        Arrays.fill(data, Math.min(bytes.length, length), length, (byte) 32);
        return data;
    }
    public void writeLongToBuffer(ByteArrayOutputStream output, long value) {
        ByteBuffer buffer = ByteBuffer.wrap(new byte[8]);
        buffer.putLong(value);
        output.writeBytes(buffer.array());
    }
    public void writeShortToBuffer(ByteArrayOutputStream output, short value) {
        ByteBuffer buffer = ByteBuffer.wrap(new byte[2]);
        buffer.putShort(value);
        output.writeBytes(buffer.array());
    }
}
生成激活码的代码主要逻辑来自 LMMain#encryptLicense 方法,部分方法来自 LMUtils 和 LMEncryption 类
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
public class LicenseGenerator {
    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
        PrivateKey privateKey = readPrivateKey("user-private-key.txt");
        License license = new License("JL-0FB16-000A2GC", LicenseType.ULTIMATE, new Date(), new Date(), null, License.FLAG_UNLIMITED_SERVERS, "dbeaver-ue", "24.0", "10000", "Linux DO", "zhuma", "[url=/cdn-cgi/l/email-protection][email protected]
");
        byte[] licenseData = license.getData();
        byte[] licenseEncrypted = encrypt(licenseData, privateKey);
        String licenseBase64 = splitLines(Base64.getEncoder().encodeToString(licenseEncrypted), 76);
        System.out.println("--- LICENSE ---");
        System.out.println(licenseBase64);
    }
    public static PrivateKey readPrivateKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        try (FileInputStream fis = new FileInputStream(filename)) {
            byte[] bytes = readEncryptedString(fis);
            return generatePrivateKey(bytes);
        }
    }
    public static byte[] readEncryptedString(InputStream stream) throws IOException {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
            StringBuilder result = new StringBuilder(4000);
            while (true) {
                String line = reader.readLine();
                if (line == null || line.isEmpty()) {
                    return Base64.getDecoder().decode(result.toString());
                }
                if (!line.startsWith("-") && !line.startsWith("#")) {
                    result.append(line);
                }
            }
        }
    }
    public static PrivateKey generatePrivateKey(byte[] privateKeyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        return keyFactory.generatePrivate(privateKeySpec);
    }
    public static byte[] encrypt(byte[] data, Key key) throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, IOException, InvalidKeyException {
        return cipherAsymmetric(data, key, 1);
    }
    public static byte[] cipherAsymmetric(byte[] data, Key key, int mode) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        int chunkSize = mode == 2 ? 256 : 245;
        int chunkCount = data.length / chunkSize;
        if (data.length % chunkSize > 0) {
            ++chunkCount;
        }
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        for (int i = 0; i  data.length) {
                length = data.length - chunkSize * i;
            }
            byte[] segment = Arrays.copyOfRange(data, offset, offset + length);
            byte[] segmentEncrypted = cipher.doFinal(segment);
            buffer.write(segmentEncrypted);
        }
        return buffer.toByteArray();
    }
    public static String splitLines(String bigString, int lineLength) {
        return bigString.replaceAll("(.{" + lineLength + "})", "$1\n");
    }
}
[/url]生成 Power 规则
生成 Power 规则的代码来自 LMMain、LMUtils 和 LMEncryption 类
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RuleGenerator {
    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        RSAPublicKey userPublicKey = (RSAPublicKey) readPublicKey("user-public-key.txt");
        RSAPublicKey dbeaverPublicKey = (RSAPublicKey) readPublicKey("dbeaver-ue-public-key.txt");
        String rule = "EQUAL,65537," + dbeaverPublicKey.getModulus() + "->65537," + userPublicKey.getModulus();
        System.out.println("--- POWER RULE ---");
        System.out.println(rule);
    }
    private static PublicKey readPublicKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        try (FileInputStream fis = new FileInputStream(filename)) {
            byte[] bytes = readEncryptedString(fis);
            return generatePublicKey(bytes);
        }
    }
    public static byte[] readEncryptedString(InputStream stream) throws IOException {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
            StringBuilder result = new StringBuilder(4000);
            while (true) {
                String line = reader.readLine();
                if (line == null || line.isEmpty()) {
                    return Base64.getDecoder().decode(result.toString());
                }
                if (!line.startsWith("-") && !line.startsWith("#")) {
                    result.append(line);
                }
            }
        }
    }
    public static PublicKey generatePublicKey(byte[] publicKeyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
        return keyFactory.generatePublic(publicKeySpec);
    }
}
[url=#p-562541-dbeaver-5]
激活 DBeaver
[/url]替换 JRE
为什么参考热佬[url=https://zhile.io/2019/05/09/dbeaver-ue-license-crack.html]DBeaver Ultimate 22.1 旗舰版激活方法
,这里改为
-vm
/Library/Java/JavaVirtualMachines/jdk-17.0.2.jdk/Contents/Home/bin/java
[/url]配置 javaagent
在 /Applications/DBeaverUltimate.app/Contents/Eclipse/dbeaver.ini 文件末尾增加如下内容
--add-opens=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED
--add-opens=java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED
-javaagent:/Users/nucintosh/janetfilter/jetbra/ja-netfilter.jar=jetbrains
[url=#p-562541-powerconf-8]
配置 power.conf
在 power.conf 文件的 [Args] 一节中增加 RuleGenerator 生成的规则,比如
EQUAL,65537,18647337145970099840985713466364918234362046859276071603267794715593136936160492846272521898537004122925301027678489984501477994730537725810211014632147698623617755644615810363782781403177803009057237675193508609212761456687315887698721555027495273857704703161501556278932648428860647172378607605329884151219327938607350280135400521619196335682733371571813479415591793504469016713220060778679994845066654727814845227443267965199130452466305398985400201871520156163836666885179554470299593371783155887571488588786209640709589687137547072170350760576933982430617266249638449664790360846298962977961246175829506878817169->65537,26568176594452198874357955233081865355601482575454463708433306578459030820569735111660768507557691552912716777149966830516251509872885609614711295305581089270555091503264286693743745315059054820199160842222042189849689922692298273645936389982899317988537289718057741782081574951312275856190235441646123049577974991407616013276510427782805925379988038959945798382561302135542700860204474353714516664853954768210723310513114678397057324482615339456351078381638951155512135128405408033884232379809701908270283694138677289134377234340940696655420259553525375619972769383153649791856349266450908175059345382153220830798463
[/url]配置 dns.conf
[DNS]
EQUAL,dbeaver.com
[url=#p-562541-h-10]
输入激活码
输入LicenseGenerator生成的激活码
Dm3qISOS+h8eu4kliBh+K6WXzIxIx03rKg6F/NxE7WqCw9HVN0/uxpGFvi8+EI2/ZGu/eDOQbirU
Y8dk2NTCekvzKldoJgPPSKFsvUUFCUp6iVtgtTeD4ddvJS6HQzXM9R+P8dR0f4v38yUGuTsU8PCv
RXfoQTXtSxkdYF4v/8bEELPf4qmnYgs7HWbcvq2YYVK2dokYxaV4F0X5oM5Tv1BsHlPqI8Dh8OHm
Nj8FkYZ1zErqZ+2zFh3b+m6XE9IHOxf3X+5HEF+0esq1J1NtyRGuoA2dIPkIoOX1zXaZkKgxFKrc
L5xn/kcqnqPiBJMg7y7AIYV9+DgE76Vv+m1PYQ==
打完收工!!!真的一行代码都不是我写的,DBeaver真的都帮你写好了,它就差出个教程教你怎么激活了,你就说DBeaver是不是大善人吧!!!
最后,和Python比起来Java真是啰里八嗦!!!
            "
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|一元网络论坛

GMT+8, 2024-11-16 03:30 , Processed in 0.064725 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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