diff --git a/lib/msf/ui/gtk2/console/console.rb b/lib/msf/ui/gtk2/console/console.rb index ddffc88daf..2e74752d41 100644 --- a/lib/msf/ui/gtk2/console/console.rb +++ b/lib/msf/ui/gtk2/console/console.rb @@ -10,16 +10,138 @@ module Msf # ### class Shell < Msf::Ui::Gtk2::SkeletonConsole - + module InteractiveChannel + + include Rex::Ui::Interactive + + # + # Interacts with self. + # + def _interact + # If the channel has a left-side socket, then we can interact with it. + if (self.lsock) + self.interactive(true) + + interact_stream(self) + + self.interactive(false) + else + print_error("Channel #{self.cid} does not support interaction.") + + self.interacting = false + end + end + + # + # Called when an interrupt is sent. + # + def _interrupt + prompt_yesno("Terminate channel #{self.cid}?") + end + + # + # Suspends interaction with the channel. + # + def _suspend + # Ask the user if they would like to background the session + if (prompt_yesno("Background channel #{self.cid}?") == true) + self.interactive(false) + + self.interacting = false + end + end + + # + # Closes the channel like it aint no thang. + # + def _interact_complete + begin + self.interactive(false) + + self.close + rescue IOError + end + end + + # + # Reads data from local input and writes it remotely. + # + def _stream_read_local_write_remote(channel) + data = user_input.gets + + self.write(data) + end + + # + # Reads from the channel and writes locally. + # + def _stream_read_remote_write_local(channel) + data = self.lsock.sysread(16384) + + user_output.print(data) + end + + # + # Returns the remote file descriptor to select on + # + def _remote_fd(stream) + self.lsock + end + + end + + module Pipe + # + # Interacts with the supplied channel. + # + def interact_with_channel(channel, pipe) + channel.extend(InteractiveChannel) unless (channel.kind_of?(InteractiveChannel) == true) + @t_run = Thread.new do + channel.interact(pipe, pipe) + end + end + end + def initialize(iter) - client = iter[3] + session = iter[3] super(iter) - - if (client.type == "meterpreter") - + + if (session.type == "meterpreter") + self.type = "shell" + # TODO: use the API instead writing into the pipe - send_cmd("execute -f cmd.exe -i -H") - end + meterconsole = Rex::Post::Meterpreter::Ui::Console.new(session) + meterconsole.extend(Pipe) + #send_cmd("execute -f cmd.exe -i -H") + cmd_exec = "cmd.exe" + cmd_args = nil + channelized = true + hidden = true + from_mem = false + dummy_exec = "cmd" + p = session.sys.process.execute(cmd_exec, cmd_args, + 'Channelized' => channelized, + 'Hidden' => hidden, + 'InMemory' => (from_mem) ? dummy_exec : nil) + + @pipe = Rex::IO::BidirectionalPipe.new + # Create a subscriber with a callback for the UI + @pipe.create_subscriber_proc() do |data| + self.insert_text(Rex::Text.to_utf8(data)) + end + meterconsole.interact_with_channel(p.channel, @pipe) + + end + # + # Send command to bidirectionnal_pipe + # + def send_cmd(cmd) + # What time is it ? + # update_access + + # Write the command plus a newline to the input + @pipe.write_input(cmd + "\n") + end end end # Console::Shell @@ -30,14 +152,14 @@ module Msf # ### class Meterpreter < Msf::Ui::Gtk2::SkeletonConsole - + def initialize(iter) # meterpreter client client = iter[3] # call the parent super(iter) - + # TODO: use the API instead writing into the pipe send_cmd("help") end diff --git a/lib/msf/ui/gtk2/console/skeleton.rb b/lib/msf/ui/gtk2/console/skeleton.rb index 4035d129fb..7f28a85628 100644 --- a/lib/msf/ui/gtk2/console/skeleton.rb +++ b/lib/msf/ui/gtk2/console/skeleton.rb @@ -11,10 +11,6 @@ module Msf require 'rex/io/bidirectional_pipe' include Msf::Ui::Gtk2::MyControls - ID_SESSION, PEER, PAYLOAD, O_SESSION, O_BUFFER = *(0..5).to_a - - @@offset = 0 - ### # # Basic command history class @@ -70,6 +66,14 @@ module Msf end + ID_SESSION, PEER, TYPE, O_SESSION = *(0..4).to_a + @@offset = 0 + + attr_accessor :type, :buffer + + # + # Init the SkeletonConsole class + # def initialize(iter) # Style console_style = File.join(driver.resource_directory, 'style', 'console.rc') @@ -78,9 +82,8 @@ module Msf # Call the parent super(Gtk::Window::TOPLEVEL) - # initialize the session and buffer vars from the iter sessions tree + # initialize the session var from the iter sessions tree @session = iter[O_SESSION] - @buffer = iter[O_BUFFER] # Layout stuff self.set_default_size(500, 400) @@ -93,8 +96,9 @@ module Msf vbox = Gtk::VBox.new(false, 5) self.add(vbox) - # Setup text view + # Setup text view and buffer @textview = Gtk::TextView.new + @buffer = Gtk::TextBuffer.new scrolled_window = Gtk::ScrolledWindow.new scrolled_window.add(@textview) vbox.pack_start(scrolled_window, true, true, 5) @@ -111,7 +115,7 @@ module Msf hbox.layout_style = Gtk::ButtonBox::END button = Gtk::Button.new(Gtk::Stock::CLOSE) button.signal_connect("clicked") do - close_console + close_console() end # Pack @@ -136,25 +140,23 @@ module Msf insert_text(Rex::Text.to_utf8(data)) end + # Init an history object @historic = History.new() + # Init the prompt variable with the session type + @type = @session.type + # Display all self.show_all end #intialize - # - # update access - # - def update_access - last_access = Time.now - end - # # Send command to bidirectionnal_pipe # def send_cmd(cmd) - update_access + # What time is it ? + # update_access # Write the command plus a newline to the input @pipe.write_input(cmd + "\n") @@ -171,6 +173,27 @@ module Msf protected # ########### + # + # update access + # + def update_access + last_access = Time.now + end + + # + # meterpreter prompt + # + def prompt + null_prompt = "" + meta_prompt = "meterpreter >> " + if (@type == "meterpreter") + @buffer.insert(@buffer.end_iter, meta_prompt) + else + @buffer.insert(@buffer.end_iter, null_prompt) + end + @@offset = @buffer.end_iter.offset + end + # # Get the current line # @@ -220,6 +243,9 @@ module Msf # Add a return line to our buffer insert_text("\n") + # Call the prompt + prompt() + # Create the mark tag if not exist if (not @buffer.get_mark('end_mark')) @buffer.create_mark('end_mark', @buffer.end_iter, false) diff --git a/lib/msf/ui/gtk2/frame/sessions_tree.rb b/lib/msf/ui/gtk2/frame/sessions_tree.rb index 80f340e84c..0e4970c8b0 100644 --- a/lib/msf/ui/gtk2/frame/sessions_tree.rb +++ b/lib/msf/ui/gtk2/frame/sessions_tree.rb @@ -8,7 +8,7 @@ module Msf # ### class MySessionTree - ID_SESSION, PEER, TYPE, O_SESSION, O_BUFFER = *(0..5).to_a + ID_SESSION, PEER, TYPE, O_SESSION = *(0..4).to_a include Msf::Ui::Gtk2::MyControls @@ -17,8 +17,7 @@ module Msf @model = Gtk::ListStore.new(String, # Session ID String, # IP Address String, # Session Type - Object, # Session Object - Object # Gtk::TextBuffer + Object # Session Object ) # Renderer @@ -108,7 +107,6 @@ module Msf iter[TYPE] = session.type ? session.type : nil #iter[PAYLOAD] = session.via_payload ? session.via_payload : nil iter[O_SESSION] = session - iter[O_BUFFER] = Gtk::TextBuffer.new end #