Class: Msf::ExploitDriver

Inherits:
Object
  • Object
show all
Defined in:
lib/msf/core/exploit_driver.rb

Overview

This class drives the exploitation process from start to finish for a given exploit module instance. It's responsible for payload generation, encoding, and padding as well as initialization handlers and finally launching the exploit.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(framework) ⇒ ExploitDriver

Initializes the exploit driver using the supplied framework instance.


19
20
21
22
23
24
25
26
27
# File 'lib/msf/core/exploit_driver.rb', line 19

def initialize(framework)
  self.payload                = nil
  self.exploit                = nil
  self.use_job                = false
  self.job_id                 = nil
  self.force_wait_for_session = false
  self.keep_handler           = false
  self.semaphore              = Mutex.new
end

Instance Attribute Details

#exploitObject

:nodoc:


182
183
184
# File 'lib/msf/core/exploit_driver.rb', line 182

def exploit
  @exploit
end

#force_wait_for_sessionObject

:nodoc:


190
191
192
# File 'lib/msf/core/exploit_driver.rb', line 190

def force_wait_for_session
  @force_wait_for_session
end

#job_idObject

The identifier of the job this exploit is launched as, if it's run as a job.


189
190
191
# File 'lib/msf/core/exploit_driver.rb', line 189

def job_id
  @job_id
end

#keep_handlerObject

:nodoc:


192
193
194
# File 'lib/msf/core/exploit_driver.rb', line 192

def keep_handler
  @keep_handler
end

#payloadObject

:nodoc:


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

def payload
  @payload
end

#semaphoreObject

To synchronize threads cleaning up the exploit and the handler


195
196
197
# File 'lib/msf/core/exploit_driver.rb', line 195

def semaphore
  @semaphore
end

#sessionObject

:nodoc:


191
192
193
# File 'lib/msf/core/exploit_driver.rb', line 191

def session
  @session
end

#use_jobObject

:nodoc:


184
185
186
# File 'lib/msf/core/exploit_driver.rb', line 184

def use_job
  @use_job
end

Instance Method Details

#compatible_payload?(payload) ⇒ Boolean

Checks to see if the supplied payload is compatible with the current exploit. Assumes that target_idx is valid.

Returns:

  • (Boolean)

55
56
57
58
59
60
# File 'lib/msf/core/exploit_driver.rb', line 55

def compatible_payload?(payload)
  # Try to use the target's platform in preference of the exploit's
  exp_platform = exploit.targets[target_idx].platform || exploit.platform

  return ((payload.platform & exp_platform).empty? == false)
end

#job_cleanup_proc(ctx) ⇒ Object (protected)

Clean up the exploit and the handler after the job completes.


258
259
260
261
262
263
264
265
266
267
268
# File 'lib/msf/core/exploit_driver.rb', line 258

def job_cleanup_proc(ctx)
  exploit, payload = ctx

  # Ensure that, no matter what, clean up of the handler occurs
  semaphore.synchronize { payload.stop_handler }

  exploit.framework.events.on_module_complete(exploit)

  # Allow the exploit to cleanup after itself, that messy bugger.
  semaphore.synchronize { exploit.cleanup }
end

#job_run_proc(ctx) ⇒ Object (protected)

Job run proc, sets up the exploit and kicks it off.


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
# File 'lib/msf/core/exploit_driver.rb', line 202

def job_run_proc(ctx)
  begin
    exploit, payload = ctx
    # Default session wait time..
    delay = payload.wfs_delay + exploit.wfs_delay
    delay = nil if exploit.passive?

    # Set the exploit up the bomb
    exploit.setup

    exploit.framework.events.on_module_run(exploit)

    # Launch the exploit
    exploit.exploit

  rescue ::Exception => e
    if [::RuntimeError, ::Interrupt].include?(e.class)
      # Wait for session, but don't wait long.
      delay = 0.01
    end

    fail_reason = exploit.handle_exception(e)
  end

  # Start bind handlers after exploit completion
  payload.start_handler if exploit.handler_bind?

  # Wait the payload to acquire a session if this isn't a passive-style
  # exploit.
  return if not delay

  if (force_wait_for_session == true) or
    (exploit.passive? == false and exploit.handler_enabled?)
    begin
      self.session = payload.wait_for_session(delay)
    rescue ::Interrupt
      # Don't let interrupt pass upward
    end
  end

  return self.session if self.session

  if exploit.fail_reason == Msf::Exploit::Failure::None
    exploit.fail_reason = Msf::Exploit::Failure::PayloadFailed
    exploit.fail_detail = "No session created"
    exploit.report_failure
  end

  if fail_reason && fail_reason == Msf::Exploit::Failure::UserInterrupt
    raise ::Interrupt
  end
end

#runObject

Kicks off an exploitation attempt and performs the following four major operations:

- Generates the payload
- Initializes & monitors the handler
- Launches the exploit
- Cleans up the handler

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/msf/core/exploit_driver.rb', line 116

def run
  # First thing's first -- validate the state.  Make sure all requirement
  # parameters are set, including those that are derived from the
  # datastore.
  validate()

  # After validation has occurred, it's time to set some values on the
  # exploit instance and begin preparing the payload
  exploit.datastore['TARGET'] = target_idx

  # Default the session to nil
  self.session = nil

  # Explicitly clear the module's job_id in case it was set in a previous
  # run
  exploit.job_id = nil

  # If we are being instructed to run as a job then let's create that job
  # like a good person.
  if (use_job or exploit.passive?)
    # Since references to the exploit and payload will hang around for
    # awhile in the job, make sure we copy them so further changes to
    # the datastore don't alter settings in existing jobs
    e = exploit.replicant
    p = payload.replicant

    # Assign the correct exploit instance to the payload
    p.assoc_exploit = e

    # Generate the encoded version of the supplied payload for the
    # newly copied exploit module instance
    e.generate_payload(p)
    ctx = [ e, p ]

    e.job_id = e.framework.jobs.start_bg_job(
      "Exploit: #{e.refname}",
      ctx,
      Proc.new { |ctx_| job_run_proc(ctx_) },
      Proc.new { |ctx_| job_cleanup_proc(ctx_) }
    )
    self.job_id = e.job_id
  else
    # Generate the encoded version of the supplied payload on the
    # exploit module instance
    exploit.generate_payload(payload)

    # No need to copy since we aren't creating a job.  We wait until
    # they're finished running to do anything else with them, so
    # nothing should be able to modify their datastore or other
    # settings until after they're done.
    ctx = [ exploit, payload ]

    begin
      job_run_proc(ctx)
      # For multi exploit targets.
      # Keep the payload handler until last target or interrupt
      job_cleanup_proc(ctx) unless keep_handler
    rescue ::Interrupt
      job_cleanup_proc(ctx)
      raise $!
    end
  end

  return session
end

#target_idxObject

This method returns the currently selected target index.


47
48
49
# File 'lib/msf/core/exploit_driver.rb', line 47

def target_idx
  @target_idx
end

#target_idx=(target_idx) ⇒ Object

Specification of the exploit target index.


32
33
34
35
36
37
38
39
40
41
42
# File 'lib/msf/core/exploit_driver.rb', line 32

def target_idx=(target_idx)
  if (target_idx)
    # Make sure the target index is valid
    if (target_idx >= exploit.targets.length)
      raise Rex::ArgumentError, "Invalid target index.", caller
    end
  end

   # Set the active target
  @target_idx = target_idx
end

#validateObject

Makes sure everything's in tip-top condition prior to launching the exploit. For things that aren't good to go, an exception is thrown.


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/msf/core/exploit_driver.rb', line 72

def validate
  # First, validate that a target has been selected
  if (target_idx == nil)
    raise MissingTargetError,
      "A payload cannot be selected until a target is specified.",
      caller
  end

  # Next, validate that a payload has been selected
  if (payload == nil)
    raise MissingPayloadError,
      "A payload has not been selected.", caller
  end

  # Make sure the payload is compatible after all
  if (compatible_payload?(payload) == false)
    raise IncompatiblePayloadError.new(payload.refname),
      "#{payload.refname} is not a compatible payload.", caller
  end

  # Associate the payload instance with the exploit
  payload.assoc_exploit = exploit

  # Finally, validate options on the exploit module to ensure that things
  # are ready to operate as they should.
  exploit.options.validate(exploit.datastore)

  # Validate the payload's options.  The payload's datastore is
  # most likely shared against the exploit's datastore, but in case it
  # isn't.
  payload.options.validate(payload.datastore)

  return true
end