Skip to content

Commit

Permalink
Land #18299, extend error message for timeouts to include more detail…
Browse files Browse the repository at this point in the history
… to user
  • Loading branch information
adfoster-r7 authored Oct 25, 2023
2 parents 216f6fb + 862e738 commit b58f963
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 24 deletions.
55 changes: 42 additions & 13 deletions lib/msf/ui/console/command_dispatcher/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1617,7 +1617,7 @@ def cmd_sessions(*args)
rescue ::Rex::Post::Meterpreter::RequestError
print_error("Failed: #{$!.class} #{$!}")
rescue Rex::TimeoutError
print_error("Operation timed out")
print_error("Operation timed out. Timeout currently #{session.response_timeout} seconds, you can configure this with %grnsessions -c <cmd> --timeout <value>%clr")
end
elsif session.type == 'shell' || session.type == 'powershell'
output = session.shell_command(cmd)
Expand Down Expand Up @@ -1653,20 +1653,28 @@ def cmd_sessions(*args)

cmds.each do |cmd|
sessions.each do |session|
session = verify_session(session)
unless session.type == 'meterpreter'
print_error "Session ##{session.sid} is not a Meterpreter shell. Skipping..."
next
end
begin
session = verify_session(session)
unless session.type == 'meterpreter'
print_error "Session ##{session.sid} is not a Meterpreter shell. Skipping..."
next
end

next unless session
print_status("Running '#{cmd}' on #{session.type} session #{session.sid} (#{session.session_host})")
if session.respond_to?(:response_timeout)
last_known_timeout = session.response_timeout
session.response_timeout = response_timeout
end
next unless session
print_status("Running '#{cmd}' on #{session.type} session #{session.sid} (#{session.session_host})")
if session.respond_to?(:response_timeout)
last_known_timeout = session.response_timeout
session.response_timeout = response_timeout
session.on_run_command_error_proc = log_on_timeout_error("Send timed out. Timeout currently #{session.response_timeout} seconds, you can configure this with %grnsessions -C <cmd> --timeout <value>%clr")
end

output = session.run_cmd(cmd, driver.output)
output = session.run_cmd(cmd, driver.output)
ensure
if session.respond_to?(:response_timeout) && last_known_timeout
session.response_timeout = last_known_timeout
session.on_run_command_error_proc = nil
end
end
end
end
when 'kill'
Expand Down Expand Up @@ -1722,16 +1730,19 @@ def cmd_sessions(*args)
if session.respond_to?(:response_timeout)
last_known_timeout = session.response_timeout
session.response_timeout = response_timeout
session.on_run_command_error_proc = log_on_timeout_error("Send timed out. Timeout currently #{session.response_timeout} seconds, you can configure this with %grnsessions --interact <id> --timeout <value>%clr")
end
print_status("Starting interaction with #{session.name}...\n") unless quiet
begin
self.active_session = session

sid = session.interact(driver.input.dup, driver.output)
self.active_session = nil
driver.input.reset_tab_completion if driver.input.supports_readline
ensure
if session.respond_to?(:response_timeout) && last_known_timeout
session.response_timeout = last_known_timeout
session.on_run_command_error_proc = nil
end
end
else
Expand All @@ -1756,20 +1767,24 @@ def cmd_sessions(*args)
if session.respond_to?(:response_timeout)
last_known_timeout = session.response_timeout
session.response_timeout = response_timeout
session.on_run_command_error_proc = log_on_timeout_error("Send timed out. Timeout currently #{session.response_timeout} seconds, you can configure this with %grnsessions --timeout <value> --script <script> <id>%clr")
end
begin
print_status("Session #{sess_id} (#{session.session_host}):")
print_status("Running #{script} on #{session.type} session" +
" #{sess_id} (#{session.session_host})")
begin
session.init_ui(driver.input, driver.output)
session.execute_script(script, *extra)
rescue ::Exception => e
log_error("Error executing script or module: #{e.class} #{e}")
end
ensure
if session.respond_to?(:response_timeout) && last_known_timeout
session.response_timeout = last_known_timeout
session.on_run_command_error_proc = nil
end
session.reset_ui
end
else
print_error("Invalid session identifier: #{sess_id}")
Expand Down Expand Up @@ -2837,6 +2852,20 @@ def verify_session(session_id, quiet = false)
end
end

#
# Custom error code to handle timeout errors
#
# @param message [String] The message to be printed when a timeout error is hit
# @return [Proc] proc function that prints the specified error when the error types match
def log_on_timeout_error(message)
proc do |e|
next unless e.is_a?(Rex::TimeoutError) || e.is_a?(Timeout::Error)
elog(e)
print_error(message)
:handled
end
end

#
# Returns an array of lines at the provided line number plus any before and/or after lines requested
# from all_lines by supplying the +before+ and/or +after+ parameters which are always positive
Expand Down
27 changes: 16 additions & 11 deletions lib/rex/post/meterpreter/ui/console.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,22 @@ def queue_cmd(cmd)
def run_command(dispatcher, method, arguments)
begin
super
rescue Timeout::Error
log_error("Operation timed out.")
rescue RequestError => info
log_error(info.to_s)
rescue Rex::InvalidDestination => e
log_error(e.message)
rescue ::Errno::EPIPE, ::OpenSSL::SSL::SSLError, ::IOError
self.client.kill
rescue ::Exception => e
log_error("Error running command #{method}: #{e.class} #{e}")
elog(e)
rescue Exception => e
is_error_handled = self.client.on_run_command_error_proc && self.client.on_run_command_error_proc.call(e) == :handled
return if is_error_handled
case e
when Rex::TimeoutError, Rex::InvalidDestination
log_error(e.message)
when Timeout::Error
log_error('Operation timed out.')
when RequestError
log_error(e.to_s)
when ::Errno::EPIPE, ::OpenSSL::SSL::SSLError, ::IOError
self.client.kill
when ::Exception
log_error("Error running command #{method}: #{e.class} #{e}")
elog(e)
end
end
end

Expand Down
6 changes: 6 additions & 0 deletions lib/rex/ui/interactive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ def detach
attr_accessor :on_print_proc
attr_accessor :on_command_proc

#
# A function to be run when running a session command hits an error
#
# @return [Proc,nil] A function to be run when running a session command hits an error
attr_accessor :on_run_command_error_proc

protected

#
Expand Down

0 comments on commit b58f963

Please sign in to comment.