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_for_ip

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:


233
234
235
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 233

def conn_threads
  @conn_threads
end

#listener_sockObject (protected)

:nodoc:


231
232
233
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 231

def listener_sock
  @listener_sock
end

#listener_threadObject (protected)

:nodoc:


232
233
234
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 232

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.


107
108
109
110
111
112
113
114
115
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 107

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

#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.


162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
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
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 162

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

#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
# 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 overriden 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'],
      'Context'   =>
        {
          'Msf'        => framework,
          'MsfPayload' => self,
          'MsfExploit' => assoc_exploit
        })

      ex = false

      via = via_string_for_ip(ip, comm)

      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.


120
121
122
123
124
125
126
127
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
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 120

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#{[email protected].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.


216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/msf/core/handler/reverse_tcp_double_ssl.rb', line 216

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