first commit
This commit is contained in:
219
src/main/java/top/zunmx/MWindow.java
Normal file
219
src/main/java/top/zunmx/MWindow.java
Normal file
@ -0,0 +1,219 @@
|
||||
package top.zunmx;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import javax.swing.JFileChooser;
|
||||
|
||||
public class MWindow extends Frame {
|
||||
private static MyList logList;
|
||||
private final MyButton selectDirButton;
|
||||
private final MyButton clearListButton;
|
||||
private final MyButton creckButton;
|
||||
private MyTextArea textLabel;
|
||||
private Thread searchThread;
|
||||
public static boolean stop = false;
|
||||
private static ArrayList<String> file_paths = new ArrayList();
|
||||
|
||||
public static String findAppJar(File dir) {
|
||||
File[] files = dir.listFiles();
|
||||
if (files != null) {
|
||||
lab1:
|
||||
for (File file : files) {
|
||||
if (stop) break;
|
||||
if (file.isDirectory()) {
|
||||
if (file.getName().equalsIgnoreCase("lib")) {
|
||||
File[] libFiles = file.listFiles();
|
||||
if (libFiles != null) {
|
||||
for (File libFile : libFiles) {
|
||||
if (stop) break;
|
||||
if (libFile.isFile() && libFile.getName().equalsIgnoreCase("app.jar")) {
|
||||
file_paths.add(file.getAbsolutePath());
|
||||
break lab1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 递归检查子目录
|
||||
if (stop) break;
|
||||
if (findAppJar(file) != null) {
|
||||
file_paths.add(file.getAbsolutePath());
|
||||
break lab1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void buttonEnabled(boolean flag) {
|
||||
// clearListButton.setEnabled(flag);
|
||||
creckButton.setEnabled(flag);
|
||||
selectDirButton.setEnabled(flag);
|
||||
}
|
||||
|
||||
|
||||
public MWindow() {
|
||||
// 设置窗口标题
|
||||
super("JetBrains License Cracker V1.0");
|
||||
|
||||
// 设置窗口布局
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
// 创建目录选择器按钮
|
||||
selectDirButton = new MyButton("Select Jetbrains Path");
|
||||
selectDirButton.addActionListener(e -> {
|
||||
File directory = selectDirectory();
|
||||
if (directory != null && directory.isDirectory()) {
|
||||
logList.removeAll();
|
||||
file_paths.clear();
|
||||
if (directory.exists() && directory.isDirectory()) {
|
||||
logList.add("=============================[SEARCHING]=================================");
|
||||
stop = false;
|
||||
logList.add("[i] Searching for jetbrains product in " + directory.getAbsolutePath());
|
||||
new Thread(() -> {
|
||||
this.buttonEnabled(false);
|
||||
Thread searchThread = new Thread(() -> findAppJar(directory));
|
||||
searchThread.start();
|
||||
try {
|
||||
searchThread.join();
|
||||
logList.add("=============================[FOUND " + file_paths.size() + " ITEM]=================================");
|
||||
for (String filePath : file_paths) {
|
||||
logList.add("[#] Found Product: " + filePath);
|
||||
}
|
||||
|
||||
if (stop) {
|
||||
logList.add("[!] STOPPED");
|
||||
}
|
||||
this.buttonEnabled(true);
|
||||
} catch (InterruptedException ex) {
|
||||
logList.add("[x] Exception: " + ex.getMessage());
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}).start();
|
||||
|
||||
|
||||
} else {
|
||||
logList.add("[!] The specified path is not a directory or does not exist.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 创建清除列表按钮
|
||||
clearListButton = new MyButton("Reset / Clear List");
|
||||
clearListButton.addActionListener(e -> {
|
||||
stop = true;
|
||||
logList.removeAll();
|
||||
file_paths.clear();
|
||||
});
|
||||
|
||||
// 创建破解按钮
|
||||
creckButton = new MyButton("Crack!");
|
||||
creckButton.addActionListener(e -> {
|
||||
if (file_paths.isEmpty()) {
|
||||
logList.removeAll();
|
||||
logList.add("[!] No product found");
|
||||
logList.add("[!] Please select the Jetbrains software installation directory.");
|
||||
return;
|
||||
}
|
||||
buttonEnabled(false);
|
||||
new Thread(() -> {
|
||||
Thread thread = new Thread(() -> {
|
||||
for (String filePath : file_paths) {
|
||||
try {
|
||||
String[] split = filePath.split("\\\\");
|
||||
String product = split[filePath.split("\\\\").length - 2];
|
||||
logList.add("=============================[CRACKING " + product + "]=================================");
|
||||
logList.add("[i] Cracking " + filePath);
|
||||
ModifyDialogWrapperPeerImpl modifyDialogWrapperPeer = new ModifyDialogWrapperPeerImpl();
|
||||
modifyDialogWrapperPeer.crack_it(filePath, logList);
|
||||
modifyDialogWrapperPeer = null;
|
||||
System.gc();
|
||||
if (stop) {
|
||||
logList.add("[!] STOPPED");
|
||||
break;
|
||||
}
|
||||
} catch (Exception except) {
|
||||
logList.add("[!] Crack Failed: " + except.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException ex) {
|
||||
logList.add("[x] Exception: " + ex.getMessage());
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
buttonEnabled(true);
|
||||
}).start();
|
||||
|
||||
});
|
||||
textLabel = new MyTextArea("[i] Usage\n" +
|
||||
" 1. Click [Select Jetbrains Path] Button\n" +
|
||||
" 2. Select Jetbrains software installation directory\n" +
|
||||
" eg. C:\\program files\\Jetbrains\n" +
|
||||
" 3. Click [crack!] Button\n" +
|
||||
" 4. Just a moment. \n\n" +
|
||||
"[!] Recovery\n" +
|
||||
" If you want to restore the original version,\n" +
|
||||
" go to the lib\\JZC-backup directory under the product installation directory,\n" +
|
||||
" find the backup files, and replace the files that in the lib directory.\n" +
|
||||
"[!] Crack by Bypass the license window for trial\n" +
|
||||
"[x] For code academic exchange only, do not use for commercial purposes\n" +
|
||||
"[x] please delete the sample within 24 hours\n" +
|
||||
"[i] Detection to prevent repeated cracking\n" +
|
||||
"[i] Patch by ZunMX\n", 9, 30, TextArea.SCROLLBARS_VERTICAL_ONLY);
|
||||
|
||||
// 创建文件列表
|
||||
logList = new MyList();
|
||||
|
||||
// 创建按钮面板
|
||||
Panel buttonPanel = new Panel();
|
||||
buttonPanel.setLayout(new FlowLayout());
|
||||
buttonPanel.add(selectDirButton);
|
||||
buttonPanel.add(clearListButton);
|
||||
buttonPanel.add(creckButton);
|
||||
|
||||
// 添加组件到窗口
|
||||
add(buttonPanel, BorderLayout.NORTH);
|
||||
add(logList, BorderLayout.CENTER);
|
||||
add(textLabel, BorderLayout.SOUTH);
|
||||
|
||||
// 设置窗口关闭行为
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
this.setSize(750, 550);
|
||||
Dimension windowSize = this.getSize();
|
||||
int x = (screenSize.width - windowSize.width) / 2;
|
||||
int y = (screenSize.height - windowSize.height) / 2;
|
||||
this.setLocation(x, y);
|
||||
setVisible(true);
|
||||
validate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
private File selectDirectory() {
|
||||
File directory = null;
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setDialogTitle("Choose Jetbrains path");
|
||||
// fileChooser.setCurrentDirectory(new File("d:\\software\\jetbrains"));
|
||||
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
int option = fileChooser.showOpenDialog(this);
|
||||
if (option == JFileChooser.APPROVE_OPTION) {
|
||||
directory = fileChooser.getSelectedFile();
|
||||
}
|
||||
return directory;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new MWindow();
|
||||
}
|
||||
}
|
||||
13
src/main/java/top/zunmx/Main.java
Normal file
13
src/main/java/top/zunmx/Main.java
Normal file
@ -0,0 +1,13 @@
|
||||
package top.zunmx;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// ModifyDialogWrapperPeerImpl.crack_it("D:\\software\\JetBrains\\DataGrip 2024.1.2\\lib");
|
||||
// ModifyDialogWrapperPeerImpl.crack_it("D:\\software\\JetBrains\\CLion 2024.1.4\\lib");
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"此程序仅用于学术交流,切勿用于商业用途,您若花钱购买此产品,请立即举报商家!","注意",2);
|
||||
new MWindow();
|
||||
}
|
||||
}
|
||||
190
src/main/java/top/zunmx/ModifyDialogWrapperPeerImpl.java
Normal file
190
src/main/java/top/zunmx/ModifyDialogWrapperPeerImpl.java
Normal file
@ -0,0 +1,190 @@
|
||||
package top.zunmx;
|
||||
|
||||
|
||||
import javassist.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.*;
|
||||
|
||||
public class ModifyDialogWrapperPeerImpl {
|
||||
public String filename = "";
|
||||
public String backupPath = "";
|
||||
public String middlePath = "";
|
||||
public String bkPath = "";
|
||||
public MyList logList;
|
||||
private CtClass ctClass;
|
||||
private URLClassLoader urlClassLoader;
|
||||
private ClassPool pool = null;
|
||||
private LoaderClassPath jarClassPath = null;
|
||||
|
||||
public boolean deleteDirectory(String dirPath) {
|
||||
File directory = new File(dirPath);
|
||||
|
||||
// 检查目录是否存在
|
||||
if (!directory.exists()) {
|
||||
logList.add("[#] Directory " + dirPath + " does not exist.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 递归删除目录中的所有文件和子目录
|
||||
File[] files = directory.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
deleteDirectory(file.getAbsolutePath());
|
||||
} else {
|
||||
file.delete();
|
||||
logList.add(" |-[#] Deleted file: " + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 最后尝试删除空目录
|
||||
logList.add(" |-[#] Deleting directory: " + directory.getAbsolutePath());
|
||||
return directory.delete();
|
||||
}
|
||||
|
||||
public void moveFile(String sourcePath, String targetPath) throws IOException {
|
||||
Path src = Paths.get(sourcePath);
|
||||
Path dest = Paths.get(targetPath);
|
||||
Files.move(src, dest, StandardCopyOption.REPLACE_EXISTING);
|
||||
logList.add("[#] Moved backup file from " + sourcePath + " to " + targetPath);
|
||||
}
|
||||
|
||||
public String checker(String dirPath) {
|
||||
File file = new File(dirPath + "\\" + "JCZ-backup");
|
||||
boolean directory = file.exists();
|
||||
if (!directory) {
|
||||
logList.add("[#] JCZ-backup folder not found, creating...");
|
||||
file.mkdir();
|
||||
}
|
||||
file = new File(dirPath + "\\" + "JCZ-middle");
|
||||
directory = file.exists();
|
||||
if (!directory) {
|
||||
logList.add("[#] JCZ-middle folder not found, creating...");
|
||||
file.mkdir();
|
||||
}
|
||||
backupPath = dirPath + "\\" + "JCZ-backup";
|
||||
middlePath = dirPath + "\\" + "JCZ-middle";
|
||||
if (new File(dirPath + "\\" + "app-client.jar").exists()) {
|
||||
filename = "app-client.jar";
|
||||
logList.add("[#] app-client.jar found, using it.");
|
||||
return dirPath + "\\" + "app-client.jar";
|
||||
} else {
|
||||
filename = "app.jar";
|
||||
logList.add("[#] app.jar found, using it.");
|
||||
return dirPath + "\\" + "app.jar";
|
||||
}
|
||||
}
|
||||
|
||||
public void crack_it(String dirPath, MyList log_list) throws Exception {
|
||||
logList = log_list;
|
||||
pool = ClassPool.getDefault();
|
||||
String d_jarPath = checker(dirPath);
|
||||
File file = new File(backupPath + "\\" + filename);
|
||||
if (file.exists()) {
|
||||
bkPath = backupPath + "\\" + System.currentTimeMillis() + filename;
|
||||
moveFile(backupPath + "\\" + filename, bkPath); // 将原来的文件备份起来
|
||||
}
|
||||
moveFile(d_jarPath, backupPath + "\\" + filename); // 将原来的文件备份起来
|
||||
bkPath = backupPath + "\\" + filename;
|
||||
String jarPath = backupPath + "\\" + filename;
|
||||
File jar_url = new File(jarPath);
|
||||
urlClassLoader = new URLClassLoader(
|
||||
new URL[]{jar_url.toURI().toURL()}
|
||||
);
|
||||
jarClassPath = new LoaderClassPath(urlClassLoader);
|
||||
|
||||
pool.insertClassPath(jarClassPath);
|
||||
logList.add("[#] Loading jar file: " + jarPath);
|
||||
ctClass = pool.get("com.intellij.openapi.ui.impl.DialogWrapperPeerImpl"); // 类名
|
||||
CtMethod setTitleMethod = ctClass.getDeclaredMethod("setTitle",
|
||||
new CtClass[]{pool.get("java.lang.String")}); // 方法名
|
||||
if (setTitleMethod.getMethodInfo().getCodeAttribute().getCode().length > 20) {
|
||||
ctClass.detach();
|
||||
urlClassLoader.close();
|
||||
pool.removeClassPath(jarClassPath);
|
||||
logList.add("[!] The file seems to have been cracked. EXIT");
|
||||
moveFile(bkPath, dirPath + "\\" + filename);
|
||||
throw new RuntimeException("PRODUCT HAS BEEN CRACKED!");
|
||||
}
|
||||
setTitleMethod.insertBefore("{ System.out.println(\"即将打开窗口-->\"+$1);" +
|
||||
"boolean isLicenseWindow = false;" +
|
||||
"if($1.indexOf(\"许可证\")>-1) {isLicenseWindow=true; this.dispose();}" +
|
||||
"if($1.indexOf(\"Licenses\")>-1) {isLicenseWindow=true; this.dispose();}" +
|
||||
"if(isLicenseWindow)System.out.println(\"发现激活窗口,即将关闭\");" +
|
||||
"Exception e = new Exception(\"↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓\");\n" +
|
||||
"System.out.println(\"调用栈信息-->\");" +
|
||||
"e.printStackTrace();" +
|
||||
" }"); // 注入的代码
|
||||
logList.add("[#] Modifying class: " + ctClass.getName());
|
||||
ctClass.writeFile(middlePath);
|
||||
ctClass.detach();
|
||||
updateJarFile(jarPath, middlePath, d_jarPath);
|
||||
logList.add("[#] Exporting modified jar file: " + d_jarPath);
|
||||
moveFile(jarPath, backupPath + "\\" + filename);
|
||||
new File(d_jarPath).renameTo(new File(jarPath));
|
||||
logList.add("[#] Deleting middle folder: " + middlePath);
|
||||
|
||||
|
||||
urlClassLoader.close();
|
||||
pool.removeClassPath(jarClassPath);
|
||||
deleteDirectory(middlePath);
|
||||
logList.add("[√] Cracked ^_^");
|
||||
|
||||
}
|
||||
|
||||
public void updateJarFile(String originalJarPath, String modifiedClassesPath, String outputJarPath) throws IOException {
|
||||
JarFile originalJar = new JarFile(originalJarPath);
|
||||
FileOutputStream fos = new FileOutputStream(outputJarPath);
|
||||
JarOutputStream jos = new JarOutputStream(fos);
|
||||
|
||||
// 复制原始JAR中的所有文件到新的JAR中,跳过要修改的类文件
|
||||
Enumeration<JarEntry> entries = originalJar.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
if (!entry.getName().equals("com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.class")) { // 跳过要修改的类文件
|
||||
InputStream is = originalJar.getInputStream(entry);
|
||||
jos.putNextEntry(new JarEntry(entry.getName()));
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer)) != -1) {
|
||||
jos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
is.close();
|
||||
jos.closeEntry();
|
||||
}
|
||||
}
|
||||
originalJar.close();
|
||||
|
||||
// 添加修改后的类文件到新的JAR中
|
||||
File modifiedClassesDir = new File(modifiedClassesPath);
|
||||
addModifiedFilesToJar(modifiedClassesDir, "", jos);
|
||||
jos.close();
|
||||
fos.close();
|
||||
}
|
||||
|
||||
private void addModifiedFilesToJar(File source, String parent, JarOutputStream jos) throws IOException {
|
||||
File[] files = source.listFiles();
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
addModifiedFilesToJar(file, parent + file.getName() + "/", jos);
|
||||
} else {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
jos.putNextEntry(new JarEntry(parent + file.getName()));
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = fis.read(buffer)) != -1) {
|
||||
jos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
fis.close();
|
||||
jos.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/main/java/top/zunmx/MyButton.java
Normal file
11
src/main/java/top/zunmx/MyButton.java
Normal file
@ -0,0 +1,11 @@
|
||||
package top.zunmx;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class MyButton extends JButton {
|
||||
public MyButton(String label)
|
||||
{
|
||||
super(label);
|
||||
}
|
||||
}
|
||||
18
src/main/java/top/zunmx/MyList.java
Normal file
18
src/main/java/top/zunmx/MyList.java
Normal file
@ -0,0 +1,18 @@
|
||||
package top.zunmx;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class MyList extends List {
|
||||
public MyList() {
|
||||
super();
|
||||
this.setBackground(new Color(125,125,125));
|
||||
this.setForeground(new Color(255, 255, 255, 255));
|
||||
Font font = new Font("Monospaced", Font.PLAIN, 14);
|
||||
this.setFont(font);
|
||||
}
|
||||
@Override
|
||||
public void add(String item) {
|
||||
super.add(item);
|
||||
this.select(this.getItemCount() - 1);
|
||||
}
|
||||
}
|
||||
15
src/main/java/top/zunmx/MyTextArea.java
Normal file
15
src/main/java/top/zunmx/MyTextArea.java
Normal file
@ -0,0 +1,15 @@
|
||||
package top.zunmx;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class MyTextArea extends TextArea {
|
||||
public MyTextArea(String text, int rows, int columns, int style) {
|
||||
super(text, rows, columns, style);
|
||||
this.setEditable(false);
|
||||
this.setBackground(new Color(125,125,125));
|
||||
this.setForeground(new Color(255, 251, 0, 255));
|
||||
this.setEditable(false);
|
||||
this.setFont(new Font("Monospaced", Font.BOLD, 14));
|
||||
this.setFocusable(false); // 禁止获取焦点
|
||||
}
|
||||
}
|
||||
3
src/main/resources/META-INF/MANIFEST.MF
Normal file
3
src/main/resources/META-INF/MANIFEST.MF
Normal file
@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: top.zunmx.Main
|
||||
|
||||
Reference in New Issue
Block a user