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.rb
Views: 11623
# -*- coding: binary -*-12module Msf34autoload :OptionContainer, 'msf/core/option_container'56###7#8# The module base class is responsible for providing the common interface9# that is used to interact with modules at the most basic levels, such as10# by inspecting a given module's attributes (name, description, version,11# authors, etc) and by managing the module's data store.12#13###14class Module15autoload :Alert, 'msf/core/module/alert'16autoload :Arch, 'msf/core/module/arch'17autoload :Auth, 'msf/core/module/auth'18autoload :Author, 'msf/core/module/author'19autoload :AuxiliaryAction, 'msf/core/module/auxiliary_action'20autoload :Compatibility, 'msf/core/module/compatibility'21autoload :DataStore, 'msf/core/module/data_store'22autoload :Deprecated, 'msf/core/module/deprecated'23autoload :Failure, 'msf/core/module/failure'24autoload :FullName, 'msf/core/module/full_name'25autoload :HasActions, 'msf/core/module/has_actions'26autoload :ModuleInfo, 'msf/core/module/module_info'27autoload :ModuleStore, 'msf/core/module/module_store'28autoload :Network, 'msf/core/module/network'29autoload :Options, 'msf/core/module/options'30autoload :Platform, 'msf/core/module/platform'31autoload :PlatformList, 'msf/core/module/platform_list'32autoload :Privileged, 'msf/core/module/privileged'33autoload :Ranking, 'msf/core/module/ranking'34autoload :Reference, 'msf/core/module/reference'35autoload :SiteReference, 'msf/core/module/reference'36autoload :Target, 'msf/core/module/target'37autoload :Type, 'msf/core/module/type'38autoload :UI, 'msf/core/module/ui'39autoload :UUID, 'msf/core/module/uuid'40autoload :SideEffects, 'msf/core/module/side_effects'41autoload :Stability, 'msf/core/module/stability'42autoload :Reliability, 'msf/core/module/reliability'4344include Msf::Module::Alert45include Msf::Module::Arch46include Msf::Module::Auth47include Msf::Module::Author48include Msf::Module::Compatibility49include Msf::Module::DataStore50include Msf::Module::FullName51include Msf::Module::ModuleInfo52include Msf::Module::ModuleStore53include Msf::Module::Network54include Msf::Module::Options55include Msf::Module::Privileged56include Msf::Module::Ranking57include Msf::Module::Type58include Msf::Module::UI59include Msf::Module::UUID60include Msf::Module::SideEffects61include Msf::Module::Stability62include Msf::Module::Reliability6364# The key where a comma-separated list of Ruby module names will live in the65# datastore, consumed by #replicant to allow clean override of MSF module methods.66REPLICANT_EXTENSION_DS_KEY = 'ReplicantExtensions'6768# Make include public so we can runtime extend69public_class_method :include7071class << self72include Framework::Offspring7374#75# This attribute holds the non-duplicated copy of the module76# implementation. This attribute is used for reloading purposes so that77# it can be re-duplicated.78#79attr_accessor :orig_cls8081#82# The path from which the module was loaded.83#84attr_accessor :file_path8586# @return [String, nil] Reference name of the payload being adapted87attr_accessor :adapted_refname8889# @return [String, nil] Reference name of the payloads adapter90attr_accessor :adapter_refname9192# @return [String, nil] Reference name of the payload stage93attr_accessor :stage_refname9495# @return [String, nil] Reference name of the payloads stager96attr_accessor :stager_refname9798end99100#101# Returns the class reference to the framework102#103def framework104self.class.framework105end106107#108# Creates an instance of an abstract module using the supplied information109# hash.110#111def initialize(info = {})112@module_info_copy = info.dup113114self.module_info = info115generate_uuid116117set_defaults118119# Initialize module compatibility hashes120init_compat121122# Fixup module fields as needed123info_fixups124125# Transform some of the fields to arrays as necessary126self.author = Msf::Author.transform(module_info['Author'])127self.arch = Rex::Transformer.transform(module_info['Arch'], Array, [ String ], 'Arch')128self.platform = PlatformList.transform(module_info['Platform'])129self.references = Rex::Transformer.transform(module_info['References'], Array, [ SiteReference, Reference ], 'Ref')130131# Create and initialize the option container for this module132self.options = Msf::OptionContainer.new133self.options.add_options(info['Options'], self.class)134self.options.add_advanced_options(info['AdvancedOptions'], self.class)135self.options.add_evasion_options(info['EvasionOptions'], self.class)136137# Create and initialize the data store for this module138self.datastore = ModuleDataStore.new(self)139140# Import default options into the datastore141import_defaults142143self.privileged = module_info['Privileged'] || false144self.license = module_info['License'] || MSF_LICENSE145146# Allow all modules to track their current workspace147register_advanced_options(148[149OptString.new('WORKSPACE', [ false, "Specify the workspace for this module" ]),150OptBool.new('VERBOSE', [ false, 'Enable detailed status messages', false ])151], Msf::Module)152153end154155def has_check?156respond_to?(:check)157end158159#160# Creates a fresh copy of an instantiated module161#162def replicant163obj = self.clone164self.instance_variables.each { |k|165old_value = instance_variable_get(k)166begin167new_value = old_value.is_a?(Rex::Ref) ? old_value.ref : old_value.dup168rescue => e169elog("#{self.class} replicant failed to dup #{k}", error: e)170new_value = old_value171end172173obj.instance_variable_set(k, new_value)174}175176obj.datastore = self.datastore.copy177obj.user_input = self.user_input178obj.user_output = self.user_output179obj.module_store = self.module_store.clone180181obj.perform_extensions182obj183end184185# Extends self with the constant list in the datastore186# @return [void]187def perform_extensions188if datastore[REPLICANT_EXTENSION_DS_KEY].present?189if datastore[REPLICANT_EXTENSION_DS_KEY].respond_to?(:each)190datastore[REPLICANT_EXTENSION_DS_KEY].each do |const|191self.extend(const)192end193else194fail "Invalid settings in datastore at key #{REPLICANT_EXTENSION_DS_KEY}"195end196end197end198199# @param rb_modules [Constant] One or more Ruby constants200# @return [void]201def register_extensions(*rb_modules)202datastore[REPLICANT_EXTENSION_DS_KEY] = [] unless datastore[REPLICANT_EXTENSION_DS_KEY].present?203rb_modules.each do |rb_mod|204datastore[REPLICANT_EXTENSION_DS_KEY] << rb_mod unless datastore[REPLICANT_EXTENSION_DS_KEY].include? rb_mod205end206end207208#209# Returns the unduplicated class associated with this module.210#211def orig_cls212self.class.orig_cls213end214215#216# The path to the file in which the module can be loaded from.217#218def file_path219self.class.file_path220end221222# @return [String, nil] Reference name of the payload being adapted223def adapted_refname224self.class.adapted_refname225end226227# @return [String, nil] Reference name of the payloads adapter228def adapter_refname229self.class.adapter_refname230end231232# @return [String, nil] Reference name of the payload stage233def stage_refname234self.class.stage_refname235end236237# @return [String, nil] Reference name of the payloads stager238def stager_refname239self.class.stager_refname240end241242#243# Returns the current workspace244#245def workspace246self.datastore['WORKSPACE'] ||247(framework.db and framework.db.active and framework.db.workspace and framework.db.workspace.name)248end249250#251# Returns the username that instantiated this module, this tries a handful of methods252# to determine what actual user ran this module.253#254def owner255# Generic method to configure a module owner256username = self.datastore['MODULE_OWNER'].to_s.strip257258# Specific method used by the commercial products259if username.empty?260username = self.datastore['PROUSER'].to_s.strip261end262263# Fallback when neither prior method is available, common for msfconsole264if username.empty?265username = (ENV['LOGNAME'] || ENV['USERNAME'] || ENV['USER'] || "unknown").to_s.strip266end267268username269end270271#272# Scans the parent module reference to populate additional information. This273# is used to inherit common settings (owner, workspace, parent uuid, etc).274#275def register_parent(ref)276self.datastore['WORKSPACE'] = (ref.datastore['WORKSPACE'] ? ref.datastore['WORKSPACE'].dup : nil)277self.datastore['PROUSER'] = (ref.datastore['PROUSER'] ? ref.datastore['PROUSER'].dup : nil)278self.datastore['MODULE_OWNER'] = ref.owner.dup279self.datastore['ParentUUID'] = ref.uuid.dup280end281282#283# Return a comma separated list of supported platforms, if any.284#285def platform_to_s286platform.all? ? "All" : platform.names.join(", ")287end288289#290# Checks to see if this module is compatible with the supplied platform291#292def platform?(what)293(platform & what).empty? == false294end295296#297# Returns true if this module is being debugged.298#299def debugging?300datastore['DEBUG']301end302303#304# Raises a RuntimeError failure message. This is meant to be used for all non-exploits,305# and allows specific classes to override.306#307# @param reason [String] A reason about the failure.308# @param msg [String] (Optional) A message about the failure.309# @raise [RuntimeError]310# @return [void]311# @note If you are writing an exploit, you don't use this API. Instead, please refer to the312# API documentation from lib/msf/core/exploit.rb.313# @see Msf::Exploit#fail_with314# @example315# fail_with('No Access', 'Unable to login')316#317def fail_with(reason, msg=nil)318raise RuntimeError, "#{reason.to_s}: #{msg}"319end320321322##323#324# Just some handy quick checks325#326##327328#329# Returns false since this is the real module330#331def self.cached?332false333end334335def default_options336self.module_info['DefaultOptions']337end338339def required_cred_options340@required_cred_options ||= lambda {341self.options.select { |name, opt|342(343opt.type?('string') &&344opt.required &&345(opt.name.match(/user(name)*$/i) || name.match(/pass(word)*$/i))346) ||347(348opt.type?('bool') &&349opt.required &&350opt.name.match(/^allow_guest$/i)351)352}353}.call354end355356def black_listed_auth_filenames357@black_listed_auth_filenames ||= lambda {358[359'fileformat',360'browser'361]362}.call363end364365def post_auth?366if self.kind_of?(Msf::Auxiliary::AuthBrute)367return true368else369# Some modules will never be post auth, so let's not waste our time370# determining it and create more potential false positives.371# If these modules happen to be post auth for some reason, then we it372# should manually override the post_auth? method as true.373directory_name = self.fullname.split('/')[0..-2]374black_listed_auth_filenames.each do |black_listed_name|375return false if directory_name.include?(black_listed_name)376end377378# Some modules create their own username and password datastore379# options, not relying on the AuthBrute mixin. In that case we380# just have to go through the options and try to identify them.381!required_cred_options.empty?382end383end384385def default_cred?386return false unless post_auth?387388required_cred_options.all? do |name, opt|389if opt.type == 'string'390if !opt.default.blank?391true392else393false394end395else396true397end398end399400false401end402403#404# The array of zero or more platforms.405#406attr_reader :platform407408#409# The reference count for the module.410#411attr_reader :references412413#414# The license under which this module is provided.415#416attr_reader :license417418#419# The job identifier that this module is running as, if any.420#421attr_accessor :job_id422423#424# The last exception to occur using this module425#426attr_accessor :error427428# An opaque bag of data to attach to a module. This is useful for attaching429# some piece of identifying info on to a module before calling430# {Msf::Simple::Exploit#exploit_simple} or431# {Msf::Simple::Auxiliary#run_simple} for correlating where modules came432# from.433#434attr_accessor :user_data435436protected437438#439# Sets the modules unsupplied info fields to their default values.440#441def set_defaults442self.module_info = {443'Name' => 'No module name',444'Description' => 'No module description',445'Version' => '0',446'Author' => nil,447'Arch' => nil, # No architectures by default.448'Platform' => [], # No platforms by default.449'Ref' => nil,450'Privileged' => false,451'License' => MSF_LICENSE,452'Notes' => {}453}.update(self.module_info)454self.module_store = {}455end456457attr_writer :platform, :references # :nodoc:458attr_writer :privileged # :nodoc:459attr_writer :license # :nodoc:460461462463end464465end466467468