java字节码
##字节码
能够恢复成一个类并在jvm中加载的字节序列
##利用URLClassLoader加载远程class文件ClassLoader
是java的类加载器,告诉java虚拟机如何加载这个类,默认根据类名加载类,并且这个类名是类完整路径,例如java.lang.Runtime
###URLClassLoader
正常情况下,java会根据sun.boot.class.path和java.class.path中列举的基础路径(这些路径是经过处理后的java.net.URl类)来寻找.class文件进行加载,基础路径有三种情况
- URL未以斜杠 / 结尾,则认为是一个JAR文件,使用 JarLoader 来寻找类,即为在Jar包中寻找.class文件
- URL以斜杠 / 结尾,且协议名是 file ,则使用 FileLoader 来寻找类,即为在本地文件系统中寻找.class文件
- URL以斜杠 / 结尾,且协议名不是 file ,则使用最基础的 Loader 来寻找类
###defineClass
在加载远程class文件、本地class或者jar包时,java都经历了
其中 - loadClass 的作用是从已加载的类缓存、父加载器等位置寻找类(这里实际上是双亲委派机制),在前面没有找到的情况下,执行 findClass
- findClass 的作用是根据基础URL指定的方式来加载类的字节码,就像上一节中说到的,可能会在
本地文件系统、jar包或远程http服务器上读取字节码,然后交给defineClass - defineClass 的作用是处理前面传入的字节码,将其处理成真正的Java类
###defineClass加载字节码
####使用反射进行加载####利用TemplatesImpl加载字节码Method defineclass = ClassLoader.class.getDeclaredMethod("defineClass",String.class,byte[].class,int.class,int.class);
defineClass,setAccessible(true);
byte[] code= Base64.getDecoder().decode("");
Class hello = (Class) defineclass.invoke(ClassLoader.getSystemClassLoader(),"hello",code,0,code.length);
hello.newInstance();com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
这个类中定义了一个内部类
TransletClassLoader :
重写了defineClass
方法,并且没有显式地声明其定义域。如果没有显式声明,则其作用域为default,可以被类外部调用,而TransletClassLoader#defineClass()
向前追溯调用链以后可以发现,其最前面的两个方法为法 TemplatesImpl#getOutputProperties() 、 TemplatesImpl#newTransformer()
#####使用newTransformer()构造poc其中:byte[] code=Base64.getDecoder().decode("");
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj,"_bytecodes",new byte[][]{code});
setFieldValue(obj,"_name","HelloTemplatesImpl");
setFieldValue(obj,"_tfactory",new TransformerFactoryImpl);
obj.newTransformer();
setFieldValue 方法用来设置私有属性,可见,这里我设置了三个属性: _bytecodes 、 _name 和 _tfactory 。
_bytecodes 是由字节码组成的数组; _name 可以是任意字符串,只要不为null即可;
_tfactory 需要是一个 TransformerFactoryImpl 对象,因为
TemplatesImpl#defineTransletClasses() 方法里有调用到
_tfactory.getExternalExtensionsMap() ,如果是null会出错。
另外,值得注意的是, TemplatesImpl 中对加载的字节码是有一定要求的:这个字节码对应的类必须
是 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet 的子类。
因此在构造这个类的时候要写extends