最近私下搭建了一下冒险岛的私服来自娱自乐下,从网上获取了冒险岛的源码。然后搭建了服务在游戏的过程中发现了不少BUG,于是就想看下源码反编译后修改下bug。
解压jar后,用反编译工具发现竟然不能反编译,然后有尝试了各种各样的反编译工具结果都失败了。然后打开了启动服务的bat脚本发现命令中有着这样的命令。
一般加了这样的命令等于在加载class之前回去执行这个dll文件进行一系列操作,这个文件名也很直白-解密。那肯定这个jar包里的class就是被加密了。然后打开了class的16进制文件发现,class16进制文件开头的魔改数字应该是ca fe ba be。此时打开发现完全对应不上。下面就开始解密了。
首先我们获取不到加密的方式,想通过加密区写解密的方法自然不现实。没法通过写解密方法去解密文件,那我们应该首先想到jvm加载执行class的过程。既然虚拟机可以正常解析class文件,那么经过虚拟机加载的class一定是解密之后。所以,解密后的文件肯定会在jvm中加载。然后经过我谷歌,一番面向谷歌百度的编程之后,发现了java探针技术,其实这个探针技术和spring的aop有点类似。就是在执行某个class的时候对他进行动态代理。在执行前后插入一些自己想要的方法操作。
具体代码下
import java.io.*;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
public class ClazzDumpCustomAgent implements ClassFileTransformer {
/**
* 导出过滤表达式,此处为类名前缀, 以 -f 参数指定
*/
private String filterStr;
/**
* 导出文件目录根目录, 以 -d 参数指定
*/
private String exportBaseDir = "/tmp/";
/**
* 是否创建多级目录, 以 -r 参数指定
*/
private boolean packageRecursive;
public ClazzDumpCustomAgent(String exportBaseDir, String filterStr) {
this(exportBaseDir, filterStr, false);
}
public ClazzDumpCustomAgent(String exportBaseDir, String filterStr, boolean packageRecursive) {
if(exportBaseDir != null) {
this.exportBaseDir = exportBaseDir;
}
this.packageRecursive = packageRecursive;
this.filterStr = filterStr;
}
/**
* 入口地址
*
* @param agentArgs agent参数
* @param inst
*/
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println("agentArgs: " + agentArgs);
String exportDir = null;
String filterStr = null;
boolean recursiveDir = false;
if(agentArgs != null) {
if(agentArgs.contains(";")) {
String[] args = agentArgs.split(";");
for (String param1 : args) {
String[] kv = param1.split("=");
if("-d".equalsIgnoreCase(kv[0])) {
exportDir = kv