2015-03-17 04:44:16 +00:00
# -*- coding: binary -*-
require 'rex/java/serialization'
require 'rex/text'
2015-03-19 22:57:21 +00:00
2015-03-17 04:44:16 +00:00
module Msf
module Java
module Rmi
module Util
# Calculates a method hash to make RMI calls as defined by the JDK 1.2
#
# @param signature [String] The remote method signature as specified by the JDK 1.2,
# method name + method descriptor (as explained in the Java Virtual Machine Specification)
# @return [Fixnum] The method hash
# @see http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmi-stubs24.html The RemoteRef Interface documentation to understand how method hashes are calculated
def calculate_method_hash ( signature )
utf = Rex :: Java :: Serialization :: Model :: Utf . new ( nil , signature )
sha1 = Rex :: Text . sha1_raw ( utf . encode )
sha1 . unpack ( 'Q<' ) [ 0 ]
end
# Calculates an interface hash to make RMI calls as defined by the JDK 1.1
#
# @param methods [Array] set of method names and their descriptors
# @return [Fixnum] The interface hash
# @see http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmi-stubs24.html The RemoteRef Interface documentation to understand how interface hashes are calculated
2015-03-25 16:29:07 +00:00
def calculate_interface_hash ( methods )
2015-03-17 04:44:16 +00:00
stream = ''
stream << [ 1 ] . pack ( 'N' ) # stub version number
methods . each do | m |
utf_method = Rex :: Java :: Serialization :: Model :: Utf . new ( nil , m [ :name ] )
utf_descriptor = Rex :: Java :: Serialization :: Model :: Utf . new ( nil , m [ :descriptor ] )
stream << utf_method . encode
stream << utf_descriptor . encode
2015-03-25 16:29:07 +00:00
m [ :exceptions ] . each do | e |
2015-03-17 04:44:16 +00:00
utf_exception = Rex :: Java :: Serialization :: Model :: Utf . new ( nil , e )
stream << utf_exception . encode
end
end
sha1 = Rex :: Text . sha1_raw ( stream )
sha1 . unpack ( 'Q<' ) [ 0 ]
end
2015-03-19 22:33:45 +00:00
# Extracts an string from an IO
#
# @param io [IO] the io to extract the string from
# @return [String, nil] the extracted string if success, nil otherwise
def extract_string ( io )
raw_length = io . read ( 2 )
unless raw_length && raw_length . length == 2
return nil
end
length = raw_length . unpack ( 's>' ) [ 0 ]
string = io . read ( length )
unless string && string . length == length
return nil
end
string
end
# Extracts an int from an IO
#
# @param io [IO] the io to extract the int from
# @return [Fixnum, nil] the extracted int if success, nil otherwise
def extract_int ( io )
int_raw = io . read ( 4 )
unless int_raw && int_raw . length == 4
return nil
end
int = int_raw . unpack ( 'l>' ) [ 0 ]
int
end
# Extracts a long from an IO
#
# @param io [IO] the io to extract the long from
# @return [Fixnum, nil] the extracted int if success, nil otherwise
def extract_long ( io )
int_raw = io . read ( 8 )
unless int_raw && int_raw . length == 8
return nil
end
int = int_raw . unpack ( 'q>' ) [ 0 ]
int
end
2015-03-24 16:44:26 +00:00
# Extract an RMI interface reference from an IO
#
2015-03-24 17:29:40 +00:00
# @param io [IO] the io to extract the reference from, should contain the data
# inside a BlockData with the reference information.
2015-03-24 16:44:26 +00:00
# @return [Hash, nil] the extracted reference if success, nil otherwise
2015-03-24 17:29:40 +00:00
# @see Msf::Java::Rmi::Client::Jmx:Server::Parser#parse_jmx_new_client_endpoint
# @see Msf::Java::Rmi::Client::Registry::Parser#parse_registry_lookup_endpoint
2015-03-24 16:44:26 +00:00
def extract_reference ( io )
ref = extract_string ( io )
unless ref && ref == 'UnicastRef'
return nil
end
address = extract_string ( io )
return nil unless address
port = extract_int ( io )
return nil unless port
object_number = extract_long ( io )
uid = Rex :: Proto :: Rmi :: Model :: UniqueIdentifier . decode ( io )
{ address : address , port : port , object_number : object_number , uid : uid }
end
2015-03-17 04:44:16 +00:00
end
end
end
end