Path: blob/master/lib/msf/core/exploit/exe.rb
22070 views
# -*- coding: binary -*-12###3#4# This module exposes a simple method to create an payload in an executable.5#6###78module Msf9module Exploit::EXE1011def initialize(info = {})12super1314# NOTE: Any new options here should also be dealt with in15# EncodedPayload#encoded_exe in lib/msf/core/encoded_payload.rb16register_advanced_options(17[18OptBool.new('EXE::EICAR', [false, 'Generate an EICAR file instead of regular payload exe']),19OptPath.new('EXE::Custom', [false, 'Use custom exe instead of automatically generating a payload exe']),20OptPath.new('EXE::Path', [false, 'The directory in which to look for the executable template']),21OptPath.new('EXE::Template', [false, 'The executable template file name.']),22OptBool.new('EXE::Inject', [false, 'Set to preserve the original EXE function']),23OptBool.new('EXE::FallBack', [false, 'Use the default template in case the specified one is missing']),24OptBool.new('MSI::EICAR', [false, 'Generate an EICAR file instead of regular payload msi']),25OptPath.new('MSI::Custom', [false, 'Use custom msi instead of automatically generating a payload msi']),26OptPath.new('MSI::Path', [false, 'The directory in which to look for the msi template']),27OptPath.new('MSI::Template', [false, 'The msi template file name']),28OptBool.new('MSI::UAC', [false, 'Create an MSI with a UAC prompt (elevation to SYSTEM if accepted)'])29], self.class)30end3132# Avoid stating the string directly, don't want to get caught by local33# antivirus!34def get_eicar_exe35obfus_eicar = ["x5o!p%@ap[4\\pzx54(p^)7cc)7}$eicar", "standard", "antivirus", "test", "file!$h+h*"]36obfus_eicar.join("-").upcase37end3839def get_custom_exe(path = nil)40path ||= datastore['EXE::Custom']41print_status("Using custom payload #{path}, no handler will be created!")42datastore['DisablePayloadHandler'] = true43exe = nil44::File.open(path,'rb') {|f| exe = f.read(f.stat.size)}45exe46end474849# Returns an executable.50#51# @param opts [Hash]52# @option opts [String] :code Payload53# @option opts [Array] :arch Architecture54# @option opts [Msf::Module::PlatformList] :platform55# @raise [Msf::NoCompatiblePayloadError] When #genereate_payload_exe fails to generate a payload.56# @return [String]57def generate_payload_exe(opts = {})58return get_custom_exe unless datastore['EXE::Custom'].to_s.strip.empty?59return get_eicar_exe if datastore['EXE::EICAR']6061exe_init_options(opts)6263pl = opts[:code]64pl ||= payload.encoded6566# Fall back to x86...67opts[:arch] = [ARCH_X86] if !opts[:arch] || opts[:arch].length < 16869# Ensure we have an array70opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array7172# Transform the PlatformList73if opts[:platform].kind_of? Msf::Module::PlatformList74opts[:platform] = opts[:platform].platforms75end7677exe = Msf::Util::EXE.to_executable(framework, opts[:arch], opts[:platform], pl, opts)7879unless exe80raise Msf::NoCompatiblePayloadError, "Failed to generate an executable payload due to an invalid platform or arch."81end8283exe_post_generation(opts)84exe85end8687def generate_payload_exe_service(opts = {})88return get_custom_exe unless datastore['EXE::Custom'].to_s.strip.empty?89return get_eicar_exe if datastore['EXE::EICAR']9091exe_init_options(opts)9293# NOTE: Only Windows is supported here.94pl = opts[:code]95pl ||= payload.encoded9697#Ensure opts[:arch] is an array98opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array99100if opts[:arch] && opts[:arch].index(ARCH_X64)101exe = Msf::Util::EXE.to_win64pe_service(framework, pl, opts)102else103exe = Msf::Util::EXE.to_win32pe_service(framework, pl, opts)104end105106exe_post_generation(opts)107exe108end109110def generate_payload_dll(opts = {})111return get_custom_exe unless datastore['EXE::Custom'].to_s.strip.empty?112return get_eicar_exe if datastore['EXE::EICAR']113114exe_init_options(opts)115plat = opts[:platform]116pl = opts[:code]117pl ||= payload.encoded118119#Ensure opts[:arch] is an array120opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array121122# NOTE: Only x86_64 linux is supported here.123if plat.index(Msf::Module::Platform::Linux)124if opts[:arch] && opts[:arch].index(ARCH_X64)125dll = Msf::Util::EXE.to_linux_x64_elf_dll(framework, pl,opts)126elsif opts[:arch] && opts[:arch].index(ARCH_AARCH64)127dll = Msf::Util::EXE.to_linux_aarch64_elf_dll(framework, pl,opts)128end129elsif plat.index(Msf::Module::Platform::Windows)130if opts[:arch] && opts[:arch].index(ARCH_X64)131dll = Msf::Util::EXE.to_win64pe_dll(framework, pl, opts)132else133dll = Msf::Util::EXE.to_win32pe_dll(framework, pl, opts)134end135end136137exe_post_generation(opts)138dll139end140141def generate_payload_dccw_gdiplus_dll(opts = {})142return get_custom_exe unless datastore['EXE::Custom'].to_s.strip.empty?143return get_eicar_exe if datastore['EXE::EICAR']144145exe_init_options(opts)146plat = opts[:platform]147pl = opts[:code]148149pl ||= payload.encoded150151#Ensure opts[:arch] is an array152opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array153if opts[:arch] && opts[:arch].index(ARCH_X64)154dll = Msf::Util::EXE.to_win64pe_dccw_gdiplus_dll(framework, pl, opts)155else156dll = Msf::Util::EXE.to_win32pe_dccw_gdiplus_dll(framework, pl, opts)157end158159exe_post_generation(opts)160dll161end162163def generate_payload_msi(opts = {})164return get_custom_exe(datastore['MSI::Custom']) unless datastore['MSI::Custom'].to_s.strip.empty?165return get_eicar_exe if datastore['MSI::EICAR']166167exe = generate_payload_exe(opts)168169opts.merge! ({170:msi_template => datastore['MSI::Template'],171:msi_template_path => datastore['MSI::Path'],172:uac => datastore['MSI::UAC']173})174175Msf::Util::EXE.to_exe_msi(framework, exe, opts)176end177178protected179def exe_init_options(opts)180opts.merge!(181{182:template_path => datastore['EXE::Path'],183:template => datastore['EXE::Template'],184:inject => datastore['EXE::Inject'],185:fallback => datastore['EXE::FallBack'],186:sub_method => false187})188189# NOTE: If code and platform/arch are supplied, we use those values and skip initialization.190#191# This part is kind of tricky so we need to explain the logic behind the following load order.192# First off, platform can be seen from different sources:193#194# 1. From the opts argument. For example: When you are using generate_payload_exe, and you want195# to set a specific platform. This is the most explicit. So we check first.196#197# 2. From the metadata of a payload module. Normally, a payload module should include the platform198# information, with the exception of some generic payloads. For example: generic/shell_reverse_tcp.199# This is the most trusted source.200#201# 3. From the exploit module's target.202#203# 4. From the exploit module's metadata.204#205# Architecture shares the same load order.206207unless opts[:code] && opts[:platform]208if self.respond_to?(:payload_instance) && payload_instance.platform.platforms != [Msf::Module::Platform]209opts[:platform] = payload_instance.platform210elsif self.respond_to? :target_platform211opts[:platform] = target_platform212elsif self.respond_to? :platform213opts[:platform] = platform214end215end216217unless opts[:code] && opts[:arch]218if self.respond_to? :payload_instance219opts[:arch] = payload_instance.arch220elsif self.respond_to? :target_arch221opts[:arch] = target_arch222elsif self.respond_to? :arch223opts[:arch] = arch224end225end226end227228def exe_post_generation(opts)229if opts[:fellback]230print_status("Warning: Falling back to default template: #{opts[:fellback]}")231end232end233234end235end236237238