Module: Msf::Handler::ReverseTcpDoubleSSL

Includes:
Msf::Handler, Reverse, Msf::Handler::Reverse::Comm, Msf::Handler::Reverse::SSL
Defined in:
lib/msf/core/handler/reverse_tcp_double_ssl.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: TcpReverseDoubleSSLChannelExt Classes: TcpReverseDoubleSSLSessionChannel

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?

Methods included from Msf::Handler

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

Instance Attribute Details

#conn_threadsObject (protected)

:nodoc:



249
250
251
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 249

def conn_threads
  @conn_threads
end

#listener_sockObject (protected)

:nodoc:



247
248
249
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 247

def listener_sock
  @listener_sock
end

#listener_threadObject (protected)

:nodoc:



248
249
250
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 248

def listener_thread
  @listener_thread
end

Class Method Details

.general_handler_typeObject

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



34
35
36
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 34

def self.general_handler_type
  "reverse"
end

.handler_typeObject

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



26
27
28
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 26

def self.handler_type
  return "reverse_tcp_double_ssl"
end

Instance Method Details

#cleanup_handlerObject

Closes the listener socket if one was created.



123
124
125
126
127
128
129
130
131
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 123

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



112
113
114
115
116
117
118
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 112

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.



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 178

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)


56
57
58
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 56

def human_name
  "reverse TCP double SSL"
end

#initialize(info = {}) ⇒ Object

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



42
43
44
45
46
47
48
49
50
51
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 42

def initialize(info = {})
  super

  register_advanced_options(
    [
      OptAddress.new('ReverseListenerBindAddress', [ false, 'The specific IP address to bind to on the local system']),
    ], Msf::Handler::ReverseTcpDoubleSSL)

  self.conn_threads = []
end

#payload_uriObject

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



106
107
108
109
110
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 106

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

#setup_handlerObject

Starts the listener but does not actually attempt to accept a connection. Throws socket exceptions if it fails to start the listener.



65
66
67
68
69
70
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
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 65

def setup_handler
  if !datastore['Proxies'].blank? && !datastore['ReverseAllowProxy']
    raise RuntimeError, 'TCP connect-back payloads cannot be used with Proxies. Can be overridden by setting ReverseAllowProxy to true'
  end

  ex = false

  comm = select_comm
  local_port = bind_port

  bind_addresses.each { |ip|
    begin

      self.listener_sock = Rex::Socket::SslTcpServer.create(
      'LocalHost'  => ip,
      'LocalPort'  => local_port,
      'Comm'       => comm,
      'SSLCert'    => datastore['HandlerSSLCert'],
      'SSLVersion' => datastore['SSLVersion'],
      'Context'    =>
        {
          'Msf'        => framework,
          'MsfPayload' => self,
          'MsfExploit' => assoc_exploit
        })

      ex = false

      via = via_string(self.listener_sock.client) if self.listener_sock.respond_to?(:client)

      print_status("Started reverse double SSL handler on #{ip}:#{local_port} #{via}")
      break
    rescue
      ex = $!
      print_error("Handler failed to bind to #{ip}:#{local_port}")
    end
  }
  raise ex if (ex)
end

#start_handlerObject

Starts monitoring for an inbound connection.



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
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 136

def start_handler
  self.listener_thread = framework.threads.spawn("ReverseTcpDoubleSSLHandlerListener", 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("ReverseTcpDoubleSSLHandlerSession", 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 = TcpReverseDoubleSSLSessionChannel.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.



232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 232

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