Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/post/meterpreter/channel.rb
Views: 11784
# -*- coding: binary -*-12require 'rex/post/meterpreter/inbound_packet_handler'34module Rex5module Post6module Meterpreter78#9# The various types of channels10#11CHANNEL_CLASS_STREAM = 112CHANNEL_CLASS_DATAGRAM = 213CHANNEL_CLASS_POOL = 31415#16# The various flags that can affect how the channel operates17#18# CHANNEL_FLAG_SYNCHRONOUS19# Specifies that I/O requests on the channel are blocking.20#21# CHANNEL_FLAG_COMPRESS22# Specifies that I/O requests on the channel have their data zlib compressed.23#24CHANNEL_FLAG_SYNCHRONOUS = (1 << 0)25CHANNEL_FLAG_COMPRESS = (1 << 1)2627#28# The core types of direct I/O requests29#30CHANNEL_DIO_READ = 'read'31CHANNEL_DIO_WRITE = 'write'32CHANNEL_DIO_CLOSE = 'close'3334###35#36# The channel class represents a logical data pipe that exists between the37# client and the server. The purpose and behavior of the channel depends on38# which type it is. The three basic types of channels are streams, datagrams,39# and pools. Streams are basically equivalent to a TCP connection.40# Bidirectional, connection-oriented streams. Datagrams are basically41# equivalent to a UDP session. Bidirectional, connectionless. Pools are42# basically equivalent to a uni-directional connection, like a file handle.43# Pools denote channels that only have requests flowing in one direction.44#45###46class Channel47# Class modifications to support global channel message48# dispatching without having to register a per-instance handler49class << self50include Rex::Post::Meterpreter::InboundPacketHandler5152# Class request handler for all channels that dispatches requests53# to the appropriate class instance's DIO handler54def request_handler(client, packet)55cid = packet.get_tlv_value(TLV_TYPE_CHANNEL_ID)5657# No channel identifier, then drop it58if cid.nil?59return false60end6162channel = client.find_channel(cid)6364# No valid channel context? The channel may not be registered yet65if channel.nil?66return false67end686970dio = channel.dio_map(packet.method)7172# Supported DIO request? Dump it.73if dio.nil?74return true75end767778# Call the channel's dio handler and return success or fail79# based on what happens80channel.dio_handler(dio, packet)81end82end8384##85#86# Factory87#88##8990#91# Creates a logical channel between the client and the server92# based on a given type.93#94def Channel.create(client, type = nil, klass = nil,95flags = CHANNEL_FLAG_SYNCHRONOUS, addends = nil, **klass_kwargs)96request = Packet.create_request(COMMAND_ID_CORE_CHANNEL_OPEN)9798# Set the type of channel that we're allocating99if !type.nil?100request.add_tlv(TLV_TYPE_CHANNEL_TYPE, type)101end102103# If no factory class was provided, use the default native class104if klass.nil?105klass = self106end107108request.add_tlv(TLV_TYPE_CHANNEL_CLASS, klass.cls)109request.add_tlv(TLV_TYPE_FLAGS, flags)110request.add_tlvs(addends)111112# Transmit the request and wait for the response113cid = nil114begin115response = client.send_request(request)116cid = response.get_tlv_value(TLV_TYPE_CHANNEL_ID)117if cid.nil?118raise Rex::Post::Meterpreter::RequestError119end120end121122# Create the channel instance123klass.new(client, cid, type, flags, response, **klass_kwargs)124end125126##127#128# Constructor129#130##131132#133# Initializes the instance's attributes, such as client context,134# class identifier, type, and flags.135#136def initialize(client, cid, type, flags, packet, **_)137self.client = client138self.cid = cid139self.type = type140self.flags = flags141@mutex = Mutex.new142143# Add this instance to the list144if (cid and client)145client.add_channel(self)146end147148# Ensure the remote object is closed when all references are removed149ObjectSpace.define_finalizer(self, self.class.finalize(client, cid))150end151152def self.finalize(client, cid)153proc {154unless cid.nil?155deferred_close_proc = proc do156begin157self._close(client, cid)158rescue => e159elog("finalize method for Channel failed", error: e)160end161end162163# Schedule the finalizing logic out-of-band; as this logic might be called in the context of a Signal.trap, which can't synchronize mutexes164client.framework.sessions.schedule(deferred_close_proc)165end166}167end168169170##171#172# Channel interaction173#174##175176#177# Wrapper around the low-level channel read operation.178#179def read(length = nil, addends = nil)180return _read(length, addends)181end182183#184# Reads data from the remote half of the channel.185#186def _read(length = nil, addends = nil)187if self.cid.nil?188raise IOError, "Channel has been closed.", caller189end190191request = Packet.create_request(COMMAND_ID_CORE_CHANNEL_READ)192193if length.nil?194# Default block size to a higher amount for passive dispatcher195length = self.client.passive_service ? (1024*1024) : 65536196end197198request.add_tlv(TLV_TYPE_CHANNEL_ID, self.cid)199request.add_tlv(TLV_TYPE_LENGTH, length)200request.add_tlvs(addends)201202begin203response = self.client.send_request(request)204rescue205return nil206end207208# If the channel is in synchronous mode, the response should contain209# data that was read from the remote side of the channel210if (flag?(CHANNEL_FLAG_SYNCHRONOUS))211data = response.get_tlv(TLV_TYPE_CHANNEL_DATA);212213if (data != nil)214return data.value215end216else217raise NotImplementedError, "Asynchronous channel mode is not implemented", caller218end219220return nil221end222223#224# Wrapper around the low-level write.225#226def write(buf, length = nil, addends = nil)227return _write(buf, length, addends)228end229230#231# Writes data to the remote half of the channel.232#233def _write(buf, length = nil, addends = nil)234if self.cid.nil?235raise IOError, "Channel has been closed.", caller236end237238request = Packet.create_request(COMMAND_ID_CORE_CHANNEL_WRITE)239240# Truncation and celebration241if ((length != nil) &&242(buf.length >= length))243buf = buf[0..length]244else245length = buf.length246end247248# Populate the request249request.add_tlv(TLV_TYPE_CHANNEL_ID, self.cid)250251cdata = request.add_tlv(TLV_TYPE_CHANNEL_DATA, buf)252if( ( self.flags & CHANNEL_FLAG_COMPRESS ) == CHANNEL_FLAG_COMPRESS )253cdata.compress = true254end255256request.add_tlv(TLV_TYPE_LENGTH, length)257request.add_tlvs(addends)258259response = self.client.send_request(request)260written = response.get_tlv(TLV_TYPE_LENGTH)261262written.nil? ? 0 : written.value263end264265#266# Wrapper around check for self.cid267#268def closed?269self.cid.nil?270end271272#273# Wrapper around the low-level close.274#275def close(addends = nil)276return _close(addends)277end278279#280# Close the channel for future writes.281#282def close_write283return _close284end285286#287# Close the channel for future reads.288#289def close_read290return _close291end292293#294# Closes the channel.295#296def self._close(client, cid, addends=nil)297if cid.nil?298raise IOError, "Channel has been closed.", caller299end300301request = Packet.create_request(COMMAND_ID_CORE_CHANNEL_CLOSE)302303# Populate the request304request.add_tlv(TLV_TYPE_CHANNEL_ID, cid)305request.add_tlvs(addends)306307client.send_request(request, nil)308309# Disassociate this channel instance310client.remove_channel(cid)311312return true313end314315def _close(addends = nil)316# let the finalizer do the work behind the scenes317@mutex.synchronize {318unless self.cid.nil?319ObjectSpace.undefine_finalizer(self)320self.class._close(self.client, self.cid, addends)321self.cid = nil322end323}324end325#326# Enables or disables interactive mode.327#328def interactive(tf = true, addends = nil)329if self.cid.nil?330raise IOError, "Channel has been closed.", caller331end332333request = Packet.create_request(COMMAND_ID_CORE_CHANNEL_INTERACT)334335# Populate the request336request.add_tlv(TLV_TYPE_CHANNEL_ID, self.cid)337request.add_tlv(TLV_TYPE_BOOL, tf)338request.add_tlvs(addends)339340self.client.send_request(request)341342return true343end344345##346#347# Direct I/O348#349##350351#352# Handles dispatching I/O requests based on the request packet.353# The default implementation does nothing with direct I/O requests.354#355def dio_handler(dio, packet)356if (dio == CHANNEL_DIO_READ)357length = packet.get_tlv_value(TLV_TYPE_LENGTH)358359return dio_read_handler(packet, length)360elsif (dio == CHANNEL_DIO_WRITE)361data = packet.get_tlv_value(TLV_TYPE_CHANNEL_DATA)362363return dio_write_handler(packet, data)364elsif (dio == CHANNEL_DIO_CLOSE)365return dio_close_handler(packet)366end367return false;368end369370#371# Stub read handler.372#373def dio_read_handler(packet, length)374return true375end376377#378# Stub write handler.379#380def dio_write_handler(packet, data)381return true382end383384#385# Stub close handler.386#387def dio_close_handler(packet)388temp_cid = nil389@mutex.synchronize {390temp_cid = self.cid391self.cid = nil392}393client.remove_channel(temp_cid)394395# Trap IOErrors as parts of the channel may have already been closed396begin397self.cleanup398rescue IOError399end400401return true402end403404#405# Maps packet request methods to DIO request identifiers on a406# per-instance basis as other instances may add custom dio407# handlers.408#409def dio_map(command_id)410if command_id == COMMAND_ID_CORE_CHANNEL_READ411return CHANNEL_DIO_READ412elsif command_id == COMMAND_ID_CORE_CHANNEL_WRITE413return CHANNEL_DIO_WRITE414elsif command_id == COMMAND_ID_CORE_CHANNEL_CLOSE415return CHANNEL_DIO_CLOSE416end417418return nil419end420421##422#423# Conditionals424#425##426427#428# Checks to see if a flag is set on the instance's flags attribute.429#430def flag?(flag)431return ((self.flags & flag) == flag)432end433434#435# Returns whether or not the channel is operating synchronously.436#437def synchronous?438return (self.flags & CHANNEL_FLAG_SYNCHRONOUS)439end440441#442# The unique channel identifier.443#444attr_reader :cid445#446# The type of channel.447#448attr_reader :type449#450# The class of channel (stream, datagram, pool).451#452attr_reader :cls453#454# Any channel-specific flag, like synchronous IO.455#456attr_reader :flags457#458# Any channel-specific parameters.459#460attr_accessor :params461#462# The associated meterpreter client instance463#464attr_accessor :client465protected466467468attr_writer :cid, :type, :cls, :flags # :nodoc:469470#471# Cleans up any lingering resources472#473def cleanup474end475476end477478end; end; end479480481