Class: Msf::OptionContainer
- Inherits:
-
Hash
- Object
- Hash
- Msf::OptionContainer
- Defined in:
- lib/msf/core/option_container.rb
Overview
The options purpose in life is to associate named options with arbitrary values at the most simplistic level. Each Module contains an OptionContainer that is used to hold the various options that the module depends on. Example of options that are stored in the OptionContainer are rhost and rport for payloads or exploits that need to connect to a host and port, for instance.
The core supported option types are:
-
OptString - Multi-byte character string
-
OptRaw - Multi-byte raw string
-
OptBool - Boolean true or false indication
-
OptPort - TCP/UDP service port
-
OptAddress - IP address or hostname
-
OptPath - Path name on disk or an Object ID
-
OptInt - An integer value
-
OptFloat - A float value
-
OptEnum - Select from a set of valid values
-
OptAddressRange - A subnet or range of addresses
-
OptRegexp - Valid Ruby regular expression
Instance Attribute Summary collapse
- #groups ⇒ Hash<String, Msf::OptionGroup>
-
#sorted ⇒ Object
The sorted array of options.
Instance Method Summary collapse
-
#[](name) ⇒ Object
Return the value associated with the supplied name.
-
#add_advanced_options(opts, owner = nil) ⇒ Object
Alias to add advanced options that sets the proper state flag.
-
#add_evasion_options(opts, owner = nil) ⇒ Object
Alias to add evasion options that sets the proper state flag.
-
#add_group(option_group) ⇒ Object
Adds an option group to the container.
-
#add_option(option, name = nil, owner = nil, advanced = false, evasion = false) ⇒ Object
Adds an option.
-
#add_options(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Adds one or more options.
-
#add_options_array(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Add options from an array of option instances or arrays.
-
#add_options_hash(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Add options from a hash of names.
-
#each(&block) ⇒ Object
Overrides the builtin ‘each’ operator to avoid the following exception on Ruby 1.9.2+ “can’t add a new key into hash during iteration”.
-
#each_option(&block) ⇒ Object
Enumerates each option name.
-
#get(name) ⇒ Object
Return the option associated with the supplied name.
-
#has_advanced_options? ⇒ Boolean
Returns whether or not the container has any advanced options.
-
#has_evasion_options? ⇒ Boolean
Returns whether or not the container has any evasion options.
-
#has_options? ⇒ Boolean
Returns whether or not the container has any options, excluding advanced (and evasions).
-
#initialize(opts = {}) ⇒ OptionContainer
constructor
Merges in the supplied options and converts them to a OptBase as necessary.
-
#merge_sort(other_container) ⇒ Object
Merges the options in this container with another option container and returns the sorted results.
-
#options_used_to_s(datastore) ⇒ Object
Creates string of options that were used from the datastore in VAR=VAL format separated by commas.
-
#remove_group(group_name) ⇒ Object
Removes an option group from the container by name.
-
#remove_option(name) ⇒ Object
Removes an option.
-
#validate(datastore) ⇒ Object
Make sures that each of the options has a value of a compatible format and that all the required options are set.
Constructor Details
#initialize(opts = {}) ⇒ OptionContainer
Merges in the supplied options and converts them to a OptBase as necessary.
50 51 52 53 54 55 |
# File 'lib/msf/core/option_container.rb', line 50 def initialize(opts = {}) self.sorted = [] self.groups = {} (opts) end |
Instance Attribute Details
#groups ⇒ Hash<String, Msf::OptionGroup>
337 338 339 |
# File 'lib/msf/core/option_container.rb', line 337 def groups @groups end |
#sorted ⇒ Object
The sorted array of options.
334 335 336 |
# File 'lib/msf/core/option_container.rb', line 334 def sorted @sorted end |
Instance Method Details
#[](name) ⇒ Object
Return the value associated with the supplied name.
60 61 62 |
# File 'lib/msf/core/option_container.rb', line 60 def [](name) return get(name) end |
#add_advanced_options(opts, owner = nil) ⇒ Object
Alias to add advanced options that sets the proper state flag.
179 180 181 182 183 |
# File 'lib/msf/core/option_container.rb', line 179 def (opts, owner = nil) return false if (opts == nil) (opts, owner, true) end |
#add_evasion_options(opts, owner = nil) ⇒ Object
Alias to add evasion options that sets the proper state flag.
188 189 190 191 192 |
# File 'lib/msf/core/option_container.rb', line 188 def (opts, owner = nil) return false if (opts == nil) (opts, owner, false, true) end |
#add_group(option_group) ⇒ Object
Adds an option group to the container
320 321 322 |
# File 'lib/msf/core/option_container.rb', line 320 def add_group(option_group) groups[option_group.name] = option_group end |
#add_option(option, name = nil, owner = nil, advanced = false, evasion = false) ⇒ Object
Adds an option.
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/msf/core/option_container.rb', line 157 def add_option(option, name = nil, owner = nil, advanced = false, evasion = false) if option.kind_of?(Array) option = option.shift.new(name, option) elsif !option.kind_of?(OptBase) raise ArgumentError, "The option named #{name} did not come in a compatible format.", caller end option.advanced = advanced option.evasion = evasion option.owner = owner self.store(option.name, option) # Re-calculate the sorted list self.sorted = self.sort end |
#add_options(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Adds one or more options.
126 127 128 129 130 131 132 133 134 |
# File 'lib/msf/core/option_container.rb', line 126 def (opts, owner = nil, advanced = false, evasion = false) return false if (opts == nil) if opts.kind_of?(Array) (opts, owner, advanced, evasion) else (opts, owner, advanced, evasion) end end |
#add_options_array(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Add options from an array of option instances or arrays.
148 149 150 151 152 |
# File 'lib/msf/core/option_container.rb', line 148 def (opts, owner = nil, advanced = false, evasion = false) opts.each { |opt| add_option(opt, nil, owner, advanced, evasion) } end |
#add_options_hash(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Add options from a hash of names.
139 140 141 142 143 |
# File 'lib/msf/core/option_container.rb', line 139 def (opts, owner = nil, advanced = false, evasion = false) opts.each_pair { |name, opt| add_option(opt, name, owner, advanced, evasion) } end |
#each(&block) ⇒ Object
Overrides the builtin ‘each’ operator to avoid the following exception on Ruby 1.9.2+
"can't add a new key into hash during iteration"
293 294 295 296 297 298 299 |
# File 'lib/msf/core/option_container.rb', line 293 def each(&block) list = [] self.keys.sort.each do |sidx| list << [sidx, self[sidx]] end list.each(&block) end |
#each_option(&block) ⇒ Object
Enumerates each option name
285 286 287 |
# File 'lib/msf/core/option_container.rb', line 285 def each_option(&block) each_pair(&block) end |
#get(name) ⇒ Object
Return the option associated with the supplied name.
67 68 69 70 71 72 |
# File 'lib/msf/core/option_container.rb', line 67 def get(name) begin return fetch(name) rescue end end |
#has_advanced_options? ⇒ Boolean
Returns whether or not the container has any advanced options.
91 92 93 94 95 96 97 |
# File 'lib/msf/core/option_container.rb', line 91 def each_option { |name, opt| return true if (opt.advanced? == true) } return false end |
#has_evasion_options? ⇒ Boolean
Returns whether or not the container has any evasion options.
103 104 105 106 107 108 109 |
# File 'lib/msf/core/option_container.rb', line 103 def each_option { |name, opt| return true if (opt.evasion? == true) } return false end |
#has_options? ⇒ Boolean
Returns whether or not the container has any options, excluding advanced (and evasions).
78 79 80 81 82 83 84 85 |
# File 'lib/msf/core/option_container.rb', line 78 def each_option { |name, opt| return true if (opt.advanced? == false) } return false end |
#merge_sort(other_container) ⇒ Object
Merges the options in this container with another option container and returns the sorted results.
305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/msf/core/option_container.rb', line 305 def merge_sort(other_container) result = self.dup other_container.each { |name, opt| if (result.get(name) == nil) result[name] = opt end } result.sort end |
#options_used_to_s(datastore) ⇒ Object
Creates string of options that were used from the datastore in VAR=VAL format separated by commas.
269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/msf/core/option_container.rb', line 269 def (datastore) used = '' each_pair { |name, option| next if (datastore[name] == nil) used += ", " if (used.length > 0) used += "#{name}=#{datastore[name]}" } return used end |
#remove_group(group_name) ⇒ Object
Removes an option group from the container by name
327 328 329 |
# File 'lib/msf/core/option_container.rb', line 327 def remove_group(group_name) groups.delete(group_name) end |
#remove_option(name) ⇒ Object
Removes an option.
115 116 117 118 119 120 121 |
# File 'lib/msf/core/option_container.rb', line 115 def remove_option(name) delete(name) sorted.each_with_index { |e, idx| sorted[idx] = nil if (e[0] == name) } sorted.delete(nil) end |
#validate(datastore) ⇒ Object
Make sures that each of the options has a value of a compatible format and that all the required options are set.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/msf/core/option_container.rb', line 197 def validate(datastore) # First mutate the datastore and normalize all valid values before validating permutations of RHOST/etc. each_pair do |name, option| if option.valid?(datastore[name]) && (val = option.normalize(datastore[name])) != nil # This *will* result in a module that previously used the # global datastore to have its local datastore set, which # means that changing the global datastore and re-running # the same module will now use the newly-normalized local # datastore value instead. This is mostly mitigated by # forcing a clone through mod.replicant, but can break # things in corner cases. datastore[name] = val end end # Validate all permutations of rhost combinations if include?('RHOSTS') && !(datastore['RHOSTS'].blank? && !self['RHOSTS'].required) = Set.new error_reasons = Hash.new do |hash, key| hash[key] = [] end rhosts_walker = Msf::RhostsWalker.new(datastore['RHOSTS'], datastore) rhosts_count = rhosts_walker.count unless rhosts_walker.valid? errors = rhosts_walker.to_enum(:errors).to_a grouped = errors.group_by { |err| err.cause.nil? ? nil : (err.cause.class.const_defined?(:MESSAGE) ? err.cause.class::MESSAGE : nil) } << 'RHOSTS' if grouped.any? grouped.each do | , error_subset | invalid_values = error_subset.map(&:value).take(5) = 'Unexpected values' if .nil? error_reasons['RHOSTS'] << "#{}: #{invalid_values.join(', ')}" end end end rhosts_walker.each do |datastore| each_pair do |name, option| unless option.valid?(datastore[name]) << name if rhosts_count > 1 error_reasons[name] << "for rhosts value #{datastore['UNPARSED_RHOSTS']}" end end end end unless .empty? raise Msf::OptionValidateError.new(.to_a, reasons: error_reasons), "One or more options failed to validate: #{.to_a.join(', ')}." end else = [] each_pair do |name, option| unless option.valid?(datastore[name]) << name end end unless .empty? raise Msf::OptionValidateError.new(), "One or more options failed to validate: #{.join(', ')}." end end true end |