2005-12-17 06:46:23 +00:00
|
|
|
#!/usr/bin/env ruby
|
2005-05-31 12:56:36 +00:00
|
|
|
|
|
|
|
require 'socket'
|
2006-01-07 18:59:04 +00:00
|
|
|
require 'fcntl'
|
2005-05-31 12:56:36 +00:00
|
|
|
|
|
|
|
module Rex
|
|
|
|
module IO
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# This class provides an abstraction to a stream based
|
|
|
|
# connection through the use of a streaming socketpair.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
module StreamAbstraction
|
|
|
|
|
2006-01-07 10:04:30 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Extension information for required Stream interface.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
module Ext
|
|
|
|
|
|
|
|
#
|
|
|
|
# Initializes peer information.
|
|
|
|
#
|
2010-03-10 06:43:46 +00:00
|
|
|
def initinfo(peer,local)
|
2006-01-07 10:04:30 +00:00
|
|
|
@peer = peer
|
2010-03-10 06:43:46 +00:00
|
|
|
@local = local
|
2006-01-07 10:04:30 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Symbolic peer information.
|
|
|
|
#
|
|
|
|
def peerinfo
|
2006-08-17 01:57:52 +00:00
|
|
|
(@peer || "Remote Pipe")
|
2006-01-07 10:04:30 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Symbolic local information.
|
|
|
|
#
|
|
|
|
def localinfo
|
2010-03-10 06:43:46 +00:00
|
|
|
(@local || "Local Pipe")
|
2006-01-07 10:04:30 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-07-19 04:21:15 +00:00
|
|
|
#
|
2005-11-15 05:22:13 +00:00
|
|
|
# This method creates a streaming socket pair and initializes it.
|
2005-07-19 04:21:15 +00:00
|
|
|
#
|
2005-05-31 12:56:36 +00:00
|
|
|
def initialize_abstraction
|
2010-02-09 16:45:46 +00:00
|
|
|
self.lsock, self.rsock = Rex::Socket.tcp_socket_pair()
|
2005-09-27 05:31:48 +00:00
|
|
|
self.lsock.extend(Rex::IO::Stream)
|
2006-01-07 10:04:30 +00:00
|
|
|
self.lsock.extend(Ext)
|
2005-09-27 05:31:48 +00:00
|
|
|
self.rsock.extend(Rex::IO::Stream)
|
2010-03-10 06:43:46 +00:00
|
|
|
|
2010-12-02 22:13:39 +00:00
|
|
|
self.monitor_rsock
|
2005-05-31 12:56:36 +00:00
|
|
|
end
|
|
|
|
|
2005-07-26 04:08:01 +00:00
|
|
|
#
|
2005-11-15 05:22:13 +00:00
|
|
|
# This method cleans up the abstraction layer.
|
2005-07-26 04:08:01 +00:00
|
|
|
#
|
|
|
|
def cleanup_abstraction
|
|
|
|
self.lsock.close if (self.lsock)
|
|
|
|
self.rsock.close if (self.rsock)
|
|
|
|
|
|
|
|
self.lsock = nil
|
|
|
|
self.rsock = nil
|
|
|
|
end
|
|
|
|
|
2006-01-07 10:04:30 +00:00
|
|
|
#
|
2011-04-30 04:25:42 +00:00
|
|
|
# Low-level write to the local side.
|
2006-01-07 10:04:30 +00:00
|
|
|
#
|
|
|
|
def syswrite(buffer)
|
|
|
|
lsock.syswrite(buffer)
|
|
|
|
end
|
2011-04-30 04:25:42 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Low-level read from the local side.
|
2006-01-07 10:04:30 +00:00
|
|
|
#
|
|
|
|
def sysread(length)
|
|
|
|
lsock.sysread(length)
|
|
|
|
end
|
2011-04-30 04:25:42 +00:00
|
|
|
|
2006-01-07 10:04:30 +00:00
|
|
|
#
|
|
|
|
# Shuts down the local side of the stream abstraction.
|
|
|
|
#
|
|
|
|
def shutdown(how)
|
|
|
|
lsock.shutdown(how)
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Closes both sides of the stream abstraction.
|
|
|
|
#
|
|
|
|
def close
|
|
|
|
cleanup_abstraction
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Symbolic peer information.
|
|
|
|
#
|
|
|
|
def peerinfo
|
|
|
|
"Remote-side of Pipe"
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Symbolic local information.
|
|
|
|
#
|
|
|
|
def localinfo
|
|
|
|
"Local-side of Pipe"
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# The left side of the stream.
|
|
|
|
#
|
|
|
|
attr_reader :lsock
|
|
|
|
#
|
|
|
|
# The right side of the stream.
|
|
|
|
#
|
|
|
|
attr_reader :rsock
|
2010-03-10 06:43:46 +00:00
|
|
|
|
2005-05-31 12:56:36 +00:00
|
|
|
protected
|
2010-02-09 16:45:46 +00:00
|
|
|
|
|
|
|
def monitor_rsock
|
2010-11-12 17:28:40 +00:00
|
|
|
self.monitor_thread = Rex::ThreadFactory.spawn("StreamMonitorRemote", false) {
|
2010-02-09 16:45:46 +00:00
|
|
|
loop do
|
|
|
|
closed = false
|
|
|
|
buf = nil
|
2010-03-10 06:43:46 +00:00
|
|
|
|
2010-12-18 03:00:26 +00:00
|
|
|
if not self.rsock
|
|
|
|
wlog("monitor_rsock: the remote socket is nil, exiting loop")
|
|
|
|
break
|
|
|
|
end
|
|
|
|
|
2010-02-09 16:45:46 +00:00
|
|
|
begin
|
|
|
|
s = Rex::ThreadSafe.select( [ self.rsock ], nil, nil, 0.2 )
|
|
|
|
if( s == nil || s[0] == nil )
|
|
|
|
next
|
|
|
|
end
|
|
|
|
rescue Exception => e
|
2010-12-18 03:00:26 +00:00
|
|
|
wlog("monitor_rsock: exception during select: #{e.class} #{e}")
|
2010-02-09 16:45:46 +00:00
|
|
|
closed = true
|
|
|
|
end
|
2010-03-10 06:43:46 +00:00
|
|
|
|
2010-02-09 16:45:46 +00:00
|
|
|
if( closed == false )
|
|
|
|
begin
|
|
|
|
buf = self.rsock.sysread( 32768 )
|
2010-12-18 03:00:26 +00:00
|
|
|
if buf == nil
|
|
|
|
closed = true
|
|
|
|
wlog("monitor_rsock: closed remote socket due to nil read")
|
|
|
|
end
|
|
|
|
rescue ::Exception
|
2010-02-09 16:45:46 +00:00
|
|
|
closed = true
|
2011-05-03 06:55:15 +00:00
|
|
|
wlog("monitor_rsock: exception during read: #{e.class} #{e}")
|
2010-02-09 16:45:46 +00:00
|
|
|
end
|
|
|
|
end
|
2010-03-10 06:43:46 +00:00
|
|
|
|
2010-02-09 16:45:46 +00:00
|
|
|
if( closed == false )
|
|
|
|
total_sent = 0
|
|
|
|
total_length = buf.length
|
|
|
|
while( total_sent < total_length )
|
|
|
|
begin
|
2011-04-21 17:29:11 +00:00
|
|
|
data = buf[total_sent, buf.length]
|
2011-04-30 04:25:42 +00:00
|
|
|
|
|
|
|
# Note that this must be write() NOT syswrite() or put() or anything like it.
|
|
|
|
# Using syswrite() breaks SSL streams.
|
2010-02-09 16:45:46 +00:00
|
|
|
sent = self.write( data )
|
2011-05-03 06:55:15 +00:00
|
|
|
|
2011-04-30 04:25:42 +00:00
|
|
|
# sf: Only remove the data off the queue is write was successfull.
|
2010-02-09 16:45:46 +00:00
|
|
|
# This way we naturally perform a resend if a failure occured.
|
2010-03-10 06:43:46 +00:00
|
|
|
# Catches an edge case with meterpreter TCP channels where remote send
|
2010-02-09 16:45:46 +00:00
|
|
|
# failes gracefully and a resend is required.
|
2011-05-03 06:55:15 +00:00
|
|
|
if (sent.nil? or sent <= 0)
|
|
|
|
wlog("monitor_rsock: failed writing, socket must be dead")
|
|
|
|
break
|
|
|
|
else
|
2010-02-09 16:45:46 +00:00
|
|
|
total_sent += sent
|
|
|
|
end
|
2011-05-03 06:55:15 +00:00
|
|
|
rescue ::IOError, ::EOFError => e
|
2010-02-09 16:45:46 +00:00
|
|
|
closed = true
|
2010-12-18 03:00:26 +00:00
|
|
|
wlog("monitor_rsock: exception during write: #{e.class} #{e}")
|
2010-02-09 16:45:46 +00:00
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2010-03-10 06:43:46 +00:00
|
|
|
|
2010-02-09 16:45:46 +00:00
|
|
|
if( closed )
|
2010-12-18 03:00:26 +00:00
|
|
|
self.close_write if self.respond_to?('close_write')
|
|
|
|
break
|
2010-02-09 16:45:46 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
2010-03-10 06:43:46 +00:00
|
|
|
|
2010-02-09 16:45:46 +00:00
|
|
|
protected
|
|
|
|
attr_accessor :monitor_thread
|
|
|
|
attr_writer :lsock
|
|
|
|
attr_writer :rsock
|
2010-03-10 06:43:46 +00:00
|
|
|
|
2005-05-31 12:56:36 +00:00
|
|
|
end
|
|
|
|
|
2010-03-10 06:43:46 +00:00
|
|
|
end; end
|
|
|
|
|