Module: Msf::ModuleManager::Loading

Extended by:
ActiveSupport::Concern
Included in:
Msf::ModuleManager
Defined in:
lib/msf/core/module_manager/loading.rb

Overview

Project

Deals with loading modules for the Msf::ModuleManager

Constant Summary collapse

LOADER_CLASSES =

Classes that can be used to load modules.

[
    Msf::Modules::Loader::Directory,
    Msf::Modules::Loader::Executable # TODO: XXX: When this is the first loader we can load normal exploits, but not payloads
]
DIRECTORY_BY_TYPE =

Maps module type directory to its module type.

Msf::Modules::Loader::Base::DIRECTORY_BY_TYPE
TYPE_BY_DIRECTORY =
Msf::Modules::Loader::Base::TYPE_BY_DIRECTORY

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#module_load_error_by_pathObject

Returns the value of attribute module_load_error_by_path.



90
91
92
# File 'lib/msf/core/module_manager/loading.rb', line 90

def module_load_error_by_path
  @module_load_error_by_path
end

#module_load_warningsObject

Returns the value of attribute module_load_warnings.



90
91
92
# File 'lib/msf/core/module_manager/loading.rb', line 90

def module_load_warnings
  @module_load_warnings
end

Instance Method Details

#file_changed?(path) ⇒ Boolean

Returns:

  • (Boolean)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/msf/core/module_manager/loading.rb', line 28

def file_changed?(path)
  changed = false

  module_info = self.module_info_by_path[path]

  # if uncached then it counts as changed
  # Payloads can't be cached due to stage/stager matching
  if module_info.nil? or module_info[:type] == Msf::MODULE_PAYLOAD
    changed = true
  else
    begin
      current_modification_time = ::File.mtime(path).to_i
    rescue ::Errno::ENOENT
      # if the file does not exist now, that's a change
      changed = true
    else
      cached_modification_time = module_info[:modification_time].to_i

      # if the file's modification time's different from the cache, then it's changed
      if current_modification_time != cached_modification_time
        changed = true
      end
    end
  end

  changed
end

#get_module_error(module_reference_name, type) ⇒ Object (protected)

Get a specific modules errors from the supplied module_reference_name and type

These @params will the be used to loop through ‘module_info_by_path` [Hash] to check for any matching modules paths. This path becomes the key and returns the associated error.

Parameters:

  • module_reference_name (String)

    e.g. 'scanner/msmail/host_id'

  • type (String)

    this will be the type of module e.g. 'auxiliary'



186
187
188
189
190
191
192
193
# File 'lib/msf/core/module_manager/loading.rb', line 186

def get_module_error(module_reference_name, type)
  module_info_by_path.each do |mod_path, module_value|
    if module_value[:reference_name] == module_reference_name && module_value[:type] == type
      return module_load_error_by_path[mod_path]
    end
  end
  nil
end

#load_error_by_name(name) ⇒ error

Return errors associated with the supplied reference name.

Parameters:

  • name (String)

    e.g. 'auxiliary/scanner/msmail/host_id' It may optionally be prefixed with a "<type>/", in which case we will pass it to 'get_module_error(module_reference_name, type)`. Otherwise, we step through all sets until we find one that matches.

Returns:

  • (error)

    which will return either an error or nil.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/msf/core/module_manager/loading.rb', line 64

def load_error_by_name(name)
  return load_error_by_name(self.aliases[name]) if self.aliases[name]
  names = name.split("/")
  potential_type_or_directory = names.first

  if DIRECTORY_BY_TYPE.has_key? potential_type_or_directory
    type = potential_type_or_directory
    # if first name is a type directory
  else
    type = TYPE_BY_DIRECTORY[potential_type_or_directory]
  end

  error = nil
  if type
    module_reference_name = names[1 .. -1].join("/")
    error = get_module_error(module_reference_name, type)
  else
    module_set_by_type.each do |type, _set|
      module_reference_name = "#{type}/#{name}"
      error = load_error_by_name(module_reference_name)
      break if error
    end
  end
  error
end

#load_modules(path, options = {}) ⇒ Hash{String => Integer} (protected)

Load all of the modules from the supplied directory or archive

Parameters:

  • path (String)

    Path to a directory

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :force (Boolean)

    Whether the force loading the modules even if they are unchanged and already loaded.

  • :modules (Array)

    An array of regex patterns to search for specific modules

Returns:

  • (Hash{String => Integer})

    Maps module type to number of modules loaded



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/msf/core/module_manager/loading.rb', line 163

def load_modules(path, options={})
  options.assert_valid_keys(:force, :whitelist, :recalculate)

  count_by_type = {}

  loaders.each do |loader|
    if loader.loadable?(path)
      count_by_type.merge!(loader.load_modules(path, options)) do |key, prev, now|
        prev + now
      end
    end
  end

  count_by_type
end

#loadersObject (protected)

Return list of LOADER_CLASSES instances that load modules into this module manager



145
146
147
148
149
150
151
152
153
# File 'lib/msf/core/module_manager/loading.rb', line 145

def loaders
  unless instance_variable_defined? :@loaders
    @loaders = LOADER_CLASSES.collect { |klass|
      klass.new(self)
    }
  end

  @loaders
end

#on_module_load(class_or_module, type, reference_name, info = {}) ⇒ void

This method returns an undefined value.

Called when a module is initially loaded such that it can be categorized accordingly.

Parameters:

  • class_or_module (Class<Msf::Module>, ::Module)

    either a module Class or a payload Module.

  • type (String)

    The module type.

  • reference_name

    The module reference name.

  • info (Hash{String => Array}) (defaults to: {})

    additional information about the module

Options Hash (info):

  • 'files' (Array<String>)

    List of paths to the ruby source files where class_or_module is defined.

  • 'paths' (Array<String>)

    List of module reference names.

  • 'type' (String)

    The module type, should match positional type argument.



106
107
108
109
110
111
112
113
114
115
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
# File 'lib/msf/core/module_manager/loading.rb', line 106

def on_module_load(class_or_module, type, reference_name, info={})
  module_set = module_set_by_type[type]
  module_set.add_module(class_or_module, reference_name, info)

  path = info['files'].first
  cache_in_memory(
      class_or_module,
      :path => path,
      :reference_name => reference_name,
      :type => type
  )

  # Automatically subscribe a wrapper around this module to the necessary
  # event providers based on whatever events it wishes to receive.
  auto_subscribe_module(class_or_module)

  # Notify the framework that a module was loaded
  framework.events.on_module_load(reference_name, class_or_module)

  # Clear and add aliases, if any (payloads cannot)

  if class_or_module.respond_to?(:realname) && aliased_as = self.inv_aliases[class_or_module.realname]
    aliased_as.each do |a|
      self.aliases.delete a
    end
    self.inv_aliases.delete class_or_module.realname
  end

  if class_or_module.respond_to? :aliases
    class_or_module.aliases.each do |a|
      self.aliases[a] = class_or_module.realname
    end
    self.inv_aliases[class_or_module.realname] = class_or_module.aliases unless class_or_module.aliases.empty?
  end
end