-
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
Extract reusable core session commands #18516
Conversation
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.
code quality issues with existing code
end | ||
# let's check to see if it's in the scripts/resource dir (like when tab completed) | ||
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.
where's end's friend? he shares an indentation level with another 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.
huh, most of this was copied over from the meterpreter command_dispatcher, I swear I rubocopped this but there's definitely still issues, I'll get it sorted cheers
if good_res | ||
client.console.load_resource(good_res) | ||
else | ||
print_error("#{res} is not a valid resource file") | ||
next | ||
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.
if good_res | |
client.console.load_resource(good_res) | |
else | |
print_error("#{res} is not a valid resource file") | |
next | |
end | |
unless good_res | |
print_error("#{res} is not a valid resource file") | |
next | |
end | |
client.console.load_resource(good_res) |
return tab_complete_filenames(str, words) | ||
elsif (!(words[1]) || !words[1].match(%r{^/})) |
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.
return tab_complete_filenames(str, words) | |
elsif (!(words[1]) || !words[1].match(%r{^/})) | |
return tab_complete_filenames(str, words) | |
end | |
if (!(words[1]) || !words[1].match(%r{^/})) |
::File.file?(path) and ::File.readable?(path) | ||
end | ||
end | ||
rescue Exception |
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.
‽
8303d8c
to
06e066b
Compare
|
||
COMMANDS = %i[help background sessions resource shell download upload source irb pry] | ||
|
||
RSpec.describe Msf::Sessions::CommandShell do |
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.
It'd be nice to clean these up to align with some of the conventions from https://www.betterspecs.org/
this should follow the conventions of https://www.betterspecs.org/#describe
i.e.
describe '.type' do
# ...
end
describe '.can_cleanup_files' do
# ...
end
# ... etc ...
And ensure context
blocks follow the naming convention of context 'when ...' do
datastore | ||
end | ||
it 'should execute the script' do | ||
is_expected.to receive(:execute_script).with(initial_auto_run_script) |
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.
Not a blocker; expect to receive is an antipattern as it doesn't follow the normal pattern of arrange/act/assert
https://automationpanda.com/2020/07/07/arrange-act-assert-a-pattern-for-writing-good-tests/
i.e. prefer adding a expect(...).to have_received(...)
after the 'act', instead of expect(...). to receive(...)
before your 'act'
spec/lib/rex/post/meterpreter/ui/console/command_dispatcher/core_spec.rb
Outdated
Show resolved
Hide resolved
06e066b
to
c7e0e09
Compare
session_id = args[0].to_i | ||
if session_id <= 0 | ||
print_status 'Invalid session id' | ||
cmd_sessions_help |
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.
Does this need a return?
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.
It would be nice to normalise the return
part in cmd_…_help
: do we want a return false
after it? do we want to return cmd_…_help
? do we want a naked return
instead?
@@ -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.' ], |
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.
['-h', '--help'] => [false, 'Help menu.' ], | |
['-h', '--help'] => [false, 'Help menu.'], |
# 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 comment
The reason will be displayed to describe this comment to others. Learn more.
# One arg, and args[0] => '-h' '--help' |
I don't think this comment is necessary.
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 comment
The reason will be displayed to describe this comment to others. Learn more.
%w[-h --help] => [false, 'Help menu.' ], | |
%w[-h --help] => [false, 'Help menu.'], |
# | ||
# Terminates the session. | ||
# | ||
def cmd_exit(*args) | ||
print_status("Shutting down session: #{client.sid}") | ||
client.exit | ||
end | ||
|
||
alias cmd_quit cmd_exit |
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.
A session can be terminated
, exit'ed
, shut down
and quit'ted
. It would be nice to reduce the amount of terms for this action I think.
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.
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
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 comment
The reason will be displayed to describe this comment to others. Learn more.
print_status("You are in the \"client\" (session) object\n") | |
print_status('You are in the "client" (session) object') | |
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 comment
The reason will be displayed to describe this comment to others. Learn more.
if args.empty? || args[0].to_i == 0 | |
if args.empty? || args[0].to_i == 0 || args.include?('-h') || args.include?('--help') |
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 comment
The 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 comment
The 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 comment
The 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
Some of the remaining comments are about existing code that's just been shuffled, will treat as not a blocker for now |
Refactoring some commands out of the Meterpreter specific command dispatcher into a new generic Sessions command dispatcher that all sessions will be able to leverage.
The common commands I pulled out were:
help background sessions resource irb pry exit
I didn't see any others that made a tonne of sense to move out but if there's any you'd like to see added feel free to dorp a comment calling it out
Also added a bunch of tests that should let us make sure any new session types have correctly implemented the api that the session command dispatcher is expecting