修改字节码有jclasslib、javassist、 asm等
jclasslib修改常量很简单,但是修改方法好像行不通
javassist:修改方法特别简单,值得一试
asm:听说要学习指令
jclasslib的使用
具体如何使用请参照原文:http://blog.csdn.net/hexin373/article/details/6669813
github官方地址:https://github.com/ingokegel/jclasslib
jclaslib bytecode viewer安装包下载路径:https://github.com/ingokegel/jclasslib/releases
关于类库的获取,我在Mac上使用安装包安装好以后,查看包内容,找到jclasslib-library.jar、kotlin-runtime-1.0.6.jar、kotlin-stdlib-1.0.6.jar、kotlinx.dom-0.0.10.jar等jar包
原作者的程序CPINFO类不存在了改用CONSTANT替换,下面是我的demo字符串替换程序
import java.io.*;
import org.gjt.jclasslib.io.ClassFileWriter;
import org.gjt.jclasslib.structures.ClassFile;
import org.gjt.jclasslib.structures.Constant;
import org.gjt.jclasslib.structures.constants.ConstantUtf8Info;
public class replaceConstant {
public static void main(String[] args) throws Exception {
String filePath = "~/Desktop/B.class";
FileInputStream fis = new FileInputStream(filePath);
DataInput di = new DataInputStream(fis);
ClassFile cf = new ClassFile();
cf.read(di);
Constant[] infos = cf.getConstantPool();
int count = infos.length;
for (int i = 0; i < count; i++) {
if (infos[i] != null) {
System.out.print(i);
System.out.print(" = ");
System.out.print(infos[i].getVerbose());
System.out.print(" = ");
System.out.println(infos[i]);
if(i == 55){
ConstantUtf8Info uInfo = (ConstantUtf8Info)infos[i];
uInfo.setString("芝麻不开门哦!");
infos[i]=uInfo;
}
}
}
cf.setConstantPool(infos);
fis.close();
File f = new File(filePath);
ClassFileWriter.writeToFile(f, cf);
}
}
至于如何修改方法,http://www.cnblogs.com/xuelu/p/3840694.html 这篇博文介绍的很详细,但是我没有实践出来 ,感觉修改起来太麻烦了。
javassist的使用
官方网址:http://jboss-javassist.github.io/javassist/
github:https://github.com/jboss-javassist/javassist
官方指南:http://jboss-javassist.github.io/javassist/tutorial/tutorial.html
Javassist简单应用小结 http://blog.csdn.net/mousebaby808/article/details/37696371
下面是一个修改方法的简单demo程序
Login.java
public class Login {
public boolean verify(){
return false;
}
}
ChangeMethod.java
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.lang.reflect.Method;
public class ChangeMethod {
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
//设置目标类的路径
pool.insertClassPath("~/demo/target/classes/") ;
//获得要修改的类
CtClass cc =pool.get("Login");//就是对Login.class的映射
//得到方法
CtMethod m = cc.getDeclaredMethod("verify");
//可以在函数的开头插入新的代码
//m.insertBefore("{return true;}") ;
//也可以直接将verify函数的内容设为return true;至于功能你懂的
m.setBody("{return true;}");
//保存到文件里,会在项目根目录下生成一个Login.class,并没有自动替换classes/Login.class,需要自己手动替换进去
cc.writeFile() ;
Object o=cc.toClass().newInstance();
Method verify=o.getClass().getDeclaredMethod("verify");
System.out.println(verify.invoke(o));
}
}
可以看到输出结果永远都是true,直接跳过授权验证。
github大神有直接修改jar包的demo,思路就是先解压缩jar包,修改.class文件,重新压缩打包成jar包
jar包解压以后打包会变大不知道为什么,test.jar包解压到test目录,修改class文件以后执行“jar -cvf jar包名 文件”
cd test
jar -cvf test.jar *