Refactor the rhosts for exploit modules.

GSoC/Meterpreter_Web_Console
Green-m 2018-09-25 11:28:59 +08:00
parent 5ddbf6fd11
commit 90b98a193c
No known key found for this signature in database
GPG Key ID: 7A4A0E684B5D6747
4 changed files with 97 additions and 42 deletions

View File

@ -78,6 +78,9 @@ module Exploit
# Start it up
driver = ExploitDriver.new(exploit.framework)
# Keep the handler of driver running if exploit multi targets.
driver.keep_handler = true if opts["multi"]
# Initialize the driver instance
driver.exploit = exploit
driver.payload = exploit.framework.payloads.create(opts['Payload'])

View File

@ -1410,6 +1410,12 @@ class Exploit < Msf::Module
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 ::Interrupt
self.fail_reason = Msf::Exploit::Failure::UserInterrupt
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
@ -1451,6 +1457,8 @@ class Exploit < Msf::Module
# Interrupt any session waiters in the handler
self.interrupt_handler
return self.fail_reason
end
def report_failure

View File

@ -22,6 +22,7 @@ class ExploitDriver
self.use_job = false
self.job_id = nil
self.force_wait_for_session = false
self.keep_handler = false
self.semaphore = Mutex.new
end
@ -164,8 +165,15 @@ class ExploitDriver
# settings until after they're done.
ctx = [ exploit, payload ]
job_run_proc(ctx)
job_cleanup_proc(ctx)
begin
job_run_proc(ctx)
# For multi exploit targets.
# Keep the payload handler until last target or interrupt
job_cleanup_proc(ctx) unless keep_handler
rescue ::Interrupt
job_cleanup_proc(ctx)
raise $!
end
end
return session
@ -181,6 +189,7 @@ class ExploitDriver
attr_accessor :job_id
attr_accessor :force_wait_for_session # :nodoc:
attr_accessor :session # :nodoc:
attr_accessor :keep_handler # :nodoc:
# To synchronize threads cleaning up the exploit and the handler
attr_accessor :semaphore
@ -211,7 +220,7 @@ protected
delay = 0.01
end
exploit.handle_exception e
fail_reason = exploit.handle_exception(e)
end
# Start bind handlers after exploit completion
@ -237,6 +246,10 @@ protected
exploit.fail_detail = "No session created"
exploit.report_failure
end
if fail_reason && fail_reason == Msf::Exploit::Failure::UserInterrupt
raise ::Interrupt
end
end
#

View File

@ -47,6 +47,9 @@ class Exploit
"Exploit"
end
#
# Launches an exploitation single attempt.
#
def exploit_single(mod, opts)
begin
session = mod.exploit_simple(opts)
@ -63,41 +66,7 @@ class Exploit
end
end
# If we were given a session, let's see what we can do with it
if session
if !opts['Background'] && session.interactive?
# If we aren't told to run in the background and the session can be
# interacted with, start interacting with it by issuing the session
# interaction command.
print_line
driver.run_single("sessions -q -i #{session.sid}")
# Otherwise, log that we created a session
else
# Otherwise, log that we created a session
print_status("Session #{session.sid} created in the background.")
end
elsif opts['RunAsJob'] && mod.job_id
# Indicate if he exploit as a job, indicate such so the user doesn't
# wonder what's up.
print_status("Exploit running as background job #{mod.job_id}.")
# Worst case, the exploit ran but we got no session, bummer.
else
# If we didn't run a payload handler for this exploit it doesn't
# make sense to complain to the user that we didn't get a session
unless mod.datastore["DisablePayloadHandler"]
fail_msg = 'Exploit completed, but no session was created.'
print_status(fail_msg)
begin
framework.events.on_session_fail(fail_msg)
rescue ::Exception => e
wlog("Exception in on_session_open event handler: #{e.class}: #{e}")
wlog("Call Stack\n#{e.backtrace.join("\n")}")
end
end
end
return session
end
def cmd_exploit_tabs(str, words)
@ -117,11 +86,12 @@ class Exploit
end
#
# Launches an exploitation attempt.
# Launches exploitation attempts.
#
def cmd_exploit(*args)
force = false
module_opts = []
any_session = false
opts = {
'Encoder' => mod.datastore['ENCODER'],
'Payload' => mod.datastore['PAYLOAD'],
@ -195,14 +165,75 @@ class Exploit
end
rhosts = mod.datastore['RHOSTS']
# For mutilple targets exploit attempts.
if rhosts
Rex::Socket::RangeWalker.new(rhosts).each do |rhost|
opts[:multi] = true
rhosts_range = Rex::Socket::RangeWalker.new(rhosts)
rhosts_range.each do |rhost|
nmod = mod.replicant
nmod.datastore['RHOST'] = rhost
exploit_single(nmod, opts)
# If rhost is the last target, let exploit handler stop.
opts["multi"] = false if rhost == (Rex::Socket.addr_itoa(rhosts_range.ranges.first.stop))
# Catch the interrupt exception to stop the whole module during exploit
begin
print_status("Exploiting target #{rhost}")
session = exploit_single(nmod, opts)
rescue ::Interrupt
print_status("Stopping exploiting current target #{rhost}...")
print_status("Control-C again to force quit exploiting all targets.")
begin
Rex.sleep(1)
rescue ::Interrupt
raise $!
end
end
# If we were given a session, report it.
if session
print_status("Session #{session.sid} created in the background.")
any_session = true
end
end
# For single target.
else
exploit_single(mod, opts)
session = exploit_single(mod, opts)
# If we were given a session, let's see what we can do with it
if session
any_session = true
if !opts['Background'] && session.interactive?
# If we aren't told to run in the background and the session can be
# interacted with, start interacting with it by issuing the session
# interaction command.
print_line
driver.run_single("sessions -q -i #{session.sid}")
# Otherwise, log that we created a session
else
# Otherwise, log that we created a session
print_status("Session #{session.sid} created in the background.")
end
elsif opts['RunAsJob'] && mod.job_id
# Indicate if he exploit as a job, indicate such so the user doesn't
# wonder what's up.
print_status("Exploit running as background job #{mod.job_id}.")
# Worst case, the exploit ran but we got no session, bummer.
end
end
# If we didn't get any session and exploit ended luanch.
unless any_session
# If we didn't run a payload handler for this exploit it doesn't
# make sense to complain to the user that we didn't get a session
unless mod.datastore["DisablePayloadHandler"]
fail_msg = 'Exploit completed, but no session was created.'
print_status(fail_msg)
begin
framework.events.on_session_fail(fail_msg)
rescue ::Exception => e
wlog("Exception in on_session_open event handler: #{e.class}: #{e}")
wlog("Call Stack\n#{e.backtrace.join("\n")}")
end
end
end
end