Parse SVN information and warns folks with out of date installations
git-svn-id: file:///home/svn/framework3/trunk@7415 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
a87fc61a63
commit
5581f5a73b
|
@ -1,4 +1,5 @@
|
|||
require 'msf/core'
|
||||
require 'msf/util'
|
||||
|
||||
module Msf
|
||||
|
||||
|
@ -13,20 +14,27 @@ class Framework
|
|||
#
|
||||
# Versioning information
|
||||
#
|
||||
|
||||
Major = 3
|
||||
Minor = 3
|
||||
Release = "-beta"
|
||||
Release = "-rc1"
|
||||
Version = "#{Major}.#{Minor}#{Release}"
|
||||
Revision = "$Revision$"
|
||||
|
||||
# Repository information
|
||||
RepoRevision = ::Msf::Util::SVN.revision
|
||||
RepoUpdated = ::Msf::Util::SVN.updated
|
||||
RepoUpdatedDays = ::Msf::Util::SVN.days_since_update
|
||||
RepoUpdatedDaysNote = ::Msf::Util::SVN.last_updated_friendly
|
||||
RepoRoot = ::Msf::Util::SVN.root
|
||||
|
||||
# API Version
|
||||
APIMajor = 1
|
||||
APIMinor = 0
|
||||
|
||||
|
||||
# Base/API Version
|
||||
VersionCore = Major + (Minor / 10.0)
|
||||
VersionAPI = APIMajor + (APIMinor / 10.0)
|
||||
|
||||
|
||||
#
|
||||
# Mixin meant to be included into all classes that can have instances that
|
||||
# should be tied to the framework, such as modules.
|
||||
|
@ -37,7 +45,7 @@ class Framework
|
|||
# A reference to the framework instance from which this offspring was
|
||||
# derived.
|
||||
#
|
||||
attr_accessor :framework
|
||||
attr_accessor :framework
|
||||
end
|
||||
|
||||
require 'msf/core/module_manager'
|
||||
|
@ -48,7 +56,7 @@ class Framework
|
|||
# Creates an instance of the framework context.
|
||||
#
|
||||
def initialize(opts={})
|
||||
|
||||
|
||||
# Allow specific module types to be loaded
|
||||
types = opts[:module_types] || MODULE_TYPES
|
||||
|
||||
|
@ -100,7 +108,7 @@ class Framework
|
|||
# Returns the framework version in Major.Minor format.
|
||||
#
|
||||
def version
|
||||
Version
|
||||
Version
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -158,3 +166,4 @@ protected
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class Core
|
|||
"-k" => [ true, "Terminate the specified job name." ],
|
||||
"-K" => [ false, "Terminate all running jobs." ],
|
||||
"-l" => [ false, "List all running jobs." ])
|
||||
|
||||
|
||||
@@persist_opts = Rex::Parser::Arguments.new(
|
||||
"-s" => [ true, "Storage medium to be used (ex: flatfile)." ],
|
||||
"-r" => [ false, "Restore framework state." ],
|
||||
|
@ -131,11 +131,11 @@ class Core
|
|||
driver.current_dispatcher.name != 'Database Backend')
|
||||
# Reset the active module if we have one
|
||||
if (active_module)
|
||||
|
||||
|
||||
# Do NOT reset the UI anymore
|
||||
# active_module.reset_ui
|
||||
|
||||
# Save the module's datastore so that we can load it later
|
||||
# Save the module's datastore so that we can load it later
|
||||
# if the module is used again
|
||||
@dscache[active_module.fullname] = active_module.datastore.dup
|
||||
|
||||
|
@ -144,7 +144,7 @@ class Core
|
|||
|
||||
# Destack the current dispatcher
|
||||
driver.destack_dispatcher
|
||||
|
||||
|
||||
# Restore the prompt
|
||||
driver.update_prompt
|
||||
end
|
||||
|
@ -159,32 +159,45 @@ class Core
|
|||
print_error("No path specified")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
begin
|
||||
Dir.chdir(args.join(" ").strip)
|
||||
rescue ::Exception
|
||||
print_error("The specified path does not exist")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Display one of the fabulous banners.
|
||||
#
|
||||
def cmd_banner(*args)
|
||||
banner = Banner.to_s + "\n\n"
|
||||
banner << " =[ msf v#{Msf::Framework::Version} [core:#{Msf::Framework::VersionCore} api:#{Msf::Framework::VersionAPI}]\n"
|
||||
banner << " =[ metasploit v#{Msf::Framework::Version} [core:#{Msf::Framework::VersionCore} api:#{Msf::Framework::VersionAPI}]\n"
|
||||
banner << "+ -- --=[ "
|
||||
banner << "#{framework.stats.num_exploits} exploits - "
|
||||
banner << "#{framework.stats.num_payloads} payloads\n"
|
||||
banner << "#{framework.stats.num_exploits} exploits - #{framework.stats.num_auxiliary} auxiliary\n"
|
||||
banner << "+ -- --=[ "
|
||||
banner << "#{framework.stats.num_encoders} encoders - "
|
||||
banner << "#{framework.stats.num_nops} nops\n"
|
||||
banner << " =[ "
|
||||
banner << "#{framework.stats.num_auxiliary} aux\n"
|
||||
|
||||
oldwarn = nil
|
||||
banner << "#{framework.stats.num_payloads} payloads - #{framework.stats.num_encoders} encoders - #{framework.stats.num_nops} nops\n"
|
||||
if ( ::Msf::Framework::RepoRevision > 0)
|
||||
banner << " =[ svn r#{::Msf::Framework::RepoRevision} updated #{::Msf::Framework::RepoUpdatedDaysNote}\n"
|
||||
if(::Msf::Framework::RepoUpdatedDays > 7)
|
||||
oldwarn = []
|
||||
oldwarn << "Warning: This copy of the Metasploit Framework was last updated #{::Msf::Framework::RepoUpdatedDays}."
|
||||
oldwarn << " We recommend that you update the framework at least every other day."
|
||||
oldwarn << " For information on updating your copy of Metasploit, please see:"
|
||||
oldwarn << " http://dev.metasploit.com/redmine/projects/framework/wiki/Updating"
|
||||
oldwarn << ""
|
||||
end
|
||||
end
|
||||
banner << "\n"
|
||||
|
||||
# Display the banner
|
||||
print(banner)
|
||||
|
||||
if(oldwarn)
|
||||
oldwarn.map{|line| print_line(line) }
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -366,7 +379,7 @@ class Core
|
|||
# Instructs the driver to stop executing.
|
||||
#
|
||||
def cmd_exit(*args)
|
||||
if(framework.sessions.count() > 0 and
|
||||
if(framework.sessions.count() > 0 and
|
||||
(args.length < 1 or (args[0] =~ /\-Y/i) == nil))
|
||||
print_status("You have active sessions open, to exit anyway type \"exit -y\"")
|
||||
return
|
||||
|
@ -383,7 +396,7 @@ class Core
|
|||
return if not (args and args.length == 1)
|
||||
Rex::ThreadSafe.sleep(args[0].to_f)
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Displays the command help banner or an individual command's help banner
|
||||
# if we can figure out how to invoke it.
|
||||
|
@ -446,13 +459,13 @@ class Core
|
|||
end
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the info command (same as use)
|
||||
#
|
||||
def cmd_info_tabs(str, words)
|
||||
cmd_use_tabs(str, words)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Goes into IRB scripting mode
|
||||
|
@ -467,11 +480,11 @@ class Core
|
|||
rescue
|
||||
print_error("Error during IRB: #{$!}\n\n#{$@.join("\n")}")
|
||||
end
|
||||
|
||||
|
||||
# Reset tab completion
|
||||
if (driver.input.supports_readline)
|
||||
driver.input.reset_tab_completion
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -494,7 +507,7 @@ class Core
|
|||
when "-k"
|
||||
print_line("Stopping job: #{val}...")
|
||||
framework.jobs.stop_job(val)
|
||||
|
||||
|
||||
when "-K"
|
||||
print_line("Stopping all jobs...")
|
||||
framework.jobs.each_key do |i|
|
||||
|
@ -510,7 +523,7 @@ class Core
|
|||
end
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the jobs command
|
||||
#
|
||||
|
@ -526,8 +539,8 @@ class Core
|
|||
end
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
# Loads a plugin from the supplied path. If no absolute path is supplied,
|
||||
# the framework root plugin directory is used.
|
||||
|
@ -563,7 +576,7 @@ class Core
|
|||
if (path !~ /#{File::SEPARATOR}/)
|
||||
plugin_file_name = path
|
||||
|
||||
# If the plugin isn't in the user direcotry (~/.msf3/plugins/), use the base
|
||||
# If the plugin isn't in the user direcotry (~/.msf3/plugins/), use the base
|
||||
path = Msf::Config.user_plugin_directory + File::SEPARATOR + plugin_file_name
|
||||
if not File.exists?( path + ".rb" )
|
||||
# If the following "path" doesn't exist it will be caught when we attempt to load
|
||||
|
@ -582,7 +595,7 @@ class Core
|
|||
print_error("Failed to load plugin from #{path}: #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the load command
|
||||
#
|
||||
|
@ -598,7 +611,7 @@ class Core
|
|||
rescue Exception
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# This method persists or restores framework state from a persistent
|
||||
|
@ -652,9 +665,9 @@ class Core
|
|||
def cmd_persist_tabs(str, words)
|
||||
if (not words[1])
|
||||
return %w{-s -r -h}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# This method handles the route command which allows a user to specify
|
||||
# which session a given subnet should route through.
|
||||
|
@ -707,7 +720,7 @@ class Core
|
|||
print_error("Missing arguments to route remove.")
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
gw = nil
|
||||
|
||||
# Satisfy case problems
|
||||
|
@ -757,7 +770,7 @@ class Core
|
|||
'Header' => "Active Routing Table",
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Columns' =>
|
||||
'Columns' =>
|
||||
[
|
||||
'Subnet',
|
||||
'Netmask',
|
||||
|
@ -783,7 +796,7 @@ class Core
|
|||
print(tbl.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the route command
|
||||
#
|
||||
|
@ -806,7 +819,7 @@ class Core
|
|||
# Save the framework's datastore
|
||||
begin
|
||||
framework.save_config
|
||||
|
||||
|
||||
if (active_module)
|
||||
active_module.save_config
|
||||
end
|
||||
|
@ -814,7 +827,7 @@ class Core
|
|||
log_error("Save failed: #{$!}")
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
print_line("Saved configuration to: #{Msf::Config.config_file}")
|
||||
end
|
||||
|
||||
|
@ -833,7 +846,7 @@ class Core
|
|||
overall = 0
|
||||
curr_path = nil
|
||||
|
||||
begin
|
||||
begin
|
||||
# Walk the list of supplied search paths attempting to add each one
|
||||
# along the way
|
||||
args.each { |path|
|
||||
|
@ -843,7 +856,7 @@ class Core
|
|||
if (counts = framework.modules.add_module_path(path, false))
|
||||
counts.each_pair { |type, count|
|
||||
totals[type] = (totals[type]) ? (totals[type] + count) : count
|
||||
|
||||
|
||||
overall += count
|
||||
}
|
||||
end
|
||||
|
@ -916,7 +929,7 @@ class Core
|
|||
end
|
||||
|
||||
print_status("Searching loaded modules for pattern '#{match}'...")
|
||||
|
||||
|
||||
case section
|
||||
when 'all'
|
||||
show_encoders(regex)
|
||||
|
@ -938,7 +951,7 @@ class Core
|
|||
print_line("Usage: search (all|encoders|nops|exploits|payloads|auxiliary) regex")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
# Provides an interface to the sessions currently active in the framework.
|
||||
|
@ -978,7 +991,7 @@ class Core
|
|||
when "-d"
|
||||
method = 'detach'
|
||||
sid = val
|
||||
|
||||
|
||||
# Display help banner
|
||||
when "-h"
|
||||
print(
|
||||
|
@ -988,10 +1001,10 @@ class Core
|
|||
return false
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
# Now, perform the actual method
|
||||
case method
|
||||
|
||||
|
||||
when 'kill'
|
||||
if ((session = framework.sessions.get(sid)))
|
||||
print_status("Killing session #{sid}")
|
||||
|
@ -1005,15 +1018,15 @@ class Core
|
|||
session.kill
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
when 'detach'
|
||||
if ((session = framework.sessions.get(sid)))
|
||||
print_status("Detaching session #{sid}")
|
||||
if (session.interactive?)
|
||||
if (session.interactive?)
|
||||
session.detach()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
when 'interact'
|
||||
if ((session = framework.sessions.get(sid)))
|
||||
if (session.interactive?)
|
||||
|
@ -1022,13 +1035,13 @@ class Core
|
|||
self.active_session = session
|
||||
|
||||
session.interact(driver.input.dup, driver.output)
|
||||
|
||||
|
||||
self.active_session = nil
|
||||
|
||||
|
||||
if (driver.input.supports_readline)
|
||||
driver.input.reset_tab_completion
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
print_error("Session #{sid} is non-interactive.")
|
||||
end
|
||||
|
@ -1036,7 +1049,7 @@ class Core
|
|||
print_error("Invalid session identifier: #{sid}")
|
||||
end
|
||||
when 'list'
|
||||
print("\n" +
|
||||
print("\n" +
|
||||
Serializer::ReadableText.dump_sessions(framework, verbose) + "\n")
|
||||
end
|
||||
|
||||
|
@ -1050,7 +1063,7 @@ class Core
|
|||
|
||||
# Reset the active session
|
||||
self.active_session = nil
|
||||
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
@ -1062,12 +1075,12 @@ class Core
|
|||
return %w{-q -i -l -h}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Sets a name to a value in a context aware environment.
|
||||
#
|
||||
def cmd_set(*args)
|
||||
|
||||
|
||||
# Figure out if these are global variables
|
||||
global = false
|
||||
|
||||
|
@ -1133,34 +1146,34 @@ class Core
|
|||
|
||||
print_line("#{name} => #{value}")
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the set command
|
||||
#
|
||||
def cmd_set_tabs(str, words)
|
||||
|
||||
|
||||
# A value has already been specified
|
||||
if (words[2])
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
# A value needs to be specified
|
||||
if(words[1])
|
||||
return tab_complete_option(str, words)
|
||||
end
|
||||
|
||||
|
||||
res = cmd_unset_tabs(str, words) || [ ]
|
||||
mod = active_module
|
||||
|
||||
|
||||
if (not mod)
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
mod.options.sorted.each { |e|
|
||||
name, opt = e
|
||||
res << name
|
||||
}
|
||||
|
||||
|
||||
# Exploits provide these three default options
|
||||
if (mod.exploit?)
|
||||
res << 'PAYLOAD'
|
||||
|
@ -1181,14 +1194,14 @@ class Core
|
|||
p.options.sorted.each { |e|
|
||||
name, opt = e
|
||||
res << name
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Sets the supplied variables in the global datastore.
|
||||
#
|
||||
|
@ -1197,14 +1210,14 @@ class Core
|
|||
|
||||
cmd_set(*args)
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the setg command
|
||||
#
|
||||
def cmd_setg_tabs(str, words)
|
||||
res = cmd_set_tabs(str, words) || [ ]
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Displays the list of modules based on their type, or all modules if
|
||||
# no type is provided.
|
||||
|
@ -1250,7 +1263,7 @@ class Core
|
|||
show_evasion_options(mod)
|
||||
else
|
||||
print_error("No module selected.")
|
||||
end
|
||||
end
|
||||
when "plugins"
|
||||
show_plugins
|
||||
when "targets"
|
||||
|
@ -1268,7 +1281,7 @@ class Core
|
|||
end
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the show command
|
||||
#
|
||||
|
@ -1279,7 +1292,7 @@ class Core
|
|||
end
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Unloads a plugin by its name.
|
||||
#
|
||||
|
@ -1302,7 +1315,7 @@ class Core
|
|||
end
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the unload command
|
||||
#
|
||||
|
@ -1368,7 +1381,7 @@ class Core
|
|||
datastore.delete(val)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the unset command
|
||||
#
|
||||
|
@ -1376,7 +1389,7 @@ class Core
|
|||
datastore = active_module ? active_module.datastore : self.framework.datastore
|
||||
datastore.keys
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Unsets variables in the global data store.
|
||||
#
|
||||
|
@ -1385,14 +1398,14 @@ class Core
|
|||
|
||||
cmd_unset(*args)
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the unsetg command
|
||||
#
|
||||
def cmd_unsetg_tabs(str, words)
|
||||
self.framework.datastore.keys
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Uses a module.
|
||||
#
|
||||
|
@ -1455,29 +1468,29 @@ class Core
|
|||
if @dscache[active_module.fullname]
|
||||
active_module.datastore.update(@dscache[active_module.fullname])
|
||||
end
|
||||
|
||||
|
||||
mod.init_ui(driver.input, driver.output)
|
||||
|
||||
# Update the command prompt
|
||||
driver.update_prompt("#{mod.type}(#{mod.shortname}) ")
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Tab completion for the use command
|
||||
#
|
||||
def cmd_use_tabs(str, words)
|
||||
res = []
|
||||
|
||||
|
||||
framework.modules.module_types.each do |mtyp|
|
||||
mset = framework.modules.module_names(mtyp)
|
||||
mset.each do |mref|
|
||||
res << mtyp + '/' + mref
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return res.sort
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Returns the revision of the framework and console library
|
||||
#
|
||||
|
@ -1497,12 +1510,12 @@ class Core
|
|||
opt = words[1]
|
||||
res = []
|
||||
mod = active_module
|
||||
|
||||
|
||||
# With no active module, we have nothing to compare
|
||||
if (not mod)
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
# Well-known option names specific to exploits
|
||||
if (mod.exploit?)
|
||||
return option_values_payloads() if opt.upcase == 'PAYLOAD'
|
||||
|
@ -1514,17 +1527,17 @@ class Core
|
|||
if (mod.auxiliary?)
|
||||
return option_values_actions() if opt.upcase == 'ACTION'
|
||||
end
|
||||
|
||||
|
||||
# The ENCODER option works for payloads and exploits
|
||||
if ((mod.exploit? or mod.payload?) and opt.upcase == 'ENCODER')
|
||||
return option_values_encoders()
|
||||
end
|
||||
|
||||
|
||||
# Is this option used by the active module?
|
||||
if (mod.options.include?(opt))
|
||||
res.concat(option_values_dispatch(mod.options[opt], str, words))
|
||||
end
|
||||
|
||||
|
||||
# How about the selected payload?
|
||||
if (mod.exploit? and mod.datastore['PAYLOAD'])
|
||||
p = framework.modules.create(mod.datastore['PAYLOAD'])
|
||||
|
@ -1535,17 +1548,17 @@ class Core
|
|||
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Provide possible option values based on type
|
||||
#
|
||||
def option_values_dispatch(o, str, words)
|
||||
def option_values_dispatch(o, str, words)
|
||||
|
||||
res = []
|
||||
res << o.default.to_s if o.default
|
||||
|
||||
case o.class.to_s
|
||||
|
||||
|
||||
when 'Msf::OptAddress'
|
||||
case o.name.upcase
|
||||
when 'RHOST'
|
||||
|
@ -1556,7 +1569,7 @@ class Core
|
|||
res << Rex::Socket.source_address()
|
||||
else
|
||||
end
|
||||
|
||||
|
||||
when 'Msf::OptAddressRange'
|
||||
|
||||
case str
|
||||
|
@ -1573,42 +1586,42 @@ class Core
|
|||
res << addr+'/16'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
when 'Msf::OptPort'
|
||||
case o.name.upcase
|
||||
when 'RPORT'
|
||||
option_values_target_ports().each do |port|
|
||||
res << port
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if (res.empty?)
|
||||
res << (rand(65534)+1).to_s
|
||||
end
|
||||
|
||||
|
||||
when 'Msf::OptEnum'
|
||||
o.enums.each do |val|
|
||||
res << val
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Provide valid payload options for the current exploit
|
||||
#
|
||||
def option_values_payloads
|
||||
|
||||
|
||||
# Module caching for significant speed improvement
|
||||
if (not (@cache_active_module and @cache_active_module == active_module.refname))
|
||||
@cache_active_module = active_module.refname
|
||||
@cache_payloads = active_module.compatible_payloads.map { |refname, payload| refname }
|
||||
end
|
||||
|
||||
|
||||
@cache_payloads
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Provide valid target options for the current exploit
|
||||
#
|
||||
|
@ -1618,9 +1631,9 @@ class Core
|
|||
1.upto(active_module.targets.length) { |i| res << (i-1).to_s }
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Provide valid action options for the current auxiliary module
|
||||
#
|
||||
|
@ -1630,15 +1643,15 @@ class Core
|
|||
active_module.actions.each { |i| res << i.name }
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
# Provide valid nops options for the current exploit
|
||||
#
|
||||
def option_values_nops
|
||||
framework.nops.map { |refname, mod| refname }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
# Provide valid encoders options for the current exploit or payload
|
||||
#
|
||||
|
@ -1653,7 +1666,7 @@ class Core
|
|||
res = [ ]
|
||||
res << Rex::Socket.source_address()
|
||||
return res if not framework.db.active
|
||||
|
||||
|
||||
# List only those hosts with matching open ports?
|
||||
mport = self.active_module.datastore['RPORT']
|
||||
if (mport)
|
||||
|
@ -1664,18 +1677,18 @@ class Core
|
|||
hosts[ service.host.address ] = true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
hosts.keys.each do |host|
|
||||
res << host
|
||||
end
|
||||
|
||||
|
||||
# List all hosts in the database
|
||||
else
|
||||
framework.db.each_host do |host|
|
||||
res << host.address
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
|
@ -1697,19 +1710,19 @@ class Core
|
|||
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
protected
|
||||
|
||||
#
|
||||
# Module list enumeration
|
||||
#
|
||||
|
||||
|
||||
def show_encoders(regex = nil) # :nodoc:
|
||||
# If an active module has been selected and it's an exploit, get the
|
||||
# list of compatible encoders and display them
|
||||
if (active_module and active_module.exploit? == true)
|
||||
tbl = generate_module_table("Compatible encoders")
|
||||
|
||||
|
||||
active_module.compatible_encoders.each { |refname, encoder|
|
||||
name = encoder.new.name
|
||||
|
||||
|
@ -1725,7 +1738,7 @@ protected
|
|||
show_module_set("Encoders", framework.encoders, regex)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def show_nops(regex = nil) # :nodoc:
|
||||
show_module_set("NOP Generators", framework.nops, regex)
|
||||
end
|
||||
|
@ -1763,7 +1776,7 @@ protected
|
|||
def show_options(mod) # :nodoc:
|
||||
mod_opt = Serializer::ReadableText.dump_options(mod, ' ')
|
||||
print("\nModule options:\n\n#{mod_opt}\n") if (mod_opt and mod_opt.length > 0)
|
||||
|
||||
|
||||
# If it's an exploit and a payload is defined, create it and
|
||||
# display the payload's options
|
||||
if (mod.exploit? and mod.datastore['PAYLOAD'])
|
||||
|
@ -1773,11 +1786,11 @@ protected
|
|||
print_error("Invalid payload defined: #{mod.datastore['PAYLOAD']}\n")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
p.share_datastore(mod.datastore)
|
||||
|
||||
if (p)
|
||||
p_opt = Serializer::ReadableText.dump_options(p, ' ')
|
||||
p_opt = Serializer::ReadableText.dump_options(p, ' ')
|
||||
print("\nPayload options (#{mod.datastore['PAYLOAD']}):\n\n#{p_opt}\n") if (p_opt and p_opt.length > 0)
|
||||
end
|
||||
end
|
||||
|
@ -1801,9 +1814,9 @@ protected
|
|||
mod_actions = Serializer::ReadableText.dump_auxiliary_actions(mod, ' ')
|
||||
print("\nAuxiliary actions:\n\n#{mod_actions}\n") if (mod_actions and mod_actions.length > 0)
|
||||
end
|
||||
|
||||
|
||||
def show_advanced_options(mod) # :nodoc:
|
||||
mod_opt = Serializer::ReadableText.dump_advanced_options(mod, ' ')
|
||||
mod_opt = Serializer::ReadableText.dump_advanced_options(mod, ' ')
|
||||
print("\nModule advanced options:\n\n#{mod_opt}\n") if (mod_opt and mod_opt.length > 0)
|
||||
|
||||
# If it's an exploit and a payload is defined, create it and
|
||||
|
@ -1815,18 +1828,18 @@ protected
|
|||
print_error("Invalid payload defined: #{mod.datastore['PAYLOAD']}\n")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
p.share_datastore(mod.datastore)
|
||||
|
||||
if (p)
|
||||
p_opt = Serializer::ReadableText.dump_advanced_options(p, ' ')
|
||||
p_opt = Serializer::ReadableText.dump_advanced_options(p, ' ')
|
||||
print("\nPayload advanced options (#{mod.datastore['PAYLOAD']}):\n\n#{p_opt}\n") if (p_opt and p_opt.length > 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def show_evasion_options(mod) # :nodoc:
|
||||
mod_opt = Serializer::ReadableText.dump_evasion_options(mod, ' ')
|
||||
mod_opt = Serializer::ReadableText.dump_evasion_options(mod, ' ')
|
||||
print("\nModule evasion options:\n\n#{mod_opt}\n") if (mod_opt and mod_opt.length > 0)
|
||||
|
||||
# If it's an exploit and a payload is defined, create it and
|
||||
|
@ -1838,16 +1851,16 @@ protected
|
|||
print_error("Invalid payload defined: #{mod.datastore['PAYLOAD']}\n")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
p.share_datastore(mod.datastore)
|
||||
|
||||
if (p)
|
||||
p_opt = Serializer::ReadableText.dump_evasion_options(p, ' ')
|
||||
p_opt = Serializer::ReadableText.dump_evasion_options(p, ' ')
|
||||
print("\nPayload evasion options (#{mod.datastore['PAYLOAD']}):\n\n#{p_opt}\n") if (p_opt and p_opt.length > 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def show_plugins # :nodoc:
|
||||
tbl = generate_module_table("Plugins")
|
||||
|
||||
|
@ -1868,7 +1881,7 @@ protected
|
|||
tbl << [ refname, o.name ]
|
||||
next
|
||||
end
|
||||
|
||||
|
||||
# handle a search string, search deep
|
||||
if(
|
||||
o.name.match(regex) or
|
||||
|
@ -1890,7 +1903,7 @@ protected
|
|||
'Header' => type,
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Columns' =>
|
||||
'Columns' =>
|
||||
[
|
||||
'Name',
|
||||
'Description'
|
||||
|
@ -1908,3 +1921,4 @@ protected
|
|||
end
|
||||
|
||||
end end end end
|
||||
|
||||
|
|
|
@ -20,3 +20,6 @@ end
|
|||
|
||||
# Executable generation and encoding
|
||||
require 'msf/util/exe'
|
||||
|
||||
# Parse SVN entries
|
||||
require 'msf/util/svn'
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
###
|
||||
#
|
||||
# framework-util-svn
|
||||
# --------------
|
||||
#
|
||||
# The class provides methods for parsing the SVN information in the framework directory
|
||||
#
|
||||
###
|
||||
|
||||
require 'date'
|
||||
|
||||
module Msf
|
||||
module Util
|
||||
class SVN
|
||||
|
||||
def self.load_root
|
||||
info = {}
|
||||
path = ::File.join(::File.dirname(__FILE__), "..", "..", "..", ".svn", "entries")
|
||||
if !::File.exists?(path)
|
||||
return info
|
||||
end
|
||||
ents = []
|
||||
File.open(path, "rb") do |fd|
|
||||
ents = fd.read(::File.size(path)).split("\x0c")
|
||||
end
|
||||
ents[0].split("\n").each do |line|
|
||||
line.strip!
|
||||
next if line.empty?
|
||||
case line
|
||||
when /framework3/
|
||||
info[:root] = line
|
||||
when /^\d+$/
|
||||
info[:revision] = line.to_i
|
||||
when /^\d{4}-\d.*T/
|
||||
info[:updated] = line
|
||||
end
|
||||
break if (info[:root] and info[:revision] and info[:updated])
|
||||
end
|
||||
info
|
||||
end
|
||||
|
||||
def self.revision
|
||||
info = load_root
|
||||
info[:revision]
|
||||
end
|
||||
|
||||
def self.updated
|
||||
info = load_root
|
||||
info[:updated]
|
||||
end
|
||||
|
||||
def self.root
|
||||
info = load_root
|
||||
info[:root]
|
||||
end
|
||||
|
||||
def self.days_since_update
|
||||
info = load_root
|
||||
svnt = info[:updated]
|
||||
if(not svnt)
|
||||
return
|
||||
end
|
||||
diff = (Date.parse(Time.now.to_s) - Date.parse(svnt)).to_f
|
||||
end
|
||||
|
||||
def self.last_updated_friendly
|
||||
diff = self.days_since_update
|
||||
case diff
|
||||
when nil
|
||||
"at a unknown date"
|
||||
when -2.0 .. 1.0
|
||||
"today"
|
||||
when 1.0 .. 2.0
|
||||
"yesterday"
|
||||
else
|
||||
"#{diff.to_i} days ago"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue