Module: Msf::Handler::BindUdp

Includes:
Msf::Handler
Defined in:
lib/msf/core/handler/bind_udp.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 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

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


209
210
211
# File 'lib/msf/core/handler/bind_udp.rb', line 209

def conn_threads
  @conn_threads
end

#listener_pairsObject (protected)

:nodoc:


211
212
213
# File 'lib/msf/core/handler/bind_udp.rb', line 211

def listener_pairs
  @listener_pairs
end

#listener_threadsObject (protected)

:nodoc:


210
211
212
# File 'lib/msf/core/handler/bind_udp.rb', line 210

def listener_threads
  @listener_threads
end

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_udp.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_udp.rb', line 22

def self.handler_type
  return "bind_udp"
end

Instance Method Details

#add_handler(opts = {}) ⇒ Object

Starts a new connecting thread


72
73
74
75
76
77
78
79
80
81
# File 'lib/msf/core/handler/bind_udp.rb', line 72

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.


61
62
63
64
65
66
67
# File 'lib/msf/core/handler/bind_udp.rb', line 61

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

#human_nameString

A string suitable for displaying to the user

Returns:

  • (String)

36
37
38
# File 'lib/msf/core/handler/bind_udp.rb', line 36

def human_name
  "bind UDP"
end

#initialize(info = {}) ⇒ Object

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


44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/msf/core/handler/bind_udp.rb', line 44

def initialize(info = {})
  super

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

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

#start_handlerObject

Starts monitoring for an outbound connection to become established.


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
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
189
190
191
192
193
# File 'lib/msf/core/handler/bind_udp.rb', line 86

def start_handler

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

  # Maximum number of seconds to await initial udp response
  rtimeout = 5

  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("BindUdpHandlerListener-#{lport}", false) {
    client = nil

    print_status("Started #{human_name} handler against #{rhost}:#{lport}")

    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::Udp.create(
          'PeerHost' => rhost,
          'PeerPort' => lport.to_i,
          'Proxies'  => datastore['Proxies'],
          'Context'  =>
            {
              'Msf'        => framework,
              'MsfPayload' => self,
              'MsfExploit' => assoc_exploit
            })
      rescue Rex::ConnectionError => e
        vprint_error(e.message)
      rescue
        wlog("Exception caught in bind handler: #{$!.class} #{$!}")
      end

      client.extend(Rex::IO::Stream)
      begin
        # If a connection was acknowledged, request a basic response before promoting as a session
        if client
          message = 'syn'
          client.write("echo #{message}\n")
          response = client.get(rtimeout)
          break if response && response.include?(message)
          client.close()
          client = nil
        end
      rescue Errno::ECONNREFUSED
        client.close()
        client = nil
        wlog("Connection failed in udp bind handler continuing attempts: #{$!.class} #{$!}")
      end

      # 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

      # Timeout and datastore options need to be passed through to the client
      opts = {
        :datastore    => datastore,
        :expiration   => datastore['SessionExpirationTimeout'].to_i,
        :comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
        :retry_total  => datastore['SessionRetryTotal'].to_i,
        :retry_wait   => datastore['SessionRetryWait'].to_i,
        :udp_session  => true
      }

      # 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("BindUdpHandlerSession", false, client) { |client_copy|
        begin
          handle_connection(client_copy, opts)
        rescue => e
          elog('Exception raised from BindUdp.handle_connection', error: e)
        end
      }
    else
      wlog("No connection received before the handler completed")
    end
  }
end

#stop_handlerObject

Nothing to speak of.


198
199
200
201
202
203
204
205
# File 'lib/msf/core/handler/bind_udp.rb', line 198

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