# -*- coding: binary -*- ### # # This module exposes a simple method to create an payload in an executable. # ### module Msf module Exploit::EXE def initialize(info = {}) super # NOTE: Any new options here should also be dealt with in # EncodedPayload#encoded_exe in lib/msf/core/encoded_payload.rb register_advanced_options( [ OptBool.new( 'EXE::EICAR', [ false, 'Generate an EICAR file instead of regular payload exe']), OptPath.new( 'EXE::Custom', [ false, 'Use custom exe instead of automatically generating a payload exe']), OptPath.new( 'EXE::Path', [ false, 'The directory in which to look for the executable template' ]), OptPath.new( 'EXE::Template', [ false, 'The executable template file name.' ]), OptBool.new( 'EXE::Inject', [ false, 'Set to preserve the original EXE function' ]), OptBool.new( 'EXE::OldMethod',[ false, 'Set to use the substitution EXE generation method.' ]), OptBool.new( 'EXE::FallBack', [ false, 'Use the default template in case the specified one is missing' ]), OptBool.new( 'MSI::EICAR', [ false, 'Generate an EICAR file instead of regular payload msi']), OptPath.new( 'MSI::Custom', [ false, 'Use custom msi instead of automatically generating a payload msi']), OptPath.new( 'MSI::Path', [ false, 'The directory in which to look for the msi template' ]), OptPath.new( 'MSI::Template', [ false, 'The msi template file name' ]), OptBool.new( 'MSI::UAC', [ false, 'Create an MSI with a UAC prompt (elevation to SYSTEM if accepted)' ]) ], self.class) end # Avoid stating the string directly, don't want to get caught by local # antivirus! def get_eicar_exe obfus_eicar = ["x5o!p%@ap[4\\pzx54(p^)7cc)7}$eicar", "standard", "antivirus", "test", "file!$h+h*"] obfus_eicar.join("-").upcase end def get_custom_exe(path = nil) path ||= datastore['EXE::Custom'] print_status("Using custom payload #{path}, RHOST and RPORT settings will be ignored!") datastore['DisablePayloadHandler'] = true exe = nil ::File.open(path,'rb') {|f| exe = f.read(f.stat.size)} exe end # Returns an executable. # # @param opts [Hash] # @option opts [String] :code Payload # @option opts [Array] :arch Architecture # @option opts [Msf::Module::PlatformList] :platform # @raise [Msf::NoCompatiblePayloadError] When #genereate_payload_exe fails to generate a payload. # @return [String] def generate_payload_exe(opts = {}) return get_custom_exe unless datastore['EXE::Custom'].to_s.strip.empty? return get_eicar_exe if datastore['EXE::EICAR'] exe_init_options(opts) pl = opts[:code] pl ||= payload.encoded # Fall back to x86... opts[:arch] = [ARCH_X86] if !opts[:arch] || opts[:arch].length < 1 # Ensure we have an array opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array # Transform the PlatformList if opts[:platform].kind_of? Msf::Module::PlatformList opts[:platform] = opts[:platform].platforms end exe = Msf::Util::EXE.to_executable(framework, opts[:arch], opts[:platform], pl, opts) unless exe raise Msf::NoCompatiblePayloadError, "Failed to generate an executable payload due to an invalid platform or arch." end exe_post_generation(opts) exe end def generate_payload_exe_service(opts = {}) return get_custom_exe unless datastore['EXE::Custom'].to_s.strip.empty? return get_eicar_exe if datastore['EXE::EICAR'] exe_init_options(opts) # NOTE: Only Windows is supported here. pl = opts[:code] pl ||= payload.encoded #Ensure opts[:arch] is an array opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array if opts[:arch] && (opts[:arch].index(ARCH_X64) or opts[:arch].index(ARCH_X86_64)) exe = Msf::Util::EXE.to_win64pe_service(framework, pl, opts) else exe = Msf::Util::EXE.to_win32pe_service(framework, pl, opts) end exe_post_generation(opts) exe end def generate_payload_dll(opts = {}) return get_custom_exe unless datastore['EXE::Custom'].to_s.strip.empty? return get_eicar_exe if datastore['EXE::EICAR'] exe_init_options(opts) plat = opts[:platform] pl = opts[:code] pl ||= payload.encoded #Ensure opts[:arch] is an array opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array # NOTE: Only x86_64 linux is supported here. if plat.index(Msf::Module::Platform::Linux) if opts[:arch] && (opts[:arch].index(ARCH_X64) || opts[:arch].index(ARCH_X86_64)) dll = Msf::Util::EXE.to_linux_x64_elf_dll(framework, pl,opts) end elsif plat.index(Msf::Module::Platform::Windows) if opts[:arch] && (opts[:arch].index(ARCH_X64) || opts[:arch].index(ARCH_X86_64)) dll = Msf::Util::EXE.to_win64pe_dll(framework, pl, opts) else dll = Msf::Util::EXE.to_win32pe_dll(framework, pl, opts) end end exe_post_generation(opts) dll end def generate_payload_msi(opts = {}) return get_custom_exe(datastore['MSI::Custom']) unless datastore['MSI::Custom'].to_s.strip.empty? return get_eicar_exe if datastore['MSI::EICAR'] exe = generate_payload_exe(opts) opts.merge! ({ :msi_template => datastore['MSI::Template'], :msi_template_path => datastore['MSI::Path'], :uac => datastore['MSI::UAC'] }) Msf::Util::EXE.to_exe_msi(framework, exe, opts) end protected def exe_init_options(opts) opts.merge!( { :template_path => datastore['EXE::Path'], :template => datastore['EXE::Template'], :inject => datastore['EXE::Inject'], :fallback => datastore['EXE::FallBack'], :sub_method => datastore['EXE::OldMethod'] }) # This part is kind of tricky so we need to explain the logic behind the following load order. # First off, platform can be seen from different sources: # # 1. From the opts argument. For example: When you are using generate_payload_exe, and you want # to set a specific platform. This is the most explicit. So we check first. # # 2. From the metadata of a payload module. Normally, a payload module should include the platform # information, with the exception of some generic payloads. For example: generic/shell_reverse_tcp. # This is the most trusted source. # # 3. From the exploit module's target. # # 4. From the exploit module's metadata. # # Architecture shares the same load order. unless opts[:platform] if self.respond_to?(:payload_instance) && payload_instance.platform.platforms != [Msf::Module::Platform] opts[:platform] = payload_instance.platform elsif self.respond_to? :target_platform opts[:platform] = target_platform elsif self.respond_to? :platform opts[:platform] = platform end end unless opts[:arch] if self.respond_to? :payload_instance opts[:arch] = payload_instance.arch elsif self.respond_to? :target_arch $stderr.puts "target specific arch" opts[:arch] = target_arch elsif self.respond_to? :arch opts[:arch] = arch end end end def exe_post_generation(opts) if opts[:fellback] print_status("Warning: Falling back to default template: #{opts[:fellback]}") end end end end