diff --git a/lib/msf/base/sessions/meterpreter.rb b/lib/msf/base/sessions/meterpreter.rb index 3580f94b45..43459651f0 100644 --- a/lib/msf/base/sessions/meterpreter.rb +++ b/lib/msf/base/sessions/meterpreter.rb @@ -108,6 +108,8 @@ class Meterpreter < Rex::Post::Meterpreter::Client # Initializes the console's I/O handles. # def init_ui(input, output) + self.user_input = input + self.user_output = output console.init_ui(input, output) console.set_log_source(log_source) diff --git a/lib/msf/base/sessions/meterpreter_options.rb b/lib/msf/base/sessions/meterpreter_options.rb index fec5771777..1ae5c6326b 100644 --- a/lib/msf/base/sessions/meterpreter_options.rb +++ b/lib/msf/base/sessions/meterpreter_options.rb @@ -33,8 +33,7 @@ module MeterpreterOptions super # Configure input/output to match the payload - session.user_input = self.user_input - session.user_output = self.user_output + session.init_ui(self.user_input, self.user_output) if (datastore['AutoLoadStdapi'] == true) session.load_stdapi diff --git a/lib/msf/core/rpc/session.rb b/lib/msf/core/rpc/session.rb index baf3c0a26e..db6ea64819 100644 --- a/lib/msf/core/rpc/session.rb +++ b/lib/msf/core/rpc/session.rb @@ -1,5 +1,6 @@ +require 'pp' require 'rex' -require 'rex/io/bidirectional_pipe' +require 'rex/ui/text/output/buffer' module Msf module RPC @@ -61,12 +62,15 @@ class Session < Base if(s.type != "meterpreter") raise ::XMLRPC::FaultException.new(403, "session is not meterpreter") end - if s.console.output.respond_to? :read_buff - data = s.console.output.read_buff - else - s.console.output.extend BufferedIO - data = '' + + if s.user_output.nil? or s.console.output.nil? + s.init_ui(Rex::Ui::Text::Input::Stdio.new, Rex::Ui::Text::Output::Buffer.new) end + if not s.user_output.respond_to? :read_buff + s.user_output.extend BufferedIO + end + + data = s.user_output.read_buff { "data" => data } end @@ -80,21 +84,20 @@ class Session < Base raise ::XMLRPC::FaultException.new(403, "session is not meterpreter") end - # We have to start buffering the console output before running the - # command so we don't lose any output. - if not s.console.output.respond_to? :read_buff - s.console.output.extend BufferedIO + if s.user_output.nil? or s.console.output.nil? + s.init_ui(Rex::Ui::Text::Input::Stdio.new, Rex::Ui::Text::Output::Buffer.new) end - found = s.console.run_single(data) - if not found - raise ::XMLRPC::FaultException.new(404, "command not found") + if not s.user_output.respond_to? :read_buff + s.user_output.extend BufferedIO end - { "data" => found } + Thread.new { s.console.run_single(data) } + + {} end def meterpreter_script(token, sid, data) - meterpreter_write("run #{data}") + meterpreter_write(token, sid, "run #{data}") end protected @@ -113,19 +116,25 @@ end # Ghetto module BufferedIO - alias_method :orig_print, :print + def supports_color?; false; end + def supports_color; false; end + def read_buff - self.buffer ||= '' - buf = self.buffer.dup - self.buffer = '' - buf + self.buf ||= '' + buffer = self.buf.dup + self.buf = '' + buffer end def print(msg) - self.buffer ||= '' - self.buffer << msg - orig_print(msg) + self.buf ||= '' + buf << msg + msg end - def print_line(msg); print(msg +"\n"); end - attr_accessor :buffer + alias :print_raw :print + + # Match this with the Output::Buffer attr name so we aren't storing it + # twice. + attr_accessor :buf end + diff --git a/lib/rex/ui/text/output/buffer.rb b/lib/rex/ui/text/output/buffer.rb index 5916953e81..c953bbc32f 100644 --- a/lib/rex/ui/text/output/buffer.rb +++ b/lib/rex/ui/text/output/buffer.rb @@ -34,6 +34,18 @@ class Output::Buffer < Rex::Ui::Text::Output msg end + alias :print :print_raw + + + # + # Read everything out of the buffer and reset it + # + def dump_buffer + self.buf ||= '' + buffer = self.buf.dup + reset() + buffer + end # # Reset the buffer to an empty string.