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

152 lines
3.5 KiB
Ruby
Raw Normal View History

Implement consistent socket abstraction In current nomenclature, Rex Sockets are objects created by calls to Rex::Socket::<Transport>.create and Rex::Socket.create_... When the LocalHost or Comm parameters are set to remotely routed addresses (currently via Meterpreter sessions), Rex will create a Channel which will abstract communications with the remote end of the session. These channel based abstractions are called pivots, and present in three separate flavors: 1 - TcpClientChannel, a fully abstracted, selectable Socket. 2 - TcpServerChannel, a virtual Channel which distributes client channels. 3 - UdpChannel, a virtual Channel which provides common methods for UDP socket operations, but is not a full (selectable) abstraction. Unfortunately this differentiation results in inconsistent returns from the aforementioned socket creation calls, as the call chain creates parameters and supplies them to the create method on the comm object referenced in the params. The comm object may be a channel, and produce a virtual representation of a socket with functional methods analogous to Sockets, but without a kernel FD. This commit begins the work of ensuring that all calls for socket creation return selectable Rex::Socket objects with semantics familiar to Ruby developers who have not read into the details of Rex::Socket and Rex::Post. ----- Summary of changes: Convert Rex::IO::StreamAbstraction to SocketAbstraction and use the new mixin in StreamAbstraction and DatagramAbstraction. This approach allows for common methods to reuse the abstraction data flow, while initializing separate types of socket obects and an optional monitor as needed. In the Rex::Post::Meterpreter namespace, extract common methods from Stream to a SocketAbstraction mixin, include that mixin in Stream, and add Datagram with the dio_write handler override exported from the current implementation of UdpChannel, also using the mixin. This relies on the Rex::IO work above to implement the proper type of socket abstraction to the Channel descendants. In Rex::Post::Meterpreter::Extensions::Stdapi::Net, convert the UdpChannel to inherit from the Rex::Post::Meterpreter::Datagram class, implementing only the send method at this tier. Convert create_udp_channel to return the local socket side of the datagram abstraction presented analogous to the TcpClientChannel approach used before. ----- Notes and intricacies: In order to implement recvfrom on the UDP abstraction, a shim layer has been put in place to forward the sockaddr information from the remote peer to the local UDP socketpair in the abstraction. This information takes up buffer space in the UDP socket, and in order to maintain compatibility with consumers, the dio_write_handler pushes the data buffer, and in a separate send call, he sockaddr information from the remote socket. On the abstraction side, the recvfrom_nonblock call of the real UDPSocket has been overriden via the mixed in module to call the real method twice, once for the data buffer, and once for the packed sockaddr data. The Rex level consumer for recvfrom calls the underlying nonblock method and expects this exact set of returns (as opposed to what standard library UDPSocket.recvfrom returns, which is a data buffer and an Array of sockaddr data). ----- Testing: Local and lab testing only so far. Test RC script to be added in GH comments. ----- Issues: Currently, sendto on a remote socket does not appear to honor LocalPort which causes DNS responses (#6611) to come from the wrong port to remote clients being serviced over a pivot socket.
2016-03-21 04:53:34 +00:00
# -*- coding: binary -*-
# require 'rex/io/socket_abstraction'
require 'rex/post/meterpreter/channel'
module Rex
module Post
module Meterpreter
###
#
# Abstraction
# ------
#
# This class represents a channel that is streaming. This means
# that sequential data is flowing in either one or both directions.
#
###
module SocketAbstraction
module SocketInterface
include Rex::Socket
Implement consistent socket abstraction In current nomenclature, Rex Sockets are objects created by calls to Rex::Socket::<Transport>.create and Rex::Socket.create_... When the LocalHost or Comm parameters are set to remotely routed addresses (currently via Meterpreter sessions), Rex will create a Channel which will abstract communications with the remote end of the session. These channel based abstractions are called pivots, and present in three separate flavors: 1 - TcpClientChannel, a fully abstracted, selectable Socket. 2 - TcpServerChannel, a virtual Channel which distributes client channels. 3 - UdpChannel, a virtual Channel which provides common methods for UDP socket operations, but is not a full (selectable) abstraction. Unfortunately this differentiation results in inconsistent returns from the aforementioned socket creation calls, as the call chain creates parameters and supplies them to the create method on the comm object referenced in the params. The comm object may be a channel, and produce a virtual representation of a socket with functional methods analogous to Sockets, but without a kernel FD. This commit begins the work of ensuring that all calls for socket creation return selectable Rex::Socket objects with semantics familiar to Ruby developers who have not read into the details of Rex::Socket and Rex::Post. ----- Summary of changes: Convert Rex::IO::StreamAbstraction to SocketAbstraction and use the new mixin in StreamAbstraction and DatagramAbstraction. This approach allows for common methods to reuse the abstraction data flow, while initializing separate types of socket obects and an optional monitor as needed. In the Rex::Post::Meterpreter namespace, extract common methods from Stream to a SocketAbstraction mixin, include that mixin in Stream, and add Datagram with the dio_write handler override exported from the current implementation of UdpChannel, also using the mixin. This relies on the Rex::IO work above to implement the proper type of socket abstraction to the Channel descendants. In Rex::Post::Meterpreter::Extensions::Stdapi::Net, convert the UdpChannel to inherit from the Rex::Post::Meterpreter::Datagram class, implementing only the send method at this tier. Convert create_udp_channel to return the local socket side of the datagram abstraction presented analogous to the TcpClientChannel approach used before. ----- Notes and intricacies: In order to implement recvfrom on the UDP abstraction, a shim layer has been put in place to forward the sockaddr information from the remote peer to the local UDP socketpair in the abstraction. This information takes up buffer space in the UDP socket, and in order to maintain compatibility with consumers, the dio_write_handler pushes the data buffer, and in a separate send call, he sockaddr information from the remote socket. On the abstraction side, the recvfrom_nonblock call of the real UDPSocket has been overriden via the mixed in module to call the real method twice, once for the data buffer, and once for the packed sockaddr data. The Rex level consumer for recvfrom calls the underlying nonblock method and expects this exact set of returns (as opposed to what standard library UDPSocket.recvfrom returns, which is a data buffer and an Array of sockaddr data). ----- Testing: Local and lab testing only so far. Test RC script to be added in GH comments. ----- Issues: Currently, sendto on a remote socket does not appear to honor LocalPort which causes DNS responses (#6611) to come from the wrong port to remote clients being serviced over a pivot socket.
2016-03-21 04:53:34 +00:00
def getsockname
return super if not channel
# Find the first host in our chain (our address)
hops = 0
csock = channel.client.sock
while(csock.respond_to?('channel'))
csock = csock.channel.client.sock
hops += 1
end
2016-03-23 20:07:00 +00:00
_address_family,caddr,_cport = csock.getsockname
2016-06-22 19:54:00 +00:00
address_family,raddr,_rport = csock.getpeername_as_array
2016-03-23 20:07:00 +00:00
_maddr,mport = [ channel.params.localhost, channel.params.localport ]
[ address_family, "#{caddr}#{(hops > 0) ? "-_#{hops}_" : ""}-#{raddr}", "#{mport}" ]
Implement consistent socket abstraction In current nomenclature, Rex Sockets are objects created by calls to Rex::Socket::<Transport>.create and Rex::Socket.create_... When the LocalHost or Comm parameters are set to remotely routed addresses (currently via Meterpreter sessions), Rex will create a Channel which will abstract communications with the remote end of the session. These channel based abstractions are called pivots, and present in three separate flavors: 1 - TcpClientChannel, a fully abstracted, selectable Socket. 2 - TcpServerChannel, a virtual Channel which distributes client channels. 3 - UdpChannel, a virtual Channel which provides common methods for UDP socket operations, but is not a full (selectable) abstraction. Unfortunately this differentiation results in inconsistent returns from the aforementioned socket creation calls, as the call chain creates parameters and supplies them to the create method on the comm object referenced in the params. The comm object may be a channel, and produce a virtual representation of a socket with functional methods analogous to Sockets, but without a kernel FD. This commit begins the work of ensuring that all calls for socket creation return selectable Rex::Socket objects with semantics familiar to Ruby developers who have not read into the details of Rex::Socket and Rex::Post. ----- Summary of changes: Convert Rex::IO::StreamAbstraction to SocketAbstraction and use the new mixin in StreamAbstraction and DatagramAbstraction. This approach allows for common methods to reuse the abstraction data flow, while initializing separate types of socket obects and an optional monitor as needed. In the Rex::Post::Meterpreter namespace, extract common methods from Stream to a SocketAbstraction mixin, include that mixin in Stream, and add Datagram with the dio_write handler override exported from the current implementation of UdpChannel, also using the mixin. This relies on the Rex::IO work above to implement the proper type of socket abstraction to the Channel descendants. In Rex::Post::Meterpreter::Extensions::Stdapi::Net, convert the UdpChannel to inherit from the Rex::Post::Meterpreter::Datagram class, implementing only the send method at this tier. Convert create_udp_channel to return the local socket side of the datagram abstraction presented analogous to the TcpClientChannel approach used before. ----- Notes and intricacies: In order to implement recvfrom on the UDP abstraction, a shim layer has been put in place to forward the sockaddr information from the remote peer to the local UDP socketpair in the abstraction. This information takes up buffer space in the UDP socket, and in order to maintain compatibility with consumers, the dio_write_handler pushes the data buffer, and in a separate send call, he sockaddr information from the remote socket. On the abstraction side, the recvfrom_nonblock call of the real UDPSocket has been overriden via the mixed in module to call the real method twice, once for the data buffer, and once for the packed sockaddr data. The Rex level consumer for recvfrom calls the underlying nonblock method and expects this exact set of returns (as opposed to what standard library UDPSocket.recvfrom returns, which is a data buffer and an Array of sockaddr data). ----- Testing: Local and lab testing only so far. Test RC script to be added in GH comments. ----- Issues: Currently, sendto on a remote socket does not appear to honor LocalPort which causes DNS responses (#6611) to come from the wrong port to remote clients being serviced over a pivot socket.
2016-03-21 04:53:34 +00:00
end
def getpeername
return super if not channel
maddr,mport = [ channel.params.peerhost, channel.params.peerport ]
::Socket.sockaddr_in(mport, maddr)
Implement consistent socket abstraction In current nomenclature, Rex Sockets are objects created by calls to Rex::Socket::<Transport>.create and Rex::Socket.create_... When the LocalHost or Comm parameters are set to remotely routed addresses (currently via Meterpreter sessions), Rex will create a Channel which will abstract communications with the remote end of the session. These channel based abstractions are called pivots, and present in three separate flavors: 1 - TcpClientChannel, a fully abstracted, selectable Socket. 2 - TcpServerChannel, a virtual Channel which distributes client channels. 3 - UdpChannel, a virtual Channel which provides common methods for UDP socket operations, but is not a full (selectable) abstraction. Unfortunately this differentiation results in inconsistent returns from the aforementioned socket creation calls, as the call chain creates parameters and supplies them to the create method on the comm object referenced in the params. The comm object may be a channel, and produce a virtual representation of a socket with functional methods analogous to Sockets, but without a kernel FD. This commit begins the work of ensuring that all calls for socket creation return selectable Rex::Socket objects with semantics familiar to Ruby developers who have not read into the details of Rex::Socket and Rex::Post. ----- Summary of changes: Convert Rex::IO::StreamAbstraction to SocketAbstraction and use the new mixin in StreamAbstraction and DatagramAbstraction. This approach allows for common methods to reuse the abstraction data flow, while initializing separate types of socket obects and an optional monitor as needed. In the Rex::Post::Meterpreter namespace, extract common methods from Stream to a SocketAbstraction mixin, include that mixin in Stream, and add Datagram with the dio_write handler override exported from the current implementation of UdpChannel, also using the mixin. This relies on the Rex::IO work above to implement the proper type of socket abstraction to the Channel descendants. In Rex::Post::Meterpreter::Extensions::Stdapi::Net, convert the UdpChannel to inherit from the Rex::Post::Meterpreter::Datagram class, implementing only the send method at this tier. Convert create_udp_channel to return the local socket side of the datagram abstraction presented analogous to the TcpClientChannel approach used before. ----- Notes and intricacies: In order to implement recvfrom on the UDP abstraction, a shim layer has been put in place to forward the sockaddr information from the remote peer to the local UDP socketpair in the abstraction. This information takes up buffer space in the UDP socket, and in order to maintain compatibility with consumers, the dio_write_handler pushes the data buffer, and in a separate send call, he sockaddr information from the remote socket. On the abstraction side, the recvfrom_nonblock call of the real UDPSocket has been overriden via the mixed in module to call the real method twice, once for the data buffer, and once for the packed sockaddr data. The Rex level consumer for recvfrom calls the underlying nonblock method and expects this exact set of returns (as opposed to what standard library UDPSocket.recvfrom returns, which is a data buffer and an Array of sockaddr data). ----- Testing: Local and lab testing only so far. Test RC script to be added in GH comments. ----- Issues: Currently, sendto on a remote socket does not appear to honor LocalPort which causes DNS responses (#6611) to come from the wrong port to remote clients being serviced over a pivot socket.
2016-03-21 04:53:34 +00:00
end
2016-03-23 20:06:35 +00:00
%i{localhost localport peerhost peerport}.map do |meth|
define_method(meth) {
Implement consistent socket abstraction In current nomenclature, Rex Sockets are objects created by calls to Rex::Socket::<Transport>.create and Rex::Socket.create_... When the LocalHost or Comm parameters are set to remotely routed addresses (currently via Meterpreter sessions), Rex will create a Channel which will abstract communications with the remote end of the session. These channel based abstractions are called pivots, and present in three separate flavors: 1 - TcpClientChannel, a fully abstracted, selectable Socket. 2 - TcpServerChannel, a virtual Channel which distributes client channels. 3 - UdpChannel, a virtual Channel which provides common methods for UDP socket operations, but is not a full (selectable) abstraction. Unfortunately this differentiation results in inconsistent returns from the aforementioned socket creation calls, as the call chain creates parameters and supplies them to the create method on the comm object referenced in the params. The comm object may be a channel, and produce a virtual representation of a socket with functional methods analogous to Sockets, but without a kernel FD. This commit begins the work of ensuring that all calls for socket creation return selectable Rex::Socket objects with semantics familiar to Ruby developers who have not read into the details of Rex::Socket and Rex::Post. ----- Summary of changes: Convert Rex::IO::StreamAbstraction to SocketAbstraction and use the new mixin in StreamAbstraction and DatagramAbstraction. This approach allows for common methods to reuse the abstraction data flow, while initializing separate types of socket obects and an optional monitor as needed. In the Rex::Post::Meterpreter namespace, extract common methods from Stream to a SocketAbstraction mixin, include that mixin in Stream, and add Datagram with the dio_write handler override exported from the current implementation of UdpChannel, also using the mixin. This relies on the Rex::IO work above to implement the proper type of socket abstraction to the Channel descendants. In Rex::Post::Meterpreter::Extensions::Stdapi::Net, convert the UdpChannel to inherit from the Rex::Post::Meterpreter::Datagram class, implementing only the send method at this tier. Convert create_udp_channel to return the local socket side of the datagram abstraction presented analogous to the TcpClientChannel approach used before. ----- Notes and intricacies: In order to implement recvfrom on the UDP abstraction, a shim layer has been put in place to forward the sockaddr information from the remote peer to the local UDP socketpair in the abstraction. This information takes up buffer space in the UDP socket, and in order to maintain compatibility with consumers, the dio_write_handler pushes the data buffer, and in a separate send call, he sockaddr information from the remote socket. On the abstraction side, the recvfrom_nonblock call of the real UDPSocket has been overriden via the mixed in module to call the real method twice, once for the data buffer, and once for the packed sockaddr data. The Rex level consumer for recvfrom calls the underlying nonblock method and expects this exact set of returns (as opposed to what standard library UDPSocket.recvfrom returns, which is a data buffer and an Array of sockaddr data). ----- Testing: Local and lab testing only so far. Test RC script to be added in GH comments. ----- Issues: Currently, sendto on a remote socket does not appear to honor LocalPort which causes DNS responses (#6611) to come from the wrong port to remote clients being serviced over a pivot socket.
2016-03-21 04:53:34 +00:00
return super if not channel
2016-03-23 20:06:35 +00:00
channel.params.send(meth)
Implement consistent socket abstraction In current nomenclature, Rex Sockets are objects created by calls to Rex::Socket::<Transport>.create and Rex::Socket.create_... When the LocalHost or Comm parameters are set to remotely routed addresses (currently via Meterpreter sessions), Rex will create a Channel which will abstract communications with the remote end of the session. These channel based abstractions are called pivots, and present in three separate flavors: 1 - TcpClientChannel, a fully abstracted, selectable Socket. 2 - TcpServerChannel, a virtual Channel which distributes client channels. 3 - UdpChannel, a virtual Channel which provides common methods for UDP socket operations, but is not a full (selectable) abstraction. Unfortunately this differentiation results in inconsistent returns from the aforementioned socket creation calls, as the call chain creates parameters and supplies them to the create method on the comm object referenced in the params. The comm object may be a channel, and produce a virtual representation of a socket with functional methods analogous to Sockets, but without a kernel FD. This commit begins the work of ensuring that all calls for socket creation return selectable Rex::Socket objects with semantics familiar to Ruby developers who have not read into the details of Rex::Socket and Rex::Post. ----- Summary of changes: Convert Rex::IO::StreamAbstraction to SocketAbstraction and use the new mixin in StreamAbstraction and DatagramAbstraction. This approach allows for common methods to reuse the abstraction data flow, while initializing separate types of socket obects and an optional monitor as needed. In the Rex::Post::Meterpreter namespace, extract common methods from Stream to a SocketAbstraction mixin, include that mixin in Stream, and add Datagram with the dio_write handler override exported from the current implementation of UdpChannel, also using the mixin. This relies on the Rex::IO work above to implement the proper type of socket abstraction to the Channel descendants. In Rex::Post::Meterpreter::Extensions::Stdapi::Net, convert the UdpChannel to inherit from the Rex::Post::Meterpreter::Datagram class, implementing only the send method at this tier. Convert create_udp_channel to return the local socket side of the datagram abstraction presented analogous to the TcpClientChannel approach used before. ----- Notes and intricacies: In order to implement recvfrom on the UDP abstraction, a shim layer has been put in place to forward the sockaddr information from the remote peer to the local UDP socketpair in the abstraction. This information takes up buffer space in the UDP socket, and in order to maintain compatibility with consumers, the dio_write_handler pushes the data buffer, and in a separate send call, he sockaddr information from the remote socket. On the abstraction side, the recvfrom_nonblock call of the real UDPSocket has been overriden via the mixed in module to call the real method twice, once for the data buffer, and once for the packed sockaddr data. The Rex level consumer for recvfrom calls the underlying nonblock method and expects this exact set of returns (as opposed to what standard library UDPSocket.recvfrom returns, which is a data buffer and an Array of sockaddr data). ----- Testing: Local and lab testing only so far. Test RC script to be added in GH comments. ----- Issues: Currently, sendto on a remote socket does not appear to honor LocalPort which causes DNS responses (#6611) to come from the wrong port to remote clients being serviced over a pivot socket.
2016-03-21 04:53:34 +00:00
}
end
def close
super
channel.cleanup_abstraction
channel.close
end
attr_accessor :channel
end
#
# Simple mixin for lsock in order to help avoid a ruby interpreter issue with ::Socket.pair
# Instead of writing to the lsock, reading from the rsock and then writing to the channel,
# we use this mixin to directly write to the channel.
#
# Note: This does not work with OpenSSL as OpenSSL is implemented natively and requires a real
# socket to write to and we cant intercept the sockets syswrite at a native level.
#
# Note: The deadlock only seems to effect the Ruby build for cygwin.
#
module DirectChannelWrite
2016-03-23 21:15:46 +00:00
def syswrite(buf)
channel._write(buf)
Implement consistent socket abstraction In current nomenclature, Rex Sockets are objects created by calls to Rex::Socket::<Transport>.create and Rex::Socket.create_... When the LocalHost or Comm parameters are set to remotely routed addresses (currently via Meterpreter sessions), Rex will create a Channel which will abstract communications with the remote end of the session. These channel based abstractions are called pivots, and present in three separate flavors: 1 - TcpClientChannel, a fully abstracted, selectable Socket. 2 - TcpServerChannel, a virtual Channel which distributes client channels. 3 - UdpChannel, a virtual Channel which provides common methods for UDP socket operations, but is not a full (selectable) abstraction. Unfortunately this differentiation results in inconsistent returns from the aforementioned socket creation calls, as the call chain creates parameters and supplies them to the create method on the comm object referenced in the params. The comm object may be a channel, and produce a virtual representation of a socket with functional methods analogous to Sockets, but without a kernel FD. This commit begins the work of ensuring that all calls for socket creation return selectable Rex::Socket objects with semantics familiar to Ruby developers who have not read into the details of Rex::Socket and Rex::Post. ----- Summary of changes: Convert Rex::IO::StreamAbstraction to SocketAbstraction and use the new mixin in StreamAbstraction and DatagramAbstraction. This approach allows for common methods to reuse the abstraction data flow, while initializing separate types of socket obects and an optional monitor as needed. In the Rex::Post::Meterpreter namespace, extract common methods from Stream to a SocketAbstraction mixin, include that mixin in Stream, and add Datagram with the dio_write handler override exported from the current implementation of UdpChannel, also using the mixin. This relies on the Rex::IO work above to implement the proper type of socket abstraction to the Channel descendants. In Rex::Post::Meterpreter::Extensions::Stdapi::Net, convert the UdpChannel to inherit from the Rex::Post::Meterpreter::Datagram class, implementing only the send method at this tier. Convert create_udp_channel to return the local socket side of the datagram abstraction presented analogous to the TcpClientChannel approach used before. ----- Notes and intricacies: In order to implement recvfrom on the UDP abstraction, a shim layer has been put in place to forward the sockaddr information from the remote peer to the local UDP socketpair in the abstraction. This information takes up buffer space in the UDP socket, and in order to maintain compatibility with consumers, the dio_write_handler pushes the data buffer, and in a separate send call, he sockaddr information from the remote socket. On the abstraction side, the recvfrom_nonblock call of the real UDPSocket has been overriden via the mixed in module to call the real method twice, once for the data buffer, and once for the packed sockaddr data. The Rex level consumer for recvfrom calls the underlying nonblock method and expects this exact set of returns (as opposed to what standard library UDPSocket.recvfrom returns, which is a data buffer and an Array of sockaddr data). ----- Testing: Local and lab testing only so far. Test RC script to be added in GH comments. ----- Issues: Currently, sendto on a remote socket does not appear to honor LocalPort which causes DNS responses (#6611) to come from the wrong port to remote clients being serviced over a pivot socket.
2016-03-21 04:53:34 +00:00
end
attr_accessor :channel
end
2016-03-23 20:06:35 +00:00
Implement consistent socket abstraction In current nomenclature, Rex Sockets are objects created by calls to Rex::Socket::<Transport>.create and Rex::Socket.create_... When the LocalHost or Comm parameters are set to remotely routed addresses (currently via Meterpreter sessions), Rex will create a Channel which will abstract communications with the remote end of the session. These channel based abstractions are called pivots, and present in three separate flavors: 1 - TcpClientChannel, a fully abstracted, selectable Socket. 2 - TcpServerChannel, a virtual Channel which distributes client channels. 3 - UdpChannel, a virtual Channel which provides common methods for UDP socket operations, but is not a full (selectable) abstraction. Unfortunately this differentiation results in inconsistent returns from the aforementioned socket creation calls, as the call chain creates parameters and supplies them to the create method on the comm object referenced in the params. The comm object may be a channel, and produce a virtual representation of a socket with functional methods analogous to Sockets, but without a kernel FD. This commit begins the work of ensuring that all calls for socket creation return selectable Rex::Socket objects with semantics familiar to Ruby developers who have not read into the details of Rex::Socket and Rex::Post. ----- Summary of changes: Convert Rex::IO::StreamAbstraction to SocketAbstraction and use the new mixin in StreamAbstraction and DatagramAbstraction. This approach allows for common methods to reuse the abstraction data flow, while initializing separate types of socket obects and an optional monitor as needed. In the Rex::Post::Meterpreter namespace, extract common methods from Stream to a SocketAbstraction mixin, include that mixin in Stream, and add Datagram with the dio_write handler override exported from the current implementation of UdpChannel, also using the mixin. This relies on the Rex::IO work above to implement the proper type of socket abstraction to the Channel descendants. In Rex::Post::Meterpreter::Extensions::Stdapi::Net, convert the UdpChannel to inherit from the Rex::Post::Meterpreter::Datagram class, implementing only the send method at this tier. Convert create_udp_channel to return the local socket side of the datagram abstraction presented analogous to the TcpClientChannel approach used before. ----- Notes and intricacies: In order to implement recvfrom on the UDP abstraction, a shim layer has been put in place to forward the sockaddr information from the remote peer to the local UDP socketpair in the abstraction. This information takes up buffer space in the UDP socket, and in order to maintain compatibility with consumers, the dio_write_handler pushes the data buffer, and in a separate send call, he sockaddr information from the remote socket. On the abstraction side, the recvfrom_nonblock call of the real UDPSocket has been overriden via the mixed in module to call the real method twice, once for the data buffer, and once for the packed sockaddr data. The Rex level consumer for recvfrom calls the underlying nonblock method and expects this exact set of returns (as opposed to what standard library UDPSocket.recvfrom returns, which is a data buffer and an Array of sockaddr data). ----- Testing: Local and lab testing only so far. Test RC script to be added in GH comments. ----- Issues: Currently, sendto on a remote socket does not appear to honor LocalPort which causes DNS responses (#6611) to come from the wrong port to remote clients being serviced over a pivot socket.
2016-03-21 04:53:34 +00:00
##
#
# Constructor
#
##
#
# Passes the initialization information up to the base class
#
def initialize(client, cid, type, flags)
# sf: initialize_abstraction() before super() as we can get a scenario where dio_write_handler() is called
# with data to write to the rsock but rsock has not yet been initialized. This happens if the channel
# is registered (client.add_channel(self) in Channel.initialize) to a session and a 'core_channel_write'
# request comes in before we have called self.initialize_abstraction()
initialize_abstraction
super(client, cid, type, flags)
end
##
#
# Remote I/O handlers
#
##
#
# Performs a write operation on the right side of the local stream.
#
def dio_write_handler(packet, data)
rv = Rex::ThreadSafe.select(nil, [rsock], nil, 0.01)
if(rv)
rsock.syswrite(data)
return true
else
return false
end
end
#
# Performs a close operation on the right side of the local stream.
#
def dio_close_handler(packet)
rsock.close
return super(packet)
end
#
# Cleans up the stream abstraction.
#
def cleanup
super
cleanup_abstraction
end
#
# Wrap the _write() call in order to catch some common, but harmless Windows exceptions
#
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
end
end; end; end