spruced things up a bit
git-svn-id: file:///home/svn/incoming/trunk@2499 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
8a192dae88
commit
e78604b603
|
@ -9,9 +9,9 @@
|
|||
###
|
||||
|
||||
# Shared single purpose classes
|
||||
require 'Shared/ReadWriteLock'
|
||||
require 'Shared/Transformer'
|
||||
require 'Msf/Shared/ReadWriteLock'
|
||||
require 'Msf/Shared/Transformer'
|
||||
|
||||
# Logging facilities
|
||||
require 'Shared/Logging/LogSink'
|
||||
require 'Shared/Logging/LogDispatcher'
|
||||
require 'Msf/Shared/Logging/LogSink'
|
||||
require 'Msf/Shared/Logging/LogDispatcher'
|
||||
|
|
|
@ -11,25 +11,26 @@
|
|||
|
||||
# Unit testing
|
||||
require 'test/unit'
|
||||
require 'Core/UnitTestSuite'
|
||||
require 'Msf/Core/UnitTestSuite'
|
||||
|
||||
# framework-core depends on framework-shared
|
||||
require 'Shared'
|
||||
require 'Msf/Shared'
|
||||
|
||||
# General
|
||||
require 'Core/Constants'
|
||||
require 'Core/Exceptions'
|
||||
require 'Core/DataTypes'
|
||||
require 'Core/EventDispatcher'
|
||||
require 'Core/DataStore'
|
||||
require 'Msf/Core/Constants'
|
||||
require 'Msf/Core/Exceptions'
|
||||
require 'Msf/Core/DataTypes'
|
||||
require 'Msf/Core/EventDispatcher'
|
||||
require 'Msf/Core/DataStore'
|
||||
require 'Msf/Core/OptionContainer'
|
||||
|
||||
# Framework context and core classes
|
||||
require 'Core/Framework'
|
||||
require 'Core/Session'
|
||||
require 'Msf/Core/Framework'
|
||||
require 'Msf/Core/Session'
|
||||
|
||||
# Modules
|
||||
require 'Core/Module'
|
||||
require 'Core/Encoder'
|
||||
require 'Core/Exploit'
|
||||
require 'Core/Nop'
|
||||
require 'Core/Recon'
|
||||
require 'Msf/Core/Module'
|
||||
require 'Msf/Core/Encoder'
|
||||
require 'Msf/Core/Exploit'
|
||||
require 'Msf/Core/Nop'
|
||||
require 'Msf/Core/Recon'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
module Msf
|
||||
module Test
|
||||
|
@ -16,7 +16,7 @@ class FrameworkCoreTestSuite
|
|||
def self.suite
|
||||
suite = ::Test::Unit::TestSuite.new
|
||||
|
||||
suite << Msf::Test::DataStoreTestCase.suite
|
||||
suite << Msf::Test::OptionContainerTestCase.suite
|
||||
|
||||
return suite;
|
||||
end
|
||||
|
|
|
@ -9,6 +9,16 @@ module Msf
|
|||
#
|
||||
###
|
||||
class DataStore < Hash
|
||||
|
||||
# This method is a helper method that imports the default value for
|
||||
# all of the supplied options
|
||||
def import_options(options)
|
||||
options.each_option { |name, opt|
|
||||
if (opt.default_value)
|
||||
self.store(name, opt.default_value)
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
module Msf
|
||||
|
||||
|
@ -260,5 +260,5 @@ end
|
|||
|
||||
end
|
||||
|
||||
require 'Core/Encoder/Xor'
|
||||
require 'Core/Encoder/XorAdditiveFeedback'
|
||||
require 'Msf/Core/Encoder/Xor'
|
||||
require 'Msf/Core/Encoder/XorAdditiveFeedback'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
###
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
###
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
module Msf
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
module Msf
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
module Msf
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
module Msf
|
||||
|
||||
|
@ -30,10 +30,14 @@ class Module
|
|||
self.refs = Transformer.transform(module_info['Ref'], Array,
|
||||
[ SiteReference, Reference ], 'Ref')
|
||||
|
||||
# Create and initialize the datastore for this module
|
||||
# Create and initialize the option container for this module
|
||||
self.options = OptionContainer.new
|
||||
self.options.add_options(info['Options'])
|
||||
self.options.add_advanced_options(info['AdvancedOptions'])
|
||||
|
||||
# Create and initialize the data store for this module
|
||||
self.datastore = DataStore.new
|
||||
self.datastore.add_options(info['Options'])
|
||||
self.datastore.add_advanced_options(info['AdvancedOptions'])
|
||||
self.datastore.import_options(self.options)
|
||||
end
|
||||
|
||||
# Return the module's name
|
||||
|
@ -86,7 +90,7 @@ class Module
|
|||
return platform.join(", ")
|
||||
end
|
||||
|
||||
attr_reader :author, :arch, :platform, :refs, :datastore
|
||||
attr_reader :author, :arch, :platform, :refs, :datastore, :options
|
||||
|
||||
protected
|
||||
|
||||
|
@ -108,7 +112,7 @@ protected
|
|||
end
|
||||
|
||||
attr_accessor :module_info
|
||||
attr_writer :author, :arch, :platform, :refs, :datastore
|
||||
attr_writer :author, :arch, :platform, :refs, :datastore, :options
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
module Msf
|
||||
|
||||
|
|
|
@ -1,31 +1,24 @@
|
|||
require 'resolv'
|
||||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# DataStoreOption
|
||||
# ---------------
|
||||
# OptBase
|
||||
# -------
|
||||
#
|
||||
# A data store option is an option that is stored in a data store! It contains
|
||||
# meta information about the type of option being stored, such as type, as
|
||||
# well as the option's actual value
|
||||
# The base class for all options.
|
||||
#
|
||||
###
|
||||
class DataStoreOption
|
||||
class OptBase
|
||||
|
||||
def initialize(in_name, attrs = [])
|
||||
self.name = in_name
|
||||
self.advanced = false
|
||||
self.required = attrs[0] || false
|
||||
self.desc = attrs[1] || nil
|
||||
self.default_value = attrs[2] || nil
|
||||
self.value = self.default_value
|
||||
end
|
||||
|
||||
def empty?
|
||||
return (value == nil)
|
||||
self.name = in_name
|
||||
self.advanced = false
|
||||
self.required = attrs[0] || false
|
||||
self.desc = attrs[1] || nil
|
||||
self.default = attrs[2] || nil
|
||||
end
|
||||
|
||||
def required?
|
||||
|
@ -36,30 +29,27 @@ class DataStoreOption
|
|||
return advanced
|
||||
end
|
||||
|
||||
def valid?
|
||||
return (empty? and required?) ? false : true
|
||||
end
|
||||
|
||||
def type?(in_type)
|
||||
return (type == in_type)
|
||||
end
|
||||
|
||||
def reset
|
||||
value = default_value
|
||||
# If it's required and the value is nil or empty, then it's not valid.
|
||||
def valid?(value)
|
||||
return (required? and (value == nil or value.to_s.empty?)) ? false : true
|
||||
end
|
||||
|
||||
attr_reader :name, :required, :desc, :default_value, :value
|
||||
attr_writer :name, :value
|
||||
attr_reader :name, :required, :desc, :default
|
||||
attr_writer :name
|
||||
attr_accessor :advanced
|
||||
|
||||
protected
|
||||
|
||||
attr_writer :required, :desc, :default_value
|
||||
attr_writer :required, :desc, :default
|
||||
end
|
||||
|
||||
###
|
||||
#
|
||||
# Core data store option types. The core supported option types are:
|
||||
# Core option types. The core supported option types are:
|
||||
#
|
||||
# OptString - Multi-byte character string
|
||||
# OptRaw - Multi-byte raw string
|
||||
|
@ -70,25 +60,25 @@ end
|
|||
#
|
||||
###
|
||||
|
||||
class OptString < DataStoreOption
|
||||
class OptString < OptBase
|
||||
def type
|
||||
return 'string'
|
||||
end
|
||||
end
|
||||
|
||||
class OptRaw < DataStoreOption
|
||||
class OptRaw < OptBase
|
||||
def type
|
||||
return 'raw'
|
||||
end
|
||||
end
|
||||
|
||||
class OptBool < DataStoreOption
|
||||
class OptBool < OptBase
|
||||
def type
|
||||
return 'bool'
|
||||
end
|
||||
|
||||
def valid?
|
||||
if ((empty? == false) and
|
||||
def valid?(value)
|
||||
if ((value != nil and value.empty? == false) and
|
||||
(value.match(/^(y|n|t|f|0|1)$/i) == nil))
|
||||
return false
|
||||
end
|
||||
|
@ -103,13 +93,13 @@ class OptBool < DataStoreOption
|
|||
end
|
||||
end
|
||||
|
||||
class OptPort < DataStoreOption
|
||||
class OptPort < OptBase
|
||||
def type
|
||||
return 'port'
|
||||
end
|
||||
|
||||
def valid?
|
||||
if ((empty? == false) and
|
||||
def valid?(value)
|
||||
if ((value != nil and value.to_s.empty? == false) and
|
||||
((value.to_i < 0 or value.to_i > 65535)))
|
||||
return false
|
||||
end
|
||||
|
@ -118,13 +108,13 @@ class OptPort < DataStoreOption
|
|||
end
|
||||
end
|
||||
|
||||
class OptAddress < DataStoreOption
|
||||
class OptAddress < OptBase
|
||||
def type
|
||||
return 'address'
|
||||
end
|
||||
|
||||
def valid?
|
||||
if (empty? == false)
|
||||
def valid?(value)
|
||||
if (value != nil and value.empty? == false)
|
||||
begin
|
||||
Resolv.getaddress(value)
|
||||
rescue
|
||||
|
@ -136,13 +126,13 @@ class OptAddress < DataStoreOption
|
|||
end
|
||||
end
|
||||
|
||||
class OptPath < DataStoreOption
|
||||
class OptPath < OptBase
|
||||
def type
|
||||
return 'path'
|
||||
end
|
||||
|
||||
def valid?
|
||||
if ((empty? == false) and
|
||||
def valid?(value)
|
||||
if ((value != nil and value.empty? == false) and
|
||||
(File.exists?(value) == false))
|
||||
return false
|
||||
end
|
||||
|
@ -153,21 +143,21 @@ end
|
|||
|
||||
###
|
||||
#
|
||||
# DataStore
|
||||
# ---------
|
||||
# OptionContainer
|
||||
# ---------------
|
||||
#
|
||||
# The data store's purpose in life is to associate named options
|
||||
# The options purpose in life is to associate named options
|
||||
# with arbitrary values at the most simplistic level. Each
|
||||
# module contains a DataStore that is used to hold the
|
||||
# module contains a OptionContainer that is used to hold the
|
||||
# various options that the module depends on. Example of options
|
||||
# that are stored in the DataStore are RHOST and RPORT for
|
||||
# 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.
|
||||
#
|
||||
###
|
||||
class DataStore < Hash
|
||||
class OptionContainer < Hash
|
||||
|
||||
# Merges in the supplied options and converts them to a DataStoreOption
|
||||
# Merges in the supplied options and converts them to a OptBase
|
||||
# as necessary.
|
||||
def initialize(opts = {})
|
||||
add_options(opts)
|
||||
|
@ -178,29 +168,11 @@ class DataStore < Hash
|
|||
return get(name)
|
||||
end
|
||||
|
||||
# Set the value associated with the supplied name
|
||||
def set(name, value)
|
||||
option = fetch(name)
|
||||
|
||||
if (option == nil)
|
||||
return false
|
||||
end
|
||||
|
||||
option.value = value
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Return the option associated with the supplied name
|
||||
def get(name)
|
||||
return fetch(name)
|
||||
end
|
||||
|
||||
# Return the value associated with the supplied name
|
||||
def get_value(name)
|
||||
return fetch(name).value
|
||||
end
|
||||
|
||||
# Adds one or more options
|
||||
def add_options(opts)
|
||||
return false if (opts == nil)
|
||||
|
@ -213,7 +185,7 @@ class DataStore < Hash
|
|||
|
||||
if (option.kind_of?(Array))
|
||||
option = option.shift.new(name, option)
|
||||
elsif (!option.kind_of?(DataStoreOption))
|
||||
elsif (!option.kind_of?(OptBase))
|
||||
raise ArgumentError,
|
||||
"The option named #{name} did not come in a compatible format.",
|
||||
caller
|
||||
|
@ -240,11 +212,11 @@ class DataStore < Hash
|
|||
|
||||
# Make sures that each of the options has a value of a compatible
|
||||
# format and that all the required options are set
|
||||
def validate
|
||||
def validate(datastore)
|
||||
errors = []
|
||||
|
||||
each_pair { |name, option|
|
||||
if (!option.valid?)
|
||||
if (!option.valid?(datastore[name]))
|
||||
errors << name
|
||||
end
|
||||
}
|
||||
|
@ -268,25 +240,25 @@ module Test
|
|||
|
||||
###
|
||||
#
|
||||
# DataStoreTestCase
|
||||
# -----------------
|
||||
# OptionContainerTestCase
|
||||
# -----------------------
|
||||
#
|
||||
# This class implements some testing routines for ensuring that the data
|
||||
# store is operating correctly.
|
||||
# This class implements some testing routines for ensuring that the option
|
||||
# container is operating correctly.
|
||||
#
|
||||
###
|
||||
class DataStoreTestCase < ::Test::Unit::TestCase
|
||||
# Tests the initialization of the DataStore object
|
||||
class OptionContainerTestCase < ::Test::Unit::TestCase
|
||||
# Tests the initialization of the OptionContainer object
|
||||
def test_initialize
|
||||
# Make sure initialization works
|
||||
ds = nil
|
||||
options = nil
|
||||
|
||||
assert_block("initialize failed") {
|
||||
ds = DataStore.new(
|
||||
'RHOST' => [ OptAddress, true, 'host.com' ],
|
||||
'RPORT' => [ OptPort, true, 1234 ])
|
||||
options = OptionContainer.new(
|
||||
'rhost' => [ OptAddress, true, 'host.com' ],
|
||||
'rport' => [ OptPort, true, 1234 ])
|
||||
|
||||
if (ds == nil)
|
||||
if (options == nil)
|
||||
false
|
||||
end
|
||||
|
||||
|
@ -294,90 +266,71 @@ class DataStoreTestCase < ::Test::Unit::TestCase
|
|||
}
|
||||
|
||||
# Make sure there are 2 options
|
||||
assert_equal(2, ds.length, "invalid number of options #{ds.length}")
|
||||
assert_equal(2, options.length, "invalid number of options #{options.length}")
|
||||
|
||||
# Make sure that the constructor raises an argument error when
|
||||
# an invalid option is supplied
|
||||
assert_raise(ArgumentError, "initialize invalid failed") {
|
||||
DataStore.new(
|
||||
'RHOST' => 'invalid');
|
||||
OptionContainer.new(
|
||||
'rhost' => 'invalid');
|
||||
}
|
||||
end
|
||||
|
||||
# Tests getting the value of an option
|
||||
def test_get
|
||||
ds = DataStore.new(
|
||||
'RPORT' => [ OptPort, true, nil, 1234 ])
|
||||
options = OptionContainer.new(
|
||||
'rport' => [ OptPort, true, nil, 1234 ])
|
||||
|
||||
assert_equal(1234, ds.get_value('RPORT'),
|
||||
"RPORT does not match")
|
||||
|
||||
ds.set('RPORT', 1235)
|
||||
|
||||
assert_equal(1235, ds.get_value('RPORT'),
|
||||
"RPORT does not match (2)")
|
||||
|
||||
assert_equal('RPORT', ds['RPORT'].name,
|
||||
assert_equal(1234, options.get('rport').default,
|
||||
"option default does not match")
|
||||
assert_equal(true, options.get('rport').required?,
|
||||
"option required does not match")
|
||||
assert_equal('rport', options['rport'].name,
|
||||
"option name does not match")
|
||||
end
|
||||
|
||||
# Tests setting the value of an option
|
||||
def test_set
|
||||
assert_block("set failed") {
|
||||
ds = DataStore.new(
|
||||
'RHOST' => [ OptAddress ])
|
||||
|
||||
ds.set('RHOST', 'host.com')
|
||||
|
||||
if (ds.get_value('RHOST') != 'host.com')
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
# Tests validation
|
||||
def test_validate
|
||||
# Test validating required options
|
||||
ds = DataStore.new(
|
||||
'RHOST' => [ OptAddress, true ],
|
||||
'RPORT' => [ OptPort, true ],
|
||||
'LIB' => [ OptString ])
|
||||
options = OptionContainer.new(
|
||||
'rhost' => [ OptAddress, true ],
|
||||
'rport' => [ OptPort, true ],
|
||||
'Lib' => [ OptString ])
|
||||
|
||||
ds = DataStore.new
|
||||
|
||||
assert_raise(OptionValidateError, "required validation failed") {
|
||||
ds.validate
|
||||
options.validate(ds)
|
||||
}
|
||||
|
||||
# Test validating the form of individual options
|
||||
ds.set('RHOST', 'www.invalid.host.tldinvalid')
|
||||
ds.set('RPORT', 1234)
|
||||
ds['rhost'] = 'www.invalid.host.tldinvalid'
|
||||
ds['rport'] = 1234
|
||||
|
||||
assert_raise(OptionValidateError, "host validation failed") {
|
||||
ds.validate
|
||||
options.validate(ds)
|
||||
}
|
||||
|
||||
# Make sure address validation does work
|
||||
ds.set('RHOST', 'www.google.com')
|
||||
ds['rhost'] = 'www.google.com'
|
||||
|
||||
assert_equal(true, ds.validate, "overall validation failed")
|
||||
assert_equal(true, options.validate(ds), "overall validation failed")
|
||||
|
||||
# Make sure port validation does work
|
||||
ds.set('RPORT', 123452)
|
||||
ds['rport'] = 23423423
|
||||
|
||||
assert_raise(OptionValidateError, "port validation failed") {
|
||||
ds.validate
|
||||
options.validate(ds)
|
||||
}
|
||||
end
|
||||
|
||||
# Make sure advanced additions work
|
||||
def test_advanced
|
||||
ds = DataStore.new
|
||||
options = OptionContainer.new
|
||||
|
||||
ds.add_advanced_options(
|
||||
options.add_advanced_options(
|
||||
'DONKEY' => [ OptString, false ])
|
||||
|
||||
assert_equal(true, ds.get('DONKEY').advanced?,
|
||||
assert_equal(true, options.get('DONKEY').advanced?,
|
||||
"advanced option failed")
|
||||
end
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
module Msf
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Shared'
|
||||
require 'Msf/Shared'
|
||||
|
||||
module Msf
|
||||
module Logging
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Shared/Constants'
|
||||
require 'Msf/Shared/Constants'
|
||||
|
||||
module Msf
|
||||
module Logging
|
||||
|
@ -52,4 +52,4 @@ end
|
|||
|
||||
end; end
|
||||
|
||||
require 'Shared/Logging/Sinks/Flatfile'
|
||||
require 'Msf/Shared/Logging/Sinks/Flatfile'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
module Msf
|
||||
module Encoders
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
module Msf
|
||||
module Nops
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/ruby -I../Framework
|
||||
#!/usr/bin/ruby -I../Lib
|
||||
|
||||
require 'test/unit/ui/console/testrunner'
|
||||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
|
||||
Test::Unit::UI::Console::TestRunner.run(Msf::Test::FrameworkCoreTestSuite)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/ruby -I../Framework -I../Modules
|
||||
#!/usr/bin/ruby -I../Lib -I../Modules
|
||||
|
||||
require 'Core'
|
||||
require 'Msf/Core'
|
||||
require 'Encoders/IA32/JmpCallAdditive'
|
||||
require 'Nops/IA32/SingleByte'
|
||||
|
||||
|
|
Loading…
Reference in New Issue