make the sessions command a little more useful, see #2097

git-svn-id: file:///home/svn/framework3/trunk@10791 4d416f70-5f16-0410-b530-b9f4589650da
unstable
James Lee 2010-10-23 00:02:09 +00:00
parent e3dac1d148
commit 745f31b20f
2 changed files with 112 additions and 78 deletions

View File

@ -89,7 +89,7 @@ class CommandShell
end end
# #
# Executes the supplied script. # Executes the supplied script, will search the script path.
# #
def execute_script(script, args) def execute_script(script, args)
full_path = self.class.find_script_path(script) full_path = self.class.find_script_path(script)
@ -99,7 +99,13 @@ class CommandShell
print_error("The specified script could not be found: #{script}") print_error("The specified script could not be found: #{script}")
return true return true
end end
execute_file(full_path, args)
end
#
# Executes the supplied script, must be specified as full path.
#
def execute_file(full_path, args)
o = Rex::Script::Shell.new(self, full_path) o = Rex::Script::Shell.new(self, full_path)
o.run(args) o.run(args)
end end

View File

@ -20,16 +20,16 @@ class Core
# Session command options # Session command options
@@sessions_opts = Rex::Parser::Arguments.new( @@sessions_opts = Rex::Parser::Arguments.new(
"-c" => [ true, "Run a command on all live sessions" ], "-c" => [ true, "Run a command on the session given with -i, or all" ],
"-h" => [ false, "Help banner." ], "-h" => [ false, "Help banner" ],
"-i" => [ true, "Interact with the supplied session identifier." ], "-i" => [ true, "Interact with the supplied session ID" ],
"-l" => [ false, "List all active sessions." ], "-l" => [ false, "List all active sessions" ],
"-v" => [ false, "List verbose fields." ], "-v" => [ false, "List verbose fields" ],
"-q" => [ false, "Quiet mode." ], "-q" => [ false, "Quiet mode" ],
"-d" => [ true, "Detach an interactive session" ], "-d" => [ true, "Detach an interactive session" ],
"-k" => [ true, "Terminate session." ], "-k" => [ true, "Terminate session" ],
"-K" => [ false, "Terminate all sessions." ], "-K" => [ false, "Terminate all sessions" ],
"-s" => [ true, "Run a script on all live meterpreter sessions" ], "-s" => [ true, "Run a script on the session given with -i, or all" ],
"-u" => [ true, "Upgrade a win32 shell to a meterpreter session" ]) "-u" => [ true, "Upgrade a win32 shell to a meterpreter session" ])
@@jobs_opts = Rex::Parser::Arguments.new( @@jobs_opts = Rex::Parser::Arguments.new(
@ -1129,18 +1129,20 @@ class Core
end end
end end
#
# #
# Provides an interface to the sessions currently active in the framework. # Provides an interface to the sessions currently active in the framework.
# #
def cmd_sessions(*args) def cmd_sessions(*args)
begin begin
method = 'list' method = nil
quiet = false quiet = false
verbose = false verbose = false
sid = nil sid = nil
cmds = [] cmds = []
script = nil script = nil
# any arguments that don't correspond to an option or option arg will
# be put in here
extra = []
# Parse the command options # Parse the command options
@@sessions_opts.parse(args) { |opt, idx, val| @@sessions_opts.parse(args) { |opt, idx, val|
@ -1148,7 +1150,7 @@ class Core
when "-q" when "-q"
quiet = true quiet = true
# Run a command on all sessions # Run a command on all sessions, or the session given with -i
when "-c" when "-c"
method = 'cmd' method = 'cmd'
if (val) if (val)
@ -1158,9 +1160,9 @@ class Core
when "-v" when "-v"
verbose = true verbose = true
# Interact with the supplied session identifier # Do something with the supplied session identifier instead of
# all sessions.
when "-i" when "-i"
method = 'interact'
sid = val sid = val
# Display the list of active sessions # Display the list of active sessions
@ -1169,7 +1171,11 @@ class Core
when "-k" when "-k"
method = 'kill' method = 'kill'
sid = val sid = val if val
if not sid
print_error("Specify a session to kill")
return false
end
when "-K" when "-K"
method = 'killall' method = 'killall'
@ -1185,7 +1191,6 @@ class Core
script = val script = val
end end
# Upload and exec to the specific command session # Upload and exec to the specific command session
when "-u" when "-u"
method = 'upexec' method = 'upexec'
@ -1198,51 +1203,67 @@ class Core
"Active session manipulation and interaction.\n" + "Active session manipulation and interaction.\n" +
@@sessions_opts.usage()) @@sessions_opts.usage())
return false return false
else
extra << val
end end
} }
if sid and not framework.sessions.get(sid)
print_error("Invalid session id")
return false
end
if method.nil? and sid
method = 'interact'
end
# Now, perform the actual method # Now, perform the actual method
case method case method
when 'cmd' when 'cmd'
if (cmds.length > 0) if (cmds.length < 1)
cmds.each do |cmd|
framework.sessions.each_sorted do |s|
session = framework.sessions.get(s)
print_status("Running '#{cmd}' on session #{s} (#{session.tunnel_peer})")
if (session.type == "meterpreter")
# If session.sys is nil, dont even try..
if not (session.sys)
print_error("Session #{s} does not have stdapi loaded, skipping...")
next
end
c,args = cmd.split(' ', 2)
begin
process = session.sys.process.execute(c, args,
{
'Channelized' => true,
'Hidden' => true
})
rescue ::Rex::Post::Meterpreter::RequestError
print_error("Failed: #{$!.class} #{$!}")
end
if process and process.channel and (data = process.channel.read)
print_line(data)
end
elsif session.type == "shell"
if (output = session.shell_command(cmd))
print_line(output)
end
end
# If the session isn't a meterpreter or shell type, it
# could be a VNC session (which can't run commands) or
# something custom (which we don't know how to run
# commands on), so don't bother.
end
end
else
print_error("No command specified!") print_error("No command specified!")
return false
end
cmds.each do |cmd|
if sid
sessions = [ sid ]
else
sessions = framework.sessions.keys.sort
end
sessions.each do |s|
session = framework.sessions.get(s)
print_status("Running '#{cmd}' on #{session.type} session #{s} (#{session.tunnel_peer})")
if (session.type == "meterpreter")
# If session.sys is nil, dont even try..
if not (session.sys)
print_error("Session #{s} does not have stdapi loaded, skipping...")
next
end
c, c_args = cmd.split(' ', 2)
begin
process = session.sys.process.execute(c, c_args,
{
'Channelized' => true,
'Hidden' => true
})
rescue ::Rex::Post::Meterpreter::RequestError
print_error("Failed: #{$!.class} #{$!}")
end
if process and process.channel and (data = process.channel.read)
print_line(data)
end
elsif session.type == "shell"
if (output = session.shell_command(cmd))
print_line(output)
end
end
# If the session isn't a meterpreter or shell type, it
# could be a VNC session (which can't run commands) or
# something custom (which we don't know how to run
# commands on), so don't bother.
end
end end
when 'kill' when 'kill'
@ -1293,33 +1314,35 @@ class Core
print_error("Invalid session identifier: #{sid}") print_error("Invalid session identifier: #{sid}")
end end
when 'list'
print("\n" +
Serializer::ReadableText.dump_sessions(framework, verbose) + "\n")
when 'scriptall' when 'scriptall'
if (not script.nil?) if (script.nil?)
sleep(0.5) print_error("No script specified!")
script_path = Msf::Sessions::Meterpreter.find_script_path(script) return false
if (not script_path.nil?) end
print_status("Running script #{script} on all meterpreter sessions ...")
framework.sessions.each_sorted do |s| script_paths = {}
if ((session = framework.sessions.get(s))) script_paths['meterpreter'] = Msf::Sessions::Meterpreter.find_script_path(script)
if (session.type == "meterpreter") script_paths['shell'] = Msf::Sessions::CommandShell.find_script_path(script)
print_status("Session #{s} (#{session.tunnel_peer}):")
begin if sid
session.execute_file(script_path, args.slice(2,args.length)) print_status("Running script #{script} on session #{sid}...")
rescue ::Exception => e sessions = [ sid ]
log_error("Error executing script: #{e.class} #{e}") else
end print_status("Running script #{script} on all sessions...")
end sessions = framework.sessions.keys.sort
end
sessions.each do |s|
if ((session = framework.sessions.get(s)))
if (script_paths[session.type])
print_status("Session #{s} (#{session.tunnel_peer}):")
begin
session.execute_file(script_paths[session.type], extra)
rescue ::Exception => e
log_error("Error executing script: #{e.class} #{e}")
end end
end end
else
print_error("The specified script \"#{script}\" does not exist.")
end end
else
print_error("No script specified!")
end end
when 'upexec' when 'upexec'
@ -1339,6 +1362,11 @@ class Core
print_error("Invalid session identifier: #{sid}") print_error("Invalid session identifier: #{sid}")
end end
when 'list',nil
print("\n" +
Serializer::ReadableText.dump_sessions(framework, verbose) + "\n")
end end
rescue IOError, EOFError, Rex::StreamClosedError rescue IOError, EOFError, Rex::StreamClosedError
@ -1360,7 +1388,7 @@ class Core
# #
def cmd_sessions_tabs(str, words) def cmd_sessions_tabs(str, words)
if (not words[1]) if (not words[1])
return %w{-q -i -l -h} return @@sessions_opts.fmt.keys
end end
end end