2015-01-07 20:42:44 -06:00
|
|
|
# -*- coding: binary -*-
|
|
|
|
|
require 'rex/proto/rmi'
|
|
|
|
|
require 'rex/java/serialization'
|
|
|
|
|
require 'stringio'
|
|
|
|
|
|
|
|
|
|
module Msf
|
2015-02-10 10:58:57 -06:00
|
|
|
module Java
|
|
|
|
|
module Rmi
|
|
|
|
|
module Client
|
2015-01-07 20:42:44 -06:00
|
|
|
|
2015-03-16 23:44:16 -05:00
|
|
|
require 'msf/java/rmi/util'
|
2015-03-18 09:25:53 -05:00
|
|
|
require 'msf/java/rmi/builder'
|
2015-03-19 11:16:04 -05:00
|
|
|
require 'msf/java/rmi/client/registry'
|
2015-03-23 15:48:10 -05:00
|
|
|
require 'msf/java/rmi/client/jmx'
|
2015-01-08 14:01:04 -06:00
|
|
|
|
2015-03-16 23:44:16 -05:00
|
|
|
include Msf::Java::Rmi::Util
|
2015-03-18 09:25:53 -05:00
|
|
|
include Msf::Java::Rmi::Builder
|
2015-03-19 11:16:04 -05:00
|
|
|
include Msf::Java::Rmi::Client::Registry
|
2015-03-23 15:48:10 -05:00
|
|
|
include Msf::Java::Rmi::Client::Jmx
|
2015-02-10 10:58:57 -06:00
|
|
|
include Exploit::Remote::Tcp
|
2015-01-07 20:42:44 -06:00
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
# Returns the target host
|
|
|
|
|
#
|
|
|
|
|
# @return [String]
|
|
|
|
|
def rhost
|
|
|
|
|
datastore['RHOST']
|
|
|
|
|
end
|
2015-01-07 20:42:44 -06:00
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
# Returns the target port
|
|
|
|
|
#
|
|
|
|
|
# @return [Fixnum]
|
|
|
|
|
def rport
|
|
|
|
|
datastore['RPORT']
|
|
|
|
|
end
|
2015-01-07 20:42:44 -06:00
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
# Returns the RMI server peer
|
|
|
|
|
#
|
|
|
|
|
# @return [String]
|
|
|
|
|
def peer
|
|
|
|
|
"#{rhost}:#{rport}"
|
|
|
|
|
end
|
2015-01-07 20:42:44 -06:00
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
# Sends a RMI header stream
|
|
|
|
|
#
|
|
|
|
|
# @param opts [Hash]
|
|
|
|
|
# @option opts [Rex::Socket::Tcp] :sock
|
|
|
|
|
# @return [Fixnum] the number of bytes sent
|
|
|
|
|
# @see Msf::Rmi::Client::Streams#build_header
|
|
|
|
|
def send_header(opts = {})
|
|
|
|
|
nsock = opts[:sock] || sock
|
|
|
|
|
stream = build_header(opts)
|
|
|
|
|
nsock.put(stream.encode + "\x00\x00\x00\x00\x00\x00")
|
|
|
|
|
end
|
2015-01-08 15:46:24 -06:00
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
# Sends a RMI CALL stream
|
|
|
|
|
#
|
|
|
|
|
# @param opts [Hash]
|
|
|
|
|
# @option opts [Rex::Socket::Tcp] :sock
|
2015-03-18 15:37:07 -05:00
|
|
|
# @option opts [Rex::Proto::Rmi::Model::Call] :call
|
2015-02-10 10:58:57 -06:00
|
|
|
# @return [Fixnum] the number of bytes sent
|
|
|
|
|
# @see Msf::Rmi::Client::Streams#build_call
|
|
|
|
|
def send_call(opts = {})
|
|
|
|
|
nsock = opts[:sock] || sock
|
2015-03-18 15:37:07 -05:00
|
|
|
call = opts[:call] || build_call(opts)
|
|
|
|
|
nsock.put(call.encode)
|
2015-02-10 10:58:57 -06:00
|
|
|
end
|
2015-01-13 11:02:16 -06:00
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
# Sends a RMI DGCACK stream
|
|
|
|
|
#
|
|
|
|
|
# @param opts [Hash]
|
|
|
|
|
# @option opts [Rex::Socket::Tcp] :sock
|
|
|
|
|
# @return [Fixnum] the number of bytes sent
|
|
|
|
|
# @see Msf::Rmi::Client::Streams#build_dgc_ack
|
|
|
|
|
def send_dgc_ack(opts = {})
|
|
|
|
|
nsock = opts[:sock] || sock
|
|
|
|
|
stream = build_dgc_ack(opts)
|
|
|
|
|
nsock.put(stream.encode)
|
2015-01-08 15:46:24 -06:00
|
|
|
end
|
|
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
# Reads the Protocol Ack
|
|
|
|
|
#
|
|
|
|
|
# @param opts [Hash]
|
|
|
|
|
# @option opts [Rex::Socket::Tcp] :sock
|
2015-03-18 15:37:07 -05:00
|
|
|
# @return [Rex::Proto::Rmi::Model::ProtocolAck] if success
|
|
|
|
|
# @return [NilClass] otherwise
|
2015-02-10 10:58:57 -06:00
|
|
|
# @see Rex::Proto::Rmi::Model::ProtocolAck.decode
|
|
|
|
|
def recv_protocol_ack(opts = {})
|
|
|
|
|
nsock = opts[:sock] || sock
|
|
|
|
|
data = safe_get_once(nsock)
|
|
|
|
|
begin
|
|
|
|
|
ack = Rex::Proto::Rmi::Model::ProtocolAck.decode(StringIO.new(data))
|
2015-04-05 18:15:04 -05:00
|
|
|
rescue Rex::Proto::Rmi::DecodeError
|
2015-02-10 10:58:57 -06:00
|
|
|
return nil
|
|
|
|
|
end
|
2015-01-08 15:46:24 -06:00
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
ack
|
2015-01-08 15:46:24 -06:00
|
|
|
end
|
|
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
# Reads a ReturnData message and returns the java serialized stream
|
|
|
|
|
# with the return data value.
|
|
|
|
|
#
|
|
|
|
|
# @param opts [Hash]
|
|
|
|
|
# @option opts [Rex::Socket::Tcp] :sock
|
2015-03-18 15:37:07 -05:00
|
|
|
# @return [Rex::Proto::Rmi::Model::ReturnValue] if success
|
|
|
|
|
# @return [NilClass] otherwise
|
2015-02-10 10:58:57 -06:00
|
|
|
# @see Rex::Proto::Rmi::Model::ReturnData.decode
|
|
|
|
|
def recv_return(opts = {})
|
|
|
|
|
nsock = opts[:sock] || sock
|
|
|
|
|
data = safe_get_once(nsock)
|
2015-03-24 19:14:10 -05:00
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
begin
|
|
|
|
|
return_data = Rex::Proto::Rmi::Model::ReturnData.decode(StringIO.new(data))
|
2015-04-05 18:15:04 -05:00
|
|
|
rescue Rex::Proto::Rmi::DecodeError
|
2015-02-10 10:58:57 -06:00
|
|
|
return nil
|
|
|
|
|
end
|
2015-01-08 15:46:24 -06:00
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
return_data.return_value
|
2015-01-08 16:04:56 -06:00
|
|
|
end
|
|
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
# Helper method to read fragmented data from a ```Rex::Socket::Tcp```
|
|
|
|
|
#
|
2015-04-03 14:01:31 -05:00
|
|
|
# @param nsock [Rex::Socket::Tcp]
|
2015-02-10 10:58:57 -06:00
|
|
|
# @return [String]
|
|
|
|
|
def safe_get_once(nsock = sock)
|
|
|
|
|
data = ''
|
2015-01-08 15:46:24 -06:00
|
|
|
begin
|
|
|
|
|
res = nsock.get_once
|
|
|
|
|
rescue ::EOFError
|
|
|
|
|
res = nil
|
|
|
|
|
end
|
2015-01-07 20:42:44 -06:00
|
|
|
|
2015-02-10 10:58:57 -06:00
|
|
|
until res.nil? || res.length < 1448
|
|
|
|
|
data << res
|
|
|
|
|
begin
|
|
|
|
|
res = nsock.get_once
|
|
|
|
|
rescue ::EOFError
|
|
|
|
|
res = nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
data << res if res
|
|
|
|
|
data
|
|
|
|
|
end
|
2015-01-07 20:42:44 -06:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|