From bebff786b71f6ef69e3ffd59f3b29458f2440231 Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 22 Jul 2016 14:15:25 -0500 Subject: [PATCH] Add timestamping to downloaded files --- .../meterpreter/extensions/stdapi/fs/dir.rb | 9 +++++++-- .../meterpreter/extensions/stdapi/fs/file.rb | 9 +++++++-- .../ui/console/command_dispatcher/stdapi/fs.rb | 17 ++++++++++++----- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb index 8ef895bfb0..b9134cfff8 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb @@ -195,7 +195,7 @@ class Dir < Rex::Post::Dir # Downloads the contents of a remote directory a # local directory, optionally in a recursive fashion. # - def Dir.download(dst, src, recursive = false, force = true, glob = nil, &stat) + def Dir.download(dst, src, recursive = false, force = true, glob = nil, timestamp = nil, &stat) self.entries(src, glob).each { |src_sub| dst_item = dst + ::File::SEPARATOR + client.unicode_filter_encode(src_sub) @@ -208,7 +208,12 @@ class Dir < Rex::Post::Dir src_stat = client.fs.filestat.new(src_item) if (src_stat.file?) + if timestamp + dst_item << timestamp + end + stat.call('downloading', src_item, dst_item) if (stat) + begin result = client.fs.file.download_file(dst_item, src_item) stat.call(result, src_item, dst_item) if (stat) @@ -231,7 +236,7 @@ class Dir < Rex::Post::Dir end stat.call('mirroring', src_item, dst_item) if (stat) - download(dst_item, src_item, recursive, force, glob, &stat) + download(dst_item, src_item, recursive, force, glob, timestamp, &stat) stat.call('mirrored', src_item, dst_item) if (stat) end } diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb index c74fe46138..0ae5b1941d 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb @@ -280,14 +280,19 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO # If a block is given, it will be called before each file is downloaded and # again when each download is complete. # - def File.download(dest, *src_files, &stat) - src_files.each { |src| + def File.download(dest, src_files, timestamp = nil, &stat) + [*src_files].each { |src| if (::File.basename(dest) != File.basename(src)) # The destination when downloading is a local file so use this # system's separator dest += ::File::SEPARATOR + File.basename(src) end + # XXX: dest can be the same object as src, so we use += instead of << + if timestamp + dest += timestamp + end + stat.call('downloading', src, dest) if (stat) result = download_file(dest, src) stat.call(result, src, dest) if (stat) 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 3dd1732ccf..7099bec0e5 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 @@ -24,7 +24,8 @@ class Console::CommandDispatcher::Stdapi::Fs # @@download_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help banner." ], - "-r" => [ false, "Download recursively." ]) + "-r" => [ false, "Download recursively." ], + "-t" => [ false, "Timestamp downloaded files." ]) # # Options for the upload command. # @@ -332,6 +333,7 @@ class Console::CommandDispatcher::Stdapi::Fs end recursive = false + timestamp = false src_items = [] last = nil dest = nil @@ -340,6 +342,8 @@ class Console::CommandDispatcher::Stdapi::Fs case opt when "-r" recursive = true + when "-t" + timestamp = true when nil src_items << last if (last) last = val @@ -367,6 +371,10 @@ class Console::CommandDispatcher::Stdapi::Fs dest = ::File.dirname(dest) end + if timestamp + ts = '_' + Time.now.iso8601 + end + # Go through each source item and download them src_items.each { |src| glob = nil @@ -389,8 +397,7 @@ class Console::CommandDispatcher::Stdapi::Fs 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| - puts step + client.fs.file.download(dest_path, src_path, ts) do |step, src, dst| print_status("#{step.ljust(11)}: #{src} -> #{dst}") client.framework.events.on_session_download(client, src, dest) if msf_loaded? end @@ -404,12 +411,12 @@ class Console::CommandDispatcher::Stdapi::Fs # 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| + client.fs.dir.download(dest, src, recursive, true, glob, ts) 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| + client.fs.file.download(dest, src, ts) do |step, src, dst| print_status("#{step.ljust(11)}: #{src} -> #{dst}") client.framework.events.on_session_download(client, src, dest) if msf_loaded? end