make the sessions command a little more useful, see #2097
git-svn-id: file:///home/svn/framework3/trunk@10791 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
e3dac1d148
commit
745f31b20f
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue