diff --git a/lib/msf/base/simple/exploit.rb b/lib/msf/base/simple/exploit.rb index 389b336ed8..8955cb74d2 100644 --- a/lib/msf/base/simple/exploit.rb +++ b/lib/msf/base/simple/exploit.rb @@ -154,6 +154,95 @@ module Exploit nil end + + def setup_fail_detail_from_exception e + # Build a user-friendly error message + msg = "#{e}" + unless e.class == Msf::Exploit::Failed + msg = "#{e.class} #{e}" + end + + self.error = e + + # Record the detailed reason + self.exploit.fail_detail ||= e.to_s + msg + end + + # + # Handle the exception + # + def handle_exception e + msg = setup_fail_detail_from_exception e + + require 'pry' + binding.pry + + case e + when Msf::Exploit::Complete + # Nothing to show in this case + return + + when Msf::Exploit::Failed + self.print_error("Exploit aborted due to failure: #{self.fail_reason}: #{msg}") + + # The caller should have already set self.fail_reason + if self.fail_reason == Msf::Exploit::Failure::None + self.fail_reason = Msf::Exploit::Failure::Unknown + end + + when Rex::ConnectionError + self.fail_reason = Msf::Exploit::Failure::Unreachable + self.print_error("Exploit failed [#{self.fail_reason}]: #{msg}") + elog("Exploit failed (#{self.refname}): #{msg}", 'core', LEV_0) + dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3) + + when Timeout::Error + self.fail_reason = Msf::Exploit::Failure::TimeoutExpired + self.print_error("Exploit failed [#{self.fail_reason}]: #{msg}") + elog("Exploit failed (#{self.refname}): #{msg}", 'core', LEV_0) + dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3) + else + + # Compare as a string since not all error classes may be loaded + case msg + when /access.denied|Login Failed/i # Covers SMB as well as some generic errors + self.fail_reason = Msf::Exploit::Failure::NoAccess + when /connection reset/i + self.fail_reason = Msf::Exploit::Failure::Disconnected + when /connection timed out|SSL_connect|unreachable|connection was refused/i + self.fail_reason = Msf::Exploit::Failure::Unreachable + when /unable.*target/i + self.fail_reason = Msf::Exploit::Failure::NoTarget + when /execution expired/i + self.fail_reason = Msf::Exploit::Failure::TimeoutExpired + when /(doesn.t|not).*vulnerable|may.*patched/i + self.fail_reason = Msf::Exploit::Failure::NotVulnerable + end + + # The caller should have already set self.fail_reason + if self.fail_reason == Msf::Exploit::Failure::None + self.fail_reason = Msf::Exploit::Failure::Unknown + end + + if self.fail_reason == Msf::Exploit::Failure::Unknown + self.print_error("Exploit failed: #{msg}") + else + self.print_error("Exploit failed [#{self.fail_reason}]: #{msg}") + end + + elog("Exploit failed (#{self.refname}): #{msg}", 'core', LEV_0) + dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3) + end + + + + # Record the error to various places + self.framework.events.on_module_error(self, msg) + + # Report the failure (and attempt) in the database + self.report_failure + end # # Calls the class method. # diff --git a/lib/msf/core/exploit_driver.rb b/lib/msf/core/exploit_driver.rb index 66e8f9e4e8..4be621a9e5 100644 --- a/lib/msf/core/exploit_driver.rb +++ b/lib/msf/core/exploit_driver.rb @@ -113,7 +113,6 @@ class ExploitDriver # - Cleans up the handler # def run - # First thing's first -- validate the state. Make sure all requirement # parameters are set, including those that are derived from the # datastore. @@ -164,6 +163,7 @@ class ExploitDriver # nothing should be able to modify their datastore or other # settings until after they're done. ctx = [ exploit, payload ] + job_run_proc(ctx) job_cleanup_proc(ctx) end @@ -187,18 +187,15 @@ class ExploitDriver protected - - # # Job run proc, sets up the exploit and kicks it off. # def job_run_proc(ctx) - # Default session wait time.. - delay = payload.wfs_delay + exploit.wfs_delay - delay = nil if exploit.passive? - begin exploit, payload = ctx + # Default session wait time.. + delay = payload.wfs_delay + exploit.wfs_delay + delay = nil if exploit.passive? # Set the exploit up the bomb exploit.setup @@ -208,88 +205,12 @@ protected # Launch the exploit exploit.exploit - - rescue ::Exception => e - if [::RuntimeError, ::Interrupt].include?(e.class) # Wait for session, but don't wait long. delay = 0.01 end - - # Build a user-friendly error message - msg = "#{e}" - unless e.class == Msf::Exploit::Failed - msg = "#{e.class} #{e}" - end - - exploit.error = e - - # Record the detailed reason - exploit.fail_detail ||= e.to_s - - case e - when Msf::Exploit::Complete - # Nothing to show in this case - return - - when Msf::Exploit::Failed - exploit.print_error("Exploit aborted due to failure: #{exploit.fail_reason}: #{msg}") - - # The caller should have already set exploit.fail_reason - if exploit.fail_reason == Msf::Exploit::Failure::None - exploit.fail_reason = Msf::Exploit::Failure::Unknown - end - - when Rex::ConnectionError - exploit.fail_reason = Msf::Exploit::Failure::Unreachable - exploit.print_error("Exploit failed [#{exploit.fail_reason}]: #{msg}") - elog("Exploit failed (#{exploit.refname}): #{msg}", 'core', LEV_0) - dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3) - - when Timeout::Error - exploit.fail_reason = Msf::Exploit::Failure::TimeoutExpired - exploit.print_error("Exploit failed [#{exploit.fail_reason}]: #{msg}") - elog("Exploit failed (#{exploit.refname}): #{msg}", 'core', LEV_0) - dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3) - else - - # Compare as a string since not all error classes may be loaded - case msg - when /access.denied|Login Failed/i # Covers SMB as well as some generic errors - exploit.fail_reason = Msf::Exploit::Failure::NoAccess - when /connection reset/i - exploit.fail_reason = Msf::Exploit::Failure::Disconnected - when /connection timed out|SSL_connect|unreachable|connection was refused/i - exploit.fail_reason = Msf::Exploit::Failure::Unreachable - when /unable.*target/i - exploit.fail_reason = Msf::Exploit::Failure::NoTarget - when /execution expired/i - exploit.fail_reason = Msf::Exploit::Failure::TimeoutExpired - when /(doesn.t|not).*vulnerable|may.*patched/i - exploit.fail_reason = Msf::Exploit::Failure::NotVulnerable - end - - # The caller should have already set exploit.fail_reason - if exploit.fail_reason == Msf::Exploit::Failure::None - exploit.fail_reason = Msf::Exploit::Failure::Unknown - end - - if exploit.fail_reason == Msf::Exploit::Failure::Unknown - exploit.print_error("Exploit failed: #{msg}") - else - exploit.print_error("Exploit failed [#{exploit.fail_reason}]: #{msg}") - end - - elog("Exploit failed (#{exploit.refname}): #{msg}", 'core', LEV_0) - dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3) - end - - # Record the error to various places - exploit.framework.events.on_module_error(exploit, msg) - - # Report the failure (and attempt) in the database - exploit.report_failure + exploit.handle_exception e end # Wait the payload to acquire a session if this isn't a passive-style