Module: Msf::Handler

Included in:
BindNamedPipe, BindTcp, BindUdp, FindPort, None, ReverseHttp, ReverseNamedPipe, ReverseSsh, ReverseTcp, ReverseTcpDouble, ReverseTcpDoubleSSL, ReverseUdp
Defined in:
lib/msf/core/handler.rb,
lib/msf/core/handler/none.rb,
lib/msf/core/handler/reverse.rb,
lib/msf/core/handler/bind_tcp.rb,
lib/msf/core/handler/bind_udp.rb,
lib/msf/core/handler/find_tag.rb,
lib/msf/core/handler/find_tty.rb,
lib/msf/core/handler/find_port.rb,
lib/msf/core/handler/find_shell.rb,
lib/msf/core/handler/reverse/ssl.rb,
lib/msf/core/handler/reverse_ssh.rb,
lib/msf/core/handler/reverse_tcp.rb,
lib/msf/core/handler/reverse_udp.rb,
lib/msf/core/handler/reverse/comm.rb,
lib/msf/core/handler/reverse_http.rb,
lib/msf/core/handler/reverse_https.rb,
lib/msf/core/handler/bind_named_pipe.rb,
lib/msf/core/handler/reverse_tcp_ssl.rb,
lib/msf/core/handler/reverse_hop_http.rb,
lib/msf/core/handler/reverse_named_pipe.rb,
lib/msf/core/handler/reverse_tcp_double.rb,
lib/msf/core/handler/reverse_https_proxy.rb,
lib/msf/core/handler/reverse_tcp_allports.rb,
lib/msf/core/handler/reverse_tcp_double_ssl.rb

Overview

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

Defined Under Namespace

Modules: BindNamedPipe, BindTcp, BindUdp, FindPort, FindShell, FindTag, FindTty, None, Reverse, ReverseHopHttp, ReverseHttp, ReverseHttps, ReverseHttpsProxy, ReverseNamedPipe, ReverseSsh, ReverseTcp, ReverseTcpAllPorts, ReverseTcpDouble, ReverseTcpDoubleSSL, ReverseTcpSsl, ReverseUdp

Constant Summary collapse

Claimed =

Returned by handlers to indicate that a socket has been claimed for use by the payload.

"claimed"
Unused =

Returned by handlers to indicate that a socket has not been claimed for use.

"unused"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#exploit_configObject

Set by the exploit module to configure handler


177
178
179
# File 'lib/msf/core/handler.rb', line 177

def exploit_config
  @exploit_config
end

#parent_payloadObject

This will be non-nil if the handler has a parent payload that it was spawned from. Right now, this is only the case with generic payloads. The parent payload is used to create a session rather than using the instance itself.


185
186
187
# File 'lib/msf/core/handler.rb', line 185

def parent_payload
  @parent_payload
end

#pending_connectionsObject (protected)

:nodoc:


297
298
299
# File 'lib/msf/core/handler.rb', line 297

def pending_connections
  @pending_connections
end

#session_waiter_eventObject (protected)

:nodoc:


296
297
298
# File 'lib/msf/core/handler.rb', line 296

def session_waiter_event
  @session_waiter_event
end

#sessionsObject (protected)

:nodoc:


298
299
300
# File 'lib/msf/core/handler.rb', line 298

def sessions
  @sessions
end

Class Method Details

.general_handler_typeObject

Returns the transport-independent handler type.


61
62
63
# File 'lib/msf/core/handler.rb', line 61

def self.general_handler_type
  "none"
end

.handler_typeObject

Returns the handler type.


54
55
56
# File 'lib/msf/core/handler.rb', line 54

def self.handler_type
  return "none"
end

Instance Method Details

#add_handler(opts = {}) ⇒ Object

Start another connection monitor


110
111
# File 'lib/msf/core/handler.rb', line 110

def add_handler(opts={})
end

#cleanup_handlerObject

Terminates the connection handler.


98
99
# File 'lib/msf/core/handler.rb', line 98

def cleanup_handler
end

#create_session(conn, opts = {}) ⇒ Object (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.


194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/msf/core/handler.rb', line 194

def create_session(conn, opts={})
  # If there is a parent payload, then use that in preference.
  return parent_payload.create_session(conn, opts) if (parent_payload)

  # If the payload we merged in with has an associated session factory,
  # allocate a new session.
  if (self.session)
    begin
      # if there's a create_session method then use it, as this
      # can form a factory for arb session types based on the
      # payload.
      if self.session.respond_to?('create_session')
        s = self.session.create_session(conn, opts)
      else
        s = self.session.new(conn, opts)
      end
    rescue ::Exception => e
      # We just wanna show and log the error, not trying to swallow it.
      print_error("#{e.class} #{e.message}")
      elog('Could not allocate a new Session.', error: e)
      raise e
    end

    # Pass along the framework context
    s.framework = framework

    # Associate this system with the original exploit
    # and any relevant information
    s.set_from_exploit(assoc_exploit)

    # set injected workspace value if db is active
    if framework.db.active && wspace = framework.db.find_workspace(s.workspace)
      framework.db.workspace = wspace
    end

    # Pass along any associated payload uuid if specified
    if opts[:payload_uuid]
      s.payload_uuid = opts[:payload_uuid]
      s.payload_uuid.registered = false

      if framework.db.active
        payload_info = {
            uuid: s.payload_uuid.puid_hex,
            workspace: framework.db.workspace
        }
        if s.payload_uuid.respond_to?(:puid_hex) && (uuid_info = framework.db.payloads(payload_info).first)
          s.payload_uuid.registered = true
          s.payload_uuid.name = uuid_info['name']
          s.payload_uuid.timestamp = uuid_info['timestamp']
        else
          s.payload_uuid.registered = false
        end
      end
    end

    # If the session is valid, register it with the framework and
    # notify any waiters we may have.
    if (s)
      register_session(s)
    end

    return s
  end
  nil
end

#handle_connection(conn, opts = {}) ⇒ Object

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 multi-staged payloads.


134
135
136
# File 'lib/msf/core/handler.rb', line 134

def handle_connection(conn, opts={})
  create_session(conn, opts)
end

#handler(sock) ⇒ Object

Checks to see if a payload connection has been established on the supplied connection. This is necessary for find-sock style payloads.


124
125
# File 'lib/msf/core/handler.rb', line 124

def handler(sock)
end

#handler_nameObject

Returns the handler's name, if any.


68
69
70
# File 'lib/msf/core/handler.rb', line 68

def handler_name
  module_info['HandlerName']
end

#initialize(info = {}) ⇒ Object

Initializes the session waiter event and other fun stuff.


75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/msf/core/handler.rb', line 75

def initialize(info = {})
  super

  # Initialize the pending_connections counter to 0
  self.pending_connections = 0

  # Initialize the sessions counter to 0
  self.sessions = 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

#interrupt_wait_for_sessionObject

Interrupts a wait_for_session call by notifying with a nil event


169
170
171
172
# File 'lib/msf/core/handler.rb', line 169

def interrupt_wait_for_session
  return unless session_waiter_event
  session_waiter_event.notify(nil)
end

#register_session(session) ⇒ Object (protected)

Registers a session with the framework and notifies any waiters of the new session.


264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/msf/core/handler.rb', line 264

def register_session(session)
  # Register the session with the framework
  framework.sessions.register(session)

  # Call the handler's on_session() method
  if session.respond_to?(:bootstrap)
    session.bootstrap(datastore, self)
  else
    # Process the auto-run scripts for this session
    if session.respond_to?(:process_autoruns)
      session.process_autoruns(datastore)
    end
    on_session(session)
  end

  # If there is an exploit associated with this payload, then let's notify
  # anyone who is interested that this exploit succeeded
  if assoc_exploit
    framework.events.on_exploit_success(assoc_exploit, session)
  end

  # 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

  # Count the number of sessions we have registered
  self.sessions += 1
end

#setup_handlerObject

Sets up the connection handler.


92
93
# File 'lib/msf/core/handler.rb', line 92

def setup_handler
end

#start_handlerObject

Start monitoring for a connection.


104
105
# File 'lib/msf/core/handler.rb', line 104

def start_handler
end

#stop_handlerObject

Stop monitoring for a connection.


116
117
# File 'lib/msf/core/handler.rb', line 116

def stop_handler
end

#wait_for_session(t = wfs_delay) ⇒ Object

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.


150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/msf/core/handler.rb', line 150

def wait_for_session(t = wfs_delay)
  session = nil

  begin
    session = session_waiter_event.wait(t)
  rescue ::Timeout::Error
  end

  # If a connection has arrived, wait longer...
  if (pending_connections > 0)
    session = session_waiter_event.wait
  end

  return session
end

#wfs_delayObject

The amount of time to wait for a session to come in.


141
142
143
# File 'lib/msf/core/handler.rb', line 141

def wfs_delay
  2
end