diff --git a/data/markdown_doc/evasion_demo_template.erb b/data/markdown_doc/evasion_demo_template.erb new file mode 100644 index 0000000000..08c9982894 --- /dev/null +++ b/data/markdown_doc/evasion_demo_template.erb @@ -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 +``` \ No newline at end of file diff --git a/lib/msf/base/serializer/readable_text.rb b/lib/msf/base/serializer/readable_text.rb index 08537fb83a..19092e230a 100644 --- a/lib/msf/base/serializer/readable_text.rb +++ b/lib/msf/base/serializer/readable_text.rb @@ -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. diff --git a/lib/msf/core/evasion.rb b/lib/msf/core/evasion.rb index 1c8d499386..ffe8ade9d5 100644 --- a/lib/msf/core/evasion.rb +++ b/lib/msf/core/evasion.rb @@ -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 diff --git a/lib/msf/core/exploit.rb b/lib/msf/core/exploit.rb index 22fe9529b1..cd8f53efc2 100644 --- a/lib/msf/core/exploit.rb +++ b/lib/msf/core/exploit.rb @@ -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 diff --git a/lib/msf/ui/console/command_dispatcher/common.rb b/lib/msf/ui/console/command_dispatcher/common.rb index 24eabcca8a..64bb02a341 100644 --- a/lib/msf/ui/console/command_dispatcher/common.rb +++ b/lib/msf/ui/console/command_dispatcher/common.rb @@ -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 diff --git a/lib/msf/ui/console/command_dispatcher/modules.rb b/lib/msf/ui/console/command_dispatcher/modules.rb index 1af8cd6008..36361b5fb3 100644 --- a/lib/msf/ui/console/command_dispatcher/modules.rb +++ b/lib/msf/ui/console/command_dispatcher/modules.rb @@ -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) diff --git a/lib/msf/util/document_generator/normalizer.rb b/lib/msf/util/document_generator/normalizer.rb index 01b514f4c6..f6030b705f 100644 --- a/lib/msf/util/document_generator/normalizer.rb +++ b/lib/msf/util/document_generator/normalizer.rb @@ -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 diff --git a/modules/evasion/windows/windows_defender_exe.rb b/modules/evasion/windows/windows_defender_exe.rb index fc8d9fdd75..0323b39ce7 100644 --- a/modules/evasion/windows/windows_defender_exe.rb +++ b/modules/evasion/windows/windows_defender_exe.rb @@ -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 \ No newline at end of file