123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- #
- # This plugin provides an msf daemon interface that spawns a listener on a
- # defined port (default 55554) and gives each connecting client its own
- # console interface. These consoles all share the same framework instance.
- # Be aware that the console instance that spawns on the port is entirely
- # unauthenticated, so realize that you have been warned.
- #
- module Msf
- ###
- #
- # This class implements the msfd plugin interface.
- #
- ###
- class Plugin::Msfd < Msf::Plugin
- #
- # The default local hostname that the server listens on.
- #
- DefaultHost = '127.0.0.1'.freeze
- #
- # The default local port that the server listens on.
- #
- DefaultPort = 55554
- #
- # Initializes the msfd plugin. The following options are supported in the
- # hash by this plugin:
- #
- # ServerHost
- #
- # The local hostname to listen on for connections. The default is
- # 127.0.0.1.
- #
- # ServerPort
- #
- # The local port to listen on for connections. The default is 55554.
- #
- # SSL
- #
- # Use SSL
- #
- # RunInForeground
- #
- # Instructs the plugin to now execute the daemon in a worker thread and to
- # instead allow the caller to manage executing the daemon through the
- # ``run'' method.
- #
- # HostsAllowed
- #
- # List of hosts (in NBO) allowed to use msfd
- #
- # HostsDenied
- #
- # List of hosts (in NBO) not allowed to use msfd
- #
- def initialize(framework, opts)
- super
- # Start listening for connections.
- self.server = Rex::Socket::TcpServer.create(
- 'LocalHost' => opts['ServerHost'] || DefaultHost,
- 'LocalPort' => opts['ServerPort'] || DefaultPort,
- 'SSL' => opts['SSL']
- )
- # If the run in foreground flag is not specified, then go ahead and fire
- # it off in a worker thread.
- if (opts['RunInForeground'] != true)
- Thread.new do
- run(opts)
- end
- end
- end
- #
- # Returns 'msfd'
- #
- def name
- 'msfd'
- end
- #
- # Returns the msfd plugin description.
- #
- def desc
- 'Provides a console interface to users over a listening TCP port'
- end
- #
- # Runs the msfd plugin by blocking on new connections and then spawning
- # threads to handle the console interface for each client.
- #
- def run(opts = {})
- loop do
- client = server.accept
- addr = Rex::Socket.resolv_nbo(client.peerhost)
- if opts['HostsAllowed'] &&
- !opts['HostsAllowed'].find { |x| x == addr }
- client.close
- next
- end
- if opts['HostsDenied'] &&
- opts['HostsDenied'].find { |x| x == addr }
- client.close
- next
- end
- msg = "Msfd: New connection from #{client.peerhost}"
- ilog(msg, 'core')
- print_status(msg)
- # Spawn a thread for the client connection
- Thread.new(client) do |cli|
- Msf::Ui::Console::Driver.new(
- Msf::Ui::Console::Driver::DefaultPrompt,
- Msf::Ui::Console::Driver::DefaultPromptChar,
- 'Framework' => framework,
- 'LocalInput' => Rex::Ui::Text::Input::Socket.new(cli),
- 'LocalOutput' => Rex::Ui::Text::Output::Socket.new(cli),
- 'AllowCommandPassthru' => false,
- 'DisableBanner' => opts['DisableBanner'] ? true : false
- ).run
- rescue StandardError => e
- elog('Msfd client error', error: e)
- ensure
- msg = "Msfd: Closing client connection with #{cli.peerhost}"
- ilog(msg, 'core')
- print_status(msg)
- begin
- cli.shutdown
- cli.close
- rescue IOError
- end
- end
- end
- end
- #
- # Closes the listener service.
- #
- def cleanup
- ilog('Msfd: Shutting down server', 'core')
- server.close
- end
- protected
- #
- # The listening socket instance.
- #
- attr_accessor :server
- end
- end
|