# -*- coding: binary -*- 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/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel' require 'rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel' 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 TLV_PARAM_MAP = { TLV_TYPE_CONNECT_RETRIES => 'Retries', TLV_TYPE_LOCAL_HOST => 'LocalHost', TLV_TYPE_LOCAL_PORT => 'LocalPort', TLV_TYPE_PEER_HOST => 'PeerHost', TLV_TYPE_PEER_PORT => 'PeerPort' } ## # # Constructor # ## # # Initialize the socket subsystem and start monitoring sockets as they come # in. # def initialize(client) self.client = client # register the inbound handler for the tcp server channel (allowing us to # receive new client connections to a tcp server channel) client.register_inbound_handler(Rex::Post::Meterpreter::Extensions::Stdapi::Net::SocketSubsystem::TcpServerChannel) end # # Deregister the inbound handler for the tcp server channel # def shutdown client.deregister_inbound_handler(Rex::Post::Meterpreter::Extensions::Stdapi::Net::SocketSubsystem::TcpServerChannel) end # # Process a response packet and extract TLVs that are relevant for updating # socket parameters. # def self.parameters_from_response(response) params = {} TLV_PARAM_MAP.each do |tlv_type, param_key| value = response.get_tlv_value(tlv_type) next if value.nil? params[param_key] = value end Rex::Socket::Parameters.from_hash(params) 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) res = nil if params.tcp? if params.server? res = create_tcp_server_channel(params) else res = create_tcp_client_channel(params) end elsif params.udp? res = create_udp_channel(params) end return res end # # Create a TCP server channel. # def create_tcp_server_channel(params) begin return SocketSubsystem::TcpServerChannel.open(client, params) rescue ::Rex::Post::Meterpreter::RequestError => e case e.code when 10048 raise ::Rex::AddressInUse.new(params.localhost, params.localport) when 10000 .. 10100 raise ::Rex::ConnectionError.new end raise e end end # # Creates a TCP client channel. # def create_tcp_client_channel(params) begin channel = SocketSubsystem::TcpClientChannel.open(client, params) if channel != nil return channel.lsock end return nil rescue ::Rex::Post::Meterpreter::RequestError => e case e.code when 10000 .. 10100 raise ::Rex::ConnectionError.new end raise e end end # # Creates a UDP channel. # def create_udp_channel(params) begin channel = SocketSubsystem::UdpChannel.open(client, params) if channel != nil return channel.lsock end return nil rescue ::Rex::Post::Meterpreter::RequestError => e case e.code when 10048 raise ::Rex::AddressInUse.new(params.localhost, params.localport) when 10000 .. 10100 raise ::Rex::ConnectionError.new end raise e end end protected attr_accessor :client # :nodoc: end end; end; end; end; end; end