161 lines
2.8 KiB
Ruby
161 lines
2.8 KiB
Ruby
#!/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
|
|
|