Module: Rex::Post::Meterpreter::Ui::Console::InteractiveChannel

Includes:
Ui::Interactive
Defined in:
lib/rex/post/meterpreter/ui/console/interactive_channel.rb

Overview

Mixin that is meant to extend the base channel class from meterpreter in a manner that adds interactive capabilities.

Instance Attribute Summary collapse

Attributes included from Ui::Interactive

#completed, #interacting, #next_session, #on_command_proc, #on_print_proc, #orig_suspend, #orig_usr1, #orig_winch

Attributes included from Ui::Subscriber::Input

#user_input

Attributes included from Ui::Subscriber::Output

#user_output

Instance Method Summary collapse

Methods included from Ui::Interactive

#_local_fd, #detach, #handle_suspend, #handle_usr1, #handle_winch, #interact, #interact_stream, #prompt, #prompt_yesno, #restore_suspend, #restore_usr1, #restore_winch

Methods included from Ui::Subscriber

#copy_ui, #init_ui, #reset_ui

Methods included from Ui::Subscriber::Input

#gets

Methods included from Ui::Subscriber::Output

#flush, #print, #print_blank_line, #print_error, #print_good, #print_line, #print_status, #print_warning

Instance Attribute Details

#colsObject

Returns the value of attribute cols.


107
108
109
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 107

def cols
  @cols
end

#on_log_procObject

Returns the value of attribute on_log_proc.


135
136
137
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 135

def on_log_proc
  @on_log_proc
end

#rawObject

Returns the value of attribute raw.


17
18
19
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 17

def raw
  @raw
end

#rowsObject

Returns the value of attribute rows.


106
107
108
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 106

def rows
  @rows
end

Instance Method Details

#_interactObject

Interacts with self.


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 21

def _interact
  # If the channel has a left-side socket, then we can interact with it.
  if (self.lsock)
    self.interactive(true)
    if raw
      update_term_size
      _local_fd.raw do
        interact_stream(self)
      end
    else
      interact_stream(self)
    end

    self.interactive(false)
  else
    print_error("Channel #{self.cid} does not support interaction.")

    self.interacting = false
  end
end

#_interact_completeObject

Closes the channel like it aint no thang.


64
65
66
67
68
69
70
71
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 64

def _interact_complete
  begin
    self.interactive(false)

    self.close
  rescue IOError
  end
end

#_interruptObject

Called when an interrupt is sent.


45
46
47
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 45

def _interrupt
  prompt_yesno("Terminate channel #{self.cid}?")
end

#_remote_fd(stream) ⇒ Object

Returns the remote file descriptor to select on


102
103
104
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 102

def _remote_fd(stream)
  self.lsock
end

#_stream_read_local_write_remote(channel) ⇒ Object

Reads data from local input and writes it remotely.


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

def _stream_read_local_write_remote(channel)
  if raw
    data = user_input.sysread(1024)
  else
    data = user_input.gets
  end
  return if not data

  self.on_command_proc.call(data.strip) if self.on_command_proc
  self.write(data)
end

#_stream_read_remote_write_local(channel) ⇒ Object

Reads from the channel and writes locally.


91
92
93
94
95
96
97
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 91

def _stream_read_remote_write_local(channel)
  data = self.lsock.sysread(16384)

  self.on_print_proc.call(data.strip) if self.on_print_proc
  self.on_log_proc.call(data.strip) if self.on_log_proc
  user_output.print(data)
end

#_suspendObject

Suspends interaction with the channel.


52
53
54
55
56
57
58
59
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 52

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

#_winchObject


109
110
111
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 109

def _winch
  update_term_size
end

#set_term_size(rows, columns) ⇒ Object


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

def set_term_size(rows, columns)
  if self.cid.nil?
    raise IOError, 'Channel has been closed.', caller
  end

  request = Packet.create_request(Extensions::Stdapi::COMMAND_ID_STDAPI_SYS_PROCESS_SET_TERM_SIZE)
  request.add_tlv(TLV_TYPE_CHANNEL_ID, self.cid)
  request.add_tlv(Extensions::Stdapi::TLV_TYPE_TERMINAL_ROWS, rows)
  request.add_tlv(Extensions::Stdapi::TLV_TYPE_TERMINAL_COLUMNS, columns)
  self.client.send_packet(request)
end

#update_term_sizeObject


113
114
115
116
117
118
119
120
121
# File 'lib/rex/post/meterpreter/ui/console/interactive_channel.rb', line 113

def update_term_size
  return unless self.client.commands.include?(Extensions::Stdapi::COMMAND_ID_STDAPI_SYS_PROCESS_SET_TERM_SIZE)
  rows, cols = ::IO.console.winsize
  unless rows == self.rows && cols == self.cols
    set_term_size(rows, cols)
    self.rows = rows
    self.cols = cols
  end
end