rmiFinder.groovy
import java.rmi.ConnectException import java.rmi.RemoteException import java.rmi.registry.LocateRegistry import java.rmi.registry.Registry if (!args || args.length < 3) { println "Provide name of host and range of ports (lowest and highest) on which to look for RMI-exposing ports." System.exit(-1) } def host = args[0] def initialPort = args[1] as Integer def finalPort = args[2] as Integer println "Searching for RMI-exposed ports on host ${host} within port range ${initialPort}:${finalPort}" for (port in initialPort..finalPort) { registry = LocateRegistry.getRegistry(host, port) try { def boundNames = registry.list() println "\nRMI Registry found on host:port ${host}:${port} with service names" boundNames.each{println "\t${it}"} } catch (ConnectException connectEx) { print "." // no RMI registry or cannot connect to it } catch (RemoteException remoteEx) { print "." // no RMI registry or cannot connect to it remotely (covers AccessException) } } println "\nNo ports with RMI exposed services found on host ${host} within range ${initialPort}:${finalPort}"
The simple rmiFinder.groovy script makes use of the approach demonstrated in the previous post regarding looking up a registry's bound names on a particular registry, but adds a simple looping mechanism to loop over a range of ports on the specified host rather than looking at a single specified port on that host.
The Registry.list() method can throw a RemoteException or its child AccessException or a ConnectException. All three of these lead to giving up on the particular port being tried in the loop and moving onto the next port. If none of these expected possible exceptions are caught, then the names of RMI services bounds to that port are displayed. I actually could have caught a RemoteException only because both AccessException and ConnectException extend RemoteException.
This approach is not particularly speedy. It takes a relatively long time to attempt the Registry.list() invocation and handle the inevitable exception handling that occurs for all non-RMI ports. Because of this incredible slowness, I had the script print out a period (.) for each failed attempt to indicate some progress being made.
The following screen snapshot shows this simple script in action. I started a simple Java application with an exposed RMI service on port 2999 to demonstrate. Because I had the luxury of knowing the port I was looking for, I could keep my example to a small range (2990 to 3000). This made it relatively quick.
The simple script did its job: it found an RMI registry on port 2999 and listed the single name bound to that registry: "jmxrmi".
It is quickest to use netstat, a similar tool, or logged output to determine a few likely candidate ports for the RMI port in question and then run the previously covered script against those. However, the script demonstrated in this post could be used to check against an arbitrary range of ports for RMI-exposed services in a more automated (albeit slower) approach. Another approach to automate this might be a script that runs a tool like netstat, parses its output, and tries only ports specified in that output that can not be ruled out as non-RMI ports. But that is left for a possible future blog post.
No comments:
Post a Comment