From fbf64adf2a6ea42da35fe3f5d47553cef48e0ea4 Mon Sep 17 00:00:00 2001 From: Stephen Fewer Date: Fri, 27 Aug 2010 14:59:38 +0000 Subject: [PATCH] Commit the ruby side for meterpreter file search. If available, will leverage Windows Search to speed up searching an indexed directory. Examples of usage as follows: Find all .PDF files on the host system: meterpreter>search *.pdf Find all files on bob's desktop: meterpreter>search -d 'c:\users\bob\desktop' -f * Find all files in the root drive c: but don't search subdirectories: meterpreter>search -d c: -r false -f * If Windows Search is available (Vista and above by default, XP/2003 by addon) we can also search any indexed IE history and indexed email meterpreter>search -d iehistory -f * meterpreter>search -d mapi -f * git-svn-id: file:///home/svn/framework3/trunk@10167 4d416f70-5f16-0410-b530-b9f4589650da --- .../meterpreter/extensions/stdapi/fs/file.rb | 31 ++++++++++ .../post/meterpreter/extensions/stdapi/tlv.rb | 6 ++ .../console/command_dispatcher/stdapi/fs.rb | 57 ++++++++++++++++++- 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb index e0dcad8cc2..4045d4a456 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb @@ -31,7 +31,38 @@ Separator = "\\" class < results.get_tlv_value( TLV_TYPE_FILE_PATH ), + 'name' => results.get_tlv_value( TLV_TYPE_FILE_NAME ), + 'size' => results.get_tlv_value( TLV_TYPE_FILE_SIZE ) + } + end + end + + return files + end + # # Returns the base name of the supplied file path to the caller. # diff --git a/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb b/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb index 0a24b7ca9f..fc7330dc10 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb @@ -28,8 +28,14 @@ TLV_TYPE_DIRECTORY_PATH = TLV_META_TYPE_STRING | 1200 TLV_TYPE_FILE_NAME = TLV_META_TYPE_STRING | 1201 TLV_TYPE_FILE_PATH = TLV_META_TYPE_STRING | 1202 TLV_TYPE_FILE_MODE = TLV_META_TYPE_STRING | 1203 +TLV_TYPE_FILE_SIZE = TLV_META_TYPE_UINT | 1204 + TLV_TYPE_STAT_BUF = TLV_META_TYPE_COMPLEX | 1220 +TLV_TYPE_SEARCH_RECURSE = TLV_META_TYPE_BOOL | 1230 +TLV_TYPE_SEARCH_GLOB = TLV_META_TYPE_STRING | 1231 +TLV_TYPE_SEARCH_ROOT = TLV_META_TYPE_STRING | 1232 +TLV_TYPE_SEARCH_RESULTS = TLV_META_TYPE_GROUP | 1233 ## # # Net 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 1161457894..846c770984 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 @@ -47,7 +47,8 @@ class Console::CommandDispatcher::Stdapi::Fs "getlwd" => "Print local working directory", "lpwd" => "Print local working directory", "rm" => "Delete the specified file", - "del" => "Delete the specified file" + "del" => "Delete the specified file", + "search" => "Search for files" } end @@ -58,6 +59,60 @@ class Console::CommandDispatcher::Stdapi::Fs "Stdapi: File system" end + # + # Search for files. + # + def cmd_search( *args ) + + root = nil + glob = nil + recurse = true + + opts = Rex::Parser::Arguments.new( + "-h" => [ false, "Help Banner." ], + "-d" => [ true, "The directory/drive to begin searching from. Leave empty to search all drives. (Default: #{root})" ], + "-f" => [ true, "The file pattern glob to search for. (e.g. *secret*.doc?)" ], + "-r" => [ true, "Recursivly search sub directories. (Default: #{recurse})" ] + ) + + opts.parse(args) { | opt, idx, val | + case opt + when "-h" + print_line( "Usage: search [-d dir] [-r recurse] -f pattern" ) + print_line( "Search for files." ) + print_line( opts.usage ) + return + when "-d" + root = val + when "-f" + glob = val + when "-r" + recurse = false if( val =~ /^(f|n|0)/i ) + end + } + + if( not glob ) + print_error( "You must specify a valid file glob to search for, e.g. >search -f *.doc" ) + return + end + + files = client.fs.file.search( root, glob, recurse ) + + if( not files.empty? ) + print_line( "Found #{files.length} result#{ files.length > 1 ? 's' : '' }..." ) + files.each do | file | + if( file['size'] > 0 ) + print( " #{file['path']}#{ file['path'].empty? ? '' : '\\' }#{file['name']} (#{file['size']} bytes)\n" ) + else + print( " #{file['path']}#{ file['path'].empty? ? '' : '\\' }#{file['name']}\n" ) + end + end + else + print_line( "No files matching your search were found." ) + end + + end + # # Reads the contents of a file and prints them to the screen. #