Module: Metasploit::Model::Module::Ancestor

Extended by:
ActiveModel::Naming, ActiveSupport::Autoload, ActiveSupport::Concern
Includes:
Translation
Defined in:
lib/metasploit/model/module/ancestor.rb

Overview

Code shared between Mdm::Module::Ancestor and Metasploit::Framework::Module::Ancestor.

Defined Under Namespace

Modules: ClassMethods, Spec

Constant Summary collapse

DIRECTORY_BY_MODULE_TYPE =

The directory for a given #module_type is a not always the pluralization of #module_type, so this maps the

module_type to the type directory that is used to generate the #real_path from the #module_type and

reference_name.

{
    Metasploit::Model::Module::Type::AUX => Metasploit::Model::Module::Type::AUX,
    Metasploit::Model::Module::Type::ENCODER => Metasploit::Model::Module::Type::ENCODER.pluralize,
    Metasploit::Model::Module::Type::EXPLOIT => Metasploit::Model::Module::Type::EXPLOIT.pluralize,
    Metasploit::Model::Module::Type::NOP => Metasploit::Model::Module::Type::NOP.pluralize,
    Metasploit::Model::Module::Type::PAYLOAD => Metasploit::Model::Module::Type::PAYLOAD.pluralize,
    Metasploit::Model::Module::Type::POST => Metasploit::Model::Module::Type::POST
}
EXTENSION =

File extension used for metasploit modules.

'.rb'
HANDLED_TYPES =

The payload types that require #handler_type.

[
    'single',
    'stager'
]
MODULE_TYPE_BY_DIRECTORY =

Maps directory to #module_type for converting a #real_path into a #module_type and #reference_name

DIRECTORY_BY_MODULE_TYPE.invert
PAYLOAD_TYPES =

Valid values for #payload_type if #payload? is true.

[
    'single',
    'stage',
    'stager'
]
REFERENCE_NAME_REGEXP =

Regexp to keep '\' out of reference names

/\A[\-0-9A-Z_a-z]+(?:\/[\-0-9A-Z_a-z]+)*\Z/
REFERENCE_NAME_SEPARATOR =

Separator used to join names in #reference_name. It is always '/', even on Windows, where '\' is a valid file separator.

'/'
SHA1_HEX_DIGEST_REGEXP =

Regular expression matching a full SHA-1 hex digest.

/\A[0-9a-z]{40}\Z/

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#full_nameString

The full name of the module. The full name is "#{module_type}/#{reference_name}".

Returns:

  • (String)


# File 'lib/metasploit/model/module/ancestor.rb', line 188

#handler_typeString?

The handler type (in the case of singles) or (in the case of stagers) the handler type alias. Handler type is appended to the end of the single's or stage's #reference_name to get the Class#reference_name.

Returns:



# File 'lib/metasploit/model/module/ancestor.rb', line 193

#module_typeString

The type of the module. This would be called #type, but #type is reserved for ActiveRecord's single table inheritance.

Returns:



# File 'lib/metasploit/model/module/ancestor.rb', line 201

#parent_pathMetasploit::Model::Module::Path

Path under which this ancestor exists on-disk.



# File 'lib/metasploit/model/module/ancestor.rb', line 179

#payload_type'single', ...

For payload modules, the type of payload, either 'single', 'stage', or 'stager'.

Returns:

  • ('single', 'stage', 'stager')

    if Metasploit::Model::Module::Ancestor#payload? is true.

  • (nil)

    if Metasploit::Model::Module::Ancestor#payload? is false

See Also:



# File 'lib/metasploit/model/module/ancestor.rb', line 207

#real_pathString

The real (absolute) path to module file on-disk.

Returns:

  • (String)


# File 'lib/metasploit/model/module/ancestor.rb', line 214

#real_path_modified_atDateTime

The modification time of the module file on-disk.

Returns:

  • (DateTime)


# File 'lib/metasploit/model/module/ancestor.rb', line 219

#real_path_sha1_hex_digestString

The SHA1 hexadecimal digest of contents of the file at #real_path. Stored as a string because postgres does not have support for a 160 bit numerical type and the hexdigest format is more recognizable when using SQL directly.

Returns:

  • (String)

See Also:

  • Digest::SHA1#hexdigest


# File 'lib/metasploit/model/module/ancestor.rb', line 224

#reference_nameString

The reference name of the module. The name of the module under its type.

Returns:

  • (String)


# File 'lib/metasploit/model/module/ancestor.rb', line 231

Instance Method Details

#contentsString?

The contents of #real_path.

Returns:



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/metasploit/model/module/ancestor.rb', line 245

def contents
  contents = nil

  if real_path
    # rescue around both File calls since file could be deleted before size or after size and before read
    begin
      size = File.size(real_path)
      # Specify full size of file for faster read on Windows (less chance of context switching mid-read).
      # Open in binary mode in Windows to handle non-text content embedded in file.
      contents = File.read(real_path, size, 0, mode: 'rb')
    rescue Errno::ENOENT
      contents = nil
    end
  end

  contents
end

#derived_module_typeString?

Returns:



268
269
270
271
272
273
# File 'lib/metasploit/model/module/ancestor.rb', line 268

def derived_module_type
  module_type_directory = relative_file_names.first
  derived = MODULE_TYPE_BY_DIRECTORY[module_type_directory]

  derived
end

#derived_payload_typeString?

Returns:



279
280
281
282
283
284
285
286
287
288
# File 'lib/metasploit/model/module/ancestor.rb', line 279

def derived_payload_type
  derived = nil
  directory = payload_type_directory

  if directory
    derived = directory.singularize
  end

  derived
end

#derived_real_pathString?

Derives #real_path by combining parent_path.real_path, #module_type_directory, and #reference_path in the same way the module loader does in metasploit-framework.

Returns:



299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/metasploit/model/module/ancestor.rb', line 299

def derived_real_path
  derived_real_path = nil

  if parent_path and parent_path.real_path and module_type_directory and reference_path
    derived_real_path = File.join(
        parent_path.real_path,
        module_type_directory,
        reference_path
    )
  end

  derived_real_path
end

#derived_real_path_modified_atTime?

Derives #real_path_modified_at by getting the modification time of the file on-disk.

Returns:

  • (Time)

    modification time of #real_path if #real_path exists on disk and modification time can be queried by user.

  • (nil)

    if #real_path does not exist or user cannot query the file's modification time.



318
319
320
321
322
323
324
325
326
327
328
# File 'lib/metasploit/model/module/ancestor.rb', line 318

def derived_real_path_modified_at
  real_path_string = real_path.to_s

  begin
    mtime = File.mtime(real_path_string)
  rescue Errno::ENOENT
    nil
  else
    mtime.utc
  end
end

#derived_real_path_sha1_hex_digestString?

Derives #real_path_sha1_hex_digest by running the contents of #real_path through Digest::SHA1.hexdigest.

Returns:

  • (String)

    40 character SHA1 hex digest if #real_path can be read.

  • (nil)

    if #real_path cannot be read.



334
335
336
337
338
339
340
341
342
343
344
# File 'lib/metasploit/model/module/ancestor.rb', line 334

def derived_real_path_sha1_hex_digest
  begin
    sha1 = Digest::SHA1.file(real_path.to_s)
  rescue Errno::ENOENT
    hex_digest = nil
  else
    hex_digest = sha1.hexdigest
  end

  hex_digest
end

#derived_reference_nameString?

Returns:



350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/metasploit/model/module/ancestor.rb', line 350

def derived_reference_name
  derived = nil
  reference_name_file_names = relative_file_names.drop(1)
  reference_name_base_name = reference_name_file_names[-1]

  if reference_name_base_name
    if File.extname(reference_name_base_name) == EXTENSION
      reference_name_file_names[-1] = File.basename(reference_name_base_name, EXTENSION)
      derived = reference_name_file_names.join(REFERENCE_NAME_SEPARATOR)
    end
  end

  derived
end

#handled?Boolean

Returns whether #handler_type is required or must be nil.

Returns:

  • (Boolean)

See Also:



369
370
371
372
373
374
# File 'lib/metasploit/model/module/ancestor.rb', line 369

def handled?
  self.class.handled?(
      :module_type => module_type,
      :payload_type => payload_type
  )
end

#loading_context?true, false (private)

Whether this ancestor is being validated for loading.

Returns:

  • (true)

    if #validation_context is :loading

  • (false)

    otherwise



494
495
496
# File 'lib/metasploit/model/module/ancestor.rb', line 494

def loading_context?
  validation_context == :loading
end

#module_type_directoryString

The directory for #module_type under parent_path.real_path.

Returns:

  • (String)

See Also:



380
381
382
# File 'lib/metasploit/model/module/ancestor.rb', line 380

def module_type_directory
  Metasploit::Model::Module::Ancestor::DIRECTORY_BY_MODULE_TYPE[module_type]
end

#payload?true, false

Return whether this forms part of a payload (either a single, stage, or stager).

Returns:



388
389
390
391
392
393
394
# File 'lib/metasploit/model/module/ancestor.rb', line 388

def payload?
  if module_type == Metasploit::Model::Module::Type::PAYLOAD
    true
  else
    false
  end
end

#payload_nameString?

The name used to forming the Class#reference_name for payloads.

Returns:



402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
# File 'lib/metasploit/model/module/ancestor.rb', line 402

def payload_name
  payload_name = nil

  if module_type == Metasploit::Model::Module::Type::PAYLOAD
    case payload_type
      when 'single', 'stage'
        if reference_name && payload_type_directory
          escaped_payload_type_directory = Regexp.escape(payload_type_directory)
          payload_type_directory_regexp = /^#{escaped_payload_type_directory}\//
          payload_name = reference_name.gsub(payload_type_directory_regexp, '')
        end
      when 'stager'
        payload_name = handler_type
    end
  end

  payload_name
end

#payload_type_directoryString?

The directory for #payload_type under #module_type_directory in #real_path.

Returns:



426
427
428
429
430
431
432
433
434
435
# File 'lib/metasploit/model/module/ancestor.rb', line 426

def payload_type_directory
  directory = nil

  if payload? and reference_name
    head, _tail = reference_name.split(REFERENCE_NAME_SEPARATOR, 2)
    directory = head
  end

  directory
end

#reference_pathString?

The path relative to the #module_type_directory under the parent_path.real_path, including the file extension.

Returns:



478
479
480
481
482
483
484
485
486
# File 'lib/metasploit/model/module/ancestor.rb', line 478

def reference_path
  path = nil

  if reference_name
    path = "#{reference_name}#{EXTENSION}"
  end

  path
end

#relative_file_namesEnumerator<String>

File names on #relative_pathname.

Returns:

  • (Enumerator<String>)


440
441
442
443
444
445
446
447
448
449
# File 'lib/metasploit/model/module/ancestor.rb', line 440

def relative_file_names
  relative_pathname = self.relative_pathname

  if relative_pathname
    relative_pathname.each_filename
  else
    # empty enumerator
    Enumerator.new { }
  end
end

#relative_pathnamePathname

Returns:

  • (Pathname)


454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
# File 'lib/metasploit/model/module/ancestor.rb', line 454

def relative_pathname
  relative_pathname = nil
  real_pathname = self.real_pathname

  if real_pathname
    parent_path = self.parent_path

    if parent_path
      parent_path_real_pathname = parent_path.real_pathname

      if parent_path_real_pathname
        relative_pathname = real_pathname.relative_path_from parent_path_real_pathname
      end
    end
  end

  relative_pathname
end