破解Java软件,这里提供两种思路, 1)修改主程序,使主程序不调用验证器; 2)修改验证器, 使验证器始终返回true.
用javassist可以实现这两种方式, 本质上一样的, 都是修改class文件达到目的. 很明显, 第一种烦琐, 第二种简单.
以下以第二种为例, 简单模拟一下.
这是主程序:
package trial.crack;
public class App {
public static void main(String[] args){
System.out.println(Checker.check());
}
}
这是验证器:
package trial.crack;
public class Checker {
public static boolean check(){
return false;
}
}
验证器的check方法负责验证工作, 该方法始终返回false.
这是Cracker:
package trial.crack;
import java.lang.reflect.Method;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
public class Cracker {
public static void main(String[] args) throws Exception {
String classname = "trial.crack.Checker";
String methodname = "check";
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get(classname);
printClass(classname);
try {
CtMethod fMethod = cc.getDeclaredMethod(methodname, null);
fMethod.setBody("return true;");
cc.writeFile("D:/Program Files/workspace_myeclipse/javassist-sample/bin");
} catch (NotFoundException e) {
System.out.println(methodname + " not found!");
}
}
public static void printClass(String classname) {
try {
System.out.println("Methods of Class " + classname + ":");
Class c = Class.forName(classname);
Method[] method = c.getDeclaredMethods();
for (int i = 0; i < method.length; i++) {
System.out.println(method[i]);
}
System.out.println();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Cracker的原理:
修改Checker的check方法的函数体, 使其始终返回true. 然后将修改写到硬盘上(这里使用的是项目的bin目录,即class文件存放地),也就是生成字节码(.class文件), 来覆盖原来的class文件.
演示:
1)编译运行App
2)编译运行Cracker
3)运行APP
可以看到, 对于步骤1)和步骤3),控制台上会先后打印出:
false
true
硬解成功.
实战破解时, 采用类似的方式修改验证器,然后生成class文件到任意指定的目录, 然后将class文件覆盖软件原来的class文件即可.