-
Notifications
You must be signed in to change notification settings - Fork 14.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extract reusable core session commands #18516
Changes from all commits
3f3531d
c7e0e09
67a3432
8205717
ea41ec7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -30,7 +30,7 @@ class CommandShell | |||
include Rex::Ui::Text::Resource | ||||
|
||||
@@irb_opts = Rex::Parser::Arguments.new( | ||||
'-h' => [false, 'Help menu.' ], | ||||
['-h', '--help'] => [false, 'Help menu.' ], | ||||
'-e' => [true, 'Expression to evaluate.'] | ||||
) | ||||
|
||||
|
@@ -235,35 +235,35 @@ def cmd_sessions_help | |||
end | ||||
|
||||
def cmd_sessions(*args) | ||||
if args.length.zero? || args[0].to_i <= 0 | ||||
# No args | ||||
if args.length != 1 | ||||
print_status "Wrong number of arguments expected: 1, received: #{args.length}" | ||||
return cmd_sessions_help | ||||
end | ||||
|
||||
if args.length == 1 && (args[1] == '-h' || args[1] == 'help') | ||||
# One arg, and args[1] => '-h' '-H' 'help' | ||||
if args[0] == '-h' || args[0] == '--help' | ||||
return cmd_sessions_help | ||||
end | ||||
|
||||
if args.length != 1 | ||||
# More than one argument | ||||
session_id = args[0].to_i | ||||
if session_id <= 0 | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we check if this works the same as before when provided with negative session ids? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dwelch-r7 Is there anything actionable here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, the previous implementation didn't accept negative session IDs so it's a nice to have but I don't think we should block the PR on it |
||||
print_status 'Invalid session id' | ||||
return cmd_sessions_help | ||||
end | ||||
|
||||
if args[0].to_s == self.name.to_s | ||||
if session_id == self.sid | ||||
# Src == Dst | ||||
print_status("Session #{self.name} is already interactive.") | ||||
else | ||||
print_status("Backgrounding session #{self.name}...") | ||||
# store the next session id so that it can be referenced as soon | ||||
# as this session is no longer interacting | ||||
self.next_session = args[0] | ||||
self.next_session = session_id | ||||
self.interacting = false | ||||
end | ||||
end | ||||
|
||||
def cmd_resource(*args) | ||||
if args.empty? | ||||
if args.empty? || args[0] == '-h' || args[0] == '--help' | ||||
cmd_resource_help | ||||
return false | ||||
end | ||||
|
@@ -320,9 +320,9 @@ def cmd_shell_help() | |||
end | ||||
|
||||
def cmd_shell(*args) | ||||
if args.length == 1 && (args[1] == '-h' || args[1] == 'help') | ||||
# One arg, and args[1] => '-h' '-H' 'help' | ||||
return cmd_sessions_help | ||||
if args.length == 1 && (args[0] == '-h' || args[0] == '--help') | ||||
# One arg, and args[0] => '-h' '--help' | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I don't think this comment is necessary. |
||||
return cmd_shell_help | ||||
end | ||||
|
||||
if platform == 'windows' | ||||
|
@@ -570,7 +570,7 @@ def cmd_pry_help | |||
# Open the Pry debugger on the current session | ||||
# | ||||
def cmd_pry(*args) | ||||
if args.include?('-h') | ||||
if args.include?('-h') || args.include?('--help') | ||||
cmd_pry_help | ||||
return | ||||
end | ||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,236 @@ | ||||||||||||||
# frozen_string_literal: true | ||||||||||||||
|
||||||||||||||
module Msf | ||||||||||||||
module Ui | ||||||||||||||
module Console | ||||||||||||||
module CommandDispatcher | ||||||||||||||
module Session | ||||||||||||||
include Rex::Ui::Text::DispatcherShell::CommandDispatcher | ||||||||||||||
|
||||||||||||||
@@irb_opts = Rex::Parser::Arguments.new( | ||||||||||||||
%w[-h --help] => [false, 'Help menu.' ], | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
'-e' => [true, 'Expression to evaluate.'] | ||||||||||||||
) | ||||||||||||||
def commands | ||||||||||||||
{ | ||||||||||||||
'?' => 'Help menu', | ||||||||||||||
'background' => 'Backgrounds the current session', | ||||||||||||||
'bg' => 'Alias for background', | ||||||||||||||
'exit' => 'Terminate the session', | ||||||||||||||
'help' => 'Help menu', | ||||||||||||||
'irb' => 'Open an interactive Ruby shell on the current session', | ||||||||||||||
'pry' => 'Open the Pry debugger on the current session', | ||||||||||||||
'quit' => 'Terminate the session', | ||||||||||||||
'resource' => 'Run the commands stored in a file', | ||||||||||||||
'uuid' => 'Get the UUID for the current session', | ||||||||||||||
'sessions' => 'Quickly switch to another session' | ||||||||||||||
} | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
def cmd_background_help | ||||||||||||||
print_line('Usage: background') | ||||||||||||||
print_line | ||||||||||||||
print_line('Stop interacting with this session and return to the parent prompt') | ||||||||||||||
print_line | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
def cmd_background(*args) | ||||||||||||||
if args.include?('-h') || args.include?('--help') | ||||||||||||||
cmd_background_help | ||||||||||||||
return | ||||||||||||||
end | ||||||||||||||
print_status("Backgrounding session #{client.name}...") | ||||||||||||||
client.interacting = false | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
alias cmd_bg cmd_background | ||||||||||||||
alias cmd_bg_help cmd_background_help | ||||||||||||||
|
||||||||||||||
# | ||||||||||||||
# Terminates the session. | ||||||||||||||
# | ||||||||||||||
def cmd_exit(*args) | ||||||||||||||
print_status("Shutting down session: #{client.sid}") | ||||||||||||||
client.exit | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
alias cmd_quit cmd_exit | ||||||||||||||
Comment on lines
+49
to
+57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A session can be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't necessarily disagree but I don't think it belongs in this PR, this is just a bit of a refactor and moving things around, the intention is not to alter the way someone would interact with a session here |
||||||||||||||
|
||||||||||||||
def cmd_irb_help | ||||||||||||||
print_line('Usage: irb') | ||||||||||||||
print_line | ||||||||||||||
print_line('Open an interactive Ruby shell on the current session.') | ||||||||||||||
print @@irb_opts.usage | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
def cmd_irb_tabs(str, words) | ||||||||||||||
return [] if words.length > 1 | ||||||||||||||
|
||||||||||||||
@@irb_opts.option_keys | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
# | ||||||||||||||
# Open an interactive Ruby shell on the current session | ||||||||||||||
# | ||||||||||||||
def cmd_irb(*args) | ||||||||||||||
expressions = [] | ||||||||||||||
|
||||||||||||||
# Parse the command options | ||||||||||||||
@@irb_opts.parse(args) do |opt, _idx, val| | ||||||||||||||
case opt | ||||||||||||||
when '-e' | ||||||||||||||
expressions << val | ||||||||||||||
when '-h', '--help' | ||||||||||||||
return cmd_irb_help | ||||||||||||||
end | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
session = client | ||||||||||||||
framework = client.framework | ||||||||||||||
|
||||||||||||||
if expressions.empty? | ||||||||||||||
print_status('Starting IRB shell...') | ||||||||||||||
print_status("You are in the \"client\" (session) object\n") | ||||||||||||||
framework.history_manager.with_context(name: :irb) do | ||||||||||||||
Rex::Ui::Text::IrbShell.new(client).run | ||||||||||||||
end | ||||||||||||||
else | ||||||||||||||
# XXX: No vprint_status here | ||||||||||||||
if framework.datastore['VERBOSE'].to_s == 'true' | ||||||||||||||
print_status("You are executing expressions in #{binding.receiver}") | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
expressions.each { |expression| eval(expression, binding) } | ||||||||||||||
end | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
def cmd_pry_help | ||||||||||||||
print_line 'Usage: pry' | ||||||||||||||
print_line | ||||||||||||||
print_line 'Open the Pry debugger on the current session.' | ||||||||||||||
print_line | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
# | ||||||||||||||
# Open the Pry debugger on the current session | ||||||||||||||
# | ||||||||||||||
def cmd_pry(*args) | ||||||||||||||
if args.include?('-h') || args.include?('--help') | ||||||||||||||
cmd_pry_help | ||||||||||||||
return | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
begin | ||||||||||||||
require 'pry' | ||||||||||||||
rescue LoadError | ||||||||||||||
print_error('Failed to load Pry, try "gem install pry"') | ||||||||||||||
return | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
print_status('Starting Pry shell...') | ||||||||||||||
print_status("You are in the \"client\" (session) object\n") | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
|
||||||||||||||
Pry.config.history_load = false | ||||||||||||||
client.framework.history_manager.with_context(history_file: Msf::Config.pry_history, name: :pry) do | ||||||||||||||
client.pry | ||||||||||||||
end | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
def cmd_sessions_help | ||||||||||||||
print_line('Usage: sessions <id>') | ||||||||||||||
print_line | ||||||||||||||
print_line('Interact with a different session Id.') | ||||||||||||||
print_line('This works the same as calling this from the MSF shell: sessions -i <session id>') | ||||||||||||||
print_line | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
def cmd_sessions(*args) | ||||||||||||||
if args.empty? || args[0].to_i == 0 | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
cmd_sessions_help | ||||||||||||||
elsif args[0].to_s == client.name.to_s | ||||||||||||||
print_status("Session #{client.name} is already interactive.") | ||||||||||||||
else | ||||||||||||||
print_status("Backgrounding session #{client.name}...") | ||||||||||||||
# store the next session id so that it can be referenced as soon | ||||||||||||||
# as this session is no longer interacting | ||||||||||||||
client.next_session = args[0] | ||||||||||||||
client.interacting = false | ||||||||||||||
end | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
def cmd_resource_help | ||||||||||||||
print_line 'Usage: resource path1 [path2 ...]' | ||||||||||||||
print_line | ||||||||||||||
print_line 'Run the commands stored in the supplied files. (- for stdin, press CTRL+D to end input from stdin)' | ||||||||||||||
print_line 'Resource files may also contain ERB or Ruby code between <ruby></ruby> tags.' | ||||||||||||||
print_line | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
def cmd_resource(*args) | ||||||||||||||
if args.empty? || args.include?('-h') || args.include?('--help') | ||||||||||||||
cmd_resource_help | ||||||||||||||
return false | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
args.each do |res| | ||||||||||||||
good_res = nil | ||||||||||||||
if res == '-' | ||||||||||||||
good_res = res | ||||||||||||||
elsif ::File.exist?(res) | ||||||||||||||
good_res = res | ||||||||||||||
elsif [ | ||||||||||||||
::Msf::Config.script_directory + ::File::SEPARATOR + 'resource' + ::File::SEPARATOR + 'meterpreter', | ||||||||||||||
::Msf::Config.user_script_directory + ::File::SEPARATOR + 'resource' + ::File::SEPARATOR + 'meterpreter' | ||||||||||||||
].each do |dir| | ||||||||||||||
res_path = dir + ::File::SEPARATOR + res | ||||||||||||||
if ::File.exist?(res_path) | ||||||||||||||
good_res = res_path | ||||||||||||||
break | ||||||||||||||
end | ||||||||||||||
end | ||||||||||||||
# let's check to see if it's in the scripts/resource dir (like when tab completed) | ||||||||||||||
end | ||||||||||||||
unless good_res | ||||||||||||||
print_error("#{res} is not a valid resource file") | ||||||||||||||
next | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
client.console.load_resource(good_res) | ||||||||||||||
end | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
def cmd_resource_tabs(str, words) | ||||||||||||||
tabs = [] | ||||||||||||||
# return tabs if words.length > 1 | ||||||||||||||
if (str && str =~ (/^#{Regexp.escape(::File::SEPARATOR)}/)) | ||||||||||||||
# then you are probably specifying a full path so let's just use normal file completion | ||||||||||||||
return tab_complete_filenames(str, words) | ||||||||||||||
elsif (!(words[1]) || !words[1].match(%r{^/})) | ||||||||||||||
Comment on lines
+207
to
+208
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
# then let's start tab completion in the scripts/resource directories | ||||||||||||||
begin | ||||||||||||||
[ | ||||||||||||||
::Msf::Config.script_directory + ::File::SEPARATOR + 'resource' + ::File::SEPARATOR + 'meterpreter', | ||||||||||||||
::Msf::Config.user_script_directory + ::File::SEPARATOR + 'resource' + ::File::SEPARATOR + 'meterpreter', | ||||||||||||||
'.' | ||||||||||||||
].each do |dir| | ||||||||||||||
next if !::File.exist? dir | ||||||||||||||
|
||||||||||||||
tabs += ::Dir.new(dir).find_all do |e| | ||||||||||||||
path = dir + ::File::SEPARATOR + e | ||||||||||||||
::File.file?(path) and ::File.readable?(path) | ||||||||||||||
end | ||||||||||||||
end | ||||||||||||||
rescue StandardError => e | ||||||||||||||
elog('Problem tab completing resource file names in the scripts/resource directories', error: e) | ||||||||||||||
end | ||||||||||||||
else | ||||||||||||||
tabs += tab_complete_filenames(str, words) | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
return tabs | ||||||||||||||
end | ||||||||||||||
end | ||||||||||||||
end | ||||||||||||||
end | ||||||||||||||
end | ||||||||||||||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.