Files
metasploit-gs/lib/msf/base/serializer/readable_text.rb
T
Tod Beardsley c5ce575543 Revert "Merge pull request #101 from chao-mu/master"
Reverting the OptRegexp commit from chao-mu. Before committing to
master, this option type needs to be tested on the various mainstream
UI's (Metasploit Pro, msfgui, and Armitage) to see if they behave
as reasonably as msfconsole. Each UI tends to handle option setting,
passing, and display in their own special way.

This should make it back in by Wednesday, assuming all goes well.

[See #101]

This reverts commit 84db5a21fc, reversing
changes made to 24aaf85a1b.
2012-01-17 15:33:47 -06:00

485 lines
11 KiB
Ruby

module Msf
module Serializer
###
#
# This class formats information in a plain-text format that
# is meant to be displayed on a console or some other non-GUI
# medium.
#
###
class ReadableText
DefaultColumnWrap = 70
DefaultIndent = 2
#
# Returns a formatted string that contains information about
# the supplied module instance.
#
def self.dump_module(mod, indent = " ")
case mod.type
when MODULE_PAYLOAD
return dump_payload_module(mod, indent)
when MODULE_NOP
return dump_basic_module(mod, indent)
when MODULE_ENCODER
return dump_basic_module(mod, indent)
when MODULE_EXPLOIT
return dump_exploit_module(mod, indent)
when MODULE_AUX
return dump_auxiliary_module(mod, indent)
when MODULE_POST
return dump_basic_module(mod, indent)
else
return dump_generic_module(mod, indent)
end
end
#
# Dumps an exploit's targets.
#
def self.dump_exploit_targets(mod, indent = '', h = nil)
tbl = Rex::Ui::Text::Table.new(
'Indent' => indent.length,
'Header' => h,
'Columns' =>
[
'Id',
'Name',
])
mod.targets.each_with_index { |target, idx|
tbl << [ idx.to_s, target.name || 'All' ]
}
tbl.to_s + "\n"
end
#
# Dumps the exploit's selected target
#
def self.dump_exploit_target(mod, indent = '', h = nil)
tbl = Rex::Ui::Text::Table.new(
'Indent' => indent.length,
'Header' => h,
'Columns' =>
[
'Id',
'Name',
])
tbl << [ mod.target_index, mod.target.name || 'All' ]
tbl.to_s + "\n"
end
#
# Dumps an auxiliary's actions
#
def self.dump_auxiliary_actions(mod, indent = '', h = nil)
tbl = Rex::Ui::Text::Table.new(
'Indent' => indent.length,
'Header' => h,
'Columns' =>
[
'Name',
'Description'
])
mod.actions.each_with_index { |target, idx|
tbl << [ target.name || 'All' , target.description || '' ]
}
tbl.to_s + "\n"
end
#
# Dumps the table of payloads that are compatible with the supplied
# exploit.
#
def self.dump_compatible_payloads(exploit, indent = '', h = nil)
tbl = Rex::Ui::Text::Table.new(
'Indent' => indent.length,
'Header' => h,
'Columns' =>
[
'Name',
'Description',
])
exploit.compatible_payloads.each { |entry|
tbl << [ entry[0], entry[1].new.description ]
}
tbl.to_s + "\n"
end
#
# Dumps information about an exploit module.
#
def self.dump_exploit_module(mod, indent = '')
output = "\n"
output << " Name: #{mod.name}\n"
output << " Module: #{mod.fullname}\n"
output << " Version: #{mod.version}\n"
output << " Platform: #{mod.platform_to_s}\n"
output << " Privileged: " + (mod.privileged? ? "Yes" : "No") + "\n"
output << " License: #{mod.license}\n"
output << " Rank: #{mod.rank_to_s.capitalize}\n"
output << "\n"
# Authors
output << "Provided by:\n"
mod.each_author { |author|
output << indent + author.to_s + "\n"
}
output << "\n"
# Targets
output << "Available targets:\n"
output << dump_exploit_targets(mod, indent)
# Options
if (mod.options.has_options?)
output << "Basic options:\n"
output << dump_options(mod, indent)
output << "\n"
end
# Payload information
if (mod.payload_info.length)
output << "Payload information:\n"
if (mod.payload_space)
output << indent + "Space: " + mod.payload_space.to_s + "\n"
end
if (mod.payload_badchars)
output << indent + "Avoid: " + mod.payload_badchars.length.to_s + " characters\n"
end
output << "\n"
end
# Description
output << "Description:\n"
output << word_wrap(Rex::Text.compress(mod.description))
output << "\n"
# References
if (mod.references.length > 0)
output << "References:\n"
mod.references.each { |ref|
output << indent + ref.to_s + "\n"
}
output << "\n"
end
return output
end
#
# Dumps information about an auxiliary module.
#
def self.dump_auxiliary_module(mod, indent = '')
output = "\n"
output << " Name: #{mod.name}\n"
output << " Module: #{mod.fullname}\n"
output << " Version: #{mod.version}\n"
output << " License: #{mod.license}\n"
output << " Rank: #{mod.rank_to_s.capitalize}\n"
output << "\n"
# Authors
output << "Provided by:\n"
mod.each_author { |author|
output << indent + author.to_s + "\n"
}
output << "\n"
# Options
if (mod.options.has_options?)
output << "Basic options:\n"
output << dump_options(mod, indent)
output << "\n"
end
# Description
output << "Description:\n"
output << word_wrap(Rex::Text.compress(mod.description))
output << "\n"
# References
if (mod.references.length > 0)
output << "References:\n"
mod.references.each { |ref|
output << indent + ref.to_s + "\n"
}
output << "\n"
end
return output
end
#
# Dumps information about a payload module.
#
def self.dump_payload_module(mod, indent = '')
# General
output = "\n"
output << " Name: #{mod.name}\n"
output << " Module: #{mod.fullname}\n"
output << " Version: #{mod.version}\n"
output << " Platform: #{mod.platform_to_s}\n"
output << " Arch: #{mod.arch_to_s}\n"
output << "Needs Admin: " + (mod.privileged? ? "Yes" : "No") + "\n"
output << " Total size: #{mod.size}\n"
output << " Rank: #{mod.rank_to_s.capitalize}\n"
output << "\n"
# Authors
output << "Provided by:\n"
mod.each_author { |author|
output << indent + author.to_s + "\n"
}
output << "\n"
# Options
if (mod.options.has_options?)
output << "Basic options:\n"
output << dump_options(mod)
output << "\n"
end
# Description
output << "Description:\n"
output << word_wrap(Rex::Text.compress(mod.description))
output << "\n\n"
return output
end
#
# Dumps information about a module, just the basics.
#
def self.dump_basic_module(mod, indent = '')
# General
output = "\n"
output << " Name: #{mod.name}\n"
output << " Module: #{mod.fullname}\n"
output << " Version: #{mod.version}\n"
output << " Platform: #{mod.platform_to_s}\n"
output << " Arch: #{mod.arch_to_s}\n"
output << " Rank: #{mod.rank_to_s.capitalize}\n"
output << "\n"
# Authors
output << "Provided by:\n"
mod.each_author { |author|
output << indent + author.to_s + "\n"
}
output << "\n"
# Description
output << "Description:\n"
output << word_wrap(Rex::Text.compress(mod.description))
output << "\n\n"
return output
end
def self.dump_generic_module(mod, indent = '')
end
#
# Dumps the list of options associated with the
# supplied module.
#
def self.dump_options(mod, indent = '')
tbl = Rex::Ui::Text::Table.new(
'Indent' => indent.length,
'Columns' =>
[
'Name',
'Current Setting',
'Required',
'Description'
])
mod.options.sorted.each { |entry|
name, opt = entry
next if (opt.advanced?)
next if (opt.evasion?)
val = mod.datastore[name] || opt.default.to_s
tbl << [ name, val.to_s, opt.required? ? "yes" : "no", opt.desc ]
}
return tbl.to_s
end
#
# Dumps the advanced options associated with the supplied module.
#
def self.dump_advanced_options(mod, indent = '')
output = ''
pad = indent
mod.options.sorted.each { |entry|
name, opt = entry
next if (!opt.advanced?)
val = mod.datastore[name] || opt.default.to_s
desc = word_wrap(opt.desc, indent.length + 3)
desc = desc.slice(indent.length + 3, desc.length)
output << pad + "Name : #{name}\n"
output << pad + "Current Setting: #{val}\n"
output << pad + "Description : #{desc}\n"
}
return output
end
#
# Dumps the evasion options associated with the supplied module.
#
def self.dump_evasion_options(mod, indent = '')
output = ''
pad = indent
mod.options.sorted.each { |entry|
name, opt = entry
next if (!opt.evasion?)
val = mod.datastore[name] || opt.default || ''
desc = word_wrap(opt.desc, indent.length + 3)
desc = desc.slice(indent.length + 3, desc.length)
output << pad + "Name : #{name}\n"
output << pad + "Current Setting: #{val}\n"
output << pad + "Description : #{desc}\n"
}
return output
end
#
# Dumps the contents of a datastore.
#
def self.dump_datastore(name, ds, indent = DefaultIndent, col = DefaultColumnWrap)
tbl = Rex::Ui::Text::Table.new(
'Indent' => indent,
'Header' => name,
'Columns' =>
[
'Name',
'Value'
])
ds.keys.sort.each { |k|
tbl << [ k, (ds[k] != nil) ? ds[k].to_s : '' ]
}
return ds.length > 0 ? tbl.to_s : "#{tbl.header_to_s}No entries in data store.\n"
end
#
# Dumps the list of active sessions.
#
def self.dump_sessions(framework, opts={})
ids = (opts[:session_ids] || framework.sessions.keys).sort
verbose = opts[:verbose] || false
indent = opts[:indent] || DefaultIndent
col = opts[:col] || DefaultColumnWrap
columns =
[
'Id',
'Type',
'Information',
'Connection'
]
columns << 'Via' if verbose
tbl = Rex::Ui::Text::Table.new(
'Indent' => indent,
'Header' => "Active sessions",
'Columns' => columns)
framework.sessions.each_sorted { |k|
session = framework.sessions[k]
row = [ session.sid.to_s, session.type.to_s, session.info.to_s, session.tunnel_to_s ]
if session.respond_to? :platform
row[1] += " " + session.platform
end
row << session.via_exploit if verbose and session.via_exploit
tbl << row
}
return framework.sessions.length > 0 ? tbl.to_s : "#{tbl.header_to_s}No active sessions.\n"
end
#
# Dumps the list of running jobs.
#
# If verbose is true, also prints the payload, LPORT, URIPATH and start
# time, if they exist, for each job.
#
def self.dump_jobs(framework, verbose = false, indent = DefaultIndent, col = DefaultColumnWrap)
columns = [ 'Id', 'Name' ]
if (verbose)
columns << "Payload"
columns << "LPORT"
columns << "URIPATH"
columns << "Start Time"
end
tbl = Rex::Ui::Text::Table.new(
'Indent' => indent,
'Header' => "Jobs",
'Columns' => columns
)
# jobs are stored as a hash with the keys being a numeric job_id.
framework.jobs.keys.sort{|a,b| a.to_i <=> b.to_i }.each { |k|
row = [ k, framework.jobs[k].name ]
if (verbose)
ctx = framework.jobs[k].ctx
uripath = ctx[0].get_resource if ctx[0].respond_to?(:get_resource)
uripath = ctx[0].datastore['URIPATH'] if uripath.nil?
row << (ctx[1].nil? ? (ctx[0].datastore['PAYLOAD'] || "") : ctx[1].refname)
row << (ctx[0].datastore['LPORT'] || "")
row << (uripath || "")
row << (framework.jobs[k].start_time || "")
end
tbl << row
}
return framework.jobs.keys.length > 0 ? tbl.to_s : "#{tbl.header_to_s}No active jobs.\n"
end
#
# Jacked from Ernest Ellingson <erne [at] powernav.com>, modified
# a bit to add indention
#
def self.word_wrap(str, indent = DefaultIndent, col = DefaultColumnWrap)
return Rex::Text.wordwrap(str, indent, col)
end
end
end end