Files
metasploit-gs/lib/msf/core/exploit/tcp_server.rb
T
Brent Cook eea8fa86dc unify the SSLVersion fields between modules and mixins
Also actually handle the 'Auto' option that we had in the crawler and remove
hardcoded defaults in modules that do not need them.
2016-03-06 22:06:27 -06:00

245 lines
5.8 KiB
Ruby

# -*- coding: binary -*-
module Msf
###
#
# This mixin provides a generic interface for running a TCP server of some
# sort that is designed to exploit clients. Exploits that include this mixin
# automatically take a passive stance.
#
###
module Exploit::Remote::TcpServer
def initialize(info = {})
super(update_info(info,
'Stance' => Msf::Exploit::Stance::Passive))
register_options(
[
OptBool.new('SSL', [ false, 'Negotiate SSL for incoming connections', false]),
# SSLVersion is currently unsupported for TCP servers (only supported by clients at the moment)
OptPath.new('SSLCert', [ false, 'Path to a custom SSL certificate (default is randomly generated)']),
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::TcpServer)
register_advanced_options(
[
OptString.new('ListenerComm', [ false, 'The specific communication channel to use for this service']),
OptBool.new('SSLCompression', [ false, 'Enable SSL/TLS-level compression', false ])
], Msf::Exploit::Remote::TcpServer)
register_evasion_options(
[
OptInt.new('TCP::max_send_size', [false, 'Maximum tcp segment size. (0 = disable)', 0]),
OptInt.new('TCP::send_delay', [false, 'Delays inserted before every send. (0 = disable)', 0])
], Msf::Exploit::Remote::Tcp
)
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 connects.
#
def on_client_connect(client)
end
#
# Called when a client has data available for reading.
#
def on_client_data(client)
end
#
# Called when a client has disconnected.
#
def on_client_close(client)
end
#
# Starts the service.
#
def start_service(*args)
begin
comm = datastore['ListenerComm']
if comm == "local"
comm = ::Rex::Socket::Comm::Local
else
comm = nil
end
self.service = Rex::Socket::TcpServer.create(
'LocalHost' => srvhost,
'LocalPort' => srvport,
'SSL' => ssl,
'SSLCert' => ssl_cert,
'SSLCompression' => ssl_compression,
'Comm' => comm,
'Context' =>
{
'Msf' => framework,
'MsfExploit' => self,
})
self.service.on_client_connect_proc = Proc.new { |client|
on_client_connect(client)
}
self.service.on_client_data_proc = Proc.new { |client|
on_client_data(client)
}
self.service.on_client_close_proc = Proc.new { |client|
on_client_close(client)
}
# Start the listening service
self.service.start
rescue ::Errno::EACCES => e
if (srvport.to_i < 1024)
print_line(" ")
print_error("Could not start the TCP server: #{e}.")
print_error(
"This module is configured to use a privileged TCP port (#{srvport}). " +
"On Unix systems, only the root user account is allowed to bind to privileged ports." +
"Please run the framework as root to use this module."
)
print_error(
"On Microsoft Windows systems, this error is returned when a process attempts to "+
"listen on a host/port combination that is already in use. For example, Windows XP "+
"will return this error if a process attempts to bind() over the system SMB/NetBIOS services."
)
print_line(" ")
end
raise e
end
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.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
#
# Returns the SSL option
#
def ssl
datastore['SSL']
end
#
# Returns the SSLCert option
#
def ssl_cert
datastore['SSLCert']
end
# @return [Bool] enable SSL/TLS-level compression
def ssl_compression
datastore['SSLCompression']
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
attr_accessor :service # :nodoc:
end
end