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.
52 53 54 55 56 57 |
# File 'lib/msf/core/option_container.rb', line 52 def initialize(opts = {}) self.sorted = [] self.groups = {} (opts) end |
Instance Attribute Details
#groups ⇒ Hash<String, Msf::OptionGroup>
339 340 341 |
# File 'lib/msf/core/option_container.rb', line 339 def groups @groups end |
#sorted ⇒ Object
The sorted array of options.
336 337 338 |
# File 'lib/msf/core/option_container.rb', line 336 def sorted @sorted end |
Instance Method Details
#[](name) ⇒ Object
Return the value associated with the supplied name.
62 63 64 |
# File 'lib/msf/core/option_container.rb', line 62 def [](name) return get(name) end |
#add_advanced_options(opts, owner = nil) ⇒ Object
Alias to add advanced options that sets the proper state flag.
181 182 183 184 185 |
# File 'lib/msf/core/option_container.rb', line 181 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.
190 191 192 193 194 |
# File 'lib/msf/core/option_container.rb', line 190 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
322 323 324 |
# File 'lib/msf/core/option_container.rb', line 322 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.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/msf/core/option_container.rb', line 159 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.
128 129 130 131 132 133 134 135 136 |
# File 'lib/msf/core/option_container.rb', line 128 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.
150 151 152 153 154 |
# File 'lib/msf/core/option_container.rb', line 150 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.
141 142 143 144 145 |
# File 'lib/msf/core/option_container.rb', line 141 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"
295 296 297 298 299 300 301 |
# File 'lib/msf/core/option_container.rb', line 295 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
287 288 289 |
# File 'lib/msf/core/option_container.rb', line 287 def each_option(&block) each_pair(&block) end |
#get(name) ⇒ Object
Return the option associated with the supplied name.
69 70 71 72 73 74 |
# File 'lib/msf/core/option_container.rb', line 69 def get(name) begin return fetch(name) rescue end end |
#has_advanced_options? ⇒ Boolean
Returns whether or not the container has any advanced options.
93 94 95 96 97 98 99 |
# File 'lib/msf/core/option_container.rb', line 93 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.
105 106 107 108 109 110 111 |
# File 'lib/msf/core/option_container.rb', line 105 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).
80 81 82 83 84 85 86 87 |
# File 'lib/msf/core/option_container.rb', line 80 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.
307 308 309 310 311 312 313 314 315 316 317 |
# File 'lib/msf/core/option_container.rb', line 307 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.
271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/msf/core/option_container.rb', line 271 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
329 330 331 |
# File 'lib/msf/core/option_container.rb', line 329 def remove_group(group_name) groups.delete(group_name) end |
#remove_option(name) ⇒ Object
Removes an option.
117 118 119 120 121 122 123 |
# File 'lib/msf/core/option_container.rb', line 117 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.
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 264 265 |
# File 'lib/msf/core/option_container.rb', line 199 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 |