Session detach support, closer to clean hand-off between session -d / session -i. Make autovnc look for both vncviewer and vncviewer.exe

git-svn-id: file:///home/svn/framework3/trunk@4424 4d416f70-5f16-0410-b530-b9f4589650da
unstable
HD Moore 2007-02-18 04:25:46 +00:00
parent a4b06e1653
commit 80c4bcd5ab
10 changed files with 99 additions and 28 deletions

View File

@ -33,6 +33,10 @@ class ConsoleController < ApplicationController
out = out.unpack('C*').map{|c| sprintf("%%%.2x", c)}.join
pro = console.prompt.unpack('C*').map{|c| sprintf("%%%.2x", c)}.join
if (console.busy)
pro = '(running)'.unpack('C*').map{|c| sprintf("%%%.2x", c)}.join
end
script = "// Metasploit Web Console Data\n"
script += "var con_prompt = unescape('#{pro}');\n"
script += "var con_update = unescape('#{out}');\n"
@ -67,6 +71,10 @@ class ConsoleController < ApplicationController
out = out.unpack('C*').map{|c| sprintf("%%%.2x", c)}.join
pro = @console.prompt.unpack('C*').map{|c| sprintf("%%%.2x", c)}.join
if (@console.busy)
pro = '(running)'.unpack('C*').map{|c| sprintf("%%%.2x", c)}.join
end
script = "// Metasploit Web Console Data\n"
script += "var con_prompt = unescape('#{pro}');\n"
script += "var con_update = unescape('#{out}');\n"
@ -79,7 +87,7 @@ class ConsoleController < ApplicationController
cmdl = params[:tab]
out = ""
if (params[:tab].strip.length > 0)
if (not @console.busy and params[:tab].strip.length > 0)
opts = @console.tab_complete(params[:tab]) || []
end
@ -108,7 +116,7 @@ class ConsoleController < ApplicationController
cmdl = cmd_top[0, depth]
end
out = "\n" + opts.map{ |c| " >> " + c }.join("\n")
out = "\n" + opts.map{ |c| ">> " + c }.join("\n")
end
end
@ -116,6 +124,10 @@ class ConsoleController < ApplicationController
pro = @console.prompt.unpack('C*').map{|c| sprintf("%%%.2x", c)}.join
tln = cmdl.unpack('C*').map{|c| sprintf("%%%.2x", c)}.join
if (@console.busy)
pro = '(running)'.unpack('C*').map{|c| sprintf("%%%.2x", c)}.join
end
script = "// Metasploit Web Console Data\n"
script += "var con_prompt = unescape('#{pro}');\n"
script += "var con_update = unescape('#{out}');\n"

View File

@ -6,7 +6,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<meta name="Author" content="LMH (lmh@info-pull.com)" />
<meta name="Copyright" content="(c) 2006, LMH (lmh@info-pull.com)" />
<title>msfweb v.3 - console demo</title>
<title>Metasploit Console</title>
<% ["prototype","effects","controls", "window", "application", "console"].each do |js| %>
<%= javascript_include_tag js %><% end %>
<%= stylesheet_link_tag "msfconsole" %>

View File

@ -127,7 +127,7 @@ function console_keypress(e) {
console_hindex = console_history.length - 1;
}
console_printline("\n" + con_prompt + ' ' + console_input.value, 'output_line')
console_printline("\n>> " + console_input.value + "\n\n", 'output_line')
if(cmd_internal[console_input.value]) {
cmd_internal[console_input.value]();

View File

@ -67,6 +67,7 @@ html,body {
#console_command_bar {
background: #000000;
margin-top: 1em;
}
#console_status {

View File

@ -126,7 +126,11 @@ class VncInject
# Launches VNC viewer against the local relay for this VNC server session.
#
def autovnc
if (Rex::FileUtils::find_full_path('vncviewer'))
vnc =
Rex::FileUtils::find_full_path('vncviewer') ||
Rex::FileUtils::find_full_path('vncviewer.exe')
if (vnc)
Thread.new {
system("vncviewer #{vlhost}::#{vlport}")
}

View File

@ -26,6 +26,7 @@ class Core
"-l" => [ false, "List all active sessions." ],
"-v" => [ false, "List verbose fields." ],
"-q" => [ false, "Quiet mode." ],
"-d" => [ true, "Detach an interactive session" ],
"-k" => [ true, "Terminate session." ])
@@jobs_opts = Rex::Parser::Arguments.new(
@ -624,6 +625,10 @@ class Core
method = 'kill'
sid = val
when "-d"
method = 'detach'
sid = val
# Display help banner
when "-h"
print(
@ -639,9 +644,18 @@ class Core
when 'kill'
if ((session = framework.sessions.get(sid)))
print_status("Killing session #{sid}")
session.kill
end
when 'detach'
if ((session = framework.sessions.get(sid)))
print_status("Detaching session #{sid}")
if (session.interactive?)
session.detach()
end
end
when 'interact'
if ((session = framework.sessions.get(sid)))
if (session.interactive?)
@ -655,12 +669,8 @@ class Core
# Interact
session.interact()
# Once interact returns, swap the output handle with a
# none output
#
# TODO: change this to use buffered output so we can call
# flush later on
session.reset_ui
self.active_session = nil
else
print_error("Session #{sid} is non-interactive.")
end

View File

@ -77,7 +77,6 @@ class WebConsole
def read
update_access
self.pipe.read_subscriber('msfweb')
end
@ -102,6 +101,10 @@ class WebConsole
self.pipe.close
self.thread.kill
end
def busy
self.console.busy
end
end

View File

@ -104,6 +104,9 @@ class Driver < Msf::Ui::Driver
# Has this session already been detached?
return if ses.user_output.has_subscriber?('session_reader')
# Detach session if necessary
ses.detach()
# Create a new pipe
spipe = WebConsole::WebConsolePipe.new
spipe.input = spipe.pipe_input

View File

@ -21,7 +21,14 @@ module Interactive
# rstream to user_output.
#
def interact
# Prevent two thread from interacting at once
if(self.interacting)
raise RuntimeError, "This session is already interacting with another console"
end
self.interacting = true
self.completed = false
eof = false
@ -53,26 +60,53 @@ module Interactive
break if eof
end
begin
# Restore the suspend handler
restore_suspend
# Restore the suspend handler
restore_suspend
# If we've hit eof, call the interact complete handler
_interact_complete if (eof == true)
# If we've hit eof, call the interact complete handler
_interact_complete if (eof == true)
# Shutdown the readline thread
# XXX disabled
# user_input.readline_stop() if user_input.supports_readline
# Shutdown the readline thread
# XXX disabled
# user_input.readline_stop() if user_input.supports_readline
# Detach from the input/output handles
reset_ui()
ensure
# Mark this as completed
self.completed = true
end
# Return whether or not EOF was reached
return eof
end
#
# Stops the current interaction
#
def detach
if (self.interacting)
self.interacting = false
stime = Time.now.to_f
while(Time.now.to_f > stime + 5 and not self.completed)
select(nil, nil, nil, 0.10)
end
end
end
#
# Whether or not the session is currently being interacted with
#
attr_accessor :interacting
#
# Whether or not the session has completed interaction
#
attr_accessor :completed
protected
#
@ -145,8 +179,9 @@ protected
#
def interact_stream(stream)
while self.interacting
# Select input and rstream
sd = Rex::ThreadSafe.select([ _local_fd, _remote_fd(stream) ])
sd = Rex::ThreadSafe.select([ _local_fd, _remote_fd(stream) ], nil, nil, 0.25)
# Cycle through the items that have data
# From the stream? Write to user_output.

View File

@ -226,7 +226,9 @@ module DispatcherShell
# Runs the supplied command on the given dispatcher.
#
def run_command(dispatcher, method, arguments)
self.busy = true
dispatcher.send('cmd_' + method, *arguments)
self.busy = false
end
#
@ -321,6 +323,7 @@ module DispatcherShell
attr_accessor :dispatcher_stack # :nodoc:
attr_accessor :tab_words # :nodoc:
attr_accessor :busy # :nodoc:
end