Module: Msf::Handler::BindNamedPipe

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

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

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

Returns the value of attribute conn_threads.



385
386
387
# File 'lib/msf/core/handler/bind_named_pipe.rb', line 385

def conn_threads
  @conn_threads
end

#listener_pairsObject (protected)

Returns the value of attribute listener_pairs.



387
388
389
# File 'lib/msf/core/handler/bind_named_pipe.rb', line 387

def listener_pairs
  @listener_pairs
end

#listener_threadsObject (protected)

Returns the value of attribute listener_threads.



386
387
388
# File 'lib/msf/core/handler/bind_named_pipe.rb', line 386

def listener_threads
  @listener_threads
end

Class Method Details

.general_handler_typeObject

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



194
195
196
# File 'lib/msf/core/handler/bind_named_pipe.rb', line 194

def self.general_handler_type
  "bind"
end

.handler_typeObject

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



186
187
188
# File 'lib/msf/core/handler/bind_named_pipe.rb', line 186

def self.handler_type
  "bind_named_pipe"
end

Instance Method Details

#cleanup_handlerObject

Cleanup



377
378
379
380
381
# File 'lib/msf/core/handler/bind_named_pipe.rb', line 377

def cleanup_handler
  self.conn_threads.each { |t|
    t.kill
  }
end

#human_nameString

A string suitable for displaying to the user

Returns:

  • (String)


227
228
229
# File 'lib/msf/core/handler/bind_named_pipe.rb', line 227

def human_name
  "bind named pipe"
end

#initialize(info = {}) ⇒ Object

Initializes the handler and ads the options that are required for bind named pipe payloads.



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/msf/core/handler/bind_named_pipe.rb', line 202

def initialize(info={})
  super

  register_options(
    [
      OptString.new('PIPENAME', [true, 'Name of the pipe to connect to', 'msf-pipe']),
      OptString.new('RHOST', [false, 'Host of the pipe to connect to', '']),
      OptPort.new('LPORT', [true, 'SMB port', 445]),
      OptString.new('SMBUser', [false, 'The username to authenticate as', ''], fallbacks: ['USERNAME']),
      OptString.new('SMBPass', [false, 'The password for the specified username', ''], fallbacks: ['PASSWORD']),
      OptString.new('SMBDomain', [false, 'The Windows domain to use for authentication', '.'], fallbacks: ['DOMAIN']),
    ], Msf::Handler::BindNamedPipe)
  register_advanced_options(
    [
      OptString.new('SMBDirect', [true, 'The target port is a raw SMB service (not NetBIOS)', true]),
    ], Msf::Handler::BindNamedPipe)

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

#start_handlerObject

Starts monitoring for an inbound connection.



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/msf/core/handler/bind_named_pipe.rb', line 234

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'].to_i
  pipe_name = datastore['PIPENAME']
  smbuser = datastore['SMBUser']
  smbpass = datastore['SMBPass']
  smbdomain = datastore['SMBDomain']
  smbdirect = datastore['SMBDirect']
  smbshare = "\\\\#{rhost}\\IPC$"

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

  # dont spawn multiple handlers for same host and pipe
  pair = rhost + ":" + lport.to_s + ":" + pipe_name
  return if self.listener_pairs[pair]
  self.listener_pairs[pair] = true

  # Start a new handling thread
  self.listener_threads << framework.threads.spawn("BindNamedPipeHandlerListener-#{pipe_name}", false) {
    sock = nil
    print_status("Started #{human_name} handler against #{rhost}:#{lport}")

    # First, create a socket and connect to the SMB service
    vprint_status("Connecting to #{rhost}:#{lport}")
    begin
      sock = Rex::Socket::Tcp.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

    if not sock
      print_error("Failed to connect socket #{rhost}:#{lport}")
      interrupt_wait_for_session
      Thread.exit
    end

    # Perform SMB logon
    simple = SimpleClientPipe.new(sock, smbdirect)

    begin
      simple.('*SMBSERVER', smbuser, smbpass, smbdomain)
      vprint_status("SMB login Success #{smbdomain}\\#{smbuser}:#{smbpass} #{rhost}:#{lport}")
    rescue
      print_error("SMB login Failure #{smbdomain}\\#{smbuser}:#{smbpass} #{rhost}:#{lport}")
      interrupt_wait_for_session
      Thread.exit
    end

    # Connect to the IPC$ share so we can use named pipes.
    simple.connect(smbshare)
    vprint_status("Connected to #{smbshare}")

    # Make several attempts to connect to the stagers named pipe. Authenticating and
    # connecting to IPC$ should be possible pre stager so we only retry this operation.
    # The stager creates the pipe with a default ACL which provides r/w to the creator
    # and administrators.
    stime = Time.now.to_i
    while (stime + ctimeout > Time.now.to_i)
      begin
        pipe = simple.create_pipe("\\"+pipe_name)
      rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
        error_name = e.get_error(e.error_code)
        unless ['STATUS_OBJECT_NAME_NOT_FOUND', 'STATUS_PIPE_NOT_AVAILABLE'].include? error_name
          print_error("Error connecting to #{pipe_name}: #{error_name}")
          interrupt_wait_for_session
          Thread.exit
        else
          # Stager pipe may not be ready
          vprint_status("Error connecting to #{pipe_name}: #{error_name}")
        end
        Rex::ThreadSafe.sleep(1.0)
      rescue RubySMB::Error::RubySMBError => e
        print_error("Error connecting to #{pipe_name}: #{e.message}")
        Rex::ThreadSafe.sleep(1.0)
      end
      break if pipe
    end

    if not pipe
      print_error("Failed to connect to pipe \\#{pipe_name} on #{rhost}")
      interrupt_wait_for_session
      Thread.exit
    end

    vprint_status("Opened pipe \\#{pipe_name}")

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

    conn_threads << framework.threads.spawn("BindNamedPipeHandlerSession", false, simple) { |simple_copy|
      begin
        session = handle_connection(simple_copy.pipe, opts)
      rescue => e
        elog('Exception raised from BindNamedPipe.handle_connection', error: e)
      end
    }
  }
end

#stop_handlerObject

Stop



366
367
368
369
370
371
372
# File 'lib/msf/core/handler/bind_named_pipe.rb', line 366

def stop_handler
  self.listener_threads.each do |t|
    t.kill
  end
  self.listener_threads = []
  self.listener_pairs = {}
end