修改字節碼有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 *