首发于Enaium的个人博客
测试类,需要混淆这里所有的字符串,上一期我们学习了如果插入一个常量,那么拦截插入常量的时候判断是不是字符串,如果是就混淆它。
public class Learn5Test {
private final String name = "Enaium";
private Learn5Test() {
render(name);
}
private void render() {
System.out.println("obfuscatory by " + name);
}
private void render(String text) {
System.out.println(text);
}
}
重写方法访问。
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return new MethodVisitor(api, super.visitMethod(access, name, desc, signature, exceptions)) {
};
}
重写常量访问。
@Override
public void visitLdcInsn(Object cst) {
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return new MethodVisitor(api, super.visitMethod(access, name, desc, signature, exceptions)) {
@Override
public void visitLdcInsn(Object cst) {
if (cst instanceof String) {
//判断是不是字符串类型,如果不是不重写。
byte[] bytes = ((String) cst).getBytes();//先将字符串转换为字节组。
mv.visitTypeInsn(NEW, "java/lang/String");//创建字符串对象。
mv.visitInsn(DUP);
mv.visitIntInsn(SIPUSH, bytes.length);//将字符串转换的字节组插入。
mv.visitIntInsn(NEWARRAY, T_BYTE);
for (int i = 0; i < bytes.length; i++) {
mv.visitInsn(DUP);
mv.visitIntInsn(SIPUSH, i);
mv.visitIntInsn(SIPUSH, bytes[i]);
mv.visitInsn(AASTORE);
}
mv.visitLdcInsn("UTF-8");
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/String", "<init>", "([BLjava/lang/String;)V", false);//调用String的构造方法,把字节组转换为字符串,使用UTF-8保证中文不乱码,因为字符串有一个解密的过程,所以反字符串混淆也很简单。
} else {
super.visitLdcInsn(cst);
}
}
};
}