动态加载字节码


所有能够恢复成一个类并在JVM虚拟机里加载的字节序列,不只是Java字节码

 

 

加载恶意类是将恶意类加载到JVM中,当这个类被初始化时,就会执行类内的静态代码块,造成代码执行

通过代码执行,可以调用Runtime.exec,也可以执行其它代码,所以这里的代码执行的灵活度比命令执行更高

 

类加载的三种方式:

  1. 命令行启动应用时候由JVM初始化加载

  2. 通过Class.forName()方法动态加载    (初始化/不初始化)

  3. 通过ClassLoader.loadClass()方法动态加载    (不初始化)

 

ClassLoader

ClassLoader加载的.class是字节码文件,它是类,包含了一个类的所有信息,当然也包括方法,变量(只有变量名,只有类被初始化时,变量才有值)。序列化只有对象的属性、类名

 

寻找.clss路径

  • url不以/结尾,是jar文件,使用jarLoader来寻找类,在jar包中寻找

  • URL以斜杠 / 结尾,且协议名是 file ,则使用 FileLoader 来寻找类,即为在本地文件系统中寻 找.class文件

  • URL以斜杠 / 结尾,且协议名不是 file ,则使用最基础的 Loader 来寻找类

URLClassLoader

实现任意加载

filr/http/jar

双亲委派

 

Application加载当前目录下

Bootstrap加载Java.lang目录下

 

子类:ClassLoader-->SecureClass-->URLClass-->Application

 

ClassLoader#defineClass

字节码加载任意类

 

远程加载class文件、本地class文件或jar文件都经过三部分调用:

  1. loadClass的作用是从已加载的类缓存、父加载器等位置寻找类(这里实际上是双亲委派机 制),在前面没有找到的情况下,执行 findClass

  2. 的作用是根据基础URL指定的方式来加载类的字节码,就像上一节中说到的,可能会在 本地文件系统、jar包或远程http服务器上读取字节码,然后交给 defineClass

  3. 的作用是处理前面传入的字节码,将其处理成真正的Java类

 

 

protected类型,不能直接调用要用反射调用

ClassLoader c1 = ClassLoader.getSystemClassLoader();
Method DefineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass",String.class, byte[].class, int.class, int.class);
DefineClassMethod.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("D:\\demo\\Java\\Bug\\BugTest\\web\\WEB-INF\\classes\\ClassLoad\\hello.class"));
Class c2 = (Class) DefineClassMethod.invoke(c1,"hello",code,0,code.length);
c2.newInstance();

Unsafe里面有defineClass类是public

Unsafe类

Unsafe.defineClass 字节码加载任意类

public类不能直接生成,Spring里面可以直接生成

 

TemplatesImpl

TemplatesImpl这个类有一个内部类transletClassLoader,里面重写了defineClass,没有定义作用域,默认为default。

 

base64编码:

//base64编码
FileInputStream fileInputStream = new FileInputStream("D:\\demo\\Java\\Bug\\BugTest\\web\\WEB-INF\\classes\\ClassLoad\\hello.class");
String content = new String();
byte[] bytes = new byte[fileInputStream.available()];
fileInputStream.read(bytes);
content = new BASE64Encoder().encode(bytes);
System.out.println(content);
fileInputStream.close();

 

调用链:

getOutputProperties()-->newTransformer()-->getTransletInstance()-->
defineTransletClasses()-->defineClass()

 

直接访问:

  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, TransformerConfigurationException {
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAVAoAEwAsCgAtAC4IAC8KADAAMQcAMgoABQAsCgATADMIADQKADUANgoANwA4BwAgCgA3ADkIADoIADsIADwHAD0KABAALAcAPgcAPwEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAhTFRlbXBsYXRlc0ltcGwvVGVtcGxhdGVzSW1wbFRlc3Q7AQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARhcmdzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEABWJ5dGVzAQACW0IBAAl0ZW1wbGF0ZXMBADxMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3RyYXgvVGVtcGxhdGVzSW1wbDsBAAlieXRlY29kZXMBABlMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQAEbmFtZQEACHRmYWN0b3J5AQAKRXhjZXB0aW9ucwcAQAcAQQEAClNvdXJjZUZpbGUBABZUZW1wbGF0ZXNJbXBsVGVzdC5qYXZhDAAUABUHAEIMAEMARgEMRHl2NjZ2Z0FBQURRQVV3b0FFZ0FyQ2dBc0FDMElBQzRLQUM4QU1BY0FNUW9BQlFBckNnQVNBRElJQURNS0FEUUFOUW9BTmdBM0NnQTJBRGdJQURrSUFEb0lBRHNIQUR3S0FBOEFLd2NBUFFjQVBnRUFCanhwYm1sMFBnRUFBeWdwVmdFQUJFTnZaR1VCQUE5TWFXNWxUblZ0WW1WeVZHRmliR1VCQUJKTWIyTmhiRlpoY21saFlteGxWR0ZpYkdVQkFBUjBhR2x6QVFBaFRGUmxiWEJzWVhSbGMwbHRjR3d2VkdWdGNHeGhkR1Z6U1cxd2JGUmxjM1E3QVFBRWJXRnBiZ0VBRmloYlRHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0tWWUJBQVJoY21kekFRQVRXMHhxWVhaaEwyeGhibWN2VTNSeWFXNW5Pd0VBQldKNWRHVnpBUUFDVzBJQkFBbDBaVzF3YkdGMFpYTUJBRHhNWTI5dEwzTjFiaTl2Y21jdllYQmhZMmhsTDNoaGJHRnVMMmx1ZEdWeWJtRnNMM2h6YkhSakwzUnlZWGd2VkdWdGNHeGhkR1Z6U1cxd2JEc0JBQWxpZVhSbFkyOWtaWE1CQUJsTWFtRjJZUzlzWVc1bkwzSmxabXhsWTNRdlJtbGxiR1E3QVFBRWJtRnRaUUVBQ0hSbVlXTjBiM0o1QVFBS1JYaGpaWEIwYVc5dWN3Y0FQd2NBUUFFQUNsTnZkWEpqWlVacGJHVUJBQlpVWlcxd2JHRjBaWE5KYlhCc1ZHVnpkQzVxWVhaaERBQVRBQlFIQUVFTUFFSUFSUUVEUEhsMk5qWjJaMEZCUVVSUlFVcG5iMEZEUVVGWVEyZEJXVUZDYTBsQlFtOUxRVUpuUVVkM1kwRklRVzlCUWxGQlpFSjNRV1ZDZDBGbVFWRkJSMUJIYkhWaFdGRXJRVkZCUkV0RGJGZEJVVUZGVVRJNWExcFJSVUZFTUhod1ltMVdUMlJYTVdsYVdFcFZXVmRLYzFwUlJVRkZhM2gyV1RKR2MxWnRSbmxoVjBacFlrZFdWVmxYU25OYVVVVkJRa2hTYjJGWVRVSkJRa1pOVVRKNGFHTXpUazFpTWtaclRESm9iR0pIZUhaUGQwVkJRMFI0YW1KSGJIVmhXRkVyUVZGQlFscFJSVUZHVlhoeFdWaGFhRXd5YkhaTU1HeFFVbGhvYWxwWVFqQmhWemwxVDNkRlFVUldUakJaVjA1eVZGZEdkMVpIUm1saVIxVklRVUozUWtGQmNGUmlNMVo1V1RKV1IyRlhlR3hCVVVGTFlVZFdjMkpIT0hWaGJVWXlXVkYzUVVOUlFVdENkMEZuUkVGQmFFRkRTVUpCUVZKcVdWZDRha1JCUVdwQlExRkNRVUpPY1ZsWVdtaE1NbXgyVERCc1VGSllhR3BhV0VJd1lWYzVkVVJCUVd4QlFXOUNRVUU1UkdKSFJucGpNSGgyV1ZkUmRtRkhWbk5pUnpoQ1FVSkNjVmxZV21oTU1uaG9ZbTFqZGxReVNuRmFWMDR3UVZGQlVtRnRSakpaVXpseldWYzFia3d4U2pGaWJsSndZbGRWUWtGQmNHNWFXRkpUWkZjMU1HRlhNV3hCVVVGV1MwTnNUV0Z0UmpKWlV6bHpXVmMxYmt3eFNqRmlibEp3WWxkVk4wRlJRVVZhV0doc1dYZEZRVXA1YUUxaGJVWXlXVk01YzFsWE5XNU1NVTR3WTIxc2RWcDZjM0JVUjNCb1pHMUZkbUpIUm5WYWVUbFJZMjA1YWxwWVRucFBkMFZCUkROQ2VXRlhOVEJWTTFKb1dUSjBWV050Um1wYVVVRm9RVUZqUVVOQlFVRkJRVUZCUVdkQlFrRkJhMEZEWjBGQ1FVRnpRVUZCUVhaQlFVVkJRVkZCUVVGQlZYRjBkMEZDYzFGQlFVRkJTVUZFUVVGQlFVRlpRVUZSUVVGQlFWVkJSRkZCUVVGQmQwRkJVVUZCUVVGVlFVUm5RVkJCUVVGQlEwRkJVVUZCYjBGQlVVRk1RVUZCUVZsUlFVTkJRVVZCUVVGQlUzVkJRVU5GWjA4eVFVRlNXSEIzUVVsVGVYRXlRVUZoZUVGQlJVRkJRVUZLUVVGM1FVSlJRVVJCUVhkQlFVRkJWMEZCVlVGQlFVRkpRVUZyUVVOM1FVMUJRV3RCUkZGQlMwRkNSVUZFUVVGT1FVRkJRVVJCUVVKQlFUQkJRa0ZCVWtGQ1NVRkJRVUZVUVVGQlFVSjNRVU5VUVdOQlJrRlJRVUZSUVZaQlFVRkJRV2RCVndjQVJnd0FSd0JJQVFBNlkyOXRMM04xYmk5dmNtY3ZZWEJoWTJobEwzaGhiR0Z1TDJsdWRHVnlibUZzTDNoemJIUmpMM1J5WVhndlZHVnRjR3hoZEdWelNXMXdiQXdBU1FCS0FRQUtYMko1ZEdWamIyUmxjd2NBU3d3QVRBQk5Cd0JPREFCUEFGQU1BRkVBVWdFQUJWOXVZVzFsQVFBU1NHVnNiRzlVWlcxd2JHRjBaWE5KYlhCc0FRQUpYM1JtWVdOMGIzSjVBUUJEWTI5dEwzTjFiaTl2Y21jdllYQmhZMmhsTDNoaGJHRnVMMmx1ZEdWeWJtRnNMM2h6YkhSakwzUnlZWGd2VkhKaGJuTm1iM0p0WlhKR1lXTjBiM0o1U1cxd2JBRUFIMVJsYlhCc1lYUmxjMGx0Y0d3dlZHVnRjR3hoZEdWelNXMXdiRlJsYzNRQkFCQnFZWFpoTDJ4aGJtY3ZUMkpxWldOMEFRQWVhbUYyWVM5c1lXNW5MMDV2VTNWamFFWnBaV3hrUlhoalpYQjBhVzl1QVFBZ2FtRjJZUzlzWVc1bkwwbHNiR1ZuWVd4QlkyTmxjM05GZUdObGNIUnBiMjRCQUJCcVlYWmhMM1YwYVd3dlFtRnpaVFkwQVFBS1oyVjBSR1ZqYjJSbGNnRUFCMFJsWTI5a1pYSUJBQXhKYm01bGNrTnNZWE56WlhNQkFCd29LVXhxWVhaaEwzVjBhV3d2UW1GelpUWTBKRVJsWTI5a1pYSTdBUUFZYW1GMllTOTFkR2xzTDBKaGMyVTJOQ1JFWldOdlpHVnlBUUFHWkdWamIyUmxBUUFXS0V4cVlYWmhMMnhoYm1jdlUzUnlhVzVuT3lsYlFnRUFDR2RsZEVOc1lYTnpBUUFUS0NsTWFtRjJZUzlzWVc1bkwwTnNZWE56T3dFQUQycGhkbUV2YkdGdVp5OURiR0Z6Y3dFQUVHZGxkRVJsWTJ4aGNtVmtSbWxsYkdRQkFDMG9UR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdLVXhxWVhaaEwyeGhibWN2Y21WbWJHVmpkQzlHYVdWc1pEc0JBQmRxWVhaaEwyeGhibWN2Y21WbWJHVmpkQzlHYVdWc1pBRUFEWE5sZEVGalkyVnpjMmxpYkdVQkFBUW9XaWxXQVFBRGMyVjBBUUFuS0V4cVlYWmhMMnhoYm1jdlQySnFaV04wTzB4cVlYWmhMMnhoYm1jdlQySnFaV04wT3lsV0FDRUFFUUFTQUFBQUFBQUNBQUVBRXdBVUFBRUFGUUFBQUM4QUFRQUJBQUFBQlNxM0FBR3hBQUFBQWdBV0FBQUFCZ0FCQUFBQUNRQVhBQUFBREFBQkFBQUFCUUFZQUJrQUFBQUpBQm9BR3dBQ0FCVUFBQURtQUFRQUJnQUFBRjY0QUFJU0E3WUFCRXk3QUFWWnR3QUdUU3kyQUFjU0NMWUFDVTR0QkxZQUNpMHNLN1lBQ3l5MkFBY1NETFlBQ1RvRUdRUUV0Z0FLR1FRc0VnMjJBQXNzdGdBSEVnNjJBQWs2QlJrRkJMWUFDaGtGTExzQUQxbTNBQkMyQUF1eEFBQUFBZ0FXQUFBQU1nQU1BQUFBQ3dBSkFBd0FFUUFPQUJzQUR3QWdBQkFBSmdBU0FERUFFd0EzQUJRQVB3QVdBRW9BRndCUUFCZ0FYUUFhQUJjQUFBQStBQVlBQUFCZUFCd0FIUUFBQUFrQVZRQWVBQjhBQVFBUkFFMEFJQUFoQUFJQUd3QkRBQ0lBSXdBREFERUFMUUFrQUNNQUJBQktBQlFBSlFBakFBVUFKZ0FBQUFZQUFnQW5BQ2dBQWdBcEFBQUFBZ0FxQUVRQUFBQUtBQUVBTHdBc0FFTUFDUT09BwBHDABIAEkBADpjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvdHJheC9UZW1wbGF0ZXNJbXBsDABKAEsBAApfYnl0ZWNvZGVzBwBMDABNAE4HAE8MAFAAUQwAUgBTAQAFX25hbWUBABJIZWxsb1RlbXBsYXRlc0ltcGwBAAlfdGZhY3RvcnkBAENjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvdHJheC9UcmFuc2Zvcm1lckZhY3RvcnlJbXBsAQAfVGVtcGxhdGVzSW1wbC9UZW1wbGF0ZXNJbXBsVGVzdAEAEGphdmEvbGFuZy9PYmplY3QBAB5qYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb24BACBqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbgEAEGphdmEvdXRpbC9CYXNlNjQBAApnZXREZWNvZGVyAQAHRGVjb2RlcgEADElubmVyQ2xhc3NlcwEAHCgpTGphdmEvdXRpbC9CYXNlNjQkRGVjb2RlcjsBABhqYXZhL3V0aWwvQmFzZTY0JERlY29kZXIBAAZkZWNvZGUBABYoTGphdmEvbGFuZy9TdHJpbmc7KVtCAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAPamF2YS9sYW5nL0NsYXNzAQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkAQANc2V0QWNjZXNzaWJsZQEABChaKVYBAANzZXQBACcoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KVYAIQASABMAAAAAAAIAAQAUABUAAQAWAAAALwABAAEAAAAFKrcAAbEAAAACABcAAAAGAAEAAAAJABgAAAAMAAEAAAAFABkAGgAAAAkAGwAcAAIAFgAAAO0ABgAGAAAAZbgAAhIDtgAETLsABVm3AAZNLLYABxIItgAJTi0EtgAKLSwEvQALWQMrU7YADCy2AAcSDbYACToEGQQEtgAKGQQsEg62AAwstgAHEg+2AAk6BRkFBLYAChkFLLsAEFm3ABG2AAyxAAAAAgAXAAAAMgAMAAAACwAJAAwAEQAOABsADwAgABAALQASADgAEwA+ABQARgAWAFEAFwBXABgAZAAaABgAAAA+AAYAAABlAB0AHgAAAAkAXAAfACAAAQARAFQAIQAiAAIAGwBKACMAJAADADgALQAlACQABABRABQAJgAkAAUAJwAAAAYAAgAoACkAAgAqAAAAAgArAEUAAAAKAAEAMAAtAEQACQ==");
        TemplatesImpl templates = new TemplatesImpl();
//        System.out.println(bytes);
        Field bytecodes = templates.getClass().getDeclaredField("_bytecodes");
        bytecodes.setAccessible(true);
        bytecodes.set(templates,new byte[][] {bytes});


        Field name = templates.getClass().getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"HelloTemplatesImpl");


        Field tfactory = templates.getClass().getDeclaredField("_tfactory");
        tfactory.setAccessible(true);
        tfactory.set(templates,new TransformerFactoryImpl());


        templates.newTransformer();

TemplatesImpl 中对加载的字节码是有一定要求的:这个字节码对应的类必须 是 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet 的子类。

恶意类:

public class HelloTemplatesImpl extends AbstractTranslet {
    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {


    }


    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {


    }


    HelloTemplatesImpl() throws IOException {
        System.out.println("Hello TemplatesImpl");
        Runtime.getRuntime().exec("calc");
    }


    public static void main(String[] args) throws IOException {
        new HelloTemplatesImpl();


    }


}

 

 

BCEL(Apache Commons) ClassLoader加载字节码


声明:啊小新sunny|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 动态加载字节码


Good friends, good books, and a sleepy conscience: this is the ideal life.