2005-05-21 17:57:00 +00:00
|
|
|
require 'resolv'
|
2005-07-09 21:18:49 +00:00
|
|
|
require 'msf/core'
|
2006-08-12 08:31:38 +00:00
|
|
|
require 'rex/socket'
|
2005-05-21 17:57:00 +00:00
|
|
|
|
|
|
|
module Msf
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
2005-05-21 18:27:24 +00:00
|
|
|
# The base class for all options.
|
2005-05-21 17:57:00 +00:00
|
|
|
#
|
|
|
|
###
|
2005-05-21 18:27:24 +00:00
|
|
|
class OptBase
|
2005-05-21 17:57:00 +00:00
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Initializes a named option with the supplied attribute array.
|
|
|
|
# The array is composed of three values.
|
|
|
|
#
|
|
|
|
# attrs[0] = required (boolean type)
|
|
|
|
# attrs[1] = description (string)
|
|
|
|
# attrs[2] = default value
|
2006-01-16 23:30:59 +00:00
|
|
|
# attrs[3] = possible enum values
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
2005-05-21 17:57:00 +00:00
|
|
|
def initialize(in_name, attrs = [])
|
2005-05-21 18:27:24 +00:00
|
|
|
self.name = in_name
|
|
|
|
self.advanced = false
|
2006-01-05 03:57:12 +00:00
|
|
|
self.evasion = false
|
2005-05-21 18:27:24 +00:00
|
|
|
self.required = attrs[0] || false
|
2005-06-05 08:38:24 +00:00
|
|
|
self.desc = attrs[1]
|
|
|
|
self.default = attrs[2]
|
2006-01-16 23:32:51 +00:00
|
|
|
self.enums = [ *(attrs[3]) ].map { |x| x.to_s }
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Returns true if this is a required option.
|
|
|
|
#
|
2005-05-21 17:57:00 +00:00
|
|
|
def required?
|
|
|
|
return required
|
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Returns true if this is an advanced option.
|
|
|
|
#
|
2005-05-21 17:57:00 +00:00
|
|
|
def advanced?
|
|
|
|
return advanced
|
|
|
|
end
|
|
|
|
|
2006-01-05 03:57:12 +00:00
|
|
|
#
|
|
|
|
# Returns true if this is an evasion option.
|
|
|
|
#
|
|
|
|
def evasion?
|
|
|
|
return evasion
|
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Returns true if the supplied type is equivalent to this option's type.
|
|
|
|
#
|
2005-05-21 17:57:00 +00:00
|
|
|
def type?(in_type)
|
|
|
|
return (type == in_type)
|
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
2005-05-21 18:27:24 +00:00
|
|
|
# If it's required and the value is nil or empty, then it's not valid.
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
2005-05-21 18:27:24 +00:00
|
|
|
def valid?(value)
|
|
|
|
return (required? and (value == nil or value.to_s.empty?)) ? false : true
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
2007-03-09 06:12:28 +00:00
|
|
|
#
|
|
|
|
# Returns true if the value supplied is nil and it's required to be
|
|
|
|
# a valid value
|
|
|
|
#
|
|
|
|
def empty_required_value?(value)
|
|
|
|
return (required? and value.nil?)
|
|
|
|
end
|
|
|
|
|
2005-11-15 21:50:10 +00:00
|
|
|
#
|
|
|
|
# Normalizes the supplied value to conform with the type that the option is
|
|
|
|
# conveying.
|
|
|
|
#
|
|
|
|
def normalize(value)
|
|
|
|
value
|
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Returns the value of the option as a string.
|
|
|
|
#
|
2005-07-11 02:03:48 +00:00
|
|
|
def to_s
|
|
|
|
return value.to_s
|
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# The name of the option.
|
|
|
|
#
|
|
|
|
attr_reader :name
|
|
|
|
#
|
|
|
|
# Whether or not the option is required.
|
|
|
|
#
|
|
|
|
attr_reader :required
|
|
|
|
#
|
|
|
|
# The description of the option.
|
|
|
|
#
|
|
|
|
attr_reader :desc
|
|
|
|
#
|
|
|
|
# The default value of the option.
|
|
|
|
#
|
|
|
|
attr_reader :default
|
|
|
|
#
|
|
|
|
# Storing the name of the option.
|
|
|
|
#
|
2005-05-21 18:27:24 +00:00
|
|
|
attr_writer :name
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Whether or not this is an advanced option.
|
|
|
|
#
|
2005-05-21 17:57:00 +00:00
|
|
|
attr_accessor :advanced
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
2006-01-05 03:57:12 +00:00
|
|
|
# Whether or not this is an evasion option.
|
|
|
|
#
|
|
|
|
attr_accessor :evasion
|
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# The module or entity that owns this option.
|
|
|
|
#
|
2005-06-05 23:45:58 +00:00
|
|
|
attr_accessor :owner
|
2006-01-16 23:30:59 +00:00
|
|
|
#
|
|
|
|
# The list of potential valid values
|
|
|
|
#
|
|
|
|
attr_accessor :enums
|
2005-05-21 17:57:00 +00:00
|
|
|
|
|
|
|
protected
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
attr_writer :required, :desc, :default # :nodoc:
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
2005-05-21 18:27:24 +00:00
|
|
|
# Core option types. The core supported option types are:
|
2005-05-21 17:57:00 +00:00
|
|
|
#
|
|
|
|
# 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
|
2005-07-18 23:32:34 +00:00
|
|
|
# OptInt - An integer value
|
2006-01-16 23:30:59 +00:00
|
|
|
# OptEnum - Select from a set of valid values
|
2006-08-12 08:31:38 +00:00
|
|
|
# OptAddressRange - A subnet or range of addresses
|
2005-05-21 17:57:00 +00:00
|
|
|
#
|
|
|
|
###
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Mult-byte character string option.
|
|
|
|
#
|
|
|
|
###
|
2005-05-21 18:27:24 +00:00
|
|
|
class OptString < OptBase
|
2005-05-21 17:57:00 +00:00
|
|
|
def type
|
|
|
|
return 'string'
|
|
|
|
end
|
2007-04-24 06:27:39 +00:00
|
|
|
|
|
|
|
def normalize(value)
|
|
|
|
if (value =~ /^file:(.*)/)
|
|
|
|
path = $1
|
|
|
|
begin
|
2007-04-24 06:37:23 +00:00
|
|
|
value = File.read(path)
|
2007-04-24 06:27:39 +00:00
|
|
|
rescue ::Errno::ENOENT, ::Errno::EISDIR
|
|
|
|
value = nil
|
|
|
|
end
|
|
|
|
end
|
2007-04-24 13:47:46 +00:00
|
|
|
value
|
2007-04-24 06:27:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def valid?(value=self.value)
|
|
|
|
value = normalize(value)
|
|
|
|
return false if empty_required_value?(value)
|
2007-04-24 13:47:46 +00:00
|
|
|
return super
|
2007-04-24 06:27:39 +00:00
|
|
|
end
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Raw, arbitrary data option.
|
|
|
|
#
|
|
|
|
###
|
2005-05-21 18:27:24 +00:00
|
|
|
class OptRaw < OptBase
|
2005-05-21 17:57:00 +00:00
|
|
|
def type
|
|
|
|
return 'raw'
|
|
|
|
end
|
2007-04-24 06:27:39 +00:00
|
|
|
|
|
|
|
def normalize(value)
|
|
|
|
if (value =~ /^file:(.*)/)
|
|
|
|
path = $1
|
|
|
|
begin
|
2007-04-24 06:37:23 +00:00
|
|
|
value = File.read(path)
|
2007-04-24 06:27:39 +00:00
|
|
|
rescue ::Errno::ENOENT, ::Errno::EISDIR
|
|
|
|
value = nil
|
|
|
|
end
|
|
|
|
end
|
2007-04-24 13:47:46 +00:00
|
|
|
value
|
2007-04-24 06:27:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def valid?(value=self.value)
|
|
|
|
value = normalize(value)
|
|
|
|
return false if empty_required_value?(value)
|
2007-04-24 13:47:46 +00:00
|
|
|
return super
|
2007-04-24 06:27:39 +00:00
|
|
|
end
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Boolean option.
|
|
|
|
#
|
|
|
|
###
|
2005-05-21 18:27:24 +00:00
|
|
|
class OptBool < OptBase
|
2005-11-15 21:50:10 +00:00
|
|
|
|
|
|
|
TrueRegex = /^(y|yes|t|1|true)$/i
|
|
|
|
|
2005-05-21 17:57:00 +00:00
|
|
|
def type
|
|
|
|
return 'bool'
|
|
|
|
end
|
|
|
|
|
2005-05-21 18:27:24 +00:00
|
|
|
def valid?(value)
|
2007-03-09 06:12:28 +00:00
|
|
|
return false if empty_required_value?(value)
|
|
|
|
|
2005-11-17 23:03:53 +00:00
|
|
|
if ((value != nil and
|
|
|
|
(value.to_s.empty? == false) and
|
|
|
|
(value.to_s.match(/^(y|yes|n|no|t|f|0|1|true|false)$/i) == nil)))
|
2005-05-21 17:57:00 +00:00
|
|
|
return false
|
|
|
|
end
|
2005-09-24 19:17:07 +00:00
|
|
|
|
|
|
|
true
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
2005-11-15 21:50:10 +00:00
|
|
|
def normalize(value)
|
2005-11-18 00:26:19 +00:00
|
|
|
if(value.nil? or value.to_s.match(TrueRegex).nil?)
|
2005-11-15 21:50:10 +00:00
|
|
|
false
|
2005-11-15 23:02:17 +00:00
|
|
|
else
|
|
|
|
true
|
2005-11-15 21:50:10 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-05-21 17:57:00 +00:00
|
|
|
def is_true?
|
2005-09-24 19:17:07 +00:00
|
|
|
return (value.match(/^(y|yes|t|1|true)$/i) != nil) ? true : false
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def is_false?
|
|
|
|
return !is_true?
|
|
|
|
end
|
2005-07-11 02:03:48 +00:00
|
|
|
|
|
|
|
def to_s
|
|
|
|
return is_true?.to_s
|
|
|
|
end
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
2006-01-16 23:30:59 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Enum option.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class OptEnum < OptBase
|
|
|
|
|
|
|
|
def type
|
|
|
|
return 'enum'
|
|
|
|
end
|
|
|
|
|
|
|
|
def valid?(value=self.value)
|
2007-03-09 06:12:28 +00:00
|
|
|
return false if empty_required_value?(value)
|
|
|
|
|
2006-01-16 23:30:59 +00:00
|
|
|
(value and self.enums.include?(value.to_s))
|
|
|
|
end
|
|
|
|
|
|
|
|
def normalize(value=self.value)
|
|
|
|
return nil if not self.valid?(value)
|
|
|
|
return value.to_s
|
|
|
|
end
|
2006-01-25 19:15:09 +00:00
|
|
|
|
|
|
|
def desc=(value)
|
|
|
|
self.desc_string = value
|
|
|
|
|
|
|
|
self.desc
|
|
|
|
end
|
|
|
|
|
|
|
|
def desc
|
|
|
|
if self.enums
|
|
|
|
str = self.enums.join(', ')
|
|
|
|
end
|
|
|
|
"#{self.desc_string || ''} (accepted: #{str})"
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
attr_accessor :desc_string # :nodoc:
|
|
|
|
|
2006-01-16 23:30:59 +00:00
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Network port option.
|
|
|
|
#
|
|
|
|
###
|
2005-05-21 18:27:24 +00:00
|
|
|
class OptPort < OptBase
|
2005-05-21 17:57:00 +00:00
|
|
|
def type
|
|
|
|
return 'port'
|
|
|
|
end
|
|
|
|
|
2005-05-21 18:27:24 +00:00
|
|
|
def valid?(value)
|
2007-03-09 06:12:28 +00:00
|
|
|
return false if empty_required_value?(value)
|
|
|
|
|
2005-05-21 18:27:24 +00:00
|
|
|
if ((value != nil and value.to_s.empty? == false) and
|
2005-07-17 08:03:54 +00:00
|
|
|
((value.to_s.match(/^\d+$/) == nil or value.to_i < 0 or value.to_i > 65535)))
|
2005-05-21 17:57:00 +00:00
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
return super
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Network address option.
|
|
|
|
#
|
|
|
|
###
|
2005-05-21 18:27:24 +00:00
|
|
|
class OptAddress < OptBase
|
2005-05-21 17:57:00 +00:00
|
|
|
def type
|
|
|
|
return 'address'
|
|
|
|
end
|
|
|
|
|
2005-05-21 18:27:24 +00:00
|
|
|
def valid?(value)
|
2007-03-09 06:12:28 +00:00
|
|
|
return false if empty_required_value?(value)
|
|
|
|
|
2005-05-21 18:27:24 +00:00
|
|
|
if (value != nil and value.empty? == false)
|
2005-05-21 17:57:00 +00:00
|
|
|
begin
|
|
|
|
Resolv.getaddress(value)
|
|
|
|
rescue
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return super
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2006-08-12 08:31:38 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Network address range option.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class OptAddressRange < OptBase
|
|
|
|
def type
|
|
|
|
return 'addressrange'
|
|
|
|
end
|
|
|
|
|
|
|
|
def normalize(value)
|
|
|
|
|
2007-04-24 06:27:39 +00:00
|
|
|
if (value =~ /^file:(.*)/)
|
|
|
|
path = $1
|
|
|
|
begin
|
|
|
|
value = File.readlines(path).map{ |s| s.strip}.join(",")
|
|
|
|
rescue ::Errno::ENOENT, ::Errno::EISDIR
|
|
|
|
value = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2006-08-12 08:31:38 +00:00
|
|
|
sets = []
|
|
|
|
return '' if not value
|
|
|
|
|
|
|
|
ranges = value.split(',')
|
|
|
|
ranges.each do |range|
|
|
|
|
begin
|
|
|
|
case range
|
2007-07-16 13:52:11 +00:00
|
|
|
when /[0-9]+-[0-9]+/
|
2006-08-12 08:31:38 +00:00
|
|
|
tmp = range.split('-')
|
|
|
|
next if tmp.length != 2
|
|
|
|
|
2006-08-12 23:08:20 +00:00
|
|
|
if (Rex::Socket.addr_atoi(tmp[0]) <= Rex::Socket.addr_atoi(tmp[1]))
|
2006-08-12 08:31:38 +00:00
|
|
|
sets << tmp
|
|
|
|
end
|
|
|
|
|
|
|
|
when /\//
|
|
|
|
sets << Rex::Socket.cidr_crack(range)
|
|
|
|
else
|
|
|
|
tmp = Rex::Socket.addr_itoa(Rex::Socket.addr_atoi(range))
|
|
|
|
sets << [tmp, tmp]
|
|
|
|
end
|
2007-04-29 23:43:39 +00:00
|
|
|
rescue ::Exception => e
|
2007-07-16 13:52:11 +00:00
|
|
|
raise e
|
2006-08-12 08:31:38 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return sets.map{|i| i[0]+'-'+i[1]}.join(',')
|
|
|
|
end
|
|
|
|
|
|
|
|
def valid?(value)
|
2007-03-09 06:12:28 +00:00
|
|
|
return false if empty_required_value?(value)
|
|
|
|
|
2006-08-12 08:31:38 +00:00
|
|
|
if (value != nil and value.empty? == false)
|
|
|
|
begin
|
|
|
|
return (normalize(value).length > 0 ? true : false)
|
|
|
|
rescue
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return super
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# File system path option.
|
|
|
|
#
|
|
|
|
###
|
2005-05-21 18:27:24 +00:00
|
|
|
class OptPath < OptBase
|
2005-05-21 17:57:00 +00:00
|
|
|
def type
|
|
|
|
return 'path'
|
|
|
|
end
|
|
|
|
|
2005-05-21 18:27:24 +00:00
|
|
|
def valid?(value)
|
2007-03-09 06:12:28 +00:00
|
|
|
return false if empty_required_value?(value)
|
|
|
|
|
2005-05-21 18:27:24 +00:00
|
|
|
if ((value != nil and value.empty? == false) and
|
2005-05-21 17:57:00 +00:00
|
|
|
(File.exists?(value) == false))
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
return super
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Integer option.
|
|
|
|
#
|
|
|
|
###
|
2005-09-15 07:16:03 +00:00
|
|
|
class OptInt < OptBase
|
2005-07-18 23:32:34 +00:00
|
|
|
def type
|
|
|
|
return 'integer'
|
|
|
|
end
|
|
|
|
|
2005-11-15 21:50:10 +00:00
|
|
|
def normalize(value)
|
2007-04-05 05:00:55 +00:00
|
|
|
if (value.to_s.match(/^0x[a-fA-F\d]+$/))
|
|
|
|
value.to_i(16)
|
|
|
|
else
|
|
|
|
value.to_i
|
|
|
|
end
|
2005-11-15 21:50:10 +00:00
|
|
|
end
|
|
|
|
|
2005-07-18 23:32:34 +00:00
|
|
|
def valid?(value)
|
2007-03-09 06:12:28 +00:00
|
|
|
return false if empty_required_value?(value)
|
|
|
|
|
2007-04-05 05:00:55 +00:00
|
|
|
if value and not normalize(value).to_s.match(/^\d+$/)
|
2005-07-18 23:32:34 +00:00
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
return super
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2005-05-21 17:57:00 +00:00
|
|
|
###
|
|
|
|
#
|
2005-05-21 18:27:24 +00:00
|
|
|
# The options purpose in life is to associate named options
|
2005-05-21 17:57:00 +00:00
|
|
|
# with arbitrary values at the most simplistic level. Each
|
2005-05-21 18:27:24 +00:00
|
|
|
# module contains a OptionContainer that is used to hold the
|
2005-05-21 17:57:00 +00:00
|
|
|
# various options that the module depends on. Example of options
|
2005-05-21 18:27:24 +00:00
|
|
|
# that are stored in the OptionContainer are rhost and rport for
|
2005-05-21 17:57:00 +00:00
|
|
|
# payloads or exploits that need to connect to a host and
|
|
|
|
# port, for instance.
|
|
|
|
#
|
|
|
|
###
|
2005-05-21 18:27:24 +00:00
|
|
|
class OptionContainer < Hash
|
2005-05-21 17:57:00 +00:00
|
|
|
|
2005-07-10 00:49:12 +00:00
|
|
|
#
|
2005-05-21 18:27:24 +00:00
|
|
|
# Merges in the supplied options and converts them to a OptBase
|
2005-05-21 17:57:00 +00:00
|
|
|
# as necessary.
|
2005-07-10 00:49:12 +00:00
|
|
|
#
|
2005-05-21 17:57:00 +00:00
|
|
|
def initialize(opts = {})
|
2005-07-11 15:34:31 +00:00
|
|
|
self.sorted = []
|
|
|
|
|
2005-05-21 17:57:00 +00:00
|
|
|
add_options(opts)
|
|
|
|
end
|
|
|
|
|
2005-07-10 00:49:12 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Return the value associated with the supplied name.
|
2005-07-10 00:49:12 +00:00
|
|
|
#
|
2005-05-21 17:57:00 +00:00
|
|
|
def [](name)
|
|
|
|
return get(name)
|
|
|
|
end
|
|
|
|
|
2005-07-10 00:49:12 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Return the option associated with the supplied name.
|
2005-07-10 00:49:12 +00:00
|
|
|
#
|
2005-05-21 17:57:00 +00:00
|
|
|
def get(name)
|
2005-06-05 05:42:14 +00:00
|
|
|
begin
|
|
|
|
return fetch(name)
|
|
|
|
rescue
|
|
|
|
end
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
2005-07-10 00:49:12 +00:00
|
|
|
#
|
|
|
|
# Returns whether or not the container has any options,
|
2006-01-05 03:57:12 +00:00
|
|
|
# excluding advanced (and evasions).
|
2005-07-10 00:49:12 +00:00
|
|
|
#
|
|
|
|
def has_options?
|
|
|
|
each_option { |name, opt|
|
|
|
|
return true if (opt.advanced? == false)
|
2006-01-05 03:57:12 +00:00
|
|
|
|
2005-07-10 00:49:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Returns whether or not the container has any advanced
|
|
|
|
# options.
|
|
|
|
#
|
|
|
|
def has_advanced_options?
|
|
|
|
each_option { |name, opt|
|
|
|
|
return true if (opt.advanced? == true)
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
2006-01-05 03:57:12 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Returns whether or not the container has any evasion
|
|
|
|
# options.
|
|
|
|
#
|
|
|
|
def has_evasion_options?
|
|
|
|
each_option { |name, opt|
|
|
|
|
return true if (opt.evasion? == true)
|
|
|
|
}
|
2005-07-10 00:49:12 +00:00
|
|
|
|
2006-01-05 03:57:12 +00:00
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
2005-07-11 05:21:19 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Removes an option.
|
2005-07-11 05:21:19 +00:00
|
|
|
#
|
|
|
|
def remove_option(name)
|
|
|
|
delete(name)
|
2005-07-11 20:32:56 +00:00
|
|
|
sorted.each_with_index { |e, idx|
|
|
|
|
sorted.delete_at(idx) if (e[0] == name)
|
|
|
|
}
|
2005-07-11 05:21:19 +00:00
|
|
|
end
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Adds one or more options.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2006-01-05 03:57:12 +00:00
|
|
|
def add_options(opts, owner = nil, advanced = false, evasion = false)
|
2005-05-21 17:57:00 +00:00
|
|
|
return false if (opts == nil)
|
|
|
|
|
2005-06-05 04:27:57 +00:00
|
|
|
if (opts.kind_of?(Array))
|
2006-01-05 03:57:12 +00:00
|
|
|
add_options_array(opts, owner, advanced, evasion)
|
2005-06-05 04:27:57 +00:00
|
|
|
else
|
2006-01-05 03:57:12 +00:00
|
|
|
add_options_hash(opts, owner, advanced, evasion)
|
2005-06-05 04:27:57 +00:00
|
|
|
end
|
|
|
|
end
|
2005-05-21 17:57:00 +00:00
|
|
|
|
2005-06-05 04:27:57 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Add options from a hash of names.
|
2005-06-05 04:27:57 +00:00
|
|
|
#
|
2006-01-05 03:57:12 +00:00
|
|
|
def add_options_hash(opts, owner = nil, advanced = false, evasion = false)
|
2005-06-05 04:27:57 +00:00
|
|
|
opts.each_pair { |name, opt|
|
2006-01-05 03:57:12 +00:00
|
|
|
add_option(opt, name, owner, advanced, evasion)
|
2005-06-05 04:27:57 +00:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Add options from an array of option instances or arrays.
|
2005-06-05 04:27:57 +00:00
|
|
|
#
|
2006-01-05 03:57:12 +00:00
|
|
|
def add_options_array(opts, owner = nil, advanced = false, evasion = false)
|
2005-06-05 04:27:57 +00:00
|
|
|
opts.each { |opt|
|
2006-01-05 03:57:12 +00:00
|
|
|
add_option(opt, nil, owner, advanced, evasion)
|
2005-06-05 04:27:57 +00:00
|
|
|
}
|
|
|
|
end
|
2005-05-21 17:57:00 +00:00
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Adds an option.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2006-01-05 03:57:12 +00:00
|
|
|
def add_option(option, name = nil, owner = nil, advanced = false, evasion = false)
|
2005-06-05 04:27:57 +00:00
|
|
|
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
|
2005-05-21 17:57:00 +00:00
|
|
|
|
2005-06-05 04:27:57 +00:00
|
|
|
option.advanced = advanced
|
2006-01-05 03:57:12 +00:00
|
|
|
option.evasion = evasion
|
2005-06-05 23:45:58 +00:00
|
|
|
option.owner = owner
|
2005-05-21 17:57:00 +00:00
|
|
|
|
2005-06-05 04:27:57 +00:00
|
|
|
self.store(option.name, option)
|
2005-07-11 15:34:31 +00:00
|
|
|
|
|
|
|
# Re-calculate the sorted list
|
|
|
|
self.sorted = self.sort
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Alias to add advanced options that sets the proper state flag.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-06-05 23:45:58 +00:00
|
|
|
def add_advanced_options(opts, owner = nil)
|
|
|
|
return false if (opts == nil)
|
|
|
|
|
|
|
|
add_options(opts, owner, true)
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
2006-01-05 03:57:12 +00:00
|
|
|
#
|
|
|
|
# Alias to add evasion options that sets the proper state flag.
|
|
|
|
#
|
|
|
|
def add_evasion_options(opts, owner = nil)
|
|
|
|
return false if (opts == nil)
|
|
|
|
|
|
|
|
add_options(opts, owner, false, true)
|
|
|
|
end
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-21 17:57:00 +00:00
|
|
|
# Make sures that each of the options has a value of a compatible
|
2005-11-15 15:11:43 +00:00
|
|
|
# format and that all the required options are set.
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-21 18:27:24 +00:00
|
|
|
def validate(datastore)
|
2005-05-21 17:57:00 +00:00
|
|
|
errors = []
|
|
|
|
|
|
|
|
each_pair { |name, option|
|
2005-05-21 18:27:24 +00:00
|
|
|
if (!option.valid?(datastore[name]))
|
2005-05-21 17:57:00 +00:00
|
|
|
errors << name
|
2005-11-15 21:50:10 +00:00
|
|
|
# If the option is valid, normalize its format to the correct type.
|
|
|
|
elsif ((val = option.normalize(datastore[name])) != nil)
|
2005-12-21 02:51:23 +00:00
|
|
|
datastore.update_value(name, val)
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
if (errors.empty? == false)
|
|
|
|
raise OptionValidateError.new(errors),
|
|
|
|
"One or more options failed to validate", caller
|
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
|
|
|
# Creates string of options that were used from the datastore in VAR=VAL
|
|
|
|
# format separated by commas.
|
|
|
|
#
|
|
|
|
def options_used_to_s(datastore)
|
|
|
|
used = ''
|
|
|
|
|
|
|
|
each_pair { |name, option|
|
|
|
|
next if (datastore[name] == nil)
|
|
|
|
|
|
|
|
used += ", " if (used.length > 0)
|
|
|
|
used += "#{name}=#{datastore[name]}"
|
|
|
|
}
|
|
|
|
|
|
|
|
return used
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2005-05-21 17:57:00 +00:00
|
|
|
# Enumerates each option name
|
2005-07-14 06:34:58 +00:00
|
|
|
#
|
2005-05-21 17:57:00 +00:00
|
|
|
def each_option(&block)
|
|
|
|
each_pair(&block)
|
|
|
|
end
|
|
|
|
|
2005-11-24 20:41:56 +00:00
|
|
|
#
|
|
|
|
# Merges the options in this container with another option container and
|
|
|
|
# returns the sorted results.
|
|
|
|
#
|
|
|
|
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
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# The sorted array of options.
|
|
|
|
#
|
2005-07-11 15:34:31 +00:00
|
|
|
attr_reader :sorted
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
attr_writer :sorted # :nodoc:
|
2005-07-11 15:34:31 +00:00
|
|
|
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|
|
|
|
|
2005-06-05 04:27:57 +00:00
|
|
|
#
|
|
|
|
# Builtin framework options with shortcut methods
|
|
|
|
#
|
|
|
|
module Opt
|
|
|
|
|
|
|
|
@@builtin_opts =
|
|
|
|
{
|
2005-11-11 01:22:03 +00:00
|
|
|
'RHOST' => [ OptAddress, 'nil', true, '"The target address"' ],
|
|
|
|
'RPORT' => [ OptPort, 'nil', true, '"The target port"' ],
|
|
|
|
'LHOST' => [ OptAddress, 'nil', true, '"The local address"' ],
|
|
|
|
'LPORT' => [ OptPort, 'nil', true, '"The local port"' ],
|
|
|
|
'CPORT' => [ OptPort, 'nil', false, '"The local client port"' ],
|
2007-02-18 07:02:47 +00:00
|
|
|
'CHOST' => [ OptAddress, 'nil', false, '"The local client address"' ],
|
2005-11-11 01:22:03 +00:00
|
|
|
'SSL' => [ OptBool, 'false', false, '"Use SSL"' ],
|
2007-02-18 07:02:47 +00:00
|
|
|
'Proxies' => [ OptString, 'nil', 'false', '"Use a proxy chain"'],
|
2005-06-05 04:27:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
|
|
# Build the builtin_xyz methods on the fly using the type information for each
|
|
|
|
# of the builtin framework options, such as RHOST.
|
|
|
|
#
|
|
|
|
class <<self
|
|
|
|
@@builtin_opts.each_pair { |opt, info|
|
|
|
|
eval(
|
|
|
|
"
|
|
|
|
def builtin_#{opt.downcase}(default = #{info[1]}, required = #{info[2]}, desc = #{info[3]})
|
|
|
|
#{info[0]}.new('#{opt}', [ required, desc, default ])
|
|
|
|
end
|
|
|
|
|
|
|
|
alias #{opt} builtin_#{opt.downcase}
|
|
|
|
")
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Define the constant versions of the options which are merely redirections to
|
|
|
|
# the class methods.
|
|
|
|
#
|
|
|
|
@@builtin_opts.each_pair { |opt, info|
|
|
|
|
eval("#{opt} = Msf::Opt::builtin_#{opt.downcase}")
|
|
|
|
}
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2005-05-21 17:57:00 +00:00
|
|
|
end
|