Class: Rex::Post::Meterpreter::Channels::Pool

Inherits:
Rex::Post::Meterpreter::Channel show all
Defined in:
lib/rex/post/meterpreter/channels/pool.rb

Overview

This class acts as a base class for all channels that are classified as ‘pools’. This means that only one side of the channel, typically the client half, acts on the other half of the channel. Examples of pools come in the form of files where the remote side never sends any unrequested data.

Another key distinction of Pools is that they, in general, support the DIO mode ‘seek’ which allows for changing the position, or offset, into the channel.

Instance Attribute Summary collapse

Attributes inherited from Rex::Post::Meterpreter::Channel

#cid, #client, #cls, #flags, #params, #type

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Rex::Post::Meterpreter::Channel

#_close, _close, #_read, #_write, #cleanup, #close, #close_read, #close_write, #closed?, create, #dio_close_handler, #dio_handler, #dio_map, #dio_read_handler, #dio_write_handler, finalize, #flag?, #interactive, request_handler, #synchronous?, #write

Methods included from InboundPacketHandler

#request_handler, #response_handler

Constructor Details

#initialize(client, cid, type, flags, packet, **_) ⇒ Pool

Passes the initialization information up to the base class



40
41
42
# File 'lib/rex/post/meterpreter/channels/pool.rb', line 40

def initialize(client, cid, type, flags, packet, **_)
  super(client, cid, type, flags, packet)
end

Instance Attribute Details

#_eofObject (protected)

:nodoc:



154
155
156
# File 'lib/rex/post/meterpreter/channels/pool.rb', line 154

def _eof
  @_eof
end

Class Method Details

.clsObject



26
27
28
# File 'lib/rex/post/meterpreter/channels/pool.rb', line 26

def cls
  return CHANNEL_CLASS_POOL
end

Instance Method Details

#eofObject

Checks to see if the EOF flag has been set on the pool.



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/rex/post/meterpreter/channels/pool.rb', line 53

def eof
  request = Packet.create_request(COMMAND_ID_CORE_CHANNEL_EOF)

  request.add_tlv(TLV_TYPE_CHANNEL_ID, self.cid)

  begin
    response = self.client.send_request(request)
  rescue
    return true
  end

  if (response.has_tlv?(TLV_TYPE_BOOL))
    return response.get_tlv_value(TLV_TYPE_BOOL)
  end

  return false
end

#posObject

Synonym for tell.



126
127
128
# File 'lib/rex/post/meterpreter/channels/pool.rb', line 126

def pos
  tell
end

#read(length = nil) ⇒ Object

Reads data from the remote side of the pool and raises EOFError if the pool has been reached EOF.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/rex/post/meterpreter/channels/pool.rb', line 75

def read(length = nil)
  begin
    data = super(length)
  rescue
    data = nil
  end

  if (((data == nil) || (data.length == 0)) &&
      (self.eof))
    raise EOFError
  end

  return data
end

#seek(offset, whence = SEEK_SET) ⇒ Object

This method seeks to an offset within the remote side of the pool using the standard seek whence clauses.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/rex/post/meterpreter/channels/pool.rb', line 94

def seek(offset, whence = SEEK_SET)
  sane = 0

  # Just in case...
  case whence
    when ::IO::SEEK_SET
      sane = 0
    when ::IO::SEEK_CUR
      sane = 1
    when ::IO::SEEK_END
      sane = 2
    else
      raise RuntimeError, "Invalid seek whence #{whence}.", caller
  end

  request = Packet.create_request(COMMAND_ID_CORE_CHANNEL_SEEK)

  request.add_tlv(TLV_TYPE_CHANNEL_ID, self.cid)
  request.add_tlv(TLV_TYPE_SEEK_OFFSET, offset)
  request.add_tlv(TLV_TYPE_SEEK_WHENCE, sane)

  begin
    self.client.send_request(request)
    tell
  rescue
    return -1
  end
end

#tellObject

This method returns the current file pointer position to the caller.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/rex/post/meterpreter/channels/pool.rb', line 133

def tell
  request = Packet.create_request(COMMAND_ID_CORE_CHANNEL_TELL)
  pos     = -1

  request.add_tlv(TLV_TYPE_CHANNEL_ID, self.cid)

  begin
    response = self.client.send_request(request)
  rescue
    return pos
  end

  # Set the return value to the position that we're at
  if (response.has_tlv?(TLV_TYPE_SEEK_POS))
    pos = response.get_tlv_value(TLV_TYPE_SEEK_POS)
  end

  return pos
end