Package eu.tneitzel.rmg.networking
Class RMIEndpoint
- java.lang.Object
-
- eu.tneitzel.rmg.networking.RMIEndpoint
-
- Direct Known Subclasses:
RMIRegistryEndpoint
public class RMIEndpoint extends Object
The RMIEndpoint class represents an RMI endpoint on a remote server. It can be used for low level communication with the corresponding endpoint that are required by the different functions of remote-method-guesser. RMIEndpoint can be extended by RMIRegistryEndpoint, which supports some more registry related functionalities.- Author:
- Tobias Neitzel (@qtc_de)
-
-
Field Summary
Fields Modifier and Type Field Description protected RMIClientSocketFactorycsfclient socket factory to use for connectionsStringhostremote host of the endpointintportremote port of the endpoint
-
Constructor Summary
Constructors Constructor Description RMIEndpoint(String host, int port)Creates a new RMIEndpoint instance and configures the corresponding client side socket factory according to the options specified on the command line.RMIEndpoint(String host, int port, RMIClientSocketFactory csf)Creates a new RMIEndpoint instance and allows the user to specify a client side socket factory.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description voidgenericCall(ObjID objID, int callID, long methodHash, MethodArguments callArguments, boolean locationStream, String callName)Wrapper around the genericCall function specified below.voidgenericCall(ObjID objID, int callID, long methodHash, MethodArguments callArguments, boolean locationStream, String callName, RemoteRef ref)Wrapper around the genericCall function specified below.voidgenericCall(ObjID objID, int callID, long methodHash, MethodArguments callArguments, boolean locationStream, String callName, RemoteRef remoteRef, javassist.CtClass rtype)From remote-method-guesser v4.0.0 on we moved the logic of the genericCall function to the unmanagedCall function.sun.rmi.server.UnicastRefgetRemoteRef(ObjID objID)Constructs a RemoteRef by using the endpoint information (host, port, csf) and the specified objID.voidguessingCall(MethodCandidate candidate, String callName, RemoteRef remoteRef)guessingCall is basically a copy of the genericCall method, that is optimized for method guessing.voidunmanagedCall(ObjID objID, int callID, long methodHash, MethodArguments callArguments, boolean locationStream, RemoteRef remoteRef, javassist.CtClass rtype)Dispatches a raw RMI call.
-
-
-
Field Detail
-
port
public int port
remote port of the endpoint
-
host
public String host
remote host of the endpoint
-
csf
protected RMIClientSocketFactory csf
client socket factory to use for connections
-
-
Constructor Detail
-
RMIEndpoint
public RMIEndpoint(String host, int port)
Creates a new RMIEndpoint instance and configures the corresponding client side socket factory according to the options specified on the command line.- Parameters:
host- Remote host where the RMIEndpoint belongs toport- Remote port where the RMIEndpoint belongs to
-
RMIEndpoint
public RMIEndpoint(String host, int port, RMIClientSocketFactory csf)
Creates a new RMIEndpoint instance and allows the user to specify a client side socket factory.- Parameters:
host- Remote host where the RMIEndpoint belongs toport- Remote port where the RMIEndpoint belongs tocsf- Socket factory to use for connection attempts
-
-
Method Detail
-
getRemoteRef
public sun.rmi.server.UnicastRef getRemoteRef(ObjID objID)
Constructs a RemoteRef by using the endpoint information (host, port, csf) and the specified objID.- Parameters:
objID- identifies the targeted remote object on the server side- Returns:
- newly constructed RemoteRef
-
genericCall
public void genericCall(ObjID objID, int callID, long methodHash, MethodArguments callArguments, boolean locationStream, String callName) throws Exception
Wrapper around the genericCall function specified below.- Parameters:
objID- identifies the RemoteObject you want to communicate with. Registry = 0, Activator = 1, DGC = 2 or custom one...callID- callID that is used for legacy calls. Basically specifies the position of the method to call in legacy RMI calls. For current calling convention, it should be negativemethodHash- hash value of the method to call or interface hash for legacy callscallArguments- map of arguments for the call. Each argument must also ship a class it desires to be serialized tolocationStream- if true, uses the MaliciousOutputStream class to write custom annotation objectscallName- the name of the call that is currently executed- Throws:
Exception- connection related exceptions are caught, but anything what can go wrong on the server side is thrown
-
genericCall
public void genericCall(ObjID objID, int callID, long methodHash, MethodArguments callArguments, boolean locationStream, String callName, RemoteRef ref) throws Exception
Wrapper around the genericCall function specified below.- Parameters:
objID- identifies the RemoteObject you want to communicate with. Registry = 0, Activator = 1, DGC = 2 or custom one...callID- callID that is used for legacy calls. Basically specifies the position of the method to call in legacy RMI calls. For current calling convention, it should be negativemethodHash- hash value of the method to call or interface hash for legacy callscallArguments- map of arguments for the call. Each argument must also ship a class it desires to be serialized tolocationStream- if true, uses the MaliciousOutputStream class to write custom annotation objectscallName- the name of the call that is currently executedref- optional remote reference to use for the call. If null, the specified ObjID and the host and port of this class are used- Throws:
Exception- connection related exceptions are caught, but anything what can go wrong on the server side is thrown
-
genericCall
public void genericCall(ObjID objID, int callID, long methodHash, MethodArguments callArguments, boolean locationStream, String callName, RemoteRef remoteRef, javassist.CtClass rtype) throws Exception
From remote-method-guesser v4.0.0 on we moved the logic of the genericCall function to the unmanagedCall function. This allows other parts of the code to perform RMI calls with their own exception handling. However, this is usually not desired, as connection related exceptions should normally be handled in a unified way. Calling genericCall is therefore the preferred solution to perform low level RMI calls.- Parameters:
objID- identifies the RemoteObject you want to communicate with. Registry = 0, Activator = 1, DGC = 2 or custom one...callID- callID that is used for legacy calls. Basically specifies the position of the method to call in legacy RMI calls. For current calling convention, it should be negativemethodHash- hash value of the method to call or interface hash for legacy callscallArguments- map of arguments for the call. Each argument must also ship a class it desires to be serialized tolocationStream- if true, uses the MaliciousOutputStream class to write custom annotation objectscallName- the name of the call that is currently executedremoteRef- optional remote reference to use for the call. If null, the specified ObjID and the host and port of this class are usedrtype- return type of the remote method. If specified, the servers response is forwarded to the ResponseHandler plugin (if registered to the plugin system)- Throws:
Exception- connection related exceptions are caught, but anything what can go wrong on the server side is thrown
-
guessingCall
public void guessingCall(MethodCandidate candidate, String callName, RemoteRef remoteRef) throws Exception
guessingCall is basically a copy of the genericCall method, that is optimized for method guessing. It takes less parameters and offers only limited control to the caller. Methods are called with a specially prepared set of arguments. In case of a method that accepts non primitive arguments, the function sends as many primitive bytes over the network as it is required to reach the first non primitive argument. The advantage of this technique is that all data is sent within one BLOCKDATA block in the ObjectOutputStream (same block that contains the method hash). The RMI server will read and drop the complete BLOCKDATA block in any case (method exists / method does not exist) and the stream is clean and ready for the next invocation. In case of methods that take only primitive arguments, the ObjectOutputStream is modified to send a RMI ping message that cuts of the BLOCKDATA array that contains the regular calling arguments. This will lead to a second dispatch within the RMI server if the method does not exist. If it does exist, the server picks up the RMI ping and throws an StreamCorruptedException. In the second case, the next RMI call can directly being dispatched. In the first case, the RMI ping response need to be read from the ObjectInputStream.- Parameters:
candidate- Candidate method to guesscallName- Name of the method for logging purposesremoteRef- Remote Reference to guess on- Throws:
Exception- connection related exceptions are caught, but anything what can go wrong on the server side is thrown
-
unmanagedCall
public void unmanagedCall(ObjID objID, int callID, long methodHash, MethodArguments callArguments, boolean locationStream, RemoteRef remoteRef, javassist.CtClass rtype) throws Exception
Dispatches a raw RMI call. Having such a function available is important for some low level RMI operations like the localhost bypass or even just calling the registry with serialization gadgets. This method provides full access to most of the relevant parts of the RMI protocol. The target remote objects can be either specified by their ObjID or by using an already existing RemoteRef. The first approach is suitable for communicating with well known RMI objects like the registry, the DGC or the Activator. The second approach can be useful, when you just looked up an object using regular RMI functions and now want to dispatch a raw RMI call to the already obtain RemoteObject. Within the current RMI protocol, you invoke methods by specifying an ObjID to identify the RemoteObject you want to talk with and a method hash to identify the method you want to invoke. In legacy RMI, methods were instead identified by using a callID. This callID is basically the position of the method within the class definition and is therefore a positive number for legacy RMI calls. Within modern RMI, this index should be always negative (except when attempting localhost bypasses :P). The currently used method hash is replaced by an interface hash in the legacy implementation. The internal RMI communication (DGC and Registry) still use the legacy calling convention today, as you can check by searching for the corresponding Skeleton classes within the Java RMI source code. By default, the genericCall function just ignores responses from the RMI server. Responses are only parsed if an expected return type was specified during the function call and a ResponseHandler was registered by using the plugin system.- Parameters:
objID- identifies the RemoteObject you want to communicate with. Registry = 0, Activator = 1, DGC = 2 or custom one...callID- callID that is used for legacy calls. Basically specifies the position of the method to call in legacy RMI calls. For current calling convention, it should be negativemethodHash- hash value of the method to call or interface hash for legacy callscallArguments- map of arguments for the call. Each argument must also ship a class it desires to be serialized tolocationStream- if true, uses the MaliciousOutputStream class to write custom annotation objectsremoteRef- optional remote reference to use for the call. If null, the specified ObjID and the host and port of this class are usedrtype- return type of the remote method. If specified, the servers response is forwarded to the ResponseHandler plugin (if registered to the plugin system)- Throws:
Exception- connection related exceptions are caught, but anything what can go wrong on the server side is thrown
-
-