Class: Rex::Post::Meterpreter::Extensions::Stdapi::Net::SocketSubsystem::UdpChannel
- Inherits:
-
Channel
- Object
- Channel
- Rex::Post::Meterpreter::Extensions::Stdapi::Net::SocketSubsystem::UdpChannel
- Includes:
- Socket::Udp
- Defined in:
- lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb
Constant Summary
Constants included from Socket
Socket::MATCH_IPV4, Socket::MATCH_IPV4_PRIVATE, Socket::MATCH_IPV6
Instance Attribute Summary
Attributes included from Socket
#context, #ipv, #localhost, #localport, #peerhost, #peerport
Attributes inherited from Channel
#cid, #client, #cls, #flags, #params, #type
Class Method Summary collapse
- .cls ⇒ Object
-
.open(client, params) ⇒ Object
Open a new UDP channel on the remote end.
Instance Method Summary collapse
-
#_write(*args) ⇒ Object
Wrap the _write() call in order to catch some common, but harmless Windows exceptions.
-
#dio_write_handler(packet, data) ⇒ Object
The channels direct io write handler for any incoming data from the remote end of the channel.
-
#initialize(client, cid, type, flags) ⇒ UdpChannel
constructor
Simply initialize this instance.
-
#recvfrom(length = 65535, timeout = def_read_timeout) ⇒ Object
We overwrite Rex::Socket::Udp.recvfrom in order to correctly hand out the datagrams which the remote end of this channel has received and are in the queue.
-
#send(buf, flags, saddr) ⇒ Object
This function is called by Rex::Socket::Udp.sendto and writes data to a specified remote peer host/port via the remote end of the channel.
-
#sysread(length) ⇒ Object
Overwrite the low level sysread to read data off our datagram queue.
-
#syswrite(buf) ⇒ Object
Overwrite the low level syswrite to write data to the remote end of the channel.
-
#timed_read(length = 65535, timeout = def_read_timeout) ⇒ Object
We overwrite Rex::Socket::Udp.timed_read in order to avoid the call to Kernel.select which wont be of use as we are not a natively backed ::Socket or ::IO instance.
Methods included from Socket::Udp
create, create_param, #def_read_timeout, #get, #read, #sendto, #type?, #write
Methods included from Socket
addr_atoc, addr_atoi, addr_atoi_list, addr_aton, addr_ctoa, addr_itoa, addr_iton, addr_ntoa, addr_ntoi, bit2netmask, cidr_crack, compress_address, create, create_ip, create_param, create_tcp, create_tcp_server, create_udp, dotted_ip?, eth_aton, eth_ntoa, #fd, from_sockaddr, getaddress, getaddresses, gethostbyname, #getlocalname, #getpeername, #getsockname, #initsock, ipv6_link_address, ipv6_mac, is_internal?, is_ipv4?, is_ipv6?, net2bitmask, portlist_to_portspec, portspec_crack, portspec_to_portlist, resolv_nbo, resolv_nbo_i, resolv_nbo_i_list, resolv_nbo_list, resolv_to_dotted, source_address, support_ipv6?, tcp_socket_pair, to_sockaddr, #type?, udp_socket_pair
Methods inherited from Channel
#_close, _close, #_read, #close, #close_read, #close_write, create, #dio_close_handler, #dio_handler, #dio_map, #dio_read_handler, finalize, #flag?, #interactive, #read, request_handler, #synchronous?, #write
Methods included from InboundPacketHandler
#request_handler, #response_handler
Constructor Details
#initialize(client, cid, type, flags) ⇒ UdpChannel
Simply initialize this instance.
67 68 69 70 71 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb', line 67 def initialize(client, cid, type, flags) super(client, cid, type, flags) # the instance variable that holds all incoming datagrams. @datagrams = [] end |
Class Method Details
.cls ⇒ Object
28 29 30 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb', line 28 def cls return CHANNEL_CLASS_DATAGRAM end |
.open(client, params) ⇒ Object
Open a new UDP channel on the remote end. The local host/port are optional, if none are specified the remote end will bind to INADDR_ANY with a random port number. The peer host/port are also optional, if specified all default send(), write() call will sendto the specified peer. If no peer host/port is specified you must use sendto() and specify the remote peer you wish to send to. This effectivly lets us create bound/unbound and connected/unconnected UDP sockets with ease.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb', line 40 def UdpChannel.open(client, params) c = Channel.create(client, 'stdapi_net_udp_client', self, CHANNEL_FLAG_SYNCHRONOUS, [ { 'type' => TLV_TYPE_LOCAL_HOST, 'value' => params.localhost }, { 'type' => TLV_TYPE_LOCAL_PORT, 'value' => params.localport }, { 'type' => TLV_TYPE_PEER_HOST, 'value' => params.peerhost }, { 'type' => TLV_TYPE_PEER_PORT, 'value' => params.peerport } ] ) c.params = params c end |
Instance Method Details
#_write(*args) ⇒ Object
Wrap the _write() call in order to catch some common, but harmless Windows exceptions
194 195 196 197 198 199 200 201 202 203 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb', line 194 def _write(*args) begin super(*args) rescue ::Rex::Post::Meterpreter::RequestError => e case e.code when 10000 .. 10100 raise ::Rex::ConnectionError.new end end end |
#dio_write_handler(packet, data) ⇒ Object
The channels direct io write handler for any incoming data from the remote end of the channel. We extract the data and peer host/port, and save this to a queue of incoming datagrams which are passed out via calls to self.recvfrom()
178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb', line 178 def dio_write_handler( packet, data ) peerhost = packet.get_tlv_value( TLV_TYPE_PEER_HOST ) peerport = packet.get_tlv_value( TLV_TYPE_PEER_PORT ) if( peerhost and peerport ) @datagrams << [ data, peerhost, peerport ] return true end return false end |
#recvfrom(length = 65535, timeout = def_read_timeout) ⇒ Object
We overwrite Rex::Socket::Udp.recvfrom in order to correctly hand out the datagrams which the remote end of this channel has received and are in the queue.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb', line 103 def recvfrom( length=65535, timeout=def_read_timeout ) result = nil # force a timeout on the wait for an incoming datagram begin Timeout.timeout( timeout ) { while( true ) # wait untill we have at least one datagram in the queue if( @datagrams.empty? ) Rex::ThreadSafe.sleep( 0.2 ) next end # grab the oldest datagram we have received... result = @datagrams.shift # break as we have a result... break end } rescue Timeout::Error result = nil end # if no result return nothing if( result == nil ) return [ '', nil, nil ] end # get the data from this datagram data = result[0] # if its only a partial read of this datagram, slice it, loosing the remainder. result[0] = data[0,length-1] if data.length > length # return the result in the form [ data, host, port ] return result end |
#send(buf, flags, saddr) ⇒ Object
This function is called by Rex::Socket::Udp.sendto and writes data to a specified remote peer host/port via the remote end of the channel.
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb', line 156 def send( buf, flags, saddr ) af, peerhost, peerport = Rex::Socket.from_sockaddr( saddr ) addends = [ { 'type' => TLV_TYPE_PEER_HOST, 'value' => peerhost }, { 'type' => TLV_TYPE_PEER_PORT, 'value' => peerport } ] return _write( buf, buf.length, addends ) end |
#sysread(length) ⇒ Object
Overwrite the low level sysread to read data off our datagram queue. Calls to read() will end up calling this.
139 140 141 142 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb', line 139 def sysread( length ) result = self.recvfrom( length ) return result[0] end |
#syswrite(buf) ⇒ Object
Overwrite the low level syswrite to write data to the remote end of the channel. Calls to write() will end up calling this.
148 149 150 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb', line 148 def syswrite( buf ) return _write( buf ) end |
#timed_read(length = 65535, timeout = def_read_timeout) ⇒ Object
We overwrite Rex::Socket::Udp.timed_read in order to avoid the call to Kernel.select which wont be of use as we are not a natively backed ::Socket or ::IO instance.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb', line 77 def timed_read( length=65535, timeout=def_read_timeout ) result = '' begin Timeout.timeout( timeout ) { while( true ) if( @datagrams.empty? ) Rex::ThreadSafe.sleep( 0.2 ) next end result = self.read( length ) break end } rescue Timeout::Error result = '' end return result end |