Files
metasploit-gs/lib/msf/core/handler/reverse_tcp.rb
T

205 lines
4.9 KiB
Ruby
Raw Normal View History

require 'rex/socket'
require 'thread'
2005-07-11 02:03:48 +00:00
module Msf
module Handler
###
#
# This module implements the reverse TCP handler. This means
# that it listens on a port waiting for a connection until
# either one is established or it is told to abort.
#
# This handler depends on having a local host and port to
# listen on.
#
###
module ReverseTcp
2005-07-15 23:46:05 +00:00
include Msf::Handler
2005-11-15 15:11:43 +00:00
#
# Returns the string representation of the handler type, in this case
# 'reverse_tcp'.
#
2005-07-11 04:07:52 +00:00
def self.handler_type
return "reverse_tcp"
end
2005-11-15 15:11:43 +00:00
#
# Returns the connection-described general handler type, in this case
# 'reverse'.
#
def self.general_handler_type
"reverse"
end
2005-11-15 15:11:43 +00:00
#
# Initializes the reverse TCP handler and ads the options that are required
# for all reverse TCP payloads, like local host and local port.
#
2005-07-11 02:03:48 +00:00
def initialize(info = {})
super
register_options(
[
Opt::LHOST,
2005-07-11 02:03:48 +00:00
Opt::LPORT(4444)
], Msf::Handler::ReverseTcp)
2005-07-11 02:03:48 +00:00
# XXX: Not supported by all modules
register_advanced_options(
[
OptInt.new('ReverseConnectRetries', [ true, 'The number of connection attempts to try before exiting the process', 5 ]),
OptAddress.new('ReverseListenerBindAddress', [ false, 'The specific IP address to bind to on the local system']),
OptString.new('ReverseListenerComm', [ false, 'The specific communication channel to use for this listener']),
], Msf::Handler::ReverseTcp)
self.handler_queue = ::Queue.new
2005-07-11 02:03:48 +00:00
end
#
# Starts the listener but does not actually attempt
# to accept a connection. Throws socket exceptions
2005-11-15 15:11:43 +00:00
# if it fails to start the listener.
2005-07-11 02:03:48 +00:00
#
def setup_handler
2006-01-27 05:33:08 +00:00
if datastore['Proxies']
raise RuntimeError, 'TCP connect-back payloads cannot be used with Proxies'
2006-01-27 05:33:08 +00:00
end
2005-12-18 02:19:21 +00:00
ex = false
# Switch to IPv6 ANY address if the LHOST is also IPv6
addr = Rex::Socket.resolv_nbo(datastore['LHOST'])
# First attempt to bind LHOST. If that fails, the user probably has
# something else listening on that interface. Try again with ANY_ADDR.
2008-11-21 05:34:39 +00:00
any = (addr.length == 4) ? "0.0.0.0" : "::0"
addrs = [ Rex::Socket.addr_ntoa(addr), any ]
comm = datastore['ReverseListenerComm']
if comm.to_s == "local"
comm = ::Rex::Socket::Comm::Local
else
comm = nil
end
if not datastore['ReverseListenerBindAddress'].to_s.empty?
# Only try to bind to this specific interface
addrs = [ datastore['ReverseListenerBindAddress'] ]
# Pick the right "any" address if either wildcard is used
addrs[0] = any if (addrs[0] == "0.0.0.0" or addrs == "::0")
end
addrs.each { |ip|
begin
self.listener_sock = Rex::Socket::TcpServer.create(
'LocalHost' => ip,
'LocalPort' => datastore['LPORT'].to_i,
'Comm' => comm,
'Context' =>
{
'Msf' => framework,
'MsfPayload' => self,
'MsfExploit' => assoc_exploit
})
ex = false
comm_used = comm || Rex::Socket::SwitchBoard.best_comm( ip )
comm_used = Rex::Socket::Comm::Local if comm_used == nil
if( comm_used.respond_to?( :type ) and comm_used.respond_to?( :sid ) )
via = "via the #{comm_used.type} on session #{comm_used.sid}"
else
via = ""
end
print_status("Started reverse handler on #{ip}:#{datastore['LPORT']} #{via}")
break
rescue
ex = $!
print_error("Handler failed to bind to #{ip}:#{datastore['LPORT']}")
end
}
raise ex if (ex)
2005-07-11 02:03:48 +00:00
end
#
2005-11-15 15:11:43 +00:00
# Closes the listener socket if one was created.
2005-07-11 02:03:48 +00:00
#
def cleanup_handler
2005-12-12 07:07:19 +00:00
stop_handler
2005-07-11 02:03:48 +00:00
end
#
# Starts monitoring for an inbound connection.
#
def start_handler
self.listener_thread = framework.threads.spawn("ReverseTcpHandlerListener-#{datastore['LPORT']}", false) {
client = nil
2005-07-11 02:03:48 +00:00
begin
2005-09-23 06:08:04 +00:00
# Accept a client connection
2005-07-16 08:12:58 +00:00
begin
client = self.listener_sock.accept
2005-07-16 08:12:58 +00:00
rescue
2005-12-12 07:07:19 +00:00
wlog("Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}")
break
2005-07-16 08:12:58 +00:00
end
# Increment the has connection counter
self.pending_connections += 1
self.handler_queue.push( client )
2005-09-23 06:08:04 +00:00
end while true
2005-07-11 02:03:48 +00:00
}
self.handler_thread = framework.threads.spawn("ReverseTcpHandlerWorker-#{datastore['LPORT']}", false) {
while true
client = self.handler_queue.pop
begin
handle_connection(client)
rescue ::Exception
elog("Exception raised from handle_connection: #{$!.class}: #{$!}\n\n#{$@.join("\n")}")
end
end
}
2005-07-11 02:03:48 +00:00
end
#
2005-11-15 15:11:43 +00:00
# Stops monitoring for an inbound connection.
2005-07-11 02:03:48 +00:00
#
def stop_handler
# Terminate the listener thread
if (self.listener_thread and self.listener_thread.alive? == true)
self.listener_thread.kill
self.listener_thread = nil
2005-07-11 02:03:48 +00:00
end
# Terminate the handler thread
if (self.handler_thread and self.handler_thread.alive? == true)
self.handler_thread.kill
self.handler_thread = nil
end
if (self.listener_sock)
self.listener_sock.close
self.listener_sock = nil
end
2005-07-11 02:03:48 +00:00
end
protected
2005-11-15 15:11:43 +00:00
attr_accessor :listener_sock # :nodoc:
attr_accessor :listener_thread # :nodoc:
attr_accessor :handler_thread # :nodoc:
attr_accessor :handler_queue # :nodoc:
2005-07-11 02:03:48 +00:00
end
end
end