diff --git a/lib/msf/core/data_store.rb b/lib/msf/core/data_store.rb index eb37dd35ce..31c00b3f34 100644 --- a/lib/msf/core/data_store.rb +++ b/lib/msf/core/data_store.rb @@ -58,7 +58,7 @@ class DataStore < Hash end # - # Imports options from a hash + # Imports options from a hash and stores them in the datastore. # def import_options_from_hash(option_hash) option_hash.each_pair { |key, val| @@ -67,7 +67,7 @@ class DataStore < Hash end # - # Serializes the options in the datastore to a string + # Serializes the options in the datastore to a string. # def to_s(delim = ' ') str = '' diff --git a/lib/msf/core/encoded_payload.rb b/lib/msf/core/encoded_payload.rb index 3b2d9cbcd4..ee46f41405 100644 --- a/lib/msf/core/encoded_payload.rb +++ b/lib/msf/core/encoded_payload.rb @@ -16,7 +16,8 @@ class EncodedPayload include Framework::Offspring # - # Creates an encoded payload instance + # This method creates an encoded payload instance and returns it to the + # caller. # def self.create(pinst, reqs) # Create the encoded payload instance @@ -225,13 +226,13 @@ class EncodedPayload protected - attr_writer :raw - attr_writer :encoded - attr_writer :nop_sled_size - attr_writer :nop_sled - attr_writer :payload - attr_writer :encoder - attr_writer :nop + attr_writer :raw # :nodoc: + attr_writer :encoded # :nodoc: + attr_writer :nop_sled_size # :nodoc: + attr_writer :nop_sled # :nodoc: + attr_writer :payload # :nodoc: + attr_writer :encoder # :nodoc: + attr_writer :nop # :nodoc: # # The payload instance used to generate the payload diff --git a/lib/msf/core/encoder.rb b/lib/msf/core/encoder.rb index 69dbad20ce..b9eda9ebe9 100644 --- a/lib/msf/core/encoder.rb +++ b/lib/msf/core/encoder.rb @@ -13,32 +13,40 @@ module Msf ### class EncoderState + # + # Initializes a new encoder state, optionally with a key. + # def initialize(key = nil) reset(key) end - # Reset the encoder state + # + # Reset the encoder state by initializing the encoded buffer to an empty + # string. + # def reset(key = nil) init_key(key) self.encoded = '' end + # # Set the initial encoding key + # def init_key(key) self.key = key self.orig_key = key end - attr_accessor :key - attr_accessor :orig_key - attr_accessor :encoded - attr_accessor :context - attr_accessor :badchars - attr_accessor :buf + attr_accessor :key # :nodoc: + attr_accessor :orig_key # :nodoc: + attr_accessor :encoded # :nodoc: + attr_accessor :context # :nodoc: + attr_accessor :badchars # :nodoc: + attr_accessor :buf # :nodoc: # Decoder settings - attr_accessor :decoder_key_offset, :decoder_key_size, :decoder_key_pack + attr_accessor :decoder_key_offset, :decoder_key_size, :decoder_key_pack # :nodoc: end @@ -56,46 +64,77 @@ class Encoder < Module super(info) end + ## # # Encoder information accessors that can be overriden # by derived classes # + ## + # + # Returns MODULE_ENCODER to indicate that this is an encoder module. + # def self.type return MODULE_ENCODER end + # + # Returns MODULE_ENCODER to indicate that this is an encoder module. + # def type return MODULE_ENCODER end # - # Returns the decoder stub to use based on the supplied length + # Returns the decoder stub to use based on the supplied length. # def decoder_stub(state) return module_info['Decoder']['Stub'] end + # + # Returns the offset to the key associated with the decoder stub. + # def decoder_key_offset return module_info['Decoder']['KeyOffset'] end + # + # Returns the size of the key, in bytes. + # def decoder_key_size return module_info['Decoder']['KeySize'] end + # + # Returns the size of each logical encoding block, in bytes. This + # is typically the same as decoder_key_size. + # def decoder_block_size return module_info['Decoder']['BlockSize'] end + # + # Returns the byte-packing character that should be used to encode + # the key. + # def decoder_key_pack return module_info['Decoder']['KeyPack'] || 'V' end + ## # # Encoding # + ## + # + # This method generates an encoded version of the supplied buffer in buf + # using the bad characters as guides. On success, an encoded and + # functional version of the supplied buffer will be returned. Otherwise, + # an exception will be thrown if an error is encountered during the + # encoding process. + # def encode(buf, badchars, state = nil) # Initialize an empty set of bad characters badchars = '' if (!badchars) @@ -139,6 +178,10 @@ class Encoder < Module return state.encoded end + # + # Performs the actual encoding operation after the encoder state has been + # initialized and is ready to go. + # def do_encode(buf, badchars, state) # Copy the decoder stub since we may need to modify it stub = decoder_stub(state).dup @@ -175,32 +218,56 @@ class Encoder < Module return true end + ## # # Buffer management # - + ## + + # + # Returns a string that should be prepended to the encoded version of the + # buffer before returning it to callers. + # def prepend_buf return '' end + ## # # Pre-processing, post-processing, and block encoding stubs # + ## + # + # Called when encoding is about to start immediately after the encoding + # state has been initialized. + # def encode_begin(state) return nil end + # + # Called after encoding has completed. + # def encode_end(state) return nil end + # + # Called once for each block being encoded based on the attributes of the + # decoder. + # def encode_block(state, block) return block end protected + # + # Initializes the encoding state supplied as an argument to the attributes + # that have been defined for this decoder stub, such as key offset, size, + # and pack. + # def init_state(state) # Update the state with default decoder information state.decoder_key_offset = decoder_key_offset @@ -208,6 +275,12 @@ protected state.decoder_key_pack = decoder_key_pack end + # + # This method finds a compatible key for the supplied buffer based also on + # the supplied bad characters list. This is meant to make encoders more + # reliable and less prone to bad character failure by doing a fairly + # complete key search before giving up on an encoder. + # def find_key(buf, badchars) key_bytes = [ ] cur_key = [ ] @@ -256,10 +329,16 @@ protected return key_bytes_to_integer(key_bytes) end + # + # Returns the list of bad keys associated with this encoder. + # def find_bad_keys return [ {}, {}, {}, {} ] end + # + # Returns the index of any bad characters found in the supplied buffer. + # def has_badchars?(buf, badchars) badchars.each_byte { |badchar| idx = buf.index(badchar) diff --git a/lib/msf/core/event_dispatcher.rb b/lib/msf/core/event_dispatcher.rb index 861b851773..23bcc0d3be 100644 --- a/lib/msf/core/event_dispatcher.rb +++ b/lib/msf/core/event_dispatcher.rb @@ -44,52 +44,88 @@ class EventDispatcher self.subscribers_rwlock = Rex::ReadWriteLock.new end + ## # # Subscriber registration # - + ## + + # + # This method adds a general subscriber. General subscribers receive + # notifications when all events occur. + # def add_general_subscriber(subscriber) add_event_subscriber(general_event_subscribers, subscriber) end + # + # Removes a general subscriber. + # def remove_general_subscriber(subscriber) remove_event_subscriber(general_event_subscribers, subscriber) end + # + # This method adds a recon event subscriber. Recon event subscribers + # receive notifications when events occur that pertain to recon modules. + # The subscriber provided must implement the ReconEvents module methods in + # some form. + # def add_recon_subscriber(subscriber) add_event_subscriber(recon_event_subscribers, subscriber) end + # + # Removes a recon event subscriber. + # def remove_recon_subscriber(subscriber) remove_event_subscriber(recon_event_subscribers, subscriber) end + # + # This method adds an exploit event subscriber. Exploit event subscribers + # receive notifications when events occur that pertain to exploits, such as + # the success or failure of an exploitation attempt. The subscriber + # provided must implement the ExploitEvents module methods in some form. + # def add_exploit_subscriber(subscriber) add_event_subscriber(exploit_event_subscribers, subscriber) end + # + # Removes an exploit event subscriber. + # def remove_exploit_subscriber(subscriber) remove_event_subscriber(exploit_event_subscribers, subscriber) end + # + # This method adds a session event subscriber. Session event subscribers + # receive notifications when sessions are opened and closed. The + # subscriber provided must implement the SessionEvents module methods in + # some form. + # def add_session_subscriber(subscriber) add_event_subscriber(session_event_subscribers, subscriber) end + # + # Removes a session event subscriber. + # def remove_session_subscriber(subscriber) remove_event_subscriber(session_event_subscribers, subscriber) end - # - # Event dispatching entry point - # - ## # # General events # ## + # + # Called when a module is loaded into the framework. This, in turn, + # notifies all registered general event subscribers. + # def on_module_load(name, mod) subscribers_rwlock.synchronize_read { general_event_subscribers.each { |subscriber| @@ -100,6 +136,10 @@ class EventDispatcher } end + # + # Called when a module is unloaded from the framework. This, in turn, + # notifies all registered general event subscribers. + # def on_module_created(instance) subscribers_rwlock.synchronize_read { general_event_subscribers.each { |subscriber| @@ -116,6 +156,10 @@ class EventDispatcher # ## + # + # Called when recon information is discovered. This, in turn, notifies all + # registered recon event subscribers. + # def on_recon_discovery(group, info) subscribers_rwlock.synchronize_read { recon_event_subscribers.each { |subscriber| @@ -130,6 +174,10 @@ class EventDispatcher # ## + # + # Called when an exploit succeeds. This notifies the registered exploit + # event subscribers. + # def on_exploit_success(exploit) subscribers_rwlock.synchronize_read { exploit_event_subscribers.each { |subscriber| @@ -138,6 +186,10 @@ class EventDispatcher } end + # + # Called when an exploit fails. This notifies the registered exploit + # event subscribers. + # def on_exploit_failure(exploit, reason) subscribers_rwlock.synchronize_read { exploit_event_subscribers.each { |subscriber| @@ -152,6 +204,10 @@ class EventDispatcher # ## + # + # Called when a new session is opened. This notifies all the registered + # session event subscribers. + # def on_session_open(session) subscribers_rwlock.synchronize_read { session_event_subscribers.each { |subscriber| @@ -160,6 +216,10 @@ class EventDispatcher } end + # + # Called when a new session is closed. This notifies all the registered + # session event subscribers. + # def on_session_close(session) subscribers_rwlock.synchronize_read { session_event_subscribers.each { |subscriber| @@ -170,13 +230,19 @@ class EventDispatcher protected - def add_event_subscriber(array, subscriber) + # + # Adds an event subscriber to the supplied subscriber array. + # + def add_event_subscriber(array, subscriber) # :nodoc: subscribers_rwlock.synchronize_write { array << subscriber } end - def remove_event_subscriber(array, subscriber) + # + # Removes an event subscriber from the supplied subscriber array. + # + def remove_event_subscriber(array, subscriber) # :nodoc: subscribers_rwlock.synchronize_write { array.delete(subscriber) } diff --git a/lib/msf/core/exploit.rb b/lib/msf/core/exploit.rb index 96bc42d825..09cfea460e 100644 --- a/lib/msf/core/exploit.rb +++ b/lib/msf/core/exploit.rb @@ -13,13 +13,13 @@ module Msf module ExploitEvents # - # Notified when an exploit is successful + # This method is called whenever an exploit succeeds. # def on_exploit_success(exploit) end # - # Notified when an exploit is unsuccessful + # This method is called whenever an exploit fails. # def on_exploit_failure(exploit, reason) end @@ -54,10 +54,31 @@ class Exploit < Msf::Module # The various check codes that can be returned from the ``check'' routine. # module CheckCode + + # + # The target is safe and is therefore not exploitable. + # Safe = [ 0, "The target is not exploitable." ] + + # + # The target is running the service in requestion but may not be + # exploitable. + # Detected = [ 1, "The target service is running, but could not be validated." ] + + # + # The target appears to be vulnerable. + # Appears = [ 2, "The target appears to be vulnerable." ] + + # + # The target is vulnerable. + # Vulnerable = [ 3, "The target is vulnerable." ] + + # + # The exploit does not support the check method. + # Unsupported = [ 4, "This exploit does not support check." ] end @@ -65,8 +86,20 @@ class Exploit < Msf::Module # The various basic types of exploits # module Type + + # + # Indicates that the exploit is a remote exploit. + # Remote = "remote" + + # + # Indicates that the exploit is a local exploit. + # Local = "local" + + # + # Indicates that the exploit can work anywhere it damn pleases. + # Omni = "omnipresent" end @@ -78,7 +111,18 @@ class Exploit < Msf::Module # be initiated (passive) # module Stance + + # + # Used to indicate that an exploit takes an aggressive stance. This + # means that the exploit proactively triggers a vulnerability. + # Aggressive = "aggresive" + + # + # Used to indicate that an exploit takes a passive stance. This means + # that the exploit waits for interaction from a client or other entity + # before being able to trigger the vulnerability. + # Passive = "passive" end @@ -94,6 +138,10 @@ class Exploit < Msf::Module # ### class Local < Exploit + + # + # Returns the fact that this exploit is a local exploit. + # def exploit_type Exploit::Type::Local end @@ -111,6 +159,10 @@ class Exploit < Msf::Module # ### class Remote < Exploit + + # + # Returns the fact that this exploit is a remote exploit. + # def exploit_type Exploit::Type::Remote end @@ -122,7 +174,7 @@ class Exploit < Msf::Module require 'msf/core/exploit/smb' # - # Constructo the clown! Watch as he kills small children with balloons. + # Creates an instance of the exploit module. Mad skillz. # def initialize(info = {}) super(info) @@ -148,6 +200,8 @@ class Exploit < Msf::Module # Checks to see if the target is vulnerable, returning unsupported if it's # not supported. # + # This method is designed to be overriden by exploit modules. + # def check CheckCode::Unsupported end @@ -156,7 +210,9 @@ class Exploit < Msf::Module # Kicks off the actual exploit. Prior to this call, the framework will # have validated the data store using the options associated with this # exploit module. It will also pre-generate the desired payload, though - # exploits can re-generate the payload if necessary. + # exploits can re-generate the payload if necessary. + # + # This method is designed to be overriden by exploit modules. # def exploit end @@ -252,16 +308,23 @@ class Exploit < Msf::Module # ## + # + # Returns true if the exploit module supports the check method. + # def supports_check? derived_implementor?(Msf::Exploit, 'check') end + # + # Returns true if the exploit module supports the exploit method. + # def supports_exploit? derived_implementor?(Msf::Exploit, 'exploit') end # - # Returns a hash of the capabilities this exploit module has + # Returns a hash of the capabilities this exploit module has support for, + # such as whether or not it supports check and exploit. # def capabilities { @@ -280,12 +343,15 @@ class Exploit < Msf::Module ## # - # The module's type + # Returns MODULE_EXPLOIT to indicate that this is an exploit module. # def self.type MODULE_EXPLOIT end + # + # Returns MODULE_EXPLOIT to indicate that this is an exploit module. + # def type MODULE_EXPLOIT end @@ -581,8 +647,17 @@ class Exploit < Msf::Module protected + # + # Writable copy of the list of targets. + # attr_writer :targets + # + # Writable copy of the default target. + # attr_writer :default_target + # + # Writable copy of the payload requirement hash. + # attr_writer :payload_info # @@ -600,6 +675,14 @@ protected CompatDefaults::Payload.each_pair { |k,v| (p[k]) ? p[k] << v : p[k] = v } + + # + # Set the default save registers if none have been explicitly + # specified. + # + if (module_info['SaveRegisters'] == nil) + module_info['SaveRegisters'] = [ 'esp', 'ebp' ] + end end end diff --git a/lib/msf/core/exploit_driver.rb b/lib/msf/core/exploit_driver.rb index 9eae7f4aee..ea8d2f4ef0 100644 --- a/lib/msf/core/exploit_driver.rb +++ b/lib/msf/core/exploit_driver.rb @@ -141,15 +141,15 @@ class ExploitDriver return session end - attr_reader :target_idx - attr_accessor :exploit - attr_accessor :payload - attr_accessor :use_job - attr_accessor :force_wait_for_session + attr_reader :target_idx # :nodoc: + attr_accessor :exploit # :nodoc: + attr_accessor :payload # :nodoc: + attr_accessor :use_job # :nodoc: + attr_accessor :force_wait_for_session # :nodoc: protected - attr_accessor :session + attr_accessor :session # :nodoc: # # Job run proc, sets up the exploit and kicks it off. diff --git a/lib/msf/core/nop.rb b/lib/msf/core/nop.rb index b519c5649b..e504792b5c 100644 --- a/lib/msf/core/nop.rb +++ b/lib/msf/core/nop.rb @@ -12,11 +12,16 @@ module Msf ### class Nop < Msf::Module - # NOP module, bitch! + # + # Returns MODULE_NOP to indicate that this is a NOP module. + # def self.type return MODULE_NOP end + # + # Returns MODULE_NOP to indicate that this is a NOP module. + # def type return MODULE_NOP end diff --git a/lib/msf/core/payload.rb b/lib/msf/core/payload.rb index 79b47559f3..3d8d695f27 100644 --- a/lib/msf/core/payload.rb +++ b/lib/msf/core/payload.rb @@ -24,8 +24,24 @@ class Payload < Msf::Module # Payload types # module Type + # + # Single payload type. These types of payloads are self contained and + # do not go through any staging. + # Single = (1 << 0) + + # + # The stager half of a staged payload. Its responsibility in life is to + # read in the stage and execute it. + # Stager = (1 << 1) + + # + # The stage half of a staged payload. This payload performs whatever + # arbitrary task it's designed to do, possibly making use of the same + # connection that the stager used to read the stage in on, if + # applicable. + # Stage = (1 << 2) end @@ -45,12 +61,15 @@ class Payload < Msf::Module ## # - # This module is a payload. + # Returns MODULE_PAYLOAD to indicate that this is a payload module. # def self.type return MODULE_PAYLOAD end + # + # Returns MODULE_PAYLOAD to indicate that this is a payload module. + # def type return MODULE_PAYLOAD end @@ -120,7 +139,8 @@ class Payload < Msf::Module end # - # The method used to resolve symbols by the payload. + # Returns the method used by the payload to resolve symbols for the purpose + # of calling functions, such as ws2ord. # def symbol_lookup module_info['SymbolLookup'] @@ -172,14 +192,16 @@ class Payload < Msf::Module ## # - # Make sure all our required options are set. + # This method ensures that the options associated with this payload all + # have valid values according to each required option in the option + # container. # def validate self.options.validate(self.datastore) end # - # Generates the payload and return the raw buffer + # Generates the payload and returns the raw buffer to the caller. # def generate raw = payload.dup @@ -271,8 +293,21 @@ class Payload < Msf::Module return nops end - # Payload prepending and appending for various situations - attr_accessor :prepend, :append, :prepend_encoder + # + # This attribute holds the string that should be prepended to the buffer + # when it's generated. + # + attr_accessor :prepend + # + # This attribute holds the string that should be appended to the buffer + # when it's generated. + # + attr_accessor :append + # + # This attribute holds the string that should be prepended to the encoded + # version of the payload (in front of the encoder as well). + # + attr_accessor :prepend_encoder protected