探究CC链的前置知识
这里是各种探究CC链的过程中使用到的类的详细讲解,一边探究CC链一边把Gadget chain出现的类补进来 …..
CommonsCollections
Transformer
Transformer为Commons Collections中提供的一个接口
ConstantTransformer
代码语言:javascript复制ConstantTransformer为Transformer的实现类,
构造函数的参数赋值到iConstant
除构造函数外还有3个成员方法:
getInstance(Object constantToReturn)返回一个新的ConstantTransformer
transform(Object input)不管传入的参数input是什么,均返回实例化时传入的iConstant
getConstant()是无参函数,作用和transform()一样
代码语言:javascript复制和一样ConstantTransformer是Transformer的实现类
有三个成员变量(均为private):
static final long serialVersionUID;
final String iMethodName;
final Class[] iParamTypes;
final Object[] iArgs;
构造函数有3个参数:
iMethodName = String methodName -> 待执⾏的⽅法函数名
iParamTypes = Class[] paramTypes -> 函数的参数列表的参数类型
iArgs = Object[] args 传给这个函数的参数列表
一个参数的构造函数:
private InvokerTransformer(String methodName) {
super();iMethodName = methodName;iParamTypes = null;iArgs = null;}
三个参数的构造函数:
public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
super();iMethodName = methodName;iParamTypes = paramTypes;iArgs = args;}
代码语言:javascript复制getInstance():
单参数时调用单参数构造方法
getInstance(String methodName){if (methodName == null){...};return new InvokerTransformer(methodName);}
三参数:
public static Transformer getInstance(String methodName, Class[] paramTypes, Object[] args) {
if (methodName == null) {
throw new IllegalArgumentException("The method to invoke must not be null");
}
if (((paramTypes == null) && (args != null))
|| ((paramTypes != null) && (args == null))
|| ((paramTypes != null) && (args != null) && (paramTypes.length != args.length))) {
throw new IllegalArgumentException("The parameter types must match the arguments");
}
if (paramTypes == null || paramTypes.length == 0) {
return new InvokerTransformer(methodName);
} else {
paramTypes = (Class[]) paramTypes.clone();
args = (Object[]) args.clone();
return new InvokerTransformer(methodName, paramTypes, args);
}
}
三参数时:
后两项均为null则是return new InvokerTransformer(methodName);
如果后两项参数!=null,那么就要长度相等,return new InvokerTransformer(methodName, paramTypes, args);
------------------------------------------------------------------------------
transform():
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);}
}
也就是执行了:input.iMethodName(iArgs)
ChainedTransformer
代码语言:javascript复制ChainedTransformer还是一个实现Transformer的接口
有两个成员变量(均为private):
static final long serialVersionUID;
final Transformer[] iTransformers;
构造函数的参数赋值到iTransformers:
public ChainedTransformer(Transformer[] transformers) {super();Transformers = transformers;}
代码语言:javascript复制除构造函数外有两个成员函数:
- getInstance():
有三种实现方法:
-
public static Transformer getInstance(Collection transformers)
将(Collection transformers)中的每个元素逐个强转为Transformer类型后添加到局部变量cmds[]中,然后 return new ChainedTransformer(cmds) -
public static Transformer getInstance(Transformer[] transformers)
return new ChainedTransformer(transformers); -
public static Transformer getInstance(Transformer transformer1, Transformer transformer2)
return new ChainedTransformer( { transformer1, transformer2 } )
- transform(Object object)
public Object transform(Object object) {
for (int i = 0; i < iTransformers.length; i ) {
object = iTransformers[i].transform(object);
}
return object;
}
transform方法通过传入的Trasnformer[]数组来对传入的数值进行遍历并且递归调用数组对象的transform()函数
利用Transform来执行命令有时还需要绑定到Map上
抽象类AbstractMapDecorator是Apache Commons Collections引入的一个类,实现类有很多,比如LazyMap、TransformedMap等,这些类都有一个decorate()方法,用于将上述的Transformer实现类绑定到Map上,当对Map进行一些操作时,会自动触发Transformer实现类的tranform()方法,不同的Map类型有不同的触发规则。
比如 :
代码语言:javascript复制HashMap<Object, Object> map = new HashMap<>();
map.put("set_key", "set_value");
Map<Object, Object> transformedMap = TransformedMap.decorate(map, null, invokerTransformer);
for (Map.Entry entry : transformedMap.entrySet()) {
entry.setValue(r);
}
在这里的entry就是一个AbstractMapDecorator的子类AbstractInputCheckedMapDecorator
entry.setValue()会执行AbstractInputCheckedMapDecorator.parent.setValue()
而parent 就是transformedMap
所以感觉 AbstractInputCheckedMapDecorator 就像是一个代理类的效果,根据parent的不同执行parent的setValue()函数
TransformedMap
代码语言:javascript复制有三个成员变量:
private static final long serialVersionUID = 7023152376788900464L;
protected final Transformer keyTransformer;
protected final Transformer valueTransformer;
构造函数(为protected类型,不能通过公共接口调用):
protected TransformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer)
成员方法:
decorate和decorateTransform都是public类型,
作为接口执行执行return new TransformedMap(map, keyTransformer, valueTransformer);
public decorate(Map map, Transformer keyTransformer, Transformer valueTransformer)
public decorateTransform(Map map, Transformer keyTransformer, Transformer valueTransformer)
private writeObject(ObjectOutputStream out)
private readObject(ObjectInputStream in)
protected transformMap(Map map)
protected transformKey(Object object)
protected transformValue(Object object)
protected Object checkSetValue(Object value)
protected boolean isSetValueChecking()
public Object put(Object key, Object value)
public void putAll(Map mapToCopy)
代码语言:javascript复制Map transformedMap = TransformedMap.decorate(normalMap, KeyTransformer, ValueTransformer);
可以将不同的Transformer实现类分别绑定到map的key和value上,当map的key或value被修改时,会调用对应Transformer实现类的transform()方法
- 执行transform()函数的方法:
transformValue() , transformKey() , transformMap() , checkSetValue()
- 修改map的key或value的方法 :
put(),putAll() 分别会触发transformValue() transformKey() , transformMap()
- 类内重写了writeObject()和readObject()函数
因此我们可以把chainedtransformer绑定到一个TransformedMap上,当此map的key或value发生改变时,自动触发chainedtransformer。
LazyMap
代码语言:javascript复制有两个成员变量:
private static final long serialVersionUID;
protected final Transformer factory;
成员方法:
构造函数(为protected类型,不能通过公共接口调用):
protected LazyMap(Map map, Factory factory)
protected LazyMap(Map map, Transformer factory)
decorate和decorateTransform都是public类型,
作为接口执行执行 return new LazyMap(map, factory);
public static Map decorate(Map map, Factory factory)
public static Map decorate(Map map, Transformer factory)
private void writeObject(ObjectOutputStream out)
private void readObject(ObjectInputStream in)
public Object get(Object key) {
if (map.containsKey(key) == false) { //检验map中是否存在传入的key键值,不存在进入执行factory.transform(key)
Object value = factory.transform(key);
map.put(key, value);
return value;
}
return map.get(key);
}
代码语言:javascript复制Map lazyMap = LazyMap.decorate(normalMap, TestTransformer);
当调用lazyMap.get(key)的key不存在时,会调用TestTransformer的transform()方法
这些不同的Map类型之间的差异也正是CommonsColletions有那么多gadget的原因之一。
参考链接:
https://www.cnblogs.com/litlife/p/12571787.html#3919742933