module Msf # this module provides instance methods to be used in overloading to do single byte sending of data module SmallSend def write(buf, opts = {}) warn "smallsend write" tsent = 0; bidx = 0 if self._send_size == nil or self._send_size == 0 self._send_size = 1 end while (bidx < buf.length) str = buf[bidx, _send_size] sent = super(str, opts) bidx += sent if sent > 0 tsent += sent if self.is_a?(SlowSend) sleep(self._send_delay) else sleep(0) end end return tsent end attr_accessor :_send_size end # this module provides instance mehtods to be used in overloading of Socket to insert delays inbetween each write module SlowSend def write(buf, opts = {}) warn 'slowsend write' if !self.is_a?(SmallSend) sleep(_send_delay) end response = super(buf, opts) return response end attr_accessor :_send_delay end ### # # This module provides methods for establish a connection to a remote host and # communicating with it. # ### module Exploit::Remote::Tcp # # Initializes an instance of an exploit module that exploits a # vulnerability in a TCP server. # def initialize(info = {}) super register_options( [ Opt::RHOST, Opt::RPORT ], Msf::Exploit::Remote::Tcp ) register_advanced_options( [ Opt::SSL, Opt::Proxies, Opt::CPORT, Opt::CHOST ], Msf::Exploit::Remote::Tcp ) register_evasion_options( [ OptInt.new('TCP::max_send_size', [false, 'Maxiumum tcp segment size. (0 = disable)', 0]), OptInt.new('TCP::send_delay', [false, 'Delays inserted before every send. (0 = disable)', 0]) ], Msf::Exploit::Remote::Tcp ) end # # Establishes a TCP connection to the specified RHOST/RPORT # def connect(global = true) nsock = Rex::Socket::Tcp.create( 'PeerHost' => rhost, 'PeerPort' => rport.to_i, 'LocalHost' => chost || "0.0.0.0", 'LocalPort' => cport ? cport.to_i : 0, 'SSL' => ssl, 'Proxies' => proxies, 'Context' => { 'Msf' => framework, 'MsfExploit' => self, }) # enable evasions on this socket # XXX implement evasions!!!! # evasions(nsock) # Set this socket to the global socket as necessary self.sock = nsock if (global) # Add this socket to the list of sockets created by this exploit sockets << nsock return nsock end def handler(nsock = self.sock) # If the handler claims the socket, then we don't want it to get closed # during cleanup if ((rv = super) == Handler::Claimed) if (nsock == self.sock) self.sock = nil end # Remove this socket from the list of sockets so that it will not be # aborted. sockets.delete(nsock) end return rv end # # Closes the TCP connection # def disconnect(nsock = self.sock) begin if (nsock) nsock.shutdown nsock.close end rescue IOError end if (nsock == sock) self.sock = nil end # Remove this socket from the list of sockets created by this exploit sockets.delete(nsock) end # # Performs cleanup, disconnects the socket if necessary # def cleanup super disconnect end ## # # Wrappers for getters # ## # # Returns the target host # def rhost datastore['RHOST'] end # # Returns the remote port # def rport datastore['RPORT'] end # # Returns the local host # def lhost datastore['LHOST'] end # # Returns the local port # def lport datastore['LPORT'] end # # Returns the local host for outgoing connections # def chost datastore['CHOST'] end # # Returns the local port for outgoing connections # def cport datastore['CPORT'] end # # Returns the boolean indicating SSL # def ssl datastore['SSL'] end # # Returns the proxy configuration # def proxies datastore['Proxies'] end protected attr_accessor :sock end ### # # This mixin provides a generic interface for running a TCP server of some # sort that is designed to exploit clients. Exploits that include this mixin # automatically take a passive stance. # ### module Exploit::Remote::TcpServer def initialize(info = {}) super(update_info(info, 'Stance' => Msf::Exploit::Stance::Passive)) register_options( [ OptAddress.new('SRVHOST', [ true, "The local host to listen on.", Rex::Socket.source_address ]), OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]) ], Msf::Exploit::Remote::TcpServer) register_evasion_options( [ OptInt.new('TCP::max_send_size', [false, 'Maxiumum tcp segment size. (0 = disable)', 0]), OptInt.new('TCP::send_delay', [false, 'Delays inserted before every send. (0 = disable)', 0]) ], Msf::Exploit::Remote::Tcp ) end # # This mixin overrides the exploit method so that it can initiate the # service that corresponds with what the client has requested. # def exploit start_service print_status("Server started."); end # # Stops the service, if one was created. # def cleanup stop_service print_status("Server stopped."); end # # Called when a client connects. # def on_client_connect(client) end # # Called when a client has data available for reading. # def on_client_data(client) end # # Called when a client has disconnected. # def on_client_close(client) end # # Starts the service. # def start_service(*args) self.service = Rex::Socket::TcpServer.create( 'LocalHost' => srvhost, 'LocalPort' => srvport, 'Context' => { 'Msf' => framework, 'MsfExploit' => self, }) self.service.on_client_connect_proc = Proc.new { |client| on_client_connect(client) } self.service.on_client_data_proc = Proc.new { |client| on_client_data(client) } self.service.on_client_close_proc = Proc.new { |client| on_client_close(client) } self.service.start end # # Stops the service. # def stop_service if (service) self.service.deref if self.service.kind_of?(Rex::Service) self.service.close if self.service.kind_of?(Rex::Socket) self.service = nil end end # Enable evasions on a given client def evasions(socket) # XXX - oooogly return if socket.instance_variables.member?('@tcp_evasion') if !socket.is_a?(SmallSend) and datastore['TCP::max_send_size'] > 0 socket.extend(SmallSend) socket._send_size = datastore['TCP::max_send_size'] end if !socket.is_a?(SlowSend) and datastore['TCP::send_delay'] > 0 socket.extend(SlowSend) socket._send_delay = datastore['TCP::send_delay'] end socket.instance_eval('@tcp_evasion = 1') end # # Returns the local host that is being listened on. # def srvhost datastore['SRVHOST'] end # # Returns the local port that is being listened on. # def srvport datastore['SRVPORT'] end protected attr_accessor :service # :nodoc: end end