动态加载字节码
0x01 Preface
Java的ClassLoader是用来加载字节码文件(.class)最基础的方法
ClassLoader是类加载器,告诉Java虚拟机如何加载这个类。Java默认的ClassLoader是根据类名来加载类,这个类名是完整类路径。
Java作为一门跨平台的编译型语言,能够做到编译一次,到处运行。
这背后是字节码文件和JVM(Java虚拟机)的支持。
java源代码(.java)通过java编译器(javac)编译成字节码文件(.class),JVM加载字节码文件并执行。
Class.forName和ClassLoader.loadClass的区别:
forName(String name, boolean initialize,ClassLoader loader)可以指定classLoader。 不显式传classLoader就是默认调用类的类加载器,且进行类初始化:public static Class<?> forName(String className) throws ClassNotFoundException { Class<?> caller = Reflection.getCallerClass(); return forName0(className, true, ClassLoader.getClassLoader(caller), caller); }
ClassLoader.loadClass不会对类进行解析和类初始化(包括静态变量的初始化、静态代码块的运行),而Class.forName是有正常的类加载过程的。
0x02 URLClassLoader
URLClassLoader是AppClassLoader(默认的Java类加载器)的父类。
URL未以斜杠/结尾
认为是一个JAR文件,使用
JarLoader来寻找类,即为在Jar包中寻找.class文件
URL以斜杠/结尾
协议名是file
使用
FileLoader来寻找类,即为在本地文件系统中寻找.class文件
协议名不是file(常见http)
使用最基础的ClassLoader来寻找类
测试远程加载字节码文件:
Hello.java编译为字节码文件后,python -m http.server 8080开启web服务监听
若能控制目标ClassLoader的路径,就能够利用远程加载执行任意代码。
0x03 ClassLoader#defineClass
不管是加载远程class文件,还是本地class或jar文件,Java都经历下面三个方法调用
loadClass:从已加载的类缓存、父加载器等位置寻找类(双亲委派机制),在前面没有找到的情况下,执行findClass
findClass:根据URL指定的方式来加载类字节码,可能会在本地文件系统或远程http服务器上读取字节码或jar包,然后交给defineClass
defineClass:处理前面传入的字节码,将其处理成真正的Java类
注:defineClass被调用时,类对象是不会被初始化的,只有显式调用其构造函数,初始化代码才会被执行
实际场景由于defineClass方法的作用域不开放,很难直接利用
0x04 TemplatesImpl
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl中定义了一个内部类
但是defineClass作用域是default。
找到如下调用链
TemplatesImpl#getOutputProperties() -> TemplatesImpl#newTransformer() -> TemplatesImpl#getTransletInstance() -> TemplatesImpl#defineTransletClasses() -> TransletClassLoader#defineClass()
defineTransletClasses方法中_tfactory.getExternalExtensionsMap()_tfactory是TransformerFactoryImpl类 为了不抛出异常需要_tfactory = new TransformerFactoryImpl()(原生反序列化实际上不用,
_tfactory被transient修饰,不能被序列化,readObject的时候会给这个字段赋值_tfactory = new TransformerFactoryImpl();)getTransletInstance方法中判断if (_name == null) return null;所以要给_name赋值(String)
TemplatesImpl 中对加载的字节码是有一定要求的:这个字节码对应的类必须 是 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet 的子类。
首先构造要加载的恶意类
TemplatesImpl加载字节码测试:
Last updated
Was this helpful?