module Msf
autoload :OptionContainer, 'msf/core/option_container'
class Module
autoload :Alert, 'msf/core/module/alert'
autoload :Arch, 'msf/core/module/arch'
autoload :Auth, 'msf/core/module/auth'
autoload :Author, 'msf/core/module/author'
autoload :AuxiliaryAction, 'msf/core/module/auxiliary_action'
autoload :Compatibility, 'msf/core/module/compatibility'
autoload :DataStore, 'msf/core/module/data_store'
autoload :Deprecated, 'msf/core/module/deprecated'
autoload :Failure, 'msf/core/module/failure'
autoload :FullName, 'msf/core/module/full_name'
autoload :HasActions, 'msf/core/module/has_actions'
autoload :ModuleInfo, 'msf/core/module/module_info'
autoload :ModuleStore, 'msf/core/module/module_store'
autoload :Network, 'msf/core/module/network'
autoload :Options, 'msf/core/module/options'
autoload :Platform, 'msf/core/module/platform'
autoload :PlatformList, 'msf/core/module/platform_list'
autoload :Privileged, 'msf/core/module/privileged'
autoload :Ranking, 'msf/core/module/ranking'
autoload :Reference, 'msf/core/module/reference'
autoload :SiteReference, 'msf/core/module/reference'
autoload :Target, 'msf/core/module/target'
autoload :Type, 'msf/core/module/type'
autoload :UI, 'msf/core/module/ui'
autoload :UUID, 'msf/core/module/uuid'
autoload :SideEffects, 'msf/core/module/side_effects'
autoload :Stability, 'msf/core/module/stability'
autoload :Reliability, 'msf/core/module/reliability'
include Msf::Module::Alert
include Msf::Module::Arch
include Msf::Module::Auth
include Msf::Module::Author
include Msf::Module::Compatibility
include Msf::Module::DataStore
include Msf::Module::Failure
include Msf::Module::FullName
include Msf::Module::ModuleInfo
include Msf::Module::ModuleStore
include Msf::Module::Network
include Msf::Module::Options
include Msf::Module::Privileged
include Msf::Module::Ranking
include Msf::Module::Type
include Msf::Module::UI
include Msf::Module::UUID
include Msf::Module::SideEffects
include Msf::Module::Stability
include Msf::Module::Reliability
REPLICANT_EXTENSION_DS_KEY = 'ReplicantExtensions'
public_class_method :include
class << self
include Framework::Offspring
attr_accessor :orig_cls
attr_accessor :file_path
attr_accessor :adapted_refname
attr_accessor :adapter_refname
attr_accessor :stage_refname
attr_accessor :stager_refname
end
def framework
self.class.framework
end
def initialize(info = {})
@module_info_copy = info.dup
self.module_info = info
set_defaults
init_compat
info_fixups
self.author = Msf::Author.transform(module_info['Author'])
self.arch = Rex::Transformer.transform(module_info['Arch'], Array, [ String ], 'Arch')
self.platform = PlatformList.transform(module_info['Platform'])
self.references = Rex::Transformer.transform(module_info['References'], Array, [ SiteReference, Reference ], 'Ref')
self.options = Msf::OptionContainer.new
self.options.add_options(info['Options'], self.class)
self.options.add_advanced_options(info['AdvancedOptions'], self.class)
self.options.add_evasion_options(info['EvasionOptions'], self.class)
self.datastore = Msf::ModuleDataStore.new(self)
import_defaults
self.privileged = module_info['Privileged'] || false
self.license = module_info['License'] || MSF_LICENSE
register_advanced_options(
[
OptString.new('WORKSPACE', [ false, "Specify the workspace for this module" ]),
OptBool.new('VERBOSE', [ false, 'Enable detailed status messages', false ])
], Msf::Module)
end
def has_check?
respond_to?(:check)
end
def replicant
obj = self.clone
self.instance_variables.each { |k|
old_value = instance_variable_get(k)
begin
new_value = old_value.is_a?(Rex::Ref) ? old_value.ref : old_value.dup
rescue => e
elog("#{self.class} replicant failed to dup #{k}", error: e)
new_value = old_value
end
obj.instance_variable_set(k, new_value)
}
obj.datastore = self.datastore.copy
obj.user_input = self.user_input
obj.user_output = self.user_output
obj.module_store = self.module_store.clone
obj.perform_extensions
obj
end
def perform_extensions
if datastore[REPLICANT_EXTENSION_DS_KEY].present?
if datastore[REPLICANT_EXTENSION_DS_KEY].respond_to?(:each)
datastore[REPLICANT_EXTENSION_DS_KEY].each do |const|
self.extend(const)
end
else
fail "Invalid settings in datastore at key #{REPLICANT_EXTENSION_DS_KEY}"
end
end
end
def register_extensions(*rb_modules)
datastore[REPLICANT_EXTENSION_DS_KEY] = [] unless datastore[REPLICANT_EXTENSION_DS_KEY].present?
rb_modules.each do |rb_mod|
datastore[REPLICANT_EXTENSION_DS_KEY] << rb_mod unless datastore[REPLICANT_EXTENSION_DS_KEY].include? rb_mod
end
end
def orig_cls
self.class.orig_cls
end
def file_path
self.class.file_path
end
def adapted_refname
self.class.adapted_refname
end
def adapter_refname
self.class.adapter_refname
end
def stage_refname
self.class.stage_refname
end
def stager_refname
self.class.stager_refname
end
def workspace
self.datastore['WORKSPACE'] ||
(framework.db and framework.db.active and framework.db.workspace and framework.db.workspace.name)
end
def owner
username = self.datastore['MODULE_OWNER'].to_s.strip
if username.empty?
username = self.datastore['PROUSER'].to_s.strip
end
if username.empty?
username = (ENV['LOGNAME'] || ENV['USERNAME'] || ENV['USER'] || "unknown").to_s.strip
end
username
end
def register_parent(ref)
self.datastore['WORKSPACE'] = (ref.datastore['WORKSPACE'] ? ref.datastore['WORKSPACE'].dup : nil)
self.datastore['PROUSER'] = (ref.datastore['PROUSER'] ? ref.datastore['PROUSER'].dup : nil)
self.datastore['MODULE_OWNER'] = ref.owner.dup
self.datastore['ParentUUID'] = ref.uuid.dup
end
def platform_to_s
platform.all? ? "All" : platform.names.join(", ")
end
def platform?(what)
(platform & what).empty? == false
end
def debugging?
datastore['DEBUG']
end
def fail_with(reason, msg=nil)
raise RuntimeError, "#{reason.to_s}: #{msg}"
end
def self.cached?
false
end
def default_options
self.module_info['DefaultOptions']
end
def required_cred_options
@required_cred_options ||= lambda {
self.options.select { |name, opt|
(
opt.type?('string') &&
opt.required &&
(opt.name.match(/user(name)*$/i) || name.match(/pass(word)*$/i))
) ||
(
opt.type?('bool') &&
opt.required &&
opt.name.match(/^allow_guest$/i)
)
}
}.call
end
def black_listed_auth_filenames
@black_listed_auth_filenames ||= lambda {
[
'fileformat',
'browser'
]
}.call
end
def post_auth?
if self.kind_of?(Msf::Auxiliary::AuthBrute)
return true
else
directory_name = self.fullname.split('/')[0..-2]
black_listed_auth_filenames.each do |black_listed_name|
return false if directory_name.include?(black_listed_name)
end
!required_cred_options.empty?
end
end
def default_cred?
return false unless post_auth?
required_cred_options.all? do |name, opt|
if opt.type == 'string'
if !opt.default.blank?
true
else
false
end
else
true
end
end
false
end
attr_reader :platform
attr_reader :references
attr_reader :license
attr_accessor :job_id
attr_accessor :error
attr_accessor :user_data
protected
def set_defaults
self.module_info = {
'Name' => 'No module name',
'Description' => 'No module description',
'Version' => '0',
'Author' => nil,
'Arch' => nil,
'Platform' => [],
'Ref' => nil,
'Privileged' => false,
'License' => MSF_LICENSE,
'Notes' => {}
}.update(self.module_info)
self.module_store = {}
end
attr_writer :platform, :references
attr_writer :privileged
attr_writer :license
end
end