diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb index a892da8bc8..47a45296a6 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb @@ -300,7 +300,7 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO src_stat = client.fs.filestat.new(src_file) if ::File.exists?(dest_file) dst_stat = ::File.stat(dest_file) - if src_stat.size == dst_stat.size and src_stat.mtime == dst_stat.mtime + if src_stat.size == dst_stat.size && src_stat.mtime == dst_stat.mtime return 'skipped' end end diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb index a0ae22cead..9e8911b9d0 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb @@ -301,17 +301,45 @@ class Console::CommandDispatcher::Stdapi::Fs glob = ::File.basename(src) src = ::File.dirname(src) end - stat = client.fs.file.stat(src) - if (stat.directory?) - client.fs.dir.download(dest, src, recursive, true, glob) { |step, src, dst| - print_status("#{step.ljust(11)}: #{src} -> #{dst}") - client.framework.events.on_session_download(client, src, dest) if msf_loaded? - } - elsif (stat.file?) - client.fs.file.download(dest, src) { |step, src, dst| - print_status("#{step.ljust(11)}: #{src} -> #{dst}") - client.framework.events.on_session_download(client, src, dest) if msf_loaded? - } + + # Use search if possible for recursive pattern matching. It will work + # more intuitively since it will not try to match on intermediate + # directories, only file names. + if glob && recursive && client.commands.include?('stdapi_fs_search') + + files = client.fs.file.search(src, glob, recursive) + if !files.empty? + print_line("Downloading #{files.length} file#{files.length > 1 ? 's' : ''}...") + + files.each do |file| + src_separator = client.fs.file.separator + src_path = file['path'] + client.fs.file.separator + file['name'] + dest_path = src_path.tr(src_separator, ::File::SEPARATOR) + + client.fs.file.download(dest_path, src_path) do |step, src, dst| + print_status("#{step.ljust(11)}: #{src} -> #{dst}") + client.framework.events.on_session_download(client, src, dest) if msf_loaded? + end + end + + else + print_status("No matching files found for download") + end + + else + # Perform direct matching + stat = client.fs.file.stat(src) + if (stat.directory?) + client.fs.dir.download(dest, src, recursive, true, glob) do |step, src, dst| + print_status("#{step.ljust(11)}: #{src} -> #{dst}") + client.framework.events.on_session_download(client, src, dest) if msf_loaded? + end + elsif (stat.file?) + client.fs.file.download(dest, src) do |step, src, dst| + print_status("#step.ljust(11)}: #{src} -> #{dst}") + client.framework.events.on_session_download(client, src, dest) if msf_loaded? + end + end end }