Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

handler.rb 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. # -*- coding: binary -*-
  2. require 'msf/core'
  3. module Msf
  4. ###
  5. #
  6. # This module acts as a base for all handler pseudo-modules. They aren't
  7. # really modules, so don't get the wrong idea champs! They're merely
  8. # mixed into dynamically generated payloads to handle monitoring for
  9. # a connection. Handlers are layered in between the base payload
  10. # class and any other payload class. A super cool ASCII diagram would
  11. # look something like this
  12. #
  13. # Module
  14. # ^
  15. # |
  16. # Payload
  17. # ^
  18. # |
  19. # Handler
  20. # ^
  21. # |
  22. # Stager
  23. # ^
  24. # |
  25. # Stage
  26. #
  27. ###
  28. module Handler
  29. require 'msf/core/handler/reverse'
  30. ##
  31. #
  32. # Constants used with the ``handler'' method to indicate whether or not the
  33. # connection was used.
  34. #
  35. ##
  36. #
  37. # Returned by handlers to indicate that a socket has been claimed for use
  38. # by the payload.
  39. #
  40. Claimed = "claimed"
  41. #
  42. # Returned by handlers to indicate that a socket has not been claimed for
  43. # use.
  44. #
  45. Unused = "unused"
  46. #
  47. # Returns the handler type.
  48. #
  49. def self.handler_type
  50. return "none"
  51. end
  52. #
  53. # Returns the transport-independent handler type.
  54. #
  55. def self.general_handler_type
  56. "none"
  57. end
  58. #
  59. # Returns the handler's name, if any.
  60. #
  61. def handler_name
  62. module_info['HandlerName']
  63. end
  64. #
  65. # Initializes the session waiter event and other fun stuff.
  66. #
  67. def initialize(info = {})
  68. super
  69. # Initialize the pending_connections counter to 0
  70. self.pending_connections = 0
  71. # Initialize the sessions counter to 0
  72. self.sessions = 0
  73. # Create the waiter event with auto_reset set to false so that
  74. # if a session is ever created, waiting on it returns immediately.
  75. self.session_waiter_event = Rex::Sync::Event.new(false, false)
  76. end
  77. #
  78. # Sets up the connection handler.
  79. #
  80. def setup_handler
  81. end
  82. #
  83. # Terminates the connection handler.
  84. #
  85. def cleanup_handler
  86. end
  87. #
  88. # Start monitoring for a connection.
  89. #
  90. def start_handler
  91. end
  92. #
  93. # Start another connection monitor
  94. #
  95. def add_handler(opts={})
  96. end
  97. #
  98. # Stop monitoring for a connection.
  99. #
  100. def stop_handler
  101. end
  102. #
  103. # Checks to see if a payload connection has been established on
  104. # the supplied connection. This is necessary for find-sock style
  105. # payloads.
  106. #
  107. def handler(sock)
  108. end
  109. #
  110. # Handles an established connection supplied in the in and out
  111. # handles. The handles are passed as parameters in case this
  112. # handler is capable of handling multiple simultaneous
  113. # connections. The default behavior is to attempt to create a session for
  114. # the payload. This path will not be taken for multi-staged payloads.
  115. #
  116. def handle_connection(conn, opts={})
  117. create_session(conn, opts)
  118. end
  119. #
  120. # The amount of time to wait for a session to come in.
  121. #
  122. def wfs_delay
  123. 2
  124. end
  125. #
  126. # Waits for a session to be created as the result of a handler connection
  127. # coming in. The return value is a session object instance on success or
  128. # nil if the timeout expires.
  129. #
  130. def wait_for_session(t = wfs_delay)
  131. session = nil
  132. begin
  133. session = session_waiter_event.wait(t)
  134. rescue ::Timeout::Error
  135. end
  136. # If a connection has arrived, wait longer...
  137. if (pending_connections > 0)
  138. session = session_waiter_event.wait
  139. end
  140. return session
  141. end
  142. #
  143. # Interrupts a wait_for_session call by notifying with a nil event
  144. #
  145. def interrupt_wait_for_session
  146. return unless session_waiter_event
  147. session_waiter_event.notify(nil)
  148. end
  149. #
  150. # Set by the exploit module to configure handler
  151. #
  152. attr_accessor :exploit_config
  153. #
  154. # This will be non-nil if the handler has a parent payload that it
  155. # was spawned from. Right now, this is only the case with generic
  156. # payloads. The parent payload is used to create a session
  157. # rather than using the instance itself.
  158. #
  159. attr_accessor :parent_payload
  160. protected
  161. #
  162. # Creates a session, if necessary, for the connection that's been handled.
  163. # Sessions are only created if the payload that's been mixed in has an
  164. # associated session.
  165. #
  166. def create_session(conn, opts={})
  167. # If there is a parent payload, then use that in preference.
  168. return parent_payload.create_session(conn, opts) if (parent_payload)
  169. # If the payload we merged in with has an associated session factory,
  170. # allocate a new session.
  171. if (self.session)
  172. begin
  173. s = self.session.new(conn, opts)
  174. rescue ::Exception => e
  175. # We just wanna show and log the error, not trying to swallow it.
  176. print_error("#{e.class} #{e.message}")
  177. elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
  178. raise e
  179. end
  180. # Pass along the framework context
  181. s.framework = framework
  182. # Associate this system with the original exploit
  183. # and any relevant information
  184. s.set_from_exploit(assoc_exploit)
  185. # Pass along any associated payload uuid if specified
  186. s.payload_uuid = opts[:payload_uuid] if opts[:payload_uuid]
  187. # If the session is valid, register it with the framework and
  188. # notify any waiters we may have.
  189. if (s)
  190. register_session(s)
  191. end
  192. return s
  193. end
  194. nil
  195. end
  196. #
  197. # Registers a session with the framework and notifies any waiters of the
  198. # new session.
  199. #
  200. def register_session(session)
  201. # Register the session with the framework
  202. framework.sessions.register(session)
  203. # Call the handler's on_session() method
  204. on_session(session)
  205. # Process the auto-run scripts for this session
  206. if session.respond_to?('process_autoruns')
  207. session.process_autoruns(datastore)
  208. end
  209. # If there is an exploit associated with this payload, then let's notify
  210. # anyone who is interested that this exploit succeeded
  211. if assoc_exploit
  212. framework.events.on_exploit_success(assoc_exploit, session)
  213. end
  214. # Notify waiters that they should be ready to rock
  215. session_waiter_event.notify(session)
  216. # Decrement the pending connections counter now that we've processed
  217. # one session.
  218. self.pending_connections -= 1
  219. # Count the number of sessions we have registered
  220. self.sessions += 1
  221. end
  222. attr_accessor :session_waiter_event # :nodoc:
  223. attr_accessor :pending_connections # :nodoc:
  224. attr_accessor :sessions # :nodoc:
  225. end
  226. end
  227. # The default none handler
  228. require 'msf/core/handler/none'