metasploit-framework/lib/msf/core/handler.rb

209 lines
4.2 KiB
Ruby

require 'msf/core'
module Msf
###
#
# This module acts as a base for all handler pseudo-modules. They aren't
# really modules, so don't get the wrong idea champs! They're merely
# mixed into dynamically generated payloads to handle monitoring for
# a connection. Handlers are layered in between the base payload
# class and any other payload class. A super cool ASCII diagram would
# look something like this
#
# Module
# ^
# |
# Payload
# ^
# |
# Handler
# ^
# |
# Stager
# ^
# |
# Stage
#
###
module Handler
##
#
# Constants used with the ``handler'' method to indicate whether or not the
# connection was used.
#
##
#
# Returned by handlers to indicate that a socket has been claimed for use
# by the payload.
#
Claimed = "claimed"
#
# Returned by handlers to indicate that a socket has not been claimed for
# use.
#
Unused = "unused"
#
# Returns the handler type.
#
def self.handler_type
return "none"
end
#
# Returns the transport-independent handler type.
#
def self.general_handler_type
"none"
end
#
# Returns the handler's name, if any.
#
def handler_name
module_info['HandlerName']
end
#
# Initializes the session waiter event and other fun stuff.
#
def initialize(info = {})
super
# Initialize the pending_connections counter to 0
self.pending_connections = 0
# Create the waiter event with auto_reset set to false so that
# if a session is ever created, waiting on it returns immediately.
self.session_waiter_event = Rex::Sync::Event.new(false, false)
end
#
# Sets up the connection handler.
#
def setup_handler
end
#
# Terminates the connection handler.
#
def cleanup_handler
end
#
# Start monitoring for a connection.
#
def start_handler
end
#
# Stop monitoring for a connection.
#
def stop_handler
end
#
# Checks to see if a payload connection has been established on
# the supplied connection. This is necessary for find-sock style
# payloads.
#
def handler(sock)
end
#
# Handles an established connection supplied in the in and out
# handles. The handles are passed as parameters in case this
# handler is capable of handling multiple simultaneous
# connections. The default behavior is to attempt to create a session for
# the payload. This path will not be taken for mutli-staged payloads.
#
def handle_connection(conn)
create_session(conn)
end
#
# The amount of time to wait for a session to come in.
#
def wfs_delay
2
end
#
# Waits for a session to be created as the result of a handler connection
# coming in. The return value is a session object instance on success or
# nil if the timeout expires.
#
def wait_for_session(t = wfs_delay)
session = nil
begin
session = session_waiter_event.wait(t)
rescue ::TimeoutError
end
# If a connection has arrived, wait longer...
if (pending_connections > 0)
session = session_waiter_event.wait
end
return session
end
protected
#
# Creates a session, if necessary, for the connection that's been handled.
# Sessions are only created if the payload that's been mixed in has an
# associated session.
#
def create_session(conn)
# If the payload we merged in with has an associated session factory,
# allocate a new session.
if (self.session)
s = self.session.new(conn)
# Pass along the framework context
s.framework = framework
# If the session is valid, register it with the framework and
# notify any waiters we may have.
if (s)
register_session(s)
end
# Call the payload's on_session handler
on_session(s)
return s
end
end
#
# Registers a session with the framework and notifies any waiters of the
# new session.
#
def register_session(session)
# Register the session with the framework
framework.sessions.register(session)
# Notify waiters that they should be ready to rock
session_waiter_event.notify(session)
# Decrement the pending connections counter now that we've processed
# one session.
self.pending_connections -= 1
end
attr_accessor :session_waiter_event # :nodoc:
attr_accessor :pending_connections # :nodoc:
end
end
# The default none handler
require 'msf/core/handler/none'