Module: Msf::Handler::ReverseTcpDouble

Includes:
Msf::Handler
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

Attributes included from Msf::Handler

#exploit_config, #parent_payload

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Msf::Handler

#add_handler, #handle_connection, #handler, #handler_name, #wait_for_session, #wfs_delay

Class Method Details

.general_handler_typeObject

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


31
32
33
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 31

def self.general_handler_type
  "reverse"
end

.handler_typeObject

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


23
24
25
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 23

def self.handler_type
  return "reverse_tcp_double"
end

Instance Method Details

#cleanup_handlerObject

Closes the listener socket if one was created.


80
81
82
83
84
85
86
87
88
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 80

def cleanup_handler
  stop_handler

  # Kill any remaining handle_connection threads that might
  # be hanging around
  conn_threads.each { |thr|
    thr.kill
  }
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.


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
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 139

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

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


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 39

def initialize(info = {})
  super

  register_options(
    [
      Opt::LHOST,
      Opt::LPORT(4444)
    ], Msf::Handler::ReverseTcpDouble)

  register_advanced_options(
    [
      OptBool.new('ReverseAllowProxy', [ true, 'Allow reverse tcp even with Proxies specified. Connect back will NOT go through proxy but directly to LHOST', false]),
    ], Msf::Handler::ReverseTcpDouble)

  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.


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 61

def setup_handler
  if datastore['Proxies'] and not datastore['ReverseAllowProxy']
    raise RuntimeError, 'TCP connect-back payloads cannot be used with Proxies. Can be overriden by setting ReverseAllowProxy to true'
  end
  self.listener_sock = Rex::Socket::TcpServer.create(
    # 'LocalHost' => datastore['LHOST'],
    'LocalPort' => datastore['LPORT'].to_i,
    'Comm'      => comm,
    'Context'   =>
      {
        'Msf'        => framework,
        'MsfPayload' => self,
        'MsfExploit' => assoc_exploit
      })
end

#start_handlerObject

Starts monitoring for an inbound connection.


93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 93

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

    print_status("Started reverse double handler")

    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...")

        sock_inp, sock_out = detect_input_output(client_a, client_b)

      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("ReverseTcpDoubleHandlerSession", false, sock_inp, sock_out) { | sock_inp_copy, sock_out_copy|
        begin
          chan = TcpReverseDoubleSessionChannel.new(framework, sock_inp_copy, sock_out_copy)
          handle_connection(chan.lsock)
        rescue
          elog("Exception raised from handle_connection: #{$!}\n\n#{[email protected].join("\n")}")
        end
      }
    end while true
  }
end

#stop_handlerObject

Stops monitoring for an inbound connection.


193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 193

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