Class: Rex::Post::Meterpreter::Ui::Console

Inherits:
Object
  • Object
show all
Includes:
Ui::Text::DispatcherShell
Defined in:
lib/rex/post/meterpreter/ui/console.rb

Overview

This class provides a shell driven interface to the meterpreter client API.

Defined Under Namespace

Modules: CommandDispatcher, InteractiveChannel

Instance Attribute Summary collapse

Attributes included from Ui::Text::DispatcherShell

#blocked, #busy, #dispatcher_stack

Attributes included from Ui::Text::Shell

#cont_flag, #cont_prompt, #disable_output, #framework, #hist_last_saved, #histfile, #history_manager, #input, #local_hostname, #local_username, #log_source, #name, #on_command_proc, #on_print_proc, #output, #prompt, #prompt_char, #stop_count, #stop_flag, #tab_complete_proc

Instance Method Summary collapse

Methods included from Ui::Text::DispatcherShell

#append_dispatcher, #block_command, #blocked_command?, #current_dispatcher, #destack_dispatcher, #enstack_dispatcher, #help_to_s, #remove_dispatcher, #run_single, #shellsplitex, #tab_complete, #tab_complete_helper, #tab_complete_stub, #unblock_command, #unknown_command

Methods included from Ui::Text::Shell

#_print_prompt, #format_prompt, #get_input_line, #init_tab_complete, #init_ui, #log_input, #log_output, #parse_line, #print, #print_error, #print_good, #print_line, #print_status, #print_warning, #prompt_yesno, #reset_ui, #run, #set_log_source, #stop, #stopped?, #supports_color?, #tab_complete, #unset_log_source, #update_prompt, #with_history_manager_context

Methods included from Ui::Text::Resource

#load_resource

Constructor Details

#initialize(client) ⇒ Console

Initialize the meterpreter console.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/rex/post/meterpreter/ui/console.rb', line 26

def initialize(client)
  if (Rex::Compat.is_windows())
    super("meterpreter")
  else
    super("%undmeterpreter%clr", '>', Msf::Config.meterpreter_history, nil, :meterpreter)
  end

  # The meterpreter client context
  self.client = client

  # Queued commands array
  self.commands = []

  # Point the input/output handles elsewhere
  reset_ui

  enstack_dispatcher(Console::CommandDispatcher::Core)

  # Set up logging to whatever logsink 'core' is using
  if ! $dispatcher['meterpreter']
    $dispatcher['meterpreter'] = $dispatcher['core']
  end
end

Instance Attribute Details

#clientObject

:nodoc:



133
134
135
# File 'lib/rex/post/meterpreter/ui/console.rb', line 133

def client
  @client
end

#commandsObject (protected)

:nodoc:



138
139
140
# File 'lib/rex/post/meterpreter/ui/console.rb', line 138

def commands
  @commands
end

Instance Method Details

#interact(&block) ⇒ Object

Called when someone wants to interact with the meterpreter client. It's assumed that init_ui has been called prior.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/rex/post/meterpreter/ui/console.rb', line 54

def interact(&block)
  # Run queued commands
  commands.delete_if { |ent|
    run_single(ent)
    true
  }

  # Run the interactive loop
  run { |line|
    # Run the command
    run_single(line)

    # If a block was supplied, call it, otherwise return false
    if (block)
      block.call
    else
      false
    end
  }
end

#interact_with_channel(channel, raw: false) ⇒ Object

Interacts with the supplied channel.



78
79
80
81
82
83
84
85
86
87
# File 'lib/rex/post/meterpreter/ui/console.rb', line 78

def interact_with_channel(channel, raw: false)
  channel.extend(InteractiveChannel) unless (channel.kind_of?(InteractiveChannel) == true)
  channel.on_command_proc = self.on_command_proc if self.on_command_proc
  channel.on_print_proc   = self.on_print_proc if self.on_print_proc
  channel.on_log_proc = method(:log_output) if self.respond_to?(:log_output, true)
  channel.raw = raw

  channel.interact(input, output)
  channel.reset_ui
end

#log_error(msg) ⇒ Object

Logs that an error occurred and persists the callstack.



125
126
127
128
129
130
131
# File 'lib/rex/post/meterpreter/ui/console.rb', line 125

def log_error(msg)
  print_error(msg)

  elog(msg, 'meterpreter')

  dlog("Call stack:\n#{$@.join("\n")}", 'meterpreter')
end

#queue_cmd(cmd) ⇒ Object

Queues a command to be run when the interactive loop is entered.



92
93
94
# File 'lib/rex/post/meterpreter/ui/console.rb', line 92

def queue_cmd(cmd)
  self.commands << cmd
end

#run_command(dispatcher, method, arguments) ⇒ Object

Runs the specified command wrapper in something to catch meterpreter exceptions.



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/rex/post/meterpreter/ui/console.rb', line 100

def run_command(dispatcher, method, arguments)
  begin
    super
  rescue Exception => e
    is_error_handled = self.client.on_run_command_error_proc && self.client.on_run_command_error_proc.call(e) == :handled
    return if is_error_handled
    case e
    when Rex::TimeoutError, Rex::InvalidDestination
      log_error(e.message)
    when Timeout::Error
      log_error('Operation timed out.')
    when RequestError
      log_error(e.to_s)
    when ::Errno::EPIPE, ::OpenSSL::SSL::SSLError, ::IOError
      self.client.kill
    when ::Exception
      log_error("Error running command #{method}: #{e.class} #{e}")
      elog(e)
    end
  end
end