lots of changes, making the simple wrapper better, lots of improvements

git-svn-id: file:///home/svn/incoming/trunk@2750 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Matt Miller 2005-07-14 06:34:58 +00:00
parent 3aaeeca644
commit d62566a68f
35 changed files with 706 additions and 158 deletions

View File

@ -19,9 +19,7 @@
require 'msf/core'
# Simple wrapper
require 'msf/base/simple/buffer'
require 'msf/base/simple/nop'
require 'msf/base/simple/payload'
require 'msf/base/simple'
# Sessions
require 'msf/base/session/command_shell'

View File

@ -232,6 +232,26 @@ class ReadableText
return output
end
#
# Dumps the contents of a datastore
#
def self.dump_datastore(name, ds, indent = 4, col = 60)
tbl = Rex::Ui::Text::Table.new(
'Indent' => indent,
'Header' => name,
'Columns' =>
[
'Name',
'Value'
])
ds.each_pair { |n, v|
tbl << [ n, v ]
}
return ds.length > 0 ? tbl.to_s : "#{tbl.header_to_s}No entries in data store.\n"
end
#
# Jacked from Ernest Ellingson <erne [at] powernav.com>, modified
# a bit to add indention

14
lib/msf/base/simple.rb Normal file
View File

@ -0,0 +1,14 @@
# Buffer management
require 'msf/base/simple/buffer'
require 'msf/base/simple/statistics'
# Simplified module interfaces
require 'msf/base/simple/module'
require 'msf/base/simple/encoder'
require 'msf/base/simple/exploit'
require 'msf/base/simple/nop'
require 'msf/base/simple/payload'
require 'msf/base/simple/recon'
# Simplified framework interface
require 'msf/base/simple/framework'

View File

@ -0,0 +1,16 @@
module Msf
module Simple
###
#
# Encoder
# -------
#
# A simplified encoder wrapper.
#
###
class Encoder
end
end
end

View File

@ -0,0 +1,16 @@
module Msf
module Simple
###
#
# Exploit
# -------
#
# A simplified exploit wrapper.
#
###
class Exploit
end
end
end

View File

@ -0,0 +1,93 @@
require 'msf/base/simple'
module Msf
module Simple
###
#
# Framework
# ---------
#
# This class wraps the framework-core supplied Framework class and adds some
# helper methods for analyzing statistics as well as other potentially useful
# information that is directly necessary to drive the framework-core.
#
###
module Framework
include GeneralEventSubscriber
ModuleSimplifiers =
{
MODULE_ENCODER => Msf::Simple::Encoder,
MODULE_EXPLOIT => Msf::Simple::Exploit,
MODULE_NOP => Msf::Simple::Nop,
MODULE_PAYLOAD => Msf::Simple::Payload,
MODULE_RECON => Msf::Simple::Recon,
}
#
# Create a simplified instance of the framework
#
def self.create
framework = Msf::Framework.new
return simplify(framework)
end
#
# Extends a framework object that may already exist
#
def self.simplify(framework)
framework.extend(Msf::Simple::Framework)
# Initialize the simplified framework
framework.init_simplified()
# Set the on_module_created procedure to simplify any module
# instance that is created
framework.on_module_created_proc = Proc.new { |instance|
simplify_module(instance)
}
# Register the framework as its own general event subscriber in this
# instance
framework.events.add_general_subscriber(framework)
return framework
end
#
# Simplifies a module instance if the type is supported by extending it
# with the simplified module interface.
#
def self.simplify_module(instance)
if ((ModuleSimplifiers[instance.type]) and
(instance.class.include?(ModuleSimplifiers[instance.type]) == false))
instance.extend(ModuleSimplifiers[instance.type])
end
end
##
#
# Simplified interface
#
##
#
# Initializes the simplified interface
#
def init_simplified
self.stats = Statistics.new(self)
end
attr_reader :stats
protected
attr_writer :stats
end
end
end

View File

@ -0,0 +1,34 @@
require 'msf/base'
module Msf
module Simple
###
#
# Module
# ------
#
# Simple module wrapper that provides some common methods for dealing with
# modules, such as importing options and other such things.
#
###
module Module
#
# Imports extra options from the supplied hash either as a string or as a
# hash.
#
def _import_extra_options(opts)
# If options were supplied, import them into the payload's
# datastore
if (opts['Option'])
self.datastore.import_options_from_hash(opts['Options'])
elsif (opts['OptionStr'])
self.datastore.import_options_from_s(opts['OptionStr'])
end
end
end
end
end

View File

@ -11,7 +11,7 @@ module Simple
# Simple nop wrapper class for performing generation.
#
###
class Nop
module Nop
#
# Generate a nop sled, optionally with a few parameters.
@ -21,7 +21,7 @@ class Nop
#
# Format => The format to represent the data as: ruby, perl, c, raw
#
def self.generate(nop, length, opts)
def self.generate_simple(nop, length, opts)
# Generate the nop sled using the options supplied
buf = nop.generate_sled(length, opts)
@ -29,6 +29,13 @@ class Nop
return Buffer.transform(buf, opts['Format'] || 'raw')
end
#
# Calls the class method
#
def generate_simple(length, opts)
Msf::Simple::Nop.generate_simple(self, length, opts)
end
end
end

View File

@ -11,7 +11,9 @@ module Simple
# Simple payload wrapper class for performing generation.
#
###
class Payload
module Payload
include Module
#
# Generate a payload with the mad skillz. The payload can be generated in
@ -20,7 +22,7 @@ class Payload
# opts can have:
#
# Encoder => A encoder module instance.
# Badchars => A string of bad characters.
# BadChars => A string of bad characters.
# Format => The format to represent the data as: ruby, perl, c, raw
# Options => A hash of options to set.
# OptionStr => A string of options in VAR=VAL form separated by
@ -34,14 +36,10 @@ class Payload
# NoKeyError => No valid encoder key could be found
# ArgumentParseError => Options were supplied improperly
#
def self.generate(payload, opts)
# If options were supplied, import them into the payload's
# datastore
if (opts['Option'])
payload.datastore.import_options_from_hash(opts['Options'])
elsif (opts['OptionStr'])
payload.datastore.import_options_from_s(opts['OptionStr'])
end
def self.generate_simple(payload, opts)
# Import any options we may need
payload._import_extra_options(opts)
# Generate the payload
e = EncodedPayload.create(payload,
@ -59,18 +57,26 @@ class Payload
# Prepend a comment
if (fmt != 'raw' and opts['NoComment'] != true)
((ds = payload.datastore.to_s) and ds.length > 0) ? ds += "\n" : ds = ''
((ou = payload.options.options_used_to_s(payload.datastore)) and ou.length > 0) ? ou += "\n" : ou = ''
buf = Buffer.comment(
"#{payload.refname} - #{len} bytes\n" +
"http://www.metasploit.com\n" +
"#{ds}" +
((e.encoder) ? "Encoder: #{e.encoder.refname}\n" : '') +
((e.nop) ? "NOP generator: #{e.nop.refname}\n" : ''), fmt) + buf
((e.nop) ? "NOP gen: #{e.nop.refname}\n" : '') +
"#{ou}",
fmt) + buf
end
return buf
end
#
# Calls the class method
#
def generate_simple(opts)
Msf::Simple::Payload.generate_simple(self, opts)
end
end
end

View File

@ -0,0 +1,16 @@
module Msf
module Simple
###
#
# Recon
# -------
#
# A simplified recon wrapper.
#
###
class Recon
end
end
end

View File

@ -0,0 +1,54 @@
module Msf
module Simple
###
#
# Statistics
# ----------
#
# This class provides an interface to various statistics about the
# framework instance.
#
###
class Statistics
include Msf::Framework::Offspring
def initialize(framework)
self.framework = framework
end
def num_encoders
self.framework.encoders.length
end
def num_exploits
self.framework.exploits.length
end
def num_nops
self.framework.nops.length
end
def num_payloads
self.framework.payloads.length
end
def num_recon
self.framework.recon.length
end
def num_payload_stages
self.framework.payloads.stages.length
end
def num_payload_stagers
self.framework.payloads.stagers.length
end
def num_payload_singles
self.framework.payloads.singles.length
end
end
end
end

View File

@ -78,4 +78,36 @@ class DataStore < Hash
end
end
###
#
# ModuleDataStore
# ---------------
#
# DataStore wrapper for modules that will attempt to back values against the
# framework's datastore if they aren't found in the module's datastore.
#
###
class ModuleDataStore < DataStore
def initialize(m)
@_module = m
end
#
# Fetch the key from the local hash first, or from the framework datastore
# if we can't directly find it
#
def fetch(key)
val = super || @_module.framework.datastore[key]
end
#
# Same as fetch
#
def [](key)
val = super || @_module.framework.datastore[key]
end
end
end

View File

@ -44,6 +44,9 @@ class EncodedPayload
self.encoder = nil
self.nop = nil
# First, validate
pinst.validate()
# Generate the raw version of the payload first
generate_raw()

View File

@ -2,6 +2,25 @@ require 'msf/core'
module Msf
###
#
# GeneralEventSubscriber
# ----------------------
#
# Called when internal framework events occur.
#
###
module GeneralEventSubscriber
#
# Called when a module is loaded
#
attr_accessor :on_module_load_proc
#
# Called when a new module instance is created
#
attr_accessor :on_module_created_proc
end
###
#
# EventDispatcher
@ -18,6 +37,7 @@ module Msf
class EventDispatcher
def initialize
self.general_event_subscribers = []
self.exploit_event_subscribers = []
self.session_event_subscribers = []
self.recon_event_subscribers = []
@ -27,6 +47,14 @@ class EventDispatcher
#
# Subscriber registration
#
def add_general_subscriber(subscriber)
add_event_subscriber(general_event_subscribers, subscriber)
end
def remove_general_subscriber(subscriber)
remove_event_subscriber(general_event_subscribers, subscriber)
end
def add_recon_subscriber(subscriber)
add_event_subscriber(recon_event_subscribers, subscriber)
@ -56,6 +84,38 @@ class EventDispatcher
# Event dispatching entry point
#
##
#
# General events
#
##
def on_module_load(name, mod)
subscribers_rwlock.synchronize_read {
general_event_subscribers.each { |subscriber|
next if (!subscriber.on_module_load_proc)
subscriber.on_module_load_proc.call(name, mod)
}
}
end
def on_module_created(instance)
subscribers_rwlock.synchronize_read {
general_event_subscribers.each { |subscriber|
next if (!subscriber.on_module_created_proc)
subscriber.on_module_created_proc.call(instance)
}
}
end
##
#
# Recon events
#
##
def on_recon_discovery(group, info)
subscribers_rwlock.synchronize_read {
recon_event_subscribers.each { |subscriber|
@ -64,6 +124,12 @@ class EventDispatcher
}
end
##
#
# Exploit events
#
##
def on_exploit_success(exploit)
subscribers_rwlock.synchronize_read {
exploit_event_subscribers.each { |subscriber|
@ -80,6 +146,12 @@ class EventDispatcher
}
end
##
#
# Session events
#
##
def on_session_open(session)
subscribers_rwlock.synchronize_read {
session_event_subscribers.each { |subscriber|
@ -110,6 +182,7 @@ protected
}
end
attr_accessor :general_event_subscribers
attr_accessor :exploit_event_subscribers
attr_accessor :session_event_subscribers
attr_accessor :recon_event_subscribers

View File

@ -12,6 +12,14 @@ module Msf
#
###
class Framework
#
# Versioning information
#
Major = 3
Minor = 0
Version = "#{Major}.#{Minor}"
Revision = "$Revision$"
#
# Mixin meant to be included into all classes that can have instances that
@ -24,10 +32,9 @@ class Framework
require 'msf/core/module_manager'
def initialize()
self.events = EventDispatcher.new
self.modules = ModuleManager.new
self.modules.framework = self
self.events = EventDispatcher.new
self.modules = ModuleManager.new(self)
self.datastore = DataStore.new
end
#
@ -67,11 +74,13 @@ class Framework
attr_reader :events
attr_reader :modules
attr_reader :datastore
protected
attr_writer :events
attr_writer :modules
attr_writer :datastore
end

View File

@ -25,7 +25,7 @@ module ReverseTcp
register_options(
[
Opt::LHOST("0.0.0.0"),
Opt::LHOST,
Opt::LPORT(4444)
], Msf::Handler::ReverseTcp)
@ -39,7 +39,7 @@ module ReverseTcp
#
def setup_handler
listener_sock = comm.create(
'LocalHost' => datastore['LHOST'] || "0.0.0.0",
'LocalHost' => datastore['LHOST'],
'LocalPort' => datastore['LPORT'].to_i,
'Server' => true,
'Proto' => 'tcp')

View File

@ -59,7 +59,7 @@ class Module
self.options.add_advanced_options(info['AdvancedOptions'], self.class)
# Create and initialize the data store for this module
self.datastore = DataStore.new
self.datastore = ModuleDataStore.new(self)
self.datastore.import_options(self.options)
# If there are default options, import their values into the datastore

View File

@ -25,16 +25,32 @@ class ModuleSet < Hash
self.mod_platform_hash = {}
self.mod_sorted = nil
self.mod_ranked = nil
self.mod_extensions = []
end
#
# Create an instance of the supplied module by its name
#
def create(name)
klass = self[name]
return (klass) ? klass.new : nil
klass = self[name]
instance = nil
# If the klass is valid for this name, try to create it
if (klass)
instance = klass.new
end
# Notify any general subscribers of the creation event
if (instance)
self.framework.events.on_module_created(instance)
end
return instance
end
#
# Enumerates each module class in the set
#
def each_module(opts = {}, &block)
mod_sorted = self.sort if (mod_sorted == nil)
@ -130,6 +146,9 @@ protected
dup.refname = name
self[name] = dup
# Notify the framework that a module was loaded
framework.events.on_module_load(name, dup)
# Invalidate the sorted array
invalidate_cache
@ -146,6 +165,7 @@ protected
attr_writer :module_type
attr_accessor :mod_arch_hash, :mod_platform_hash
attr_accessor :mod_sorted, :mod_ranked
attr_accessor :mod_extensions
end
@ -171,11 +191,12 @@ class ModuleManager < ModuleSet
include Framework::Offspring
def initialize()
def initialize(framework)
self.module_paths = []
self.module_history = {}
self.module_history_mtime = {}
self.module_sets = {}
self.framework = framework
MODULE_TYPES.each { |type|
case type
@ -188,7 +209,7 @@ class ModuleManager < ModuleSet
self.module_sets[type] = instance
# Set the module set's framework reference
instance.framework = self.framework
instance.framework = framework
}
super
@ -198,56 +219,85 @@ class ModuleManager < ModuleSet
# Accessors by module type
#
#
# Returns the set of loaded encoder module classes
#
def encoders
return module_sets[MODULE_ENCODER]
end
#
# Returns the set of loaded exploit module classes
#
def exploits
return module_sets[MODULE_EXPLOIT]
end
#
# Returns the set of loaded nop module classes
#
def nops
return module_sets[MODULE_NOP]
end
#
# Returns the set of loaded payload module classes
#
def payloads
return module_sets[MODULE_PAYLOAD]
end
#
# Returns the set of loaded recon module classes
#
def recon
return module_sets[MODULE_RECON]
end
##
#
# Module path management
#
##
#
# Adds a path to be searched for new modules
#
def add_module_path(path)
path.sub!(/#{File::SEPARATOR}$/, '')
# Make sure the path is a valid directory before we try to rock the
# house
if (File.directory?(path) == false)
raise NameError, "The path supplied is not a valid directory.",
caller
end
module_paths << path
load_modules(path)
return load_modules(path)
end
#
# Removes a path from which to search for modules
#
def remove_module_path(path)
module_paths.delete(path)
end
def register_type_extension(type, ext)
end
protected
#
# Load all of the modules from the supplied module path (independent of
# module type)
#
def load_modules(path)
loaded = {}
recalc = {}
counts = {}
Find.find(path) { |file|
@ -319,6 +369,9 @@ protected
# Append the added module to the hash of file->module
loaded[file] = added
# The number of loaded modules this round
counts[type] = (counts[type]) ? (counts[type] + 1) : 1
}
# Cache the loaded file mtimes
@ -335,17 +388,22 @@ protected
module_sets[key].recalculate
}
return loaded.values
# Return per-module loaded counts
return counts
end
#
# Checks to see if the supplied file has changed (if it's even in the
# cache)
#
def has_module_file_changed?(file)
return (module_history_mtime[file] != File.new(file).mtime)
end
#
# Returns the module object that is associated with the supplied module
# name
#
def mod_from_name(name)
obj = Msf
@ -364,8 +422,10 @@ protected
return obj
end
#
# Called when a module is initially loaded such that it can be
# categorized accordingly
#
def on_module_load(mod, type, name)
# Payload modules require custom loading as the individual files
# may not directly contain a logical payload that a user would

View File

@ -27,7 +27,7 @@ class Nop < Msf::Module
# - SaveRegisters (array)
# The list of registers that should not be clobbered by the NOP
# generator.
# - Badchars (string)
# - BadChars (string)
# The list of characters that should be avoided by the NOP
# generator.
#

View File

@ -227,7 +227,9 @@ class OptionContainer < Hash
}
end
#
# Adds one or more options
#
def add_options(opts, owner = nil, advanced = false)
return false if (opts == nil)
@ -256,6 +258,9 @@ class OptionContainer < Hash
}
end
#
# Adds an option
#
def add_option(option, name = nil, owner = nil, advanced = false)
if (option.kind_of?(Array))
option = option.shift.new(name, option)
@ -274,15 +279,19 @@ class OptionContainer < Hash
self.sorted = self.sort
end
#
# Alias to add advanced options that sets the proper state flag
#
def add_advanced_options(opts, owner = nil)
return false if (opts == nil)
add_options(opts, owner, true)
end
#
# Make sures that each of the options has a value of a compatible
# format and that all the required options are set
#
def validate(datastore)
errors = []
@ -300,7 +309,26 @@ class OptionContainer < Hash
return true
end
#
# 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
#
# Enumerates each option name
#
def each_option(&block)
each_pair(&block)
end

View File

@ -98,6 +98,13 @@ class Payload < Msf::Module
#
##
#
# Make sure all our required options are set.
#
def validate
self.options.validate(self.datastore)
end
#
# Generates the payload and return the raw buffer
#

View File

@ -33,12 +33,12 @@ module CommandDispatcher
return driver.framework
end
def set_active_module(mod)
driver.datastore['_ActiveModule'] = mod
def active_module
driver.active_module
end
def get_active_module
return driver.datastore['_ActiveModule']
def active_module=(mod)
driver.active_module = mod
end
#

View File

@ -14,27 +14,30 @@ class Core
# Returns the list of commands supported by this command dispatcher
def commands
return {
"?" => "Help menu",
"back" => "Move back from the current context",
"exit" => "Exit the console",
"help" => "Help menu",
"info" => "Displays information about one or more module",
"quit" => "Exit the console",
"search" => "Adds one or more module search paths",
"set" => "Sets a variable to a value",
"show" => "Displays modules of a given type, or all modules",
"unset" => "Unsets one or more variables",
"use" => "Selects a module by name",
"version" => "Show the console library version number",
}
{
"?" => "Help menu",
"back" => "Move back from the current context",
"banner" => "Display an awesome metasploit banner",
"exit" => "Exit the console",
"help" => "Help menu",
"info" => "Displays information about one or more module",
"quit" => "Exit the console",
"search" => "Adds one or more module search paths",
"set" => "Sets a variable to a value",
"setg" => "Sets a global variable to a value",
"show" => "Displays modules of a given type, or all modules",
"unset" => "Unsets one or more variables",
"unsetg" => "Unsets one or more global variables",
"use" => "Selects a module by name",
"version" => "Show the console library version number",
}
end
#
# Pop the current dispatcher stack context, assuming it isn't pointed at
# the core stack context.
#
def cmd_back(args)
def cmd_back(*args)
if (driver.dispatcher_stack.size > 1)
# Destack the current dispatcher
driver.destack_dispatcher
@ -44,10 +47,16 @@ class Core
end
end
#
# Display one of the fabulous banners
#
def cmd_banner(*args)
end
#
# Instructs the driver to stop executing
#
def cmd_exit(args)
def cmd_exit(*args)
driver.stop
end
@ -56,7 +65,7 @@ class Core
#
# Displays the command help banner
#
def cmd_help(args)
def cmd_help(*args)
all_commands = {}
driver.dispatcher_stack.reverse.each { |dispatcher|
@ -89,10 +98,10 @@ class Core
#
# Displays information about one or more module
#
def cmd_info(args)
def cmd_info(*args)
if (args.length == 0)
if (mod = get_active_module())
print(Serializer::ReadableText.dump_module(mod))
if (active_module)
print(Serializer::ReadableText.dump_module(active_module))
return true
else
print(
@ -118,17 +127,42 @@ class Core
#
# Adds one or more search paths
#
def cmd_search(args)
def cmd_search(*args)
if (args.length == 0)
print_error("No search paths were provided.")
return false
return true
end
args.each { |path|
framework.modules.add_module_path(path)
totals = {}
overall = 0
curr_path = nil
begin
# Walk the list of supplied search paths attempting to add each one
# along the way
args.each { |path|
curr_path = path
if (counts = framework.modules.add_module_path(path))
counts.each_pair { |type, count|
totals[type] = (totals[type]) ? (totals[type] + count) : count
overall += count
}
end
}
rescue NameError
print_error("Failed to add search path #{curr_path}: #{$!}")
return true
end
added = "Loaded #{overall} modules:\n"
totals.each_pair { |type, count|
added += " #{count} #{type}#{count != 1 ? 's' : ''}\n"
}
print_line("Added #{args.length} search paths.")
print(added)
recalculate_tab_complete
end
@ -136,31 +170,36 @@ class Core
#
# Sets a name to a value in a context aware environment
#
def cmd_set(args)
def cmd_set(*args)
# Figure out if these are global variables
global = false
if (args[0] == '-g')
args.shift
global = true
end
# Determine which data store we're operating on
if (mod = get_active_module())
datastore = mod.datastore
if (active_module and global == false)
datastore = active_module.datastore
else
datastore = driver.datastore
global = true
datastore = self.framework.datastore
end
# Dump the contents of the active datastore if no args were supplied
if (args.length == 0)
tbl = Table.new(
Table::Style::Default,
'Columns' =>
[
'Name',
'Value'
])
datastore.each_pair { |name, value|
tbl << [ name, value ]
}
print(tbl.to_s)
if (!global)
print("\n" +
Msf::Serializer::ReadableText.dump_datastore(
"Global", framework.datastore))
end
print("\n" +
Msf::Serializer::ReadableText.dump_datastore(
(global) ? "Global" : "Module: #{active_module.refname}",
datastore) + "\n")
return true
elsif (args.length < 2)
print(
@ -178,12 +217,21 @@ class Core
print_line("#{name} => #{value}")
end
#
# Sets the supplied variables in the global datastore
#
def cmd_setg(*args)
args.unshift('-g')
cmd_set(*args)
end
#
# Displays the list of modules based on their type, or all modules if
# no type is provided
#
def cmd_show(args)
mod = get_active_module()
def cmd_show(*args)
mod = self.active_module
args << "all" if (args.length == 0)
@ -224,12 +272,21 @@ class Core
#
# Unsets a value if it's been set
#
def cmd_unset(args)
def cmd_unset(*args)
# Figure out if these are global variables
global = false
if (args[0] == '-g')
args.shift
global = true
end
# Determine which data store we're operating on
if (mod = get_active_module())
datastore = mod.datastore
if (active_module and global == false)
datastore = active_module.datastore
else
datastore = driver.datastore
datastore = framework.datastore
end
# No arguments? No cookie.
@ -248,8 +305,19 @@ class Core
end
end
#
# Unsets variables in the global data store
#
def cmd_unsetg(*args)
args.unshift('-g')
cmd_unset(*args)
end
#
# Uses a module
def cmd_use(args)
#
def cmd_use(*args)
if (args.length == 0)
print(
"Usage: use module_name\n\n" +
@ -266,7 +334,7 @@ class Core
return false
end
rescue NameError => info
print_error("The supplied module name is ambiguous.")
print_error("The supplied module name is ambiguous: #{$!}.")
return false
end
@ -288,8 +356,8 @@ class Core
end
# If there's currently an active module, go back
if (old_mod = get_active_module())
cmd_back([])
if (active_module)
cmd_back()
end
if (dispatcher != nil)
@ -297,7 +365,7 @@ class Core
end
# Update the active module
set_active_module(mod)
self.active_module = mod
# Update the command prompt
driver.update_prompt("#{mod.type}(#{mod_name}) ")
@ -306,7 +374,7 @@ class Core
#
# Returns the revision of the console library
#
def cmd_version(args)
def cmd_version(*args)
ver = "$Revision$"
print_line("Version: #{ver.match(/ (.+?) \$/)[1]}")

View File

@ -7,9 +7,6 @@ class Encoder
include Msf::Ui::Console::ModuleCommandDispatcher
def cmd_encode(args)
end
end
end end end end

View File

@ -5,8 +5,29 @@ module CommandDispatcher
class Exploit
@@exploit_opts = Rex::Parser::Arguments.new(
"-e" => [ true, "The payload encoder to use. If none is specified, ENCODER is used." ],
"-h" => [ false, "Help banner." ],
"-n" => [ true, "The NOP generator to use. If none is specified, NOP is used." ],
"-o" => [ true, "A comma separated list of options in VAR=VAL format." ],
"-p" => [ true, "The payload to use. If none is specified, PAYLOAD is used." ],
"-t" => [ true, "The target index to use." ],
"-z" => [ true, "Do not interact with the session after successful exploitation." ])
include Msf::Ui::Console::ModuleCommandDispatcher
def commands
{
"exploit" => "Launch an exploit attempt",
}
end
#
# Launches an exploitation attempt
#
def cmd_exploit(*args)
end
end
end end end end

View File

@ -9,15 +9,15 @@ class Nop
@@generate_opts = Rex::Parser::Arguments.new(
"-b" => [ true, "The list of characters to avoid: '\\x00\\xff'" ],
"-t" => [ true, "The output type: ruby, perl, c, or raw." ],
"-h" => [ false, "Help banner." ])
"-h" => [ false, "Help banner." ],
"-t" => [ true, "The output type: ruby, perl, c, or raw." ])
include Msf::Ui::Console::ModuleCommandDispatcher
def commands
return {
"generate" => "Generates a NOP sled",
}
{
"generate" => "Generates a NOP sled",
}
end
#
@ -40,7 +40,7 @@ class Nop
when nil
length = val.to_i
when '-b'
badchars = [ val.downcase.gsub(/\\x([a-f0-9][a-f0-9])/, '\1') ].pack("H*")
badchars = Rex::Text.hex_to_raw(val)
when '-t'
type = val
when '-h'
@ -54,10 +54,9 @@ class Nop
# Generate the sled
begin
sled = Msf::Simple::Nop.generate(
mod,
sled = mod.generate_simple(
length,
'Badchars' => badchars,
'BadChars' => badchars,
'Format' => type)
rescue
print_error("Sled generation failed: #{$!}.")

View File

@ -8,25 +8,25 @@ module CommandDispatcher
class Payload
@@generate_opts = Rex::Parser::Arguments.new(
"-b" => [ true, "The list of characters to avoid '\\x00\\xff'" ],
"-t" => [ true, "The output type: ruby, perl, c, or raw." ],
"-b" => [ true, "The list of characters to avoid: '\\x00\\xff'" ],
"-e" => [ true, "The name of the encoder module to use." ],
"-o" => [ true, "A space separated list of options in VAR=VAL format." ],
"-h" => [ false, "Help banner." ],
"-o" => [ true, "A comma separated list of options in VAR=VAL format." ],
"-s" => [ true, "NOP sled length." ],
"-h" => [ false, "Help banner." ])
"-t" => [ true, "The output type: ruby, perl, c, or raw." ])
include Msf::Ui::Console::ModuleCommandDispatcher
def commands
return {
"generate" => "Generates a payload",
}
{
"generate" => "Generates a payload",
}
end
#
# Generates a payload
#
def cmd_generate(args)
def cmd_generate(*args)
# Parse the arguments
encoder_name = nil
@ -58,8 +58,7 @@ class Payload
# Generate the payload
begin
buf = Msf::Simple::Payload.generate(
mod,
buf = mod.generate_simple(
'BadChars' => badchars,
'Encoder' => encoder_name,
'Format' => type,

View File

@ -25,7 +25,7 @@ class Driver < Msf::Ui::Driver
def initialize(prompt = "%umsf", prompt_char = ">%c")
# Initialize attributes
self.framework = Msf::Framework.new
self.framework = Msf::Simple::Framework.create
self.dispatcher_stack = []
# Add the core command dispatcher as the root of the dispatcher
@ -74,7 +74,7 @@ class Driver < Msf::Ui::Driver
begin
if (dispatcher.respond_to?('cmd_' + method))
eval("
dispatcher.#{'cmd_' + method}(arguments)
dispatcher.#{'cmd_' + method}(*arguments)
found = true")
end
rescue
@ -105,6 +105,7 @@ class Driver < Msf::Ui::Driver
end
attr_reader :dispatcher_stack, :framework
attr_accessor :active_module
protected

View File

@ -7,7 +7,7 @@ module ModuleCommandDispatcher
include Msf::Ui::Console::CommandDispatcher
def mod
return get_active_module
return driver.active_module
end
end

View File

@ -34,10 +34,6 @@ class Table < Rex::Ui::Text::Table
end
end
def header_to_s
return super + "\n"
end
# Print nothing if there are no rows if the style is default
def to_s
if (style == Style::Default)

View File

@ -13,7 +13,6 @@ module Ui
class Driver
def initialize
self.datastore = DataStore.new
end
# Executes the user interface, optionally in an asynchronous fashion
@ -29,26 +28,8 @@ class Driver
def cleanup
end
#
# Arbitrary state storage
#
# Store a keyed value
def store(key, value)
datastore[key] = value
end
# Retrieve a keyed value
def fetch(key)
return datastore[key]
end
attr_reader :datastore
protected
attr_writer :datastore
end
end

View File

@ -12,14 +12,14 @@ class Rex::Text::UnitTest < Test::Unit::TestCase
assert_equal("\"\\x01\\x02\\xff\"\n", Rex::Text.to_ruby(str))
assert_equal("\"\\x01\\x02\\xff\";\n", Rex::Text.to_perl(str))
assert_equal("unsigned char buf[] = \n \"\\x01\\x02\\xff\";\n", Rex::Text.to_c(str))
assert_equal("unsigned char buf[] = \n\"\\x01\\x02\\xff\";\n", Rex::Text.to_c(str))
# 0 -> 20
str = "\000\001\002\003\004\005\006\a\010\t\n\v\f\r\016\017\020\021\022\023"
assert_equal("\"\\x00\\x01\\x02\\x03\" +\n\"\\x04\\x05\\x06\\x07\" +\n\"\\x08\\x09\\x0a\\x0b\" +\n\"\\x0c\\x0d\\x0e\\x0f\" +\n\"\\x10\\x11\\x12\\x13\"\n", Rex::Text.to_ruby(str, 20))
assert_equal("\"\\x00\\x01\\x02\\x03\" .\n\"\\x04\\x05\\x06\\x07\" .\n\"\\x08\\x09\\x0a\\x0b\" .\n\"\\x0c\\x0d\\x0e\\x0f\" .\n\"\\x10\\x11\\x12\\x13\";\n", Rex::Text.to_perl(str, 20))
assert_equal("unsigned char buf[] = \n \"\\x00\\x01\\x02\\x03\"\n \"\\x04\\x05\\x06\\x07\"\n \"\\x08\\x09\\x0a\\x0b\"\n \"\\x0c\\x0d\\x0e\\x0f\"\n \"\\x10\\x11\\x12\\x13\";\n", Rex::Text.to_c(str, 20, "buf"))
assert_equal("unsigned char buf[] = \n\"\\x00\\x01\\x02\\x03\\x04\"\n\"\\x05\\x06\\x07\\x08\\x09\"\n\"\\x0a\\x0b\\x0c\\x0d\\x0e\"\n\"\\x0f\\x10\\x11\\x12\\x13\";\n", Rex::Text.to_c(str, 20, "buf"))
end
def test_wordwrap

View File

@ -67,6 +67,21 @@ class Table
return str
end
#
# :nodoc:
#
# Returns the header string
#
def header_to_s
if (header)
pad = " " * headeri
return pad + header + "\n" + pad + "=" * header.length + "\n\n"
end
return ''
end
#
# Prints the contents of the table
#
@ -129,21 +144,6 @@ protected
return ((row.kind_of?(String)) && (row == '__hr__'))
end
#
# :nodoc:
#
# Returns the header string
#
def header_to_s
if (header)
pad = " " * headeri
return pad + header + "\n" + pad + "=" * header.length + "\n"
end
return ''
end
#
# :nodoc:
#

View File

@ -101,7 +101,7 @@ SINGLE_BYTE_SLED =
out_sled = ''
random = opts['Random']
badchars = opts['Badchars'] || ''
badchars = opts['BadChars'] || ''
badregs = opts['SaveRegisters'] || []
# Did someone specify random NOPs in the environment?

View File

@ -46,7 +46,7 @@ nop = Msf::Nops::IA32::SingleByte.new
sled = nop.generate_sled(
100,
'Random' => true)
# 'Badchars' => "\x95")
# 'BadChars' => "\x95")
# 'SaveRegisters' => [ 'eax' ])
puts sled.unpack("H*")[0]