metasploit-framework/lib/rex/post/meterpreter/channels/pool.rb

160 lines
2.8 KiB
Ruby
Raw Normal View History

#!/usr/bin/env ruby
require 'rex/post/meterpreter/channel'
module Rex
module Post
module Meterpreter
module Channels
###
#
# 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.
#
###
class Pool < Rex::Post::Meterpreter::Channel
class <<self
def cls
return CHANNEL_CLASS_POOL
end
end
##
#
# Constructor
#
##
#
# Passes the initialization information up to the base class
#
def initialize(client, cid, type, flags)
super(client, cid, type, flags)
end
##
#
# Channel interaction
#
##
#
# Checks to see if the EOF flag has been set on the pool.
#
def eof
request = Packet.create_request('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
#
# Reads data from the remote side of the pool and raises EOFError if the
# pool has been reached EOF.
#
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
#
# This method seeks to an offset within the remote side of the pool using
# the standard seek whence clauses.
#
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('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
response = self.client.send_request(request)
rescue
return -1
end
return tell
end
#
# Synonym for tell.
#
def pos
return tell
end
#
# This method returns the current file pointer position to the caller.
#
def tell
request = Packet.create_request('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
protected
attr_accessor :_eof # :nodoc:
end
end; end; end; end