TonyLiu ·¢±íÓÚ 2024-3-28 16:26
Àϸç¿ÉÒÔÌùÏ´úÂëÂð£¿
import com.dbeaver.lm.api.LMEncryption;
import com.dbeaver.lm.api.LMException;
import com.dbeaver.lm.api.LMLicense;
import com.dbeaver.lm.api.LMLicenseType;
import com.dbeaver.lm.api.LMProduct;
import com.dbeaver.lm.api.LMProductType;
import com.dbeaver.lm.api.LMUtils;
import org.jkiss.utils.Base64;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
/**
* ±¾´úÂëÒÀÀµ 2 ¸ö jar °ü
* <ul>
* <li>${DBEAVER_ECLIPSE_HOME}/plugins/org.jkiss.utils_**.jar</li>
* <li>${DBEAVER_ECLIPSE_HOME}/plugins/com.dbeaver.lm.**.jar</li>
* </ul>
*/
public class DBeaverLicenseCrack {
private static String productID = "dbeaver-ue";
private static String productVersion = "24.0.0";
private static String ownerID = "10006";
private static String ownerCompany = "DBeaver Corporation";
private static String ownerName = "Ultimate User";
private static String ownerEmail = "developer@dbeaver.com";
/**
* ¸ù¾Ýµ±Ç°°æ±¾ÐÞ¸Äʵ¼Êjar°üÃû³Æ
* ÐèÒªÌæ»»¹«Ô¿µÄÎļþ (com.dbeaver.app.ultimate_**.jar)
*/
private static String replaceJarFile = "com.dbeaver.app.ultimate_24.0.0.202403110838.jar";
private static File privateKeyFile = new File(new File(System.getProperty("user.home"), ".jkiss-lm"), "private-key.txt");
private static File publicKeyFile = new File(new File(System.getProperty("user.home"), ".jkiss-lm"), "public-key.txt");
private static File licenseFile = new File(new File(System.getProperty("user.home"), ".jkiss-lm"), "license.txt");
/**
* ʹÓøÃÎļþ£¬ÐèÒªÌæ»» jar °üÖÐµÄ key Îļþ(Çë±£ÁôÔʼ jar °ü), ²¢ÔÚ dbeaver.ini Ìí¼Ó²ÎÊý-Dlm.debug.mode=true
* <p>
* Èç¹ûÐÞ¸Ä jar °üÖÐµÄ plugin.xml µÄ product ½ÚµãÌí¼Ó <property name="lmServerURL" value="http://localhost:7879"/> ÐèÒªÒ»¸öÊÚȨ·þÎñÆ÷
* <ul>
* <li>Mac °æ±¾µÄ jar °ü·¾¶ÊÇ ${DBEAVER_ECLIPSE_HOME}/plugins/com.dbeaver.app.ultimate_23.1.0.202306120813.jar</li>
* <li>Mac °æ±¾µÄÅäÖÃÎļþ·¾¶ÊÇ ${DBEAVER_ECLIPSE_HOME}/dbeaver.ini</li>
* </ul>
* </p>
*/
private static File jarPublicKey = new File(new File(System.getProperty("user.home"), ".jkiss-lm"), "dbeaver-ue-public.key");
private static final String DBEAVER_ECLIPSE_HOME = "/Applications/DBeaverUltimate.app/Contents/Eclipse";
public static void main(String[] args) throws Exception {
String dbeaverPluginDir = DBEAVER_ECLIPSE_HOME + File.separator + "plugins";
// ÐèÒªÌæ»»¹«Ô¿µÄÎļþ (com.dbeaver.app.ultimate_**.jar)
List<File> matchingFiles = findFilesByPattern(dbeaverPluginDir, replaceJarFile);
if (matchingFiles.size() != 1) {
throw new IOException("δÕÒµ½ÐèÒªÌæ»»µÄ jar Îļþ");
}
String dbeaverJar = matchingFiles.get(0).getAbsolutePath();
generateKeyLicenseAndPatch(dbeaverJar, "keys/dbeaver-ue-public.key");
String iniFile = DBEAVER_ECLIPSE_HOME + File.separator + "dbeaver.ini";
updateEclipseIniFile(iniFile, "-Dlm.debug.mode=true");
}
/**
* ÔÚÎļþÖÐ×·¼ÓÒ»ÐÐÅäÖÃÎı¾(ÒѾ´æÔÚÔòÌø¹ý)
*
* @Param iniFile
* @param configLine
* @throws IOException
*/
public static void updateEclipseIniFile(String iniFile, String configLine) throws IOException {
boolean targetLineFound = false;
// ¶ÁÈ¡ ini Îļþ
File file = new File(iniFile);
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String line;
StringBuilder content = new StringBuilder();
while ((line = br.readLine()) != null) {
content.append(line).append(System.lineSeparator());
if (line.trim().equals(configLine)) {
targetLineFound = true;
}
}
br.close();
// Èç¹ûδÕÒµ½Ä¿±êÐУ¬ÔÚÄÚÈݵÄĩβ׷¼ÓÎı¾
if (!targetLineFound) {
content.append(configLine).append(System.lineSeparator());
// ½«¸üеÄÄÚÈÝд»Ø ini Îļþ
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content.toString());
bw.close();
}
}
/**
* ͨ¹ýÕýÔò±í´ïÆ¥Å䣬ËÑË÷Æ¥ÅäµÄÎļþ
*
* @param directoryPath Ŀ¼
* @param pattern ÎļþÆ¥ÅäÕýÔò
* @return
*/
public static List<File> findFilesByPattern(String directoryPath, String pattern) {
List<File> matchingFiles = new ArrayList<>();
File directory = new File(directoryPath);
if (directory.exists() && directory.isDirectory()) {
File[] files = directory.listFiles((dir, name) -> name.matches(pattern));
if (files != null) {
for (File file : files) {
if (file.isFile()) {
matchingFiles.add(file);
}
}
}
} else {
System.out.println("ÎÞЧµÄĿ¼£¬»òÕßÕÒ²»µ½Ä¿Â¼Â·¾¶£¡");
}
return matchingFiles;
}
/**
* Éú³É¹«Ô¿¡¢Ë½Ô¿¡¢ÊÚȨÂ룬²¢Ìæ»»Îļþ
*
* @param jarFilePath ÐèÒªÌæ»»¹«Ô¿µÄ jar Îļþ
* @param filePathInJar jar °üÖеĹ«Ô¿Îļþ·¾¶
* @throws LMException
* @throws IOException
*/
public static void generateKeyLicenseAndPatch(String jarFilePath, String filePathInJar) throws LMException, IOException {
// ´Ó LMMain.generateKeyPair() ¸´ÖƵĴúÂë
KeyPair keyPair = LMEncryption.generateKeyPair(2048);
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
System.out.println("\n--- PUBLIC KEY ---");
String publicKeyContent = Base64.splitLines(Base64.encode(publicKey.getEncoded()), 76);
System.out.println(publicKeyContent);
writeFileToPath(publicKeyContent, publicKeyFile, "¹«Ô¿");
System.out.println("\n--- PRIVATE KEY ---");
String privateKeyContent = Base64.splitLines(Base64.encode(privateKey.getEncoded()), 76);
System.out.println(privateKeyContent);
writeFileToPath(publicKeyContent, privateKeyFile, "˽Կ");
writeFileToPath(publicKeyContent, jarPublicKey, "¹«Ô¿");
// Ìæ»» jar °üÖÐµÄ public key Îļþ
replaceFileInJar(jarFilePath, filePathInJar, jarPublicKey.getAbsolutePath());
// ´Ó LMMain.encryptLicense() ¸´ÖƵĴúÂë
LMProduct TEST_PRODUCT = new LMProduct("dbeaver-ue", "DB", "DBeaver Ultimate", "DBeaver Ultimate Edition", productVersion, LMProductType.DESKTOP, new Date(), new String[0]);
String licenseID = LMUtils.generateLicenseId(TEST_PRODUCT);
LMLicense license = new LMLicense(licenseID, LMLicenseType.ULTIMATE, new Date(), new Date(), (Date) null, LMLicense.FLAG_UNLIMITED_SERVERS, productID, productVersion, ownerID, ownerCompany, ownerName, ownerEmail);
byte[] licenseData = license.getData();
byte[] licenseEncrypted = LMEncryption.encrypt(licenseData, privateKey);
String licenseContent = Base64.splitLines(Base64.encode(licenseEncrypted), 76);
System.out.println("\n--- LICENSE ---");
System.out.println(licenseContent);
System.out.println("--- ´¦ÀíÍê³É£¬Çë´ò¿ªÈí¼þʹÓÃÒÔÉÏÊÚȨÂ루ÒѸ´ÖƵ½¼ôÇа壩 ---");
copyToClipboard(licenseContent);
writeFileToPath(licenseContent, licenseFile, "ÊÚȨÂë");
}
/**
* дÈë²¢¸²¸ÇÎļþÄÚÈÝ
*
* @param contentдÈ븲¸ÇµÄÄÚÈÝ
* @param filePath ҪдÈëµÄÎļþ·¾¶
* @param tip Ìáʾ
*/
public static void writeFileToPath(String content, File filePath, String tip) {
try {
Path path = Paths.get(filePath.getAbsolutePath());
Files.write(path, content.getBytes());
System.out.println(String.format("[%sÄÚÈÝ]Òѳɹ¦Ð´ÈëÎļþ£º%s", tip, path));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Ìæ»» jar °üÖеÄÖ¸¶¨Â·¾¶µÄÎļþΪÐÂÎļþ
*
* @param jarFilePath
* @param targetFile
* @param newFile
* @throws IOException
*/
public static void replaceFileInJar(String jarFilePath, String targetFile, String newFile) throws IOException {
File tempFile = File.createTempFile("temp-file", ".tmp");
File tempJarFile = File.createTempFile("temp-jar", ".tmp");
boolean replaceSuccess = false;
try (JarFile jarFile = new JarFile(new File(jarFilePath));
JarOutputStream tempJarOutputStream = new JarOutputStream(new FileOutputStream(tempJarFile))) {
// Copy the existing entries to the temp jar, excluding the entry to be replaced
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (!entry.getName().equals(targetFile)) {
tempJarOutputStream.putNextEntry(new JarEntry(entry.getName()));
try (InputStream inputStream = jarFile.getInputStream(entry)) {
copyStream(inputStream, tempJarOutputStream);
}
}
}
// ½«ÐÂÎļþÌí¼Óµ½ÁÙʱjar
tempJarOutputStream.putNextEntry(new JarEntry(targetFile));
try (InputStream newFileStream = new FileInputStream(newFile)) {
copyStream(newFileStream, tempJarOutputStream);
}
replaceSuccess = true;
} finally {
// ½«Ôʼ jar ÎļþÌ滻ΪÁÙʱ jar Îļþ
File originalJarFile = new File(jarFilePath);
if (originalJarFile.delete() && tempJarFile.renameTo(originalJarFile) && replaceSuccess) {
System.out.println(String.format("jar°üÖеÄÎļþ [%s] Ìæ»»³É¹¦£¡", targetFile));
} else {
System.out.println(String.format("jar°üÖеÄÎļþ [%s] Ì滻ʧ°Ü£¡", targetFile));
}
tempFile.delete();
tempJarFile.delete();
}
}
private static void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
}
/**
* ½«Ö¸¶¨×Ö·û´®¸´ÖƵ½¼ôÇаå
*
* @param text
*/
public static void copyToClipboard(String text) {
StringSelection stringSelection = new StringSelection(text);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, null);
}
}