Module: Msf::Handler::BindTcp

Includes:
Msf::Handler
Defined in:
lib/msf/core/handler/bind_tcp.rb

Overview

This module implements the Bind TCP handler. This means that it will attempt to connect to a remote host on a given port for a period of time (typically the duration of an exploit) to see if a the payload has started listening. This can tend to be rather verbose in terms of traffic and in general it is preferable to use reverse payloads.

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

#handle_connection, #handler, #handler_name, #setup_handler, #wait_for_session, #wfs_delay

Class Method Details

.general_handler_typeObject

Returns the connection oriented general handler type, in this case bind.


29
30
31
# File 'lib/msf/core/handler/bind_tcp.rb', line 29

def self.general_handler_type
  "bind"
end

.handler_typeObject

Returns the handler specific string representation, in this case 'bind_tcp'.


22
23
24
# File 'lib/msf/core/handler/bind_tcp.rb', line 22

def self.handler_type
  return "bind_tcp"
end

Instance Method Details

#add_handler(opts = {}) ⇒ Object

Starts a new connecting thread


65
66
67
68
69
70
71
72
73
74
# File 'lib/msf/core/handler/bind_tcp.rb', line 65

def add_handler(opts={})

  # Merge the updated datastore values
  opts.each_pair do |k,v|
    datastore[k] = v
  end

  # Start a new handler
  start_handler
end

#cleanup_handlerObject

Kills off the connection threads if there are any hanging around.


54
55
56
57
58
59
60
# File 'lib/msf/core/handler/bind_tcp.rb', line 54

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

#initialize(info = {}) ⇒ Object

Initializes a bind handler and adds the options common to all bind payloads, such as local port.


37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/msf/core/handler/bind_tcp.rb', line 37

def initialize(info = {})
  super

  register_options(
    [
      Opt::LPORT(4444),
      OptAddress.new('RHOST', [false, 'The target address', '']),
    ], Msf::Handler::BindTcp)

  self.conn_threads = []
  self.listener_threads = []
  self.listener_pairs = {}
end

#start_handlerObject

Starts monitoring for an outbound connection to become established.


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

def start_handler

  # Maximum number of seconds to run the handler
  ctimeout = 150

  if (exploit_config and exploit_config['active_timeout'])
    ctimeout = exploit_config['active_timeout'].to_i
  end

  # Take a copy of the datastore options
  rhost = datastore['RHOST']
  lport = datastore['LPORT']

  # Ignore this if one of the required options is missing
  return if not rhost
  return if not lport

  # Only try the same host/port combination once
  phash = rhost + ':' + lport.to_s
  return if self.listener_pairs[phash]
  self.listener_pairs[phash] = true

  # Start a new handling thread
  self.listener_threads << framework.threads.spawn("BindTcpHandlerListener-#{lport}", false) {
    client = nil

    print_status("Started bind handler")

    if (rhost == nil)
      raise ArgumentError,
        "RHOST is not defined; bind stager cannot function.",
        caller
    end

    stime = Time.now.to_i

    while (stime + ctimeout > Time.now.to_i)
      begin
        client = Rex::Socket::Tcp.create(
          'PeerHost' => rhost,
          'PeerPort' => lport.to_i,
          'Proxies'  => datastore['Proxies'],
          'Context'  =>
            {
              'Msf'        => framework,
              'MsfPayload' => self,
              'MsfExploit' => assoc_exploit
            })
      rescue Rex::ConnectionRefused
        # Connection refused is a-okay
      rescue ::Exception
        wlog("Exception caught in bind handler: #{$!.class} #{$!}")
      end

      break if client

      # Wait a second before trying again
      Rex::ThreadSafe.sleep(0.5)
    end

    # Valid client connection?
    if (client)
      # 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("BindTcpHandlerSession", false, client) { |client_copy|
        begin
          handle_connection(wrap_aes_socket(client_copy))
        rescue
          elog("Exception raised from BindTcp.handle_connection: #{$!}")
        end
      }
    else
      wlog("No connection received before the handler completed")
    end
  }
end

#stop_handlerObject

Nothing to speak of.


210
211
212
213
214
215
216
217
# File 'lib/msf/core/handler/bind_tcp.rb', line 210

def stop_handler
  # Stop the listener threads
  self.listener_threads.each do |t|
    t.kill
  end
  self.listener_threads = []
  self.listener_pairs = {}
end

#wrap_aes_socket(sock) ⇒ Object


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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/msf/core/handler/bind_tcp.rb', line 160

def wrap_aes_socket(sock)
  if datastore["PAYLOAD"] !~ /java\// or (datastore["AESPassword"] || "") == ""
    return sock
  end

  socks = Rex::Socket::tcp_socket_pair()
  socks[0].extend(Rex::Socket::Tcp)
  socks[1].extend(Rex::Socket::Tcp)

  m = OpenSSL::Digest.new('md5')
  m.reset
  key = m.digest(datastore["AESPassword"] || "")

  Rex::ThreadFactory.spawn('AESEncryption', false) {
    c1 = OpenSSL::Cipher::Cipher.new('aes-128-cfb8')
    c1.encrypt
    c1.key=key
    sock.put([0].pack('N'))
    sock.put(c1.iv=c1.random_iv)
    buf1 = socks[0].read(4096)
    while buf1 and buf1 != ""
      sock.put(c1.update(buf1))
      buf1 = socks[0].read(4096)
    end
    sock.close()
  }

  Rex::ThreadFactory.spawn('AESEncryption', false) {
    c2 = OpenSSL::Cipher::Cipher.new('aes-128-cfb8')
    c2.decrypt
    c2.key=key
    iv=""
    while iv.length < 16
      iv << sock.read(16-iv.length)
    end
    c2.iv = iv
    buf2 = sock.read(4096)
    while buf2 and buf2 != ""
      socks[0].put(c2.update(buf2))
      buf2 = sock.read(4096)
    end
    socks[0].close()
  }

  return socks[1]
end