Module: Msf::Handler::ReverseTcpDouble

Includes:
Msf::Handler, Reverse, Msf::Handler::Reverse::Comm
Defined in:
lib/msf/core/handler/reverse_tcp_double.rb

Overview

This module implements the reverse double TCP handler. This means that it listens on a port waiting for a two connections, one connection is treated as stdin, the other as stdout.

This handler depends on having a local host and port to listen on.

Defined Under Namespace

Modules: TcpReverseDoubleChannelExt Classes: TcpReverseDoubleSessionChannel

Constant Summary

Constants included from Msf::Handler

Claimed, Unused

Instance Attribute Summary collapse

Attributes included from Msf::Handler

#exploit_config, #parent_payload, #pending_connections, #session_waiter_event, #sessions

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Msf::Handler::Reverse::Comm

#select_comm, #via_string

Methods included from Reverse

#bind_addresses, #bind_port, #is_loopback_address?, #setup_handler

Methods included from Msf::Handler

#add_handler, #create_session, #handle_connection, #handler, #handler_name, #interrupt_wait_for_session, #register_session, #setup_handler, #wait_for_session, #wfs_delay

Instance Attribute Details

#conn_threadsObject (protected)

:nodoc:



199
200
201
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 199

def conn_threads
  @conn_threads
end

#listener_sockObject (protected)

:nodoc:



197
198
199
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 197

def listener_sock
  @listener_sock
end

#listener_threadObject (protected)

:nodoc:



198
199
200
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 198

def listener_thread
  @listener_thread
end

Class Method Details

.general_handler_typeObject

Returns the connection-described general handler type, in this case 'reverse'.



33
34
35
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 33

def self.general_handler_type
  "reverse"
end

.handler_typeObject

Returns the string representation of the handler type, in this case 'reverse_tcp_double'.



25
26
27
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 25

def self.handler_type
  return "reverse_tcp_double"
end

Instance Method Details

#cleanup_handlerObject

Closes the listener socket if one was created.



51
52
53
54
55
56
57
58
59
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 51

def cleanup_handler
  stop_handler

  # Kill any remaining handle_connection threads that might
  # be hanging around
  conn_threads.each { |thr|
    thr.kill rescue nil
  }
end

#comm_stringObject



115
116
117
118
119
120
121
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 115

def comm_string
  if listener_sock.nil?
    "(setting up)"
  else
    via_string(listener_sock.client) if listener_sock.respond_to?(:client)
  end
end

#detect_input_output(sock_a, sock_b) ⇒ Object

Accept two sockets and determine which one is the input and which is the output. This method assumes that these sockets pipe to a remote shell, it should overridden if this is not the case.



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 128

def detect_input_output(sock_a, sock_b)

  begin

    # Flush any pending socket data
    sock_a.get_once if sock_a.has_read_data?(0.25)
    sock_b.get_once if sock_b.has_read_data?(0.25)

    etag = Rex::Text.rand_text_alphanumeric(16)
    echo = "echo #{etag};\n"

    print_status("Command: #{echo.strip}")

    print_status("Writing to socket A")
    sock_a.put(echo)

    print_status("Writing to socket B")
    sock_b.put(echo)

    print_status("Reading from sockets...")

    resp_a = ''
    resp_b = ''

    if (sock_a.has_read_data?(1))
      print_status("Reading from socket A")
      resp_a = sock_a.get_once
      print_status("A: #{resp_a.inspect}")
    end

    if (sock_b.has_read_data?(1))
      print_status("Reading from socket B")
      resp_b = sock_b.get_once
      print_status("B: #{resp_b.inspect}")
    end

    print_status("Matching...")
    if (resp_b.match(etag))
      print_status("A is input...")
      return sock_a, sock_b
    else
      print_status("B is input...")
      return sock_b, sock_a
    end

  rescue ::Exception
    print_status("Caught exception in detect_input_output: #{$!}")
  end

end

#human_nameString

A string suitable for displaying to the user

Returns:

  • (String)


64
65
66
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 64

def human_name
  "reverse TCP double"
end

#initialize(info = {}) ⇒ Object

Initializes the reverse TCP handler and ads the options that are required for all reverse TCP payloads, like local host and local port.



41
42
43
44
45
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 41

def initialize(info = {})
  super

  self.conn_threads = []
end

#payload_uriObject

A URI describing what the payload is configured to use for transport



109
110
111
112
113
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 109

def payload_uri
  addr = datastore['LHOST']
  uri_host = Rex::Socket.is_ipv6?(addr) ? "[#{addr}]" : addr
  "ssl://#{uri_host}:#{datastore['LPORT']}"
end

#start_handlerObject

Starts monitoring for an inbound connection.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 71

def start_handler
  self.listener_thread = framework.threads.spawn("ReverseTcpDoubleHandlerListener", false) {
    sock_inp = nil
    sock_out = nil

    begin
      # Accept two client connection
      begin
        client_a = self.listener_sock.accept
        print_status("Accepted the first client connection...")

        client_b = self.listener_sock.accept
        print_status("Accepted the second client connection...")
      rescue
        wlog("Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}")
        return nil
      end

      # Increment the has connection counter
      self.pending_connections += 1

      # Start a new thread and pass the client connection
      # as the input and output pipe.  Client's are expected
      # to implement the Stream interface.
      conn_threads << framework.threads.spawn("ReverseTcpDoubleHandlerSession", false, client_a, client_b) { | client_a_copy, client_b_copy|
        begin
          sock_inp, sock_out = detect_input_output(client_a_copy, client_b_copy)
          chan = TcpReverseDoubleSessionChannel.new(framework, sock_inp, sock_out)
          handle_connection(chan.lsock, { datastore: datastore })
        rescue => e
          elog('Exception raised from handle_connection', error: e)
        end
      }
    end while true
  }
end

#stop_handlerObject

Stops monitoring for an inbound connection.



182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 182

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
  end

  if (self.listener_sock)
    self.listener_sock.close
    self.listener_sock = nil
  end
end