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/framework.rb
Views: 11780
# -*- coding: binary -*-12#3# Standard Library4#56require 'monitor'78#9# Project10#1112require 'metasploit/framework/version'13require 'rex/socket/ssl'14require 'metasploit/framework/thread_factory_provider'15module Msf1617###18#19# This class is the primary context that modules, scripts, and user20# interfaces interact with. It ties everything together.21#22###23class Framework24include MonitorMixin2526#27# Versioning information28#2930Major = Metasploit::Framework::Version::MAJOR31Minor = Metasploit::Framework::Version::MINOR32Point = Metasploit::Framework::Version::PATCH33Release = "-#{Metasploit::Framework::Version::PRERELEASE}"34Version = Metasploit::Framework::VERSION3536Revision = "$Revision$"3738#39# Mixin meant to be included into all classes that can have instances that40# should be tied to the framework, such as modules.41#42module Offspring4344#45# A reference to the framework instance from which this offspring was46# derived.47#48attr_accessor :framework49end5051require 'metasploit/framework/data_service/proxy/core'5253#54# Creates an instance of the framework context.55#56def initialize(options={})57self.options = options58# call super to initialize MonitorMixin. #synchronize won't work without this.59super()6061# Allow specific module types to be loaded62types = options[:module_types] || Msf::MODULE_TYPES6364self.history_manager = Rex::Ui::Text::Shell::HistoryManager.new6566self.features = FeatureManager.instance67self.features.load_config6869self.events = EventDispatcher.new(self)70self.modules = ModuleManager.new(self,types)71self.datastore = DataStore.new72self.jobs = Rex::JobContainer.new73self.analyze = Analyze.new(self)74self.plugins = PluginManager.new(self)75self.browser_profiles = Hash.new7677# Configure the thread factory78Rex::ThreadFactory.provider = Metasploit::Framework::ThreadFactoryProvider.new(framework: self)7980# Configure the SSL certificate generator81require 'msf/core/cert_provider'82Rex::Socket::Ssl.cert_provider = Msf::Ssl::CertProvider8384if options.include?('CustomDnsResolver') && Msf::FeatureManager.instance.enabled?(Msf::FeatureManager::DNS)85self.dns_resolver = options['CustomDnsResolver']86self.dns_resolver.set_framework(self)87Rex::Socket._install_global_resolver(self.dns_resolver)88end8990subscriber = FrameworkEventSubscriber.new(self)91events.add_exploit_subscriber(subscriber)92events.add_session_subscriber(subscriber)93events.add_general_subscriber(subscriber)94events.add_db_subscriber(subscriber)95events.add_ui_subscriber(subscriber)96end9798def inspect99"#<Framework (#{sessions.length} sessions, #{jobs.length} jobs, #{plugins.length} plugins#{db.active ? ", #{db.driver} database active" : ""})>"100end101102#103# Returns the module set for encoders.104#105def encoders106return modules.encoders107end108109#110# Returns the module set for exploits.111#112def exploits113return modules.exploits114end115116#117# Returns the module set for nops118#119def nops120return modules.nops121end122123#124# Returns the module set for payloads125#126def payloads127return modules.payloads128end129130#131# Returns the module set for auxiliary modules132#133def auxiliary134return modules.auxiliary135end136137#138# Returns the module set for post modules139#140def post141return modules.post142end143144def evasion145return modules.evasion146end147148#149# Returns the framework version in Major.Minor format.150#151def version152Version153end154155#156# DNS resolver for the framework157#158attr_reader :dns_resolver159#160# Event management interface for registering event handler subscribers and161# for interacting with the correlation engine.162#163attr_reader :events164#165# Module manager that contains information about all loaded modules,166# regardless of type.167#168attr_reader :modules169#170# The global framework datastore that can be used by modules.171#172attr_reader :datastore173#174# The framework instance's aux manager. The aux manager is responsible175# for collecting and cataloging all aux information that comes in from176# aux modules.177#178attr_reader :auxmgr179#180# Background job management specific to things spawned from this instance181# of the framework.182#183attr_reader :jobs184#185# The framework instance's plugin manager. The plugin manager is186# responsible for exposing an interface that allows for the loading and187# unloading of plugins.188#189attr_reader :plugins190#191# The framework instance's browser profile store. These profiles are192# generated by client-side modules and need to be shared across193# different contexts.194#195attr_reader :browser_profiles196#197# The framework instance's analysis utility. Provide method to analyze198# framework objects to offer related objects/actions available.199#200attr_reader :analyze201#202# The framework instance's feature manager. The feature manager is responsible203# for configuring feature flags that can change characteristics of framework.204# @return [Msf::FeatureManager]205attr_reader :features206207# The framework instance's history manager, responsible for managing command history208# in different contexts209# @return [Rex::Ui::Text::Shell::HistoryManager]210attr_reader :history_manager211212#213# The framework instance's data service proxy214#215# @return [Metasploit::Framework::DataService::DataProxy]216def db217return @db if @db218219synchronize {220@db ||= get_db221}222end223224# Session manager that tracks sessions associated with this framework225# instance over the course of their lifetime.226#227# @return [Msf::SessionManager]228def sessions229return @sessions if @sessions230231synchronize {232@sessions ||= Msf::SessionManager.new(self)233}234end235236# The framework instance's thread manager. The thread manager237# provides a cleaner way to manage spawned threads238#239# @return [Msf::ThreadManager]240def threads241return @threads if @threads242243synchronize {244@threads ||= Msf::ThreadManager.new(self)245}246end247248# Whether {#threads} has been initialized249#250# @return [true] if {#threads} has been initialized251# @return [false] otherwise252def threads?253synchronize {254instance_variable_defined? :@threads255}256end257258def search(search_string)259search_params = Msf::Modules::Metadata::Search.parse_search_string(search_string)260Msf::Modules::Metadata::Cache.instance.find(search_params)261end262263#264# EICAR Canary265# @return [Boolean] Should return true if the EICAR file has been corrupted266def eicar_corrupted?267path = ::File.expand_path(::File.join(268::File.dirname(__FILE__),"..", "..", "..", "data", "eicar.com")269)270return true unless ::File.exist?(path)271272data = ::File.read(path, mode: 'rb')273return true unless Digest::SHA1.hexdigest(data) == "3395856ce81f2b7382dee72602f798b642f14140"274275false276277# If anything goes wrong assume AV got us278rescue ::Exception279true280end281282protected283284# @!attribute options285# Options passed to {#initialize}286#287# @return [Hash]288attr_accessor :options289290attr_writer :dns_resolver #:nodoc:291attr_writer :events # :nodoc:292attr_writer :modules # :nodoc:293attr_writer :datastore # :nodoc:294attr_writer :auxmgr # :nodoc:295attr_writer :jobs # :nodoc:296attr_writer :plugins # :nodoc:297attr_writer :db # :nodoc:298attr_writer :browser_profiles # :nodoc:299attr_writer :analyze # :nodoc:300attr_writer :features # :nodoc:301attr_writer :history_manager # :nodoc:302303private304305def get_db306unless options['DisableDatabase']307db_manager = Msf::DBManager.new(self)308options[:db_manager] = db_manager309unless options['SkipDatabaseInit']310db_manager.init_db(options)311end312end313314Metasploit::Framework::DataService::DataProxy.new(options)315end316317end318319class FrameworkEventSubscriber320include Framework::Offspring321def initialize(framework)322self.framework = framework323end324325def report_event(data)326if framework.db.active327framework.db.report_event(data)328end329end330331include Msf::GeneralEventSubscriber332333#334# Generic handler for module events335#336def module_event(name, instance, opts={})337if framework.db.active338event = {339:workspace => framework.db.find_workspace(instance.workspace),340:name => name,341:username => instance.owner,342:info => {343:module_name => instance.fullname,344:module_uuid => instance.uuid345}.merge(opts)346}347348report_event(event)349end350end351352##353# :category: ::Msf::GeneralEventSubscriber implementors354def on_module_run(instance)355opts = { :datastore => instance.datastore.to_h }356module_event('module_run', instance, opts)357end358359##360# :category: ::Msf::GeneralEventSubscriber implementors361def on_module_complete(instance)362module_event('module_complete', instance)363end364365##366# :category: ::Msf::GeneralEventSubscriber implementors367def on_module_error(instance, exception=nil)368module_event('module_error', instance, :exception => exception.to_s)369end370371include ::Msf::UiEventSubscriber372##373# :category: ::Msf::UiEventSubscriber implementors374def on_ui_command(command)375if (framework.db and framework.db.active)376report_event(:name => "ui_command", :info => {:command => command})377end378end379380##381# :category: ::Msf::UiEventSubscriber implementors382def on_ui_stop()383if (framework.db and framework.db.active)384report_event(:name => "ui_stop")385end386end387388##389# :category: ::Msf::UiEventSubscriber implementors390def on_ui_start(rev)391#392# The database is not active at startup time unless msfconsole was393# started with a database.yml, so this event won't always be saved to394# the db. Not great, but best we can do.395#396info = { :revision => rev }397report_event(:name => "ui_start", :info => info)398end399400401include ::Msf::SessionEvent402403#404# Generic handler for session events405#406def session_event(name, session, opts={})407address = session.session_host408409if not (address and address.length > 0)410elog("Session with no session_host/target_host/tunnel_peer. Session Info: #{session.inspect}")411return412end413414if framework.db.active415ws = framework.db.find_workspace(session.workspace)416opts.each_key do |attr|417opts[attr].force_encoding('UTF-8') if opts[attr].is_a?(String)418end419420event = {421:workspace => ws,422:username => session.username,423:name => name,424:host => address,425:info => {426:session_id => session.sid,427:session_info => session.info,428:session_uuid => session.uuid,429:session_type => session.type,430:username => session.username,431:target_host => address,432:via_exploit => session.via_exploit,433:via_payload => session.via_payload,434:tunnel_peer => session.tunnel_peer,435:exploit_uuid => session.exploit_uuid436}.merge(opts)437}438report_event(event)439end440end441442443##444# :category: ::Msf::SessionEvent implementors445def on_session_open(session)446opts = { :datastore => session.exploit_datastore.to_h, :critical => true }447session_event('session_open', session, opts)448framework.db.report_session(:session => session)449end450451##452# :category: ::Msf::SessionEvent implementors453def on_session_upload(session, lpath, rpath)454session_event('session_upload', session, :local_path => lpath, :remote_path => rpath)455framework.db.report_session_event({456:etype => 'upload',457:session => session,458:local_path => lpath,459:remote_path => rpath460})461end462##463# :category: ::Msf::SessionEvent implementors464def on_session_download(session, rpath, lpath)465session_event('session_download', session, :local_path => lpath, :remote_path => rpath)466framework.db.report_session_event({467:etype => 'download',468:session => session,469:local_path => lpath,470:remote_path => rpath471})472end473474##475# :category: ::Msf::SessionEvent implementors476def on_session_close(session, reason='')477session_event('session_close', session)478if session.db_record479# Don't bother saving here, the session's cleanup method will take480# care of that later.481session.db_record.close_reason = reason482session.db_record.closed_at = Time.now.utc483end484end485486#def on_session_interact(session)487# $stdout.puts('session_interact', session.inspect)488#end489490##491# :category: ::Msf::SessionEvent implementors492def on_session_command(session, command)493session_event('session_command', session, :command => command)494framework.db.report_session_event({495:etype => 'command',496:session => session,497:command => command498})499end500501##502# :category: ::Msf::SessionEvent implementors503def on_session_output(session, output)504# Break up the output into chunks that will fit into the database.505buff = output.dup506chunks = []507if buff.length > 1024508while buff.length > 0509chunks << buff.slice!(0,1024)510end511else512chunks << buff513end514chunks.each { |chunk|515session_event('session_output', session, :output => chunk)516framework.db.report_session_event({517:etype => 'output',518:session => session,519:output => chunk520})521}522end523524##525# :category: ::Msf::SessionEvent implementors526def on_session_route(session, route)527framework.db.report_session_route({session: session, route: route})528end529530##531# :category: ::Msf::SessionEvent implementors532def on_session_route_remove(session, route)533framework.db.report_session_route_remove({session: session, route: route})534end535536##537# :category: ::Msf::SessionEvent implementors538def on_session_script_run(session, script)539framework.db.report_session_event({540:etype => 'script_run',541:session => session,542:local_path => script543})544end545546##547# :category: ::Msf::SessionEvent implementors548def on_session_module_run(session, mod)549framework.db.report_session_event({550:etype => 'module_run',551:session => session,552:local_path => mod.fullname553})554end555556#557# This is covered by on_module_run and on_session_open, so don't bother558#559#include ExploitEvent560#def on_exploit_success(exploit, session)561#end562563end564end565566567