187 lines
4.1 KiB
Ruby
187 lines
4.1 KiB
Ruby
# -*- coding: binary -*-
|
|
|
|
module Msf
|
|
|
|
###
|
|
#
|
|
# This mixin provides a generic interface for running a socket server of some
|
|
# sort that is designed to exploit clients. Exploits that include this mixin
|
|
# automatically take a passive stance.
|
|
#
|
|
###
|
|
|
|
module Exploit::Remote::SocketServer
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Stance' => Msf::Exploit::Stance::Passive))
|
|
|
|
register_options(
|
|
[
|
|
OptAddress.new('SRVHOST', [ true, "The local host to listen on. This must be an address on the local machine or 0.0.0.0", '0.0.0.0' ]),
|
|
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]),
|
|
|
|
], Msf::Exploit::Remote::SocketServer
|
|
)
|
|
|
|
register_advanced_options(
|
|
[
|
|
OptString.new('ListenerComm', [ false, 'The specific communication channel to use for this service'])
|
|
], Msf::Exploit::Remote::SocketServer
|
|
)
|
|
end
|
|
|
|
#
|
|
# This mixin overrides the exploit method so that it can initiate the
|
|
# service that corresponds with what the client has requested.
|
|
#
|
|
def exploit
|
|
|
|
start_service()
|
|
print_status("Server started.")
|
|
|
|
# Call the exploit primer
|
|
primer
|
|
|
|
# Wait on the service to stop
|
|
self.service.wait
|
|
end
|
|
|
|
#
|
|
# Primer method to call after starting service but before handling connections
|
|
#
|
|
def primer
|
|
end
|
|
|
|
#
|
|
# Stops the service, if one was created.
|
|
#
|
|
def cleanup
|
|
super
|
|
if(service)
|
|
stop_service()
|
|
print_status("Server stopped.")
|
|
end
|
|
end
|
|
|
|
#
|
|
# Called when a client has data available for reading.
|
|
#
|
|
def on_client_data(client)
|
|
end
|
|
|
|
#
|
|
# Starts the service. Override this method in consumers
|
|
#
|
|
def start_service(*args)
|
|
end
|
|
|
|
#
|
|
# Stops the service.
|
|
#
|
|
def stop_service
|
|
if (service)
|
|
begin
|
|
self.service.deref if self.service.kind_of?(Rex::Service)
|
|
if self.service.kind_of?(Rex::Socket) || self.service.kind_of?(Rex::Post::Meterpreter::Channel)
|
|
self.service.close
|
|
self.service.stop
|
|
end
|
|
|
|
self.service = nil
|
|
rescue ::Exception
|
|
end
|
|
end
|
|
end
|
|
|
|
#
|
|
# Returns the local host that is being listened on.
|
|
#
|
|
def srvhost
|
|
datastore['SRVHOST']
|
|
end
|
|
|
|
#
|
|
# Returns the local port that is being listened on.
|
|
#
|
|
def srvport
|
|
datastore['SRVPORT']
|
|
end
|
|
|
|
#
|
|
# Re-generates the payload, substituting the current RHOST and RPORT with
|
|
# the supplied client host and port from the socket.
|
|
#
|
|
def regenerate_payload(cli, arch = nil, platform = nil, target = nil)
|
|
|
|
ohost = datastore['RHOST']
|
|
oport = datastore['RPORT']
|
|
p = nil
|
|
|
|
begin
|
|
# Update the datastore with the supplied client peerhost/peerport
|
|
datastore['RHOST'] = cli.peerhost
|
|
datastore['RPORT'] = cli.peerport
|
|
|
|
if ((p = super(arch, platform, target)) == nil)
|
|
print_error("Failed to generate payload")
|
|
return nil
|
|
end
|
|
|
|
# Allow the payload to start a new handler
|
|
add_handler({
|
|
'RHOST' => datastore['RHOST'],
|
|
'RPORT' => datastore['RPORT']
|
|
})
|
|
|
|
ensure
|
|
datastore['RHOST'] = ohost
|
|
datastore['RPORT'] = oport
|
|
end
|
|
|
|
p
|
|
end
|
|
|
|
protected
|
|
|
|
#
|
|
# Determines appropriate listener comm
|
|
#
|
|
def _determine_server_comm(srv_comm = datastore['ListenerComm'].to_s)
|
|
case srv_comm
|
|
when 'local'
|
|
comm = ::Rex::Socket::Comm::Local
|
|
when /\A[0-9]+\Z/
|
|
comm = framework.sessions[srv_comm.to_i]
|
|
raise(RuntimeError, "Socket Server Comm (Session #{srv_comm}) does not exist") unless comm
|
|
raise(RuntimeError, "Socket Server Comm (Session #{srv_comm}) does not implement Rex::Socket::Comm") unless comm.is_a? ::Rex::Socket::Comm
|
|
when nil, ''
|
|
comm = nil
|
|
else
|
|
raise(RuntimeError, "SocketServer Comm '#{srv_comm}' is invalid")
|
|
end
|
|
|
|
comm
|
|
end
|
|
|
|
def via_string_for_ip(ip, comm)
|
|
comm_used = comm
|
|
comm_used ||= Rex::Socket::SwitchBoard.best_comm(ip)
|
|
comm_used ||= Rex::Socket::Comm::Local
|
|
|
|
if comm_used.respond_to?(:type) && comm_used.respond_to?(:sid)
|
|
via = "via the #{comm_used.type} on session #{comm_used.sid}"
|
|
else
|
|
via = ""
|
|
end
|
|
|
|
via
|
|
end
|
|
|
|
attr_accessor :service # :nodoc:
|
|
|
|
end
|
|
|
|
end
|
|
|