Files
metasploit-gs/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb
T
Spoon M d89ac6478c more meterp decoupling
git-svn-id: file:///home/svn/framework3/trunk@3836 4d416f70-5f16-0410-b530-b9f4589650da
2006-08-21 22:50:27 +00:00

230 lines
4.2 KiB
Ruby

#!/usr/bin/env ruby
require 'thread'
require 'rex/socket'
require 'rex/post/meterpreter/extensions/stdapi/tlv'
require 'rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel'
require 'rex/logging'
module Rex
module Post
module Meterpreter
module Extensions
module Stdapi
module Net
###
#
# This class provides an interface to interacting with sockets
# on the remote machine. It allows callers to open TCP, UDP,
# and other arbitrary socket-based connections as channels that
# can then be interacted with through the established
# meterpreter connection.
#
###
class Socket
##
#
# Constructor
#
##
#
# Initialize the socket subsystem and start monitoring sockets
# as they come in.
#
def initialize(client)
self.client = client
self.monitored_sockets = []
self.monitored_socket_channels = {}
# Start monitoring shit like the business
self.monitor_sockets
end
#
# Terminate the monitor thread.
#
def shutdown
monitor_thread.kill
end
##
#
# Factory
#
##
#
# Creates an arbitrary client socket channel using the information
# supplied in the socket parameters instance. The 'params' argument
# is expected to be of type Rex::Socket::Parameters.
#
def create(params)
channel = nil
res = nil
# begin
if (params.tcp?)
if (params.server?)
channel = create_tcp_server(params)
else
channel = create_tcp_client(params)
end
# Add this channel's right socket to the socket monitor
add_monitored_socket(channel.rsock, channel)
# If we get a valid channel back, create a stream
# representation of the left side of the socket for
# the caller to use
if (channel != nil)
res = channel.lsock
end
elsif (params.udp?)
if (params.server?)
res = create_udp_server(params)
else
res = create_udp_client(params)
end
# TODO: Datagram wrapper
end
# rescue
# end
return res
end
#
# Create a TCP server channel.
#
def create_tcp_server(params)
end
#
# Creates a TCP client channel.
#
def create_tcp_client(params)
return SocketSubsystem::TcpClientChannel.open(client, params)
end
#
# Creates a UDP server channel.
#
def create_udp_server(params)
end
#
# Creates a UDP client channel.
#
def create_udp_client(params)
end
protected
##
#
# Socket monitoring
#
##
#
# Monitors zero or more sockets and handles forwarding traffic
# to the remote half of the associated channel.
#
def monitor_sockets
self.monitor_thread = ::Thread.new {
loop do
# Watch for data
begin
socks = select(monitored_sockets, nil, nil, 1)
rescue StreamClosedError => e
channel = monitored_socket_channels[e.stream.object_id]
dlog("monitor_channels: channel #{channel} closed (#{e.stream})",
'rex', LEV_3)
if (channel)
begin
channel.close
rescue IOError
end
remove_monitored_socket(e.stream)
end
next
end
# No data?
if (socks == nil || socks[0] == nil)
next
end
# Enumerate through each of the indicated sockets
socks[0].each { |sock|
channel = monitored_socket_channels[sock.object_id]
closed = false
data = nil
if (channel == nil)
remove_monitored_socket(sock)
next
end
begin
data = sock.sysread(16384)
rescue
closed = true
end
if (data == nil)
closed = true
end
# If the socket closed, notify the other side and remove
# this socket from the monitored socket list
if (closed)
channel.close_write
remove_monitored_socket(sock)
# Otherwise, write the data to the remote side
else
channel.write(data)
end
}
end
}
end
#
# Adds a socket to the list of monitored sockets.
#
def add_monitored_socket(sock, channel)
monitored_sockets << sock
monitored_socket_channels[sock.object_id] = channel
end
#
# Removes a socket from the list of monitored sockets.
#
def remove_monitored_socket(sock)
monitored_socket_channels.delete(sock.object_id)
monitored_sockets.delete(sock)
end
attr_accessor :monitored_sockets, :monitored_socket_channels # :nodoc:
attr_accessor :monitor_thread # :nodoc:
attr_accessor :client # :nodoc:
end
end; end; end; end; end; end