Class: Msf::Evasion

Inherits:
Module show all
Includes:
Auxiliary::Report
Defined in:
lib/msf/core/evasion.rb

Defined Under Namespace

Classes: Complete, Failed

Constant Summary

Constants inherited from Module

Module::REPLICANT_EXTENSION_DS_KEY

Constants included from Module::ModuleInfo

Module::ModuleInfo::UpdateableOptions

Instance Attribute Summary collapse

Attributes inherited from Module

#error, #job_id, #license, #platform, #privileged, #references, #user_data

Attributes included from Framework::Offspring

#framework

Attributes included from Module::UUID

#uuid

Attributes included from Rex::Ui::Subscriber::Input

#user_input

Attributes included from Rex::Ui::Subscriber::Output

#user_output

Attributes included from Module::Privileged

#priveli, #privileged

Attributes included from Module::Options

#options

Attributes included from Module::ModuleStore

#module_store

Attributes included from Module::ModuleInfo

#module_info

Attributes included from Module::FullName

#aliased_as

Attributes included from Module::DataStore

#datastore

Attributes included from Module::Author

#author

Attributes included from Module::Arch

#arch

Attributes included from Module::Alert

#alerts, #you_have_been_warned

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Auxiliary::Report

#active_db?, #create_cracked_credential, #create_credential, #create_credential_and_login, #create_credential_login, #db, #db_warning_given?, #get_client, #get_host, #inside_workspace_boundary?, #invalidate_login, #mytask, #myworkspace, #myworkspace_id, #report_auth_info, #report_client, #report_exploit, #report_host, #report_loot, #report_note, #report_service, #report_vuln, #report_web_form, #report_web_page, #report_web_site, #report_web_vuln, #store_cred, #store_local, #store_loot

Methods included from Metasploit::Framework::Require

optionally, optionally_active_record_railtie, optionally_include_metasploit_credential_creation, #optionally_include_metasploit_credential_creation, optionally_require_metasploit_db_gem_engines

Methods inherited from Module

#black_listed_auth_filenames, cached?, #debugging?, #default_cred?, #file_path, #framework, #has_check?, #orig_cls, #owner, #perform_extensions, #platform?, #platform_to_s, #post_auth?, #register_extensions, #register_parent, #replicant, #required_cred_options, #set_defaults, #workspace

Methods included from Module::Reliability

#reliability, #reliability_to_s

Methods included from Module::Stability

#stability, #stability_to_s

Methods included from Module::SideEffects

#side_effects, #side_effects_to_s

Methods included from Module::UUID

#generate_uuid

Methods included from Module::UI

#init_ui

Methods included from Module::UI::Message

#print_error, #print_good, #print_prefix, #print_status, #print_warning

Methods included from Module::UI::Message::Verbose

#vprint_error, #vprint_good, #vprint_status, #vprint_warning

Methods included from Module::UI::Line

#print_line, #print_line_prefix

Methods included from Module::UI::Line::Verbose

#vprint_line

Methods included from Rex::Ui::Subscriber

#copy_ui, #init_ui, #reset_ui

Methods included from Rex::Ui::Subscriber::Input

#gets

Methods included from Rex::Ui::Subscriber::Output

#flush, #print, #print_blank_line, #print_error, #print_good, #print_line, #print_status, #print_warning

Methods included from Module::Type

#auxiliary?, #encoder?, #evasion?, #exploit?, #nop?, #payload?, #post?

Methods included from Module::Ranking

#rank, #rank_to_h, #rank_to_s

Methods included from Module::Privileged

#privileged?

Methods included from Module::Options

#deregister_options, #register_advanced_options, #register_evasion_options, #register_options, #validate

Methods included from Module::Network

#comm, #support_ipv6?, #target_host, #target_port

Methods included from Module::ModuleStore

#[], #[]=

Methods included from Module::ModuleInfo

#alias, #description, #disclosure_date, #info_fixups, #merge_check_key, #merge_info, #merge_info_advanced_options, #merge_info_alias, #merge_info_description, #merge_info_evasion_options, #merge_info_name, #merge_info_options, #merge_info_string, #merge_info_version, #name, #notes, #update_info

Methods included from Module::FullName

#aliases, #fullname, #promptname, #realname, #refname, #shortname

Methods included from Module::DataStore

#import_defaults, #import_target_defaults, #share_datastore

Methods included from Module::Compatibility

#compat, #compatible?, #init_compat

Methods included from Module::Author

#author_to_s, #each_author

Methods included from Module::Auth

#store_valid_credential

Methods included from Module::Arch

#arch?, #arch_to_s, #each_arch

Methods included from Module::Alert

#add_alert, #add_error, #add_warning, #alert_user, #errors, #get_alerts, included, #is_usable?, #warnings

Constructor Details

#initialize(info = {}) ⇒ Evasion

Returns a new instance of Evasion.


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/msf/core/evasion.rb', line 11

def initialize(info={})
  if (info['Payload'] and info['Payload']['Compat'])
    info['Compat'] = Hash.new if (info['Compat'] == nil)
    info['Compat']['Payload'] = Hash.new if (info['Compat']['Payload'] == nil)
    info['Compat']['Payload'].update(info['Payload']['Compat'])
  end

  super(info)

  self.payload_info = info['Payload'] || {}
  self.targets = Rex::Transformer.transform(info['Targets'], Array, [ Target ], 'Targets')

  if info.key? 'DefaultTarget'
    self.default_target = info['DefaultTarget']
  else
    self.default_target = 0
    # Add an auto-target to the evasion if it doesn't have one
    if info['Targets'] && info['Targets'].count > 1 && !has_auto_target?(info['Targets'])
      # Finally, only add the target if there is a remote host option
      if self.respond_to?(:rhost) && self.respond_to?(:auto_targeted_index)
        auto = ["Automatic", {'AutoGenerated' => true}.merge(info['Targets'][self.default_target][1])]
        info['Targets'].unshift(auto)
      end
    end
  end

  if (info['Payload'] and info['Payload']['ActiveTimeout'])
    self.active_timeout = info['Payload']['ActiveTimeout'].to_i
  end

  register_options([
    OptString.new(
      'FILENAME',
        [
          true,
          'Filename for the evasive file (default: random)',
          "#{Rex::Text.rand_text_alpha(3..10)}.exe"
        ])
  ], self.class)
end

Instance Attribute Details

#default_targetObject

Returns the value of attribute default_target.


322
323
324
# File 'lib/msf/core/evasion.rb', line 322

def default_target
  @default_target
end

#payloadObject

Returns the value of attribute payload.


332
333
334
# File 'lib/msf/core/evasion.rb', line 332

def payload
  @payload
end

#payload_infoObject

Returns the value of attribute payload_info.


326
327
328
# File 'lib/msf/core/evasion.rb', line 326

def payload_info
  @payload_info
end

#payload_instanceObject

Returns the value of attribute payload_instance.


330
331
332
# File 'lib/msf/core/evasion.rb', line 330

def payload_instance
  @payload_instance
end

#targetsObject

Returns the value of attribute targets.


324
325
326
# File 'lib/msf/core/evasion.rb', line 324

def targets
  @targets
end

Class Method Details

.typeObject


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

def self.type
  Msf::MODULE_EVASION
end

Instance Method Details

#aggressive?Boolean

Returns:

  • (Boolean)

164
165
166
# File 'lib/msf/core/evasion.rb', line 164

def aggressive?
  false
end

#cleanupObject


145
146
# File 'lib/msf/core/evasion.rb', line 145

def cleanup
end

#compatible_payloads(excluded_platforms: [], excluded_archs: []) ⇒ Object

Returns a list of compatible payloads based on platform, architecture, and size requirements.


120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/msf/core/evasion.rb', line 120

def compatible_payloads(excluded_platforms: [], excluded_archs: [])
  payloads = []

  c_platform, c_arch = normalize_platform_arch

  # The "All" platform name represents generic payloads
  results = Msf::Modules::Metadata::Cache.instance.find(
    'type'     => [['payload'], []],
    'platform' => [[*c_platform.names, 'All'], excluded_platforms],
    'arch'     => [c_arch, excluded_archs]
  )

  results.each do |res|
    if is_payload_compatible?(res.ref_name)
      payloads << [res.ref_name, framework.payloads[res.ref_name]]
    end
  end

  payloads
end

#define_context_encoding_reqs(reqs) ⇒ Object


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

def define_context_encoding_reqs(reqs)
  return unless datastore['EnableContextEncoding']

  # At present, we don't support any automatic methods of obtaining
  # context information.  In the future, we might support obtaining
  # temporal information remotely.

  # Pass along the information specified in our evasion datastore as
  # encoder options
  reqs['EncoderOptions'] = {} if reqs['EncoderOptions'].nil?
  reqs['EncoderOptions']['EnableContextEncoding']  = datastore['EnableContextEncoding']
  reqs['EncoderOptions']['ContextInformationFile'] = datastore['ContextInformationFile']
end

#encode_begin(real_payload, reqs) ⇒ Object


270
271
# File 'lib/msf/core/evasion.rb', line 270

def encode_begin(real_payload, reqs)
end

#encode_end(real_payload, reqs, encoded) ⇒ Object


273
274
275
# File 'lib/msf/core/evasion.rb', line 273

def encode_end(real_payload, reqs, encoded)
  encoded
end

#evasion_commandsObject


152
153
154
# File 'lib/msf/core/evasion.rb', line 152

def evasion_commands
  {}
end

#fail_with(reason, msg = nil) ⇒ Object


148
149
150
# File 'lib/msf/core/evasion.rb', line 148

def fail_with(reason, msg=nil)
  raise Msf::Evasion::Failed, "#{reason}: #{msg}"
end

#file_create(data) ⇒ Object


68
69
70
71
72
73
# File 'lib/msf/core/evasion.rb', line 68

def file_create(data)
  fname = file_format_filename
  ltype = "evasion.fileformat.#{self.shortname}"
  full_path = store_local(ltype, nil, data, fname)
  print_good "#{fname} stored at #{full_path}"
end

#file_format_filenameObject


64
65
66
# File 'lib/msf/core/evasion.rb', line 64

def file_format_filename
  datastore['FILENAME']
end

#generate_payload(pinst = nil) ⇒ Object

Generates the encoded version of the supplied payload using the payload requirements specific to this evasion module. The encoded instance is returned to the caller. This method is exposed in the manner that it is such that passive evasions and re-generate an encoded payload on the fly rather than having to use the pre-generated one.


173
174
175
176
177
178
179
180
181
# File 'lib/msf/core/evasion.rb', line 173

def generate_payload(pinst = nil)
  # Set the encoded payload to the result of the encoding process
  self.payload = generate_single_payload(pinst)

  # Save the payload instance
  self.payload_instance = (pinst) ? pinst : self.payload_instance

  return self.payload
end

#generate_single_payload(pinst = nil, platform = nil, arch = nil, explicit_target = nil) ⇒ Object


183
184
185
186
187
188
189
190
191
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
# File 'lib/msf/core/evasion.rb', line 183

def generate_single_payload(pinst = nil, platform = nil, arch = nil, explicit_target = nil)
  explicit_target ||= target

  # If a payload instance was supplied, use it, otherwise
  # use the active payload instance
  real_payload = (pinst) ? pinst : self.payload_instance

  if (real_payload == nil)
    raise MissingPayloadError, "No payload has been selected.",
      caller
  end

  # If this is a generic payload, then we should specify the platform
  # and architecture so that it knows how to pass things on.
  if real_payload.kind_of?(Msf::Payload::Generic)
    # Convert the architecture specified into an array.
    if arch and arch.kind_of?(String)
      arch = [ arch ]
    end

    # Define the explicit platform and architecture information only if
    # it's been specified.
    if platform
      real_payload.explicit_platform = Msf::Module::PlatformList.transform(platform)
    end

    if arch
      real_payload.explicit_arch = arch
    end

    # Force it to reset so that it will find updated information.
    real_payload.reset
  end

  # Duplicate the evasion payload requirements
  reqs = self.payload_info.dup

  # Pass save register requirements to the NOP generator
  reqs['Space']           = payload_info['Space'] ? payload_info['Space'].to_i : nil
  reqs['SaveRegisters']   = module_info['SaveRegisters']
  reqs['Prepend']         = payload_info['Prepend']
  reqs['PrependEncoder']  = payload_info['PrependEncoder']
  reqs['BadChars']        = payload_info['BadChars']
  reqs['Append']          = payload_info['Append']
  reqs['AppendEncoder']   = payload_info['AppendEncoder']
  reqs['DisableNops']     = payload_info['DisableNops']
  reqs['MaxNops']         = payload_info['MaxNops']
  reqs['MinNops']         = payload_info['MinNops']
  reqs['Encoder']         = datastore['ENCODER'] || payload_info['Encoder']
  reqs['Nop']             = datastore['NOP'] || payload_info['Nop']
  reqs['EncoderType']     = payload_info['EncoderType']
  reqs['EncoderOptions']  = payload_info['EncoderOptions']
  reqs['ExtendedOptions'] = payload_info['ExtendedOptions']
  reqs['ForceEncode']     = payload_info['ForceEncode']
  reqs['Evasion']         = self

  # Pass along the encoder don't fall through flag
  reqs['EncoderDontFallThrough'] = datastore['EncoderDontFallThrough']

  # Incorporate any context encoding requirements that are needed
  define_context_encoding_reqs(reqs)

  # Call the encode begin routine.
  encode_begin(real_payload, reqs)

  # Generate the encoded payload.
  encoded = EncodedPayload.create(real_payload, reqs)

  # Call the encode end routine which is expected to return the actual
  # encoded payload instance.
  return encode_end(real_payload, reqs, encoded)
end

#has_auto_target?(targets = []) ⇒ Boolean

Returns:

  • (Boolean)

314
315
316
317
318
319
320
# File 'lib/msf/core/evasion.rb', line 314

def has_auto_target?(targets=[])
  target_names = targets.collect { |target| target.first}
  target_names.each do |target|
    return true if target =~ /Automatic/
  end
  return false
end

#is_payload_compatible?(name) ⇒ Boolean

Returns whether the requested payload is compatible with the module

Parameters:

  • name (String)

    The payload name

  • Payload (TrueClass)

    is compatible.

  • Payload (FlaseClass)

    is not compatible.

Returns:

  • (Boolean)

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/msf/core/evasion.rb', line 102

def is_payload_compatible?(name)
  p = framework.payloads[name]

  pi = p.new

  # Are we compatible in terms of conventions and connections and
  # what not?
  return false if !compatible?(pi)

  # If the payload is privileged but the evasion does not give
  # privileged access, then fail it.
  return false if !self.privileged && pi.privileged

  return true
end

#normalize_platform_archObject


90
91
92
93
94
95
# File 'lib/msf/core/evasion.rb', line 90

def normalize_platform_arch
  c_platform = (target && target.platform) ? target.platform : platform
  c_arch     = (target && target.arch)     ? target.arch     : (arch == []) ? nil : arch
  c_arch   ||= [ ARCH_X86 ]
  return c_platform, c_arch
end

#passive?Boolean

Returns:

  • (Boolean)

160
161
162
# File 'lib/msf/core/evasion.rb', line 160

def passive?
  true
end

#runObject

Raises:

  • (NotImplementedError)

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

def run
  raise NotImplementedError
end

#setupObject


60
61
62
# File 'lib/msf/core/evasion.rb', line 60

def setup
  alert_user
end

#stanceObject


156
157
158
# File 'lib/msf/core/evasion.rb', line 156

def stance
  'passive'
end

#targetObject


277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/msf/core/evasion.rb', line 277

def target
  if self.respond_to?(:auto_targeted_index)
    if auto_target?
      auto_idx = auto_targeted_index
      if auto_idx.present?
        datastore['TARGET'] = auto_idx
      else
        # If our inserted Automatic Target was selected but we failed to
        # find a suitable target, we just grab the original first target.
        datastore['TARGET'] = 1
      end
    end
  end

  target_idx = target_index
  return (target_idx) ? targets[target_idx.to_i] : nil
end

#target_archObject

Returns the target's architecture, or the one assigned to the module itself.


86
87
88
# File 'lib/msf/core/evasion.rb', line 86

def target_arch
  (target and target.arch) ? target.arch : (arch == []) ? nil : arch
end

#target_indexObject


295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/msf/core/evasion.rb', line 295

def target_index
  target_idx =
    begin
      Integer(datastore['TARGET'])
    rescue TypeError, ArgumentError
      datastore['TARGET']
    end

  default_idx = default_target || 0
  # Use the default target if one was not supplied.
  if (target_idx == nil and default_idx and default_idx >= 0)
    target_idx = default_idx
  elsif target_idx.is_a?(String)
    target_idx = targets.index { |target| target.name == target_idx }
  end

  return (target_idx) ? target_idx.to_i : nil
end

#target_platformObject

Returns the target's platform, or the one assigned to the module itself.


78
79
80
# File 'lib/msf/core/evasion.rb', line 78

def target_platform
  (target and target.platform) ? target.platform : platform
end

#typeObject


56
57
58
# File 'lib/msf/core/evasion.rb', line 56

def type
  Msf::MODULE_EVASION
end