Class 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 Detail

      • port

        public int port
        remote port of the endpoint
      • host

        public String host
        remote host of the endpoint
    • 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 to
        port - 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 to
        port - Remote port where the RMIEndpoint belongs to
        csf - 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 negative
        methodHash - hash value of the method to call or interface hash for legacy calls
        callArguments - map of arguments for the call. Each argument must also ship a class it desires to be serialized to
        locationStream - if true, uses the MaliciousOutputStream class to write custom annotation objects
        callName - 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 negative
        methodHash - hash value of the method to call or interface hash for legacy calls
        callArguments - map of arguments for the call. Each argument must also ship a class it desires to be serialized to
        locationStream - if true, uses the MaliciousOutputStream class to write custom annotation objects
        callName - the name of the call that is currently executed
        ref - 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 negative
        methodHash - hash value of the method to call or interface hash for legacy calls
        callArguments - map of arguments for the call. Each argument must also ship a class it desires to be serialized to
        locationStream - if true, uses the MaliciousOutputStream class to write custom annotation objects
        callName - the name of the call that is currently executed
        remoteRef - optional remote reference to use for the call. If null, the specified ObjID and the host and port of this class are used
        rtype - 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 guess
        callName - Name of the method for logging purposes
        remoteRef - 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 negative
        methodHash - hash value of the method to call or interface hash for legacy calls
        callArguments - map of arguments for the call. Each argument must also ship a class it desires to be serialized to
        locationStream - if true, uses the MaliciousOutputStream class to write custom annotation objects
        remoteRef - optional remote reference to use for the call. If null, the specified ObjID and the host and port of this class are used
        rtype - 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