Parent

Class/Module Index [+]

Quicksearch

Rex::Post::Meterpreter::Channel

The channel class represents a logical data pipe that exists between the client and the server. The purpose and behavior of the channel depends on which type it is. The three basic types of channels are streams, datagrams, and pools. Streams are basically equivalent to a TCP connection. Bidirectional, connection-oriented streams. Datagrams are basically equivalent to a UDP session. Bidirectional, connectionless. Pools are basically equivalent to a uni-directional connection, like a file handle. Pools denote channels that only have requests flowing in one direction.

Attributes

cid[R]

The unique channel identifier.

client[RW]

The associated meterpreter client instance

cls[R]

The class of channel (stream, datagram, pool).

flags[R]

Any channel-specific flag, like synchronous IO.

params[RW]

Any channel-specific parameters.

type[R]

The type of channel.

Public Class Methods

_close(client, cid, addends=nil) click to toggle source

Closes the channel.

# File lib/rex/post/meterpreter/channel.rb, line 270
def self._close(client, cid, addends=nil)
        if (cid == nil)
                raise IOError, "Channel has been closed.", caller
        end

        request = Packet.create_request('core_channel_close')

        # Populate the request
        request.add_tlv(TLV_TYPE_CHANNEL_ID, cid)
        request.add_tlvs(addends)

        client.send_request(request, nil)

        # Disassociate this channel instance
        client.remove_channel(cid)

        return true
end
create(client, type = nil, klass = nil, flags = CHANNEL_FLAG_SYNCHRONOUS, addends = nil) click to toggle source

Creates a logical channel between the client and the server based on a given type.

# File lib/rex/post/meterpreter/channel.rb, line 95
def Channel.create(client, type = nil, klass = nil,
                flags = CHANNEL_FLAG_SYNCHRONOUS, addends = nil)
        request = Packet.create_request('core_channel_open')

        # Set the type of channel that we're allocating
        if (type != nil)
                request.add_tlv(TLV_TYPE_CHANNEL_TYPE, type)
        end

        # If no factory class was provided, use the default native class
        if (klass == nil)
                klass = self
        end

        request.add_tlv(TLV_TYPE_CHANNEL_CLASS, klass.cls)
        request.add_tlv(TLV_TYPE_FLAGS, flags)
        request.add_tlvs(addends);

        # Transmit the request and wait for the response
        response = client.send_request(request)
        cid      = response.get_tlv(TLV_TYPE_CHANNEL_ID).value

        # Create the channel instance
        channel  = klass.new(client, cid, type, flags)

        return channel
end
finalize(client,cid) click to toggle source
# File lib/rex/post/meterpreter/channel.rb, line 146
def self.finalize(client,cid)
        proc { self._close(client,cid) }
end
new(client, cid, type, flags) click to toggle source

Initializes the instance's attributes, such as client context, class identifier, type, and flags.

# File lib/rex/post/meterpreter/channel.rb, line 133
def initialize(client, cid, type, flags)
        self.client = client
        self.cid    = cid
        self.type   = type
        self.flags  = flags

        # Add this instance to the list
        if (cid and client)
                client.add_channel(self)
        end
        ObjectSpace.define_finalizer( self, self.class.finalize(self.client, self.cid) )
end
request_handler(client, packet) click to toggle source

Class request handler for all channels that dispatches requests to the appropriate class instance's DIO handler

# File lib/rex/post/meterpreter/channel.rb, line 55
def request_handler(client, packet)
        cid = packet.get_tlv_value(TLV_TYPE_CHANNEL_ID)

        # No channel identifier, then drop it
        if (cid == nil)
                return false
        end

        channel = client.find_channel(cid)

        # No valid channel context? The channel may not be registered yet
        if (channel == nil)
                return false
        end


        dio = channel.dio_map(packet.method)

        # Supported DIO request? Dump it.
        if (dio == nil)
                return true
        end


        # Call the channel's dio handler and return success or fail
        # based on what happens
        channel.dio_handler(dio, packet)
end

Public Instance Methods

_close(addends = nil) click to toggle source
# File lib/rex/post/meterpreter/channel.rb, line 289
def _close(addends = nil)
        self.class._close(self.client, self.cid, addends)
        self.cid = nil
end
_read(length = nil, addends = nil) click to toggle source

Reads data from the remote half of the channel.

# File lib/rex/post/meterpreter/channel.rb, line 166
def _read(length = nil, addends = nil)
        if (self.cid == nil)
                raise IOError, "Channel has been closed.", caller
        end

        request = Packet.create_request('core_channel_read')

        if (length == nil)
                # Default block size to a higher amount for passive dispatcher
                length = self.client.passive_service ? (1024*1024) : 65536
        end

        request.add_tlv(TLV_TYPE_CHANNEL_ID, self.cid)
        request.add_tlv(TLV_TYPE_LENGTH, length)
        request.add_tlvs(addends)

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

        # If the channel is in synchronous mode, the response should contain
        # data that was read from the remote side of the channel
        if (flag?(CHANNEL_FLAG_SYNCHRONOUS))
                data = response.get_tlv(TLV_TYPE_CHANNEL_DATA);

                if (data != nil)
                        return data.value
                end
        else
                raise NotImplementedError, "Asynchronous channel mode is not implemented", caller
        end

        return nil
end
_write(buf, length = nil, addends = nil) click to toggle source

Writes data to the remote half of the channel.

# File lib/rex/post/meterpreter/channel.rb, line 213
def _write(buf, length = nil, addends = nil)

        if (self.cid == nil)
                raise IOError, "Channel has been closed.", caller
        end

        request = Packet.create_request('core_channel_write')

        # Truncation and celebration
        if ((length != nil) &&
            (buf.length >= length))
                buf = buf[0..length]
        else
                length = buf.length
        end

        # Populate the request
        request.add_tlv(TLV_TYPE_CHANNEL_ID, self.cid)

        cdata = request.add_tlv(TLV_TYPE_CHANNEL_DATA, buf)
        if( ( self.flags & CHANNEL_FLAG_COMPRESS ) == CHANNEL_FLAG_COMPRESS )
                cdata.compress = true
        end

        request.add_tlv(TLV_TYPE_LENGTH, length)
        request.add_tlvs(addends)

        response = self.client.send_request(request)
        written  = response.get_tlv(TLV_TYPE_LENGTH)

        return (written == nil) ? 0 : written.value
end
close(addends = nil) click to toggle source

Wrapper around the low-level close.

# File lib/rex/post/meterpreter/channel.rb, line 249
def close(addends = nil)
        return _close(addends)
end
close_read() click to toggle source

Close the channel for future reads.

# File lib/rex/post/meterpreter/channel.rb, line 263
def close_read
        return _close
end
close_write() click to toggle source

Close the channel for future writes.

# File lib/rex/post/meterpreter/channel.rb, line 256
def close_write
        return _close
end
dio_close_handler(packet) click to toggle source

Stub close handler.

# File lib/rex/post/meterpreter/channel.rb, line 355
def dio_close_handler(packet)
        client.remove_channel(self.cid)

        # Trap IOErrors as parts of the channel may have already been closed
        begin
                self.cleanup
        rescue IOError
        end

        # No more channel action, foo.
        self.cid = nil

        return true
end
dio_handler(dio, packet) click to toggle source

Handles dispatching I/O requests based on the request packet. The default implementation does nothing with direct I/O requests.

# File lib/rex/post/meterpreter/channel.rb, line 323
def dio_handler(dio, packet)
        if (dio == CHANNEL_DIO_READ)
                length = packet.get_tlv_value(TLV_TYPE_LENGTH)

                return dio_read_handler(packet, length)
        elsif (dio == CHANNEL_DIO_WRITE)
                data = packet.get_tlv_value(TLV_TYPE_CHANNEL_DATA)

                return dio_write_handler(packet, data)
        elsif (dio == CHANNEL_DIO_CLOSE)
                return dio_close_handler(packet)
        end
        return false;
end
dio_map(method) click to toggle source

Maps packet request methods to DIO request identifiers on a per-instance basis as other instances may add custom dio handlers.

# File lib/rex/post/meterpreter/channel.rb, line 375
def dio_map(method)
        if (method == 'core_channel_read')
                return CHANNEL_DIO_READ
        elsif (method == 'core_channel_write')
                return CHANNEL_DIO_WRITE
        elsif (method == 'core_channel_close')
                return CHANNEL_DIO_CLOSE
        end

        return nil
end
dio_read_handler(packet, length) click to toggle source

Stub read handler.

# File lib/rex/post/meterpreter/channel.rb, line 341
def dio_read_handler(packet, length)
        return true
end
dio_write_handler(packet, data) click to toggle source

Stub write handler.

# File lib/rex/post/meterpreter/channel.rb, line 348
def dio_write_handler(packet, data)
        return true
end
flag?(flag) click to toggle source

Checks to see if a flag is set on the instance's flags attribute.

# File lib/rex/post/meterpreter/channel.rb, line 396
def flag?(flag)
        return ((self.flags & flag) == flag)
end
interactive(tf = true, addends = nil) click to toggle source

Enables or disables interactive mode.

# File lib/rex/post/meterpreter/channel.rb, line 296
def interactive(tf = true, addends = nil)
        if (self.cid == nil)
                raise IOError, "Channel has been closed.", caller
        end

        request = Packet.create_request('core_channel_interact')

        # Populate the request
        request.add_tlv(TLV_TYPE_CHANNEL_ID, self.cid)
        request.add_tlv(TLV_TYPE_BOOL, tf)
        request.add_tlvs(addends)

        self.client.send_request(request)

        return true
end
read(length = nil, addends = nil) click to toggle source

Wrapper around the low-level channel read operation.

# File lib/rex/post/meterpreter/channel.rb, line 159
def read(length = nil, addends = nil)
        return _read(length, addends)
end
synchronous?() click to toggle source

Returns whether or not the channel is operating synchronously.

# File lib/rex/post/meterpreter/channel.rb, line 403
def synchronous?
        return (self.flags & CHANNEL_FLAG_SYNCHRONOUS)
end
write(buf, length = nil, addends = nil) click to toggle source

Wrapper around the low-level write.

# File lib/rex/post/meterpreter/channel.rb, line 206
def write(buf, length = nil, addends = nil)
        return _write(buf, length, addends)
end

Protected Instance Methods

cleanup() click to toggle source

Cleans up any lingering resources

# File lib/rex/post/meterpreter/channel.rb, line 439
def cleanup
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.