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_all_ports.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


175
176
177
# File 'lib/msf/core/handler.rb', line 175

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.


183
184
185
# File 'lib/msf/core/handler.rb', line 183

def parent_payload
  @parent_payload
end

#pending_connectionsObject (protected)

:nodoc:


311
312
313
# File 'lib/msf/core/handler.rb', line 311

def pending_connections
  @pending_connections
end

#session_waiter_eventObject (protected)

:nodoc:


310
311
312
# File 'lib/msf/core/handler.rb', line 310

def session_waiter_event
  @session_waiter_event
end

#sessionsObject (protected)

:nodoc:


312
313
314
# File 'lib/msf/core/handler.rb', line 312

def sessions
  @sessions
end

Class Method Details

.general_handler_typeObject

Returns the transport-independent handler type.


59
60
61
# File 'lib/msf/core/handler.rb', line 59

def self.general_handler_type
  "none"
end

.handler_typeObject

Returns the handler type.


52
53
54
# File 'lib/msf/core/handler.rb', line 52

def self.handler_type
  return "none"
end

Instance Method Details

#add_handler(opts = {}) ⇒ Object

Start another connection monitor


108
109
# File 'lib/msf/core/handler.rb', line 108

def add_handler(opts={})
end

#cleanup_handlerObject

Terminates the connection handler.


96
97
# File 'lib/msf/core/handler.rb', line 96

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.


192
193
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
259
# File 'lib/msf/core/handler.rb', line 192

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 }
        uuid_info = framework.db.payloads(payload_info).first
      else
        print_warning('Without a database connected that payload UUID tracking will not work!')
      end
      if s.payload_uuid.respond_to?(:puid_hex) && uuid_info
        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

    # If the session is valid, register it with the framework and
    # notify any waiters we may have.
    if (s)
      # Defer the session registration to the Session Manager scheduler
      registration = Proc.new do
        register_session(s)
      end
      framework.sessions.schedule registration
    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.


132
133
134
# File 'lib/msf/core/handler.rb', line 132

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.


122
123
# File 'lib/msf/core/handler.rb', line 122

def handler(sock)
end

#handler_nameObject

Returns the handler's name, if any.


66
67
68
# File 'lib/msf/core/handler.rb', line 66

def handler_name
  module_info['HandlerName']
end

#initialize(info = {}) ⇒ Object

Initializes the session waiter event and other fun stuff.


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

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


167
168
169
170
# File 'lib/msf/core/handler.rb', line 167

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.


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
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/msf/core/handler.rb', line 265

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)

    return unless session.alive
  end

  # Process the auto-run scripts for this session
  if session.respond_to?(:process_autoruns)
    session.process_autoruns(datastore)
  end

  # Tell the handler that we have a session
  on_session(session)

  # Notify the framework that we have a new session opening up...
  # Don't let errant event handlers kill our session
  begin
    framework.events.on_session_open(session)
  rescue ::Exception => e
    wlog("Exception in on_session_open event handler: #{e.class}: #{e}")
    wlog("Call Stack\n#{e.backtrace.join("\n")}")
  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.


90
91
# File 'lib/msf/core/handler.rb', line 90

def setup_handler
end

#start_handlerObject

Start monitoring for a connection.


102
103
# File 'lib/msf/core/handler.rb', line 102

def start_handler
end

#stop_handlerObject

Stop monitoring for a connection.


114
115
# File 'lib/msf/core/handler.rb', line 114

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.


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

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.


139
140
141
# File 'lib/msf/core/handler.rb', line 139

def wfs_delay
  2
end