Add support for evasion targets, also module doc

GSoC/Meterpreter_Web_Console
Wei Chen 2018-08-31 11:45:29 -05:00
parent ea41127c6e
commit 5c6b33bcf4
8 changed files with 158 additions and 10 deletions

View File

@ -0,0 +1,6 @@
```
msf > use <%= mod.fullname %>
msf <%= mod.type %>(<%= mod.shortname %>) > show options
... show and set options ...
msf <%= mod.type %>(<%= mod.shortname %>) > exploit
```

View File

@ -64,6 +64,23 @@ class ReadableText
tbl.to_s + "\n"
end
def self.dump_evasion_targets(mod, indent = '', h = nil)
tbl = Rex::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
#
# @param mod [Msf::Exploit] the exploit module.
@ -86,6 +103,27 @@ class ReadableText
tbl.to_s + "\n"
end
# Dumps the evasion module's selected target
#
# @param mod [Msf::Evasion] The evasion module.
# @param indent [String] The indentation to use (only the length matters)
# @param h [String] The string to display as the table heading.
# @return [String] The strong form of the table.
def self.dump_evasion_target(mod, indent = '', h = nil)
tbl = Rex::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 a module's actions
#
# @param mod [Msf::Module] the module.

View File

@ -19,6 +19,21 @@ module Msf
super(info)
self.payload_info = info['Payload'] || {}
self.targets = Rex::Transformer.transform(info['Targets'], Array, [ Target ], 'Targets')
if info.key? 'DefaultTarget'
self.default_target = info['DefaultTarget']
else
self.default_target = 0
# Add an auto-target to the exploit if it doesn't have one
if info['Targets'] && info['Targets'].count > 1 && !has_auto_target?(info['Targets'])
# Finally, only add the target if there is a remote host option
if self.respond_to?(:rhost) && self.respond_to?(:auto_targeted_index)
auto = ["Automatic", {'AutoGenerated' => true}.merge(info['Targets'][self.default_target][1])]
info['Targets'].unshift(auto)
end
end
end
if (info['Payload'] and info['Payload']['ActiveTimeout'])
self.active_timeout = info['Payload']['ActiveTimeout'].to_i
@ -57,6 +72,28 @@ module Msf
print_good "#{fname} stored at #{full_path}"
end
#
# Returns the target's platform, or the one assigned to the module itself.
#
def target_platform
(target and target.platform) ? target.platform : platform
end
#
# Returns the target's architecture, or the one assigned to the module
# itself.
#
def target_arch
(target and target.arch) ? target.arch : (arch == []) ? nil : arch
end
def normalize_platform_arch
c_platform = (target && target.platform) ? target.platform : platform
c_arch = (target && target.arch) ? target.arch : (arch == []) ? nil : arch
c_arch ||= [ ARCH_X86 ]
return c_platform, c_arch
end
def is_payload_compatible?(name)
p = framework.payloads[name]
@ -76,8 +113,10 @@ module Msf
def compatible_payloads
payloads = []
c_platform, c_arch = normalize_platform_arch
framework.payloads.each_module(
'Arch' => arch, 'Platform' => platform) { |name, mod|
'Arch' => c_arch, 'Platform' => c_platform) { |name, mod|
payloads << [ name, mod ] if is_payload_compatible?(name)
}
@ -109,7 +148,9 @@ module Msf
return self.payload
end
def generate_single_payload(pinst = nil, platform = nil, arch = nil)
def generate_single_payload(pinst = nil, platform = nil, arch = nil, explicit_target = nil)
explicit_target ||= target
# If a payload instance was supplied, use it, otherwise
# use the active payload instance
real_payload = (pinst) ? pinst : self.payload_instance
@ -199,6 +240,50 @@ module Msf
encoded
end
def target
if self.respond_to?(:auto_targeted_index)
if auto_target?
auto_idx = auto_targeted_index
if auto_idx.present?
datastore['TARGET'] = auto_idx
else
# If our inserted Automatic Target was selected but we failed to
# find a suitable target, we just grab the original first target.
datastore['TARGET'] = 1
end
end
end
target_idx = target_index
return (target_idx) ? targets[target_idx.to_i] : nil
end
def target_index
target_idx = Integer(datastore['TARGET']) rescue datastore['TARGET']
default_idx = default_target || 0
# Use the default target if one was not supplied.
if (target_idx == nil and default_idx and default_idx >= 0)
target_idx = default_idx
elsif target_idx.is_a?(String)
target_idx = targets.index { |target| target.name == target_idx }
end
return (target_idx) ? target_idx.to_i : nil
end
def has_auto_target?(targets=[])
target_names = targets.collect { |target| target.first}
target_names.each do |target|
return true if target =~ /Automatic/
end
return false
end
attr_accessor :default_target
attr_accessor :targets
attr_reader :payload_info
attr_accessor :payload_info

View File

@ -309,8 +309,7 @@ class Exploit < Msf::Module
end
end
self.targets = Rex::Transformer.transform(info['Targets'], Array,
[ Target ], 'Targets')
self.targets = Rex::Transformer.transform(info['Targets'], Array, [ Target ], 'Targets')
self.payload_info = info['Payload'] || {}
self.successful = false
self.session_count = 0

View File

@ -127,6 +127,9 @@ module Common
if (mod.exploit? and mod.target)
mod_targ = Serializer::ReadableText.dump_exploit_target(mod, ' ')
print("\nExploit target:\n\n#{mod_targ}\n") if (mod_targ and mod_targ.length > 0)
elsif mod.evasion? and mod.target
mod_targ = Serializer::ReadableText.dump_evasion_target(mod, ' ')
print("\nEvasion target:\n\n#{mod_targ}\n") if (mod_targ and mod_targ.length > 0)
end
# Print the selected action

View File

@ -548,7 +548,7 @@ module Msf
when "plugins"
show_plugins
when "targets"
if (mod and mod.exploit?)
if (mod and (mod.exploit? or mod.evasion?))
show_targets(mod)
else
print_error("No exploit module selected.")
@ -1055,8 +1055,14 @@ module Msf
end
def show_targets(mod) # :nodoc:
mod_targs = Serializer::ReadableText.dump_exploit_targets(mod, ' ')
print("\nExploit targets:\n\n#{mod_targs}\n") if (mod_targs and mod_targs.length > 0)
case mod
when Msf::Exploit
mod_targs = Serializer::ReadableText.dump_exploit_targets(mod, ' ')
print("\nExploit targets:\n\n#{mod_targs}\n") if (mod_targs and mod_targs.length > 0)
when Msf::Evasion
mod_targs = Serializer::ReadableText.dump_evasion_targets(mod, ' ')
print("\nEvasion targets:\n\n#{mod_targs}\n") if (mod_targs and mod_targs.length > 0)
end
end
def show_actions(mod) # :nodoc:
@ -1093,7 +1099,7 @@ module Msf
# 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'])
if (mod.evasion? and mod.datastore['PAYLOAD'])
p = framework.payloads.create(mod.datastore['PAYLOAD'])
if (!p)

View File

@ -64,6 +64,7 @@ module Msf
POST_DEMO_TEMPLATE = 'post_demo_template.erb'
AUXILIARY_SCANNER_DEMO_TEMPLATE = 'auxiliary_scanner_template.erb'
PAYLOAD_DEMO_TEMPLATE = 'payload_demo_template.erb'
EVASION_DEMO_TEMPLATE = 'evasion_demo_template.erb'
# Special messages
NO_CVE_MESSAGE = %Q|CVE: [Not available](https://github.com/rapid7/metasploit-framework/wiki/Why-is-a-CVE-Not-Available%3F)|
@ -309,6 +310,8 @@ module Msf
load_demo_template(mod, AUXILIARY_SCANNER_DEMO_TEMPLATE)
elsif is_remote_exploit?(mod)
load_demo_template(mod, REMOTE_EXPLOIT_DEMO_TEMPLATE)
elsif mod.kind_of?(Msf::Evasion)
load_demo_template(mod, EVASION_DEMO_TEMPLATE)
else
load_demo_template(mod, GENERIC_DEMO_TEMPLATE)
end

View File

@ -21,8 +21,13 @@ class MetasploitModule < Msf::Evasion
},
'Author' => [ 'sinn3r' ],
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X86
#'Platform' => 'win',
#'Arch' => ARCH_X86,
'Targets' =>
[
[ 'Linux', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ],
[ 'Windows', { 'Arch' => ARCH_X86, 'Platform' => 'win' } ]
]
))
end
@ -72,10 +77,13 @@ int main() {
end
def run
puts target.inspect
=begin
puts c_template
bin = Metasploit::Framework::Compiler::Windows.compile_random_c(c_template)
print_status("Compiled binary size: #{bin.length}")
file_create(bin)
=end
end
end