前言
在CC链的前置基础学习完后,就可以开始学习CC链的具体执行流程。
CC链分析
先来看下poc代码
1 | import org.apache.commons.collections.*; |
下面逐一分析
先看下面这段代码,ConstantTransformer
和InvokerTransformer
都是Transformer
接口的实现类,通过new创建了一个 Transformer类型的数组,里面存储的是 Transformer的实现类对象。
1 | //此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码 |
ConstantTransformer分析
先来分析一下ConstantTransformer
这里是使用了构造方法传入参数,poc中传入的参数为Runtime.class
,而在调用到transform时,会返回我们传入的参数,也就是返回这里的iConstant
。
InvokerTransformer分析
打一个debug跟踪到InvokerTransformer
类的构造方法里面
可以看到传入到构造方法中有三个参数,第一个是方法名,第二个是参数类型,第三个是参数的值。
poc里的三个InvokerTransformer
的参数值,如下
1 | getMethod,new Class[]{String.class, Class[].class},new Object[] {"getRuntime", new Class[0] } |
在InvokerTransformer
类中同样存在transform
方法,后面再具体分析
ChainedTransformer分析
poc代码继续往下分析,可以看到如下代码
1 | Transformer transformerChain = new ChainedTransformer(transformers); |
将transformers
数组传入ChainedTransformer
构造方法里面。在构造方法中将transformers
赋值给本类的成员变量iTransformers
该类同样存在transform
方法
transform
方法的作用会遍历transformers
数组,然后逐个去调用它的transform
方法。 并且还可以看出该方法会将第一次的执行结果传递给第二次执行的参数里面去。知道了ChainedTransformer
的作用后,我们需要知道的是ChainedTransformer
的transform
什么时候会被调用。继续往下调试
进入setValue
方法,继续跟进,可以在TransformedMap#checkSetValue
方法中发现调用了ChainedTransformer
的transform
方法,这里之前在前置学习中就已经分析过了
后面自然就循环调用每个Transformer
的transform
方法
根据顺序,会调用第一个ConstantTransformer
的transform
方法,也就是返回构造函数中设置的iConstant
,这里就是Runtime.class
接着往下,就到了InvokerTransformer,可以看到参数input的值是上个Transformer返回的结果Runtime.class,后面就是利用反射拿到Runtime对象,因为Runtime没有构造方法需要调用getRuntime()方法获取到Runtime对象,所以这里的流程是:
1 | Runtime.getClass().getMethod("getRuntime",null).invoke() -> Method |
继续跟,来到第二个InvokerTransformer
,分析如上,因为上面获得了一个Method,那么我们就需要调用它的invoke方法来执行,所以这里getMethod方法里的参数值为invoke,第二个参数即参传入的参数类型Object
接着往下,来到第三个InvokerTransformer
,也就是最后一个Transformer
,这里可以看到输入input成功拿到Runtime对象,现在只需要执行Runtime#exe
方法即可,同样先通过getMethod
方法拿到exec对应的Method,所以这里getMethod
的第一个参数,就是exec,第二个参数即exec方法执行的参数类型String,返回method,然后调用invoke执行,参数为calc.exe。
之后弹出计算器
整个过程归纳
1 | 通过ConstantTransformer得到Runtime.class,然后再InvokerTransformer反射得到getRuntime方法,然后通过反射执行invoke才能去调用getRuntime方法,这样得到一个Runtime对象,然后再去调用Runtime对象的exec方法去达到命令执行。 |
transform方法调用分析
分析下poc中TransformedMap#decorate
方法
1 | Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain); |
调试进入decorate方法,然后跟进来到TransformedMap
的构造方法
构造方法把传入的map和Transformer进行赋值。那么要想知道ChainedTransformer
是如何调用transform
方法,只需在当前类中搜索valueTransformer
,因为ChainedTransformer
是赋值给valueTransformer
的,然后在transformValue
方法中发现了transform方法的调用
继续查找transformValue
方法是在哪被调用的,发现在put方法里会调用transformValue
方法,从而导致transformValue
调用transform
方法去执行命令。
所以我们在调用TransformedMap#decorate
方法绑定transformer之后,再调用put方法也可触发命令执行。