MyBatisCodeHelperPro Crack
准备工作
开始处理
1. 反编译
- 反编译Jar包
- 使用IDEA编辑器打开编译包
- 全局检索关键词 TUlHZk1BMEdDU3FHU0liM0RRRUJBUVVBQTRHTkFEQ0JpUUtCZ1FDZzUyUjExV0h1MysvNUV2WnhkS0l2a3ovekpnS2VNUUhNLytMVkxSZS9zWUpFQlUxbUUrODc3MmJJckk4UThscldqSHc5cmVjQ1RWVVhXUnhWYXBndk1HYTZ3KzU4STZwYXdSaFhwZDBrRkhUY2xxeUZGWFpoS3ZiQUtoblphRGNuZkJtSkhObTQwR0JFTGpCTmx5MXpha2FIblFmUzF0QlhaSGQwOUV0c2VRSURBUUFC
- 正式版类名以及方法名称都会被混淆,反编译后细心查找,示例如下:
java
package com.ccnode.codegenerator.validate.utils;
import com.ccnode.codegenerator.validate.response.ValidateNewResultData;
import com.google.gson.Gson;
import java.io.UnsupportedEncodingException;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;
import kotlin.text.Charsets;
public class RsaUtils {
private static Gson gson = new Gson();
public static ValidateNewResultData fromEncrptData(String encrptString) {
Object var1 = null;
byte[] res;
try {
res = RSAEncrypt.decrypt(RSAEncrypt.loadPublicKeyByStr(new String(Base64.getDecoder().decode("TUlHZk1BMEdDU3FHU0liM0RRRUJBUVVBQTRHTkFEQ0JpUUtCZ1FDZzUyUjExV0h1MysvNUV2WnhkS0l2a3ovekpnS2VNUUhNLytMVkxSZS9zWUpFQlUxbUUrODc3MmJJckk4UThscldqSHc5cmVjQ1RWVVhXUnhWYXBndk1HYTZ3KzU4STZwYXdSaFhwZDBrRkhUY2xxeUZGWFpoS3ZiQUtoblphRGNuZkJtSkhObTQwR0JFTGpCTmx5MXpha2FIblFmUzF0QlhaSGQwOUV0c2VRSURBUUFC"), Charsets.UTF_8)), Base64.getDecoder().decode(encrptString));
} catch (MyException var7) {
res = RSAEncrypt.decrypt((RSAPublicKey)(new MyPublicKey()), Base64.getDecoder().decode(encrptString));
}
ValidateNewResultData data = null;
String json;
try {
json = new String(res, "UTF-8");
} catch (UnsupportedEncodingException var6) {
throw new RuntimeException(var6);
}
try {
data = (ValidateNewResultData)gson.fromJson(json, ValidateNewResultData.class);
return data;
} catch (Exception var5) {
throw new RuntimeException("gson catch exception, the json string is" + json, var5);
}
}
}
2. 添加依赖
xml
<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.30.2-GA</version>
</dependency>
注: 反编译后找到实际的全限定类名,以及方法名称后替换。
java
import javassist.*;
import org.springframework.lang.NonNull;
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.stream.Stream;
/**
* MyBatisCodeHelperProCrack
*
* @author xm.z
*/
public class MyBatisCodeHelperProCrack {
/**
* 插件名称,用于构建查找路径。
* 通常对应插件存放的主目录名。
*/
private static final String TARGET_CLASS = "com.ccnode.codegenerator.validate.utils.RsaUtils";
/**
* 要修改的方法名。
* 该方法将被替换为自定义逻辑。
*/
private static final String METHOD_NAME = "fromEncrptData";
/**
* 替换后的方法体内容。
* 使用 Javassist 语法,返回伪造的授权信息。
*/
private static final String METHOD_BODY = "return (com.ccnode.codegenerator.validate.response.ValidateNewResultData)gson.fromJson($1,com.ccnode.codegenerator.validate.response.ValidateNewResultData.class);";
public static void main(String[] args) throws FileNotFoundException {
try {
File jarFile = findMatchingJar();
File modifiedClassFile = modifyTargetClass(jarFile);
updateJarFile(jarFile, modifiedClassFile);
cleanupTempDirectory(jarFile);
} catch (Exception e) {
System.err.println("❌ 程序异常: " + e.getMessage());
}
}
/**
* 查找匹配的 JAR 文件
*/
private static File findMatchingJar() throws Exception {
String userHome = System.getProperty("user.home");
Path basePath = Paths.get(userHome, "Downloads", PLUGIN_NAME, "lib");
if (!Files.exists(basePath) || !Files.isDirectory(basePath)) {
throw new FileNotFoundException("目录不存在: " + basePath);
}
try (Stream<Path> stream = Files.list(basePath)) {
return stream
.filter(path -> path.getFileName().toString().contains(PLUGIN_NAME) && path.toString().endsWith(".jar"))
.findFirst()
.map(Path::toFile)
.orElseThrow(() -> new FileNotFoundException("未找到匹配的 JAR 文件"));
}
}
/**
* 修改目标类的方法
*/
private static File modifyTargetClass(File jarFile) throws Exception {
String outputDirPath = Paths.get(jarFile.getParent()).toString();
Path outputDir = Paths.get(outputDirPath);
if (Files.exists(outputDir)) {
deleteDirectoryRecursively(outputDir.toFile());
}
if (!Files.exists(outputDir) && !Files.createDirectory(outputDir).isAbsolute()) {
throw new IOException("❌ 创建目录失败: " + outputDir);
}
ClassPool pool = ClassPool.getDefault();
pool.appendClassPath(jarFile.getAbsolutePath());
CtClass ctClass = null;
try {
ctClass = pool.get(TARGET_CLASS);
CtMethod method = ctClass.getDeclaredMethod(METHOD_NAME, new CtClass[]{pool.get("java.lang.String")});
method.setBody(METHOD_BODY);
ctClass.writeFile(outputDirPath);
String modifiedClassPath = outputDirPath + File.separator + TARGET_CLASS.replace('.', File.separatorChar) + ".class";
File modifiedClassFile = new File(modifiedClassPath);
if (!modifiedClassFile.exists()) {
throw new FileNotFoundException("❌ 修改后的类文件未生成: " + modifiedClassPath);
}
System.out.println("✅ 类文件已修改并保存至: " + modifiedClassPath);
return modifiedClassFile;
} finally {
// 释放 CtClass 资源
if (ctClass != null) {
ctClass.detach();
}
}
}
/**
* 更新 JAR 文件
*/
private static void updateJarFile(File jarFile, File modifiedClassFile) throws Exception {
File directory = jarFile.getParentFile();
String classPath = directory.toPath().relativize(modifiedClassFile.toPath()).toString();
ProcessBuilder pb = new ProcessBuilder("jar", "uvf", jarFile.getName(), classPath);
pb.redirectErrorStream(true);
pb.directory(directory);
System.out.println("🔧 正在更新 JAR 文件...");
Process process = pb.start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(" | " + line);
}
}
int exitCode = process.waitFor();
if (exitCode == 0) {
System.out.println("✅ JAR 文件更新成功!");
} else {
System.err.println("❌ JAR 文件更新失败,退出码: " + exitCode);
}
}
/**
* 清理临时目录
*/
private static void cleanupTempDirectory(File jarFile) throws IOException {
File tempDir = new File(Paths.get(jarFile.getParent()).toAbsolutePath().toString());
if (tempDir.exists()) {
deleteDirectoryRecursively(tempDir);
}
}
/**
* 递归删除目录
*/
private static void deleteDirectoryRecursively(@NonNull File directory) throws IOException {
// 构建 com 目录路径
Path comDir = directory.toPath().resolve("com");
if (Files.isDirectory(comDir)) {
System.out.println("🔧 正在删除 com 目录: " + comDir);
// 使用 try-with-resources 包裹 Files.walk() 生成的 Stream
try (Stream<Path> walkStream = Files.walk(comDir)) {
walkStream.sorted(Comparator.reverseOrder()).forEach(path -> {
try {
Files.delete(path);
System.out.println("🗑️ 删除: " + path);
} catch (IOException e) {
System.err.println("❌ 删除失败: " + path + ",原因: " + e.getMessage());
}
});
}
}
}
}
3. 打包安装
- 将最终修改后的目录压缩为ZIP插件包
- 将修改后的插件包安装到IDEA编辑器
4. 离线激活
- Download ⚠️ 仅供个人学习使用
text
{
"paidKey": "xm.z",
"valid": true,
"userMac": "${your unique code}",
"validTo": 4859711999000
}