Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/msf/core/module_set.rb
Views: 11778
# -*- coding: binary -*-1require 'pathname'23###4#5# A module set contains zero or more named module classes of an arbitrary6# type.7#8###9class Msf::ModuleSet < Hash10include Msf::Framework::Offspring1112# Wrapper that detects if a symbolic module is in use. If it is, it creates an instance to demand load the module13# and then returns the now-loaded class afterwards.14#15# @param [String] name the module reference name16# @return [Msf::Module] Class of the of the Msf::Module with the given reference name17def [](name)18module_class = super19if module_class.nil?20load_module_class(name)21end2223super24end2526# Create an instance of the supplied module by its reference name27#28# @param reference_name [String] The module reference name.29# @return [Msf::Module,nil] Instance of the named module or nil if it30# could not be created.31def create(reference_name, cache_type: Msf::ModuleManager::Cache::FILESYSTEM)32klass = load_module_class(reference_name, cache_type: cache_type)33instance = nil34# If the klass is valid for this reference_name, try to create it35unless klass.nil?36instance = klass.new37end3839# Notify any general subscribers of the creation event40if instance41self.framework.events.on_module_created(instance)42else43self.delete(reference_name)44end4546instance47end4849# Overrides the builtin 'each' operator to avoid the following exception on Ruby 1.9.2+50# "can't add a new key into hash during iteration"51#52# @yield [module_reference_name, module]53# @yieldparam [String] module_reference_name the reference_name of the module.54# @yieldparam [Class] module The module class: a subclass of Msf::Module.55# @return [void]56def each(&block)57list = []58module_metadata.keys.sort.each do |sidx|59list << [sidx, self[sidx]]60end61list.each(&block)62end6364# Enumerates each module class in the set.65#66# @param opts (see #each_module_list)67# @yield (see #each_module_list)68# @yieldparam (see #each_module_list)69# @return (see #each_module_list)70def each_module(opts = {}, &block)71self.mod_sorted = module_metadata.sort7273each_module_list(mod_sorted, opts, &block)74end7576# Custom each_module filtering if an advanced set supports doing extended filtering.77#78# @param opts (see #each_module_list)79# @param [String] name the module reference name80# @param [Array<String, Class>] entry pair of the module reference name and the module class.81# @return [false] if the module should not be filtered; it should be yielded by {#each_module_list}.82# @return [true] if the module should be filtered; it should not be yielded by {#each_module_list}.83def each_module_filter(opts, name, entry)84return false85end8687# Enumerates each module class in the set based on their relative ranking to one another. Modules that are ranked88# higher are shown first.89#90# @param opts (see #each_module_list)91# @yield (see #each_module_list)92# @yieldparam (see #each_module_list)93# @return (see #each_module_list)94def each_module_ranked(opts = {}, &block)95each_module_list(rank_modules, opts, &block)96end9798# Forces all modules in this set to be loaded.99#100# @return [void]101def force_load_set102each_module { |name, mod| }103end104105# Initializes a module set that will contain modules of a specific type and expose the mechanism necessary to create106# instances of them.107#108# @param [String] type The type of modules cached by this {Msf::ModuleSet}.109def initialize(type = nil)110#111# Defaults112#113self.ambiguous_module_reference_name_set = Set.new114# Hashes that convey the supported architectures and platforms for a115# given module116self.architectures_by_module = {}117self.platforms_by_module = {}118self.mod_sorted = nil119self.mod_extensions = []120121#122# Arguments123#124self.module_type = type125end126127# @!attribute [r] module_type128# The type of modules stored by this {Msf::ModuleSet}.129#130# @return [String] type of modules131attr_reader :module_type132133# Gives the module set an opportunity to handle a module reload event134#135# @param [Class] mod the module class: a subclass of Msf::Module136# @return [void]137def on_module_reload(mod)138end139140# Dummy placeholder to recalculate aliases and other fun things.141#142# @return [void]143def recalculate144end145146# Checks to see if the supplied module reference name is valid.147#148# @param reference_name [String] The module reference name.149# @return [true] if the module can be {#create created} and cached.150# @return [false] otherwise151def valid?(reference_name)152(self[reference_name]) ? true : false153end154155# Adds a module with a the supplied reference_name.156#157# @param [Class<Msf::Module>] klass The module class.158# @param [String] reference_name The module reference name.159# @param [Hash{String => Object}] info optional module information.160# @option info [Array<String>] 'files' List of paths to files that defined161# +klass+.162# @return [Class] The klass parameter modified to have163# Msf::Module.framework, Msf::Module#refname, Msf::Module#file_path,164# and Msf::Module#orig_cls set.165def add_module(klass, reference_name, info = {})166# Set the module's reference_name so that it can be referenced when167# instances are created.168klass.framework = framework169klass.refname = reference_name170klass.file_path = ((info and info['files']) ? info['files'][0] : nil)171klass.orig_cls = klass172173# don't want to trigger a create, so use fetch174cached_module = self.fetch(reference_name, nil)175176if cached_module177ambiguous_module_reference_name_set.add(reference_name)178179# TODO this isn't terribly helpful since the refnames will always match, that's why they are ambiguous.180wlog("The module #{klass.refname} is ambiguous with #{self[reference_name].refname}.")181end182183self[reference_name] = klass184185klass186end187188def module_refnames189module_metadata.keys190end191192protected193194# Enumerates the modules in the supplied array with possible limiting factors.195#196# @param [Array<Array<String, Class>>] ary Array of module reference name and module class pairs197# @param [Hash{String => Object}] opts198# @option opts [Array<String>] 'Arch' List of 1 or more architectures that the module must support. The module need199# only support one of the architectures in the array to be included, not all architectures.200# @option opts [Array<String>] 'Platform' List of 1 or more platforms that the module must support. The module need201# only support one of the platforms in the array to be include, not all platforms.202# @yield [module_reference_name, module]203# @yieldparam [String] module_reference_name the name of module204# @yieldparam [Class] module The module class: a subclass of {Msf::Module}.205# @return [void]206def each_module_list(ary, opts, &block)207ary.each do |entry|208name, module_metadata = entry209210# Filter out incompatible architectures211if (opts['Arch'])212if (!architectures_by_module[name])213architectures_by_module[name] = Array.wrap(module_metadata.arch)214end215216next if ((architectures_by_module[name] & opts['Arch']).empty? == true)217end218219# Filter out incompatible platforms220if (opts['Platform'])221if (!platforms_by_module[name])222platforms_by_module[name] = module_metadata.platform_list223end224225next if ((platforms_by_module[name] & opts['Platform']).empty? == true)226end227228# Custom filtering229next if (each_module_filter(opts, name, entry) == true)230231mod = self[name]232next if mod.nil?233234block.call(name, mod)235end236end237238# @!attribute [rw] ambiguous_module_reference_name_set239# Set of module reference names that are ambiguous because two or more paths have modules with the same reference240# name241#242# @return [Set<String>] set of module reference names loaded from multiple paths.243attr_accessor :ambiguous_module_reference_name_set244# @!attribute [rw] architectures_by_module245# Maps a module to the list of architectures it supports.246#247# @return [Hash{Class => Array<String>}] Maps module class to Array of architecture Strings.248attr_accessor :architectures_by_module249attr_accessor :mod_extensions250# @!attribute [rw] platforms_by_module251# Maps a module to the list of platforms it supports.252#253# @return [Hash{Class => Array<String>}] Maps module class to Array of platform Strings.254attr_accessor :platforms_by_module255# @!attribute [rw] mod_sorted256# Array of module names and module classes ordered by their names.257#258# @return [Array<Array<String, Class>>] Array of arrays where the inner array is a pair of the module reference259# name and the module class.260attr_accessor :mod_sorted261# @!attribute [w] module_type262# The type of modules stored by this {Msf::ModuleSet}.263#264# @return [String] type of modules265attr_writer :module_type266267# Ranks modules based on their constant rank value, if they have one. Modules without a Rank are treated as if they268# had {Msf::NormalRanking} for Rank.269#270# @return [Array<Array<String, Class>>] Array of arrays where the inner array is a pair of the module reference name271# and the module class.272def rank_modules273module_metadata.sort_by do |refname, metadata|274[metadata.rank || Msf::NormalRanking, refname]275end.reverse!276end277278def module_metadata279Msf::Modules::Metadata::Cache.instance.module_metadata(module_type)280end281282def load_module_class(reference_name, cache_type: Msf::ModuleManager::Cache::FILESYSTEM)283klass = fetch(reference_name, nil)284285# If there is no module associated with this class, then try to demand load it.286if klass.nil?287framework.modules.load_cached_module(module_type, reference_name, cache_type: cache_type)288klass = fetch(reference_name, nil)289end290klass291end292end293294295