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

161 lines
3.6 KiB
Ruby

# -*- 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
class << self
def cls
raise NotImplementedError
end
end
module SocketInterface
def type?
raise NotImplementedError
end
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
tmp,caddr,cport = csock.getsockname
tmp,raddr,rport = csock.getpeername
maddr,mport = [ channel.params.localhost, channel.params.localport ]
[ tmp, "#{caddr}#{(hops > 0) ? "-_#{hops}_" : ""}-#{raddr}", "#{mport}" ]
end
def getpeername
return super if not channel
tmp,caddr,cport = channel.client.sock.getpeername
maddr,mport = [ channel.params.peerhost, channel.params.peerport ]
[ tmp, "#{maddr}", "#{mport}" ]
end
%i{localhost localport peerhost peerport}.map do |meth|
define_method(meth) {
return super if not channel
channel.params.send(meth)
}
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
def syswrite( buf )
channel._write( buf )
end
attr_accessor :channel
end
##
#
# 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