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.

exploit_driver.rb 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. # -*- coding: binary -*-
  2. require 'msf/core'
  3. module Msf
  4. ###
  5. #
  6. # This class drives the exploitation process from start to finish for a given
  7. # exploit module instance. It's responsible for payload generation, encoding,
  8. # and padding as well as initialization handlers and finally launching the
  9. # exploit.
  10. #
  11. ###
  12. class ExploitDriver
  13. #
  14. # Initializes the exploit driver using the supplied framework instance.
  15. #
  16. def initialize(framework)
  17. self.payload = nil
  18. self.exploit = nil
  19. self.use_job = false
  20. self.job_id = nil
  21. self.force_wait_for_session = false
  22. self.semaphore = Mutex.new
  23. end
  24. #
  25. # Specification of the exploit target index.
  26. #
  27. def target_idx=(target_idx)
  28. if (target_idx)
  29. # Make sure the target index is valid
  30. if (target_idx >= exploit.targets.length)
  31. raise Rex::ArgumentError, "Invalid target index.", caller
  32. end
  33. end
  34. # Set the active target
  35. @target_idx = target_idx
  36. end
  37. #
  38. # This method returns the currently selected target index.
  39. #
  40. def target_idx
  41. @target_idx
  42. end
  43. #
  44. # Checks to see if the supplied payload is compatible with the
  45. # current exploit. Assumes that target_idx is valid.
  46. #
  47. def compatible_payload?(payload)
  48. # Try to use the target's platform in preference of the exploit's
  49. exp_platform = exploit.targets[target_idx].platform || exploit.platform
  50. return ((payload.platform & exp_platform).empty? == false)
  51. end
  52. ##
  53. #
  54. # Exploit execution
  55. #
  56. ##
  57. #
  58. # Makes sure everything's in tip-top condition prior to launching the
  59. # exploit. For things that aren't good to go, an exception is thrown.
  60. #
  61. def validate
  62. # First, validate that a target has been selected
  63. if (target_idx == nil)
  64. raise MissingTargetError,
  65. "A payload cannot be selected until a target is specified.",
  66. caller
  67. end
  68. # Next, validate that a payload has been selected
  69. if (payload == nil)
  70. raise MissingPayloadError,
  71. "A payload has not been selected.", caller
  72. end
  73. # Make sure the payload is compatible after all
  74. if (compatible_payload?(payload) == false)
  75. raise IncompatiblePayloadError.new(payload.refname),
  76. "Incompatible payload", caller
  77. end
  78. # Associate the payload instance with the exploit
  79. payload.assoc_exploit = exploit
  80. # Finally, validate options on the exploit module to ensure that things
  81. # are ready to operate as they should.
  82. exploit.options.validate(exploit.datastore)
  83. # Validate the payload's options. The payload's datastore is
  84. # most likely shared against the exploit's datastore, but in case it
  85. # isn't.
  86. payload.options.validate(payload.datastore)
  87. return true
  88. end
  89. #
  90. # Kicks off an exploitation attempt and performs the following four major
  91. # operations:
  92. #
  93. # - Generates the payload
  94. # - Initializes & monitors the handler
  95. # - Launches the exploit
  96. # - Cleans up the handler
  97. #
  98. def run
  99. # First thing's first -- validate the state. Make sure all requirement
  100. # parameters are set, including those that are derived from the
  101. # datastore.
  102. validate()
  103. # After validation has occurred, it's time to set some values on the
  104. # exploit instance and begin preparing the payload
  105. exploit.datastore['TARGET'] = target_idx
  106. # Default the session to nil
  107. self.session = nil
  108. # Explicitly clear the module's job_id in case it was set in a previous
  109. # run
  110. exploit.job_id = nil
  111. # If we are being instructed to run as a job then let's create that job
  112. # like a good person.
  113. if (use_job or exploit.stance == Msf::Exploit::Stance::Passive)
  114. # Since references to the exploit and payload will hang around for
  115. # awhile in the job, make sure we copy them so further changes to
  116. # the datastore don't alter settings in existing jobs
  117. e = exploit.replicant
  118. p = payload.replicant
  119. # Assign the correct exploit instance to the payload
  120. p.assoc_exploit = e
  121. # Generate the encoded version of the supplied payload for the
  122. # newly copied exploit module instance
  123. e.generate_payload(p)
  124. ctx = [ e, p ]
  125. e.job_id = e.framework.jobs.start_bg_job(
  126. "Exploit: #{e.refname}",
  127. ctx,
  128. Proc.new { |ctx_| job_run_proc(ctx_) },
  129. Proc.new { |ctx_| job_cleanup_proc(ctx_) }
  130. )
  131. self.job_id = e.job_id
  132. else
  133. # Generate the encoded version of the supplied payload on the
  134. # exploit module instance
  135. exploit.generate_payload(payload)
  136. # No need to copy since we aren't creating a job. We wait until
  137. # they're finished running to do anything else with them, so
  138. # nothing should be able to modify their datastore or other
  139. # settings until after they're done.
  140. ctx = [ exploit, payload ]
  141. job_run_proc(ctx)
  142. job_cleanup_proc(ctx)
  143. end
  144. return session
  145. end
  146. attr_accessor :exploit # :nodoc:
  147. attr_accessor :payload # :nodoc:
  148. attr_accessor :use_job # :nodoc:
  149. #
  150. # The identifier of the job this exploit is launched as, if it's run as a
  151. # job.
  152. #
  153. attr_accessor :job_id
  154. attr_accessor :force_wait_for_session # :nodoc:
  155. attr_accessor :session # :nodoc:
  156. # To synchronize threads cleaning up the exploit and the handler
  157. attr_accessor :semaphore
  158. protected
  159. #
  160. # Job run proc, sets up the exploit and kicks it off.
  161. #
  162. def job_run_proc(ctx)
  163. begin
  164. exploit, payload = ctx
  165. # Default session wait time..
  166. delay = payload.wfs_delay + exploit.wfs_delay
  167. delay = nil if exploit.passive?
  168. # Set the exploit up the bomb
  169. exploit.setup
  170. exploit.framework.events.on_module_run(exploit)
  171. # Launch the exploit
  172. exploit.exploit
  173. rescue ::Exception => e
  174. if [::RuntimeError, ::Interrupt].include?(e.class)
  175. # Wait for session, but don't wait long.
  176. delay = 0.01
  177. end
  178. exploit.handle_exception e
  179. end
  180. # Wait the payload to acquire a session if this isn't a passive-style
  181. # exploit.
  182. return if not delay
  183. if (force_wait_for_session == true) or
  184. (exploit.passive? == false and exploit.handler_enabled?)
  185. begin
  186. self.session = payload.wait_for_session(delay)
  187. rescue ::Interrupt
  188. # Don't let interrupt pass upward
  189. end
  190. end
  191. return self.session if self.session
  192. if exploit.fail_reason == Msf::Exploit::Failure::None
  193. exploit.fail_reason = Msf::Exploit::Failure::PayloadFailed
  194. exploit.fail_detail = "No session created"
  195. exploit.report_failure
  196. end
  197. end
  198. #
  199. # Clean up the exploit and the handler after the job completes.
  200. #
  201. def job_cleanup_proc(ctx)
  202. exploit, payload = ctx
  203. # Ensure that, no matter what, clean up of the handler occurs
  204. semaphore.synchronize { payload.stop_handler }
  205. exploit.framework.events.on_module_complete(exploit)
  206. # Allow the exploit to cleanup after itself, that messy bugger.
  207. semaphore.synchronize { exploit.cleanup }
  208. end
  209. end
  210. end