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_for_ip

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:


184
185
186
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 184

def conn_threads
  @conn_threads
end

#listener_sockObject (protected)

:nodoc:


182
183
184
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 182

def listener_sock
  @listener_sock
end

#listener_threadObject (protected)

:nodoc:


183
184
185
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 183

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

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


113
114
115
116
117
118
119
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
156
157
158
159
160
161
162
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 113

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

#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#{[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, 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.


167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/msf/core/handler/reverse_tcp_double.rb', line 167

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