Navigation
« Parsing CDP Packets with Scapy | Main | My Last Rant of the Year and New Year Wishes »
Thursday
Mar172011

Meterpreter Resource Files

Tonight while chatting via IRC with Egyp7 he mentioned that Meterpreter should have capability of using Resource files for cleanup in post exploitation and for automating tasks by users without the knowledge in Ruby and the Framework to write a Meterpreter Script or Post Module. He opened and ticket and assigned me the task. Here are the results

I first opened the file  lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb this file has all the command for the Meterpreter console so the first this was defining the Resource command:

 def commands
                c = {
                        "?"          => "Help menu",
                        "background" => "Backgrounds the current session",
                        "close"      => "Closes a channel",
                        "channel"    => "Displays information about active channels",
                        "exit"       => "Terminate the meterpreter session",
                        "help"       => "Help menu",
                        "interact"   => "Interacts with a channel",
                        "irb"        => "Drop into irb scripting mode",
                        "migrate"    => "Migrate the server to another process",
                        "use"        => "Load a one or more meterpreter extensions",
                        "quit"       => "Terminate the meterpreter session",
                        "resource"   => "Run the commands stored in a file",
                        "read"       => "Reads data from a channel",
                        "run"        => "Executes a meterpreter script or Post module",
                        "bgrun"      => "Executes a meterpreter script as a background thread",
                        "bgkill"     => "Kills a background meterpreter script",
                        "bglist"     => "Lists running background scripts",
                        "write"      => "Writes data to a channel",
                }

Once this was done I added 2 methods, the first one for tab completion of the command:

  1:  def cmd_resource_tabs(str, words)
  2:                 return [] if words.length > 1
  3: 
  4:                 tab_complete_filenames(str, words)
  5:         end
  6: 

Then the method that defined the command it self:

  1: def cmd_resource(*args)
  2:                 if args.empty?
  3:                         print(
  4:                                 "Usage: resource path1 path2" +
  5:                                   "Run the commands stored in the supplied files.\n")
  6:                         return false
  7:                 end
  8:                 args.each do |glob|
  9:                         files = ::Dir.glob(::File.expand_path(glob))
 10:                         if files.empty?
 11:                                 print_error("No such file #{glob}")
 12:                                 next
 13:                         end
 14:                         files.each do |filename|
 15:                                 print_status("Reading #{filename}")
 16:                                 if (not ::File.readable?(filename))
 17:                                         print_error("Could not read file #{filename}")
 18:                                         next
 19:                                 else
 20:                                         ::File.open(filename, "r").each_line do |line|
 21:                                                 next if line.strip.length < 1
 22:                                                 next if line[0,1] == "#"
 23:                                                 begin
 24:                                                         print_status("Running #{line}")
 25:                                                         client.console.run_single(line)
 26:                                                 rescue ::Exception => e
 27:                                                         print_error("Error Running Command #{line}: #{e.class} #{e}")
 28:                                                 end
 29: 
 30:                                         end
 31:                                 end
 32:                         end
 33:                 end
 34:         end
 35: 

One of the first things I did was from lines 1 to 7 is check if an argument is given if not display a help message and return false.  Next thing I do from lines 8 to 13 is check that each argument is actually a file. You can give it several files to process. Then from lines 14 to the end of the method you will see I check if the file is readable, open it and use the client.console.run_single() to run each command as if they where typed in the console. You will notice that on lines 21 and 22 I check for empty lines and commented lines, this will allow you to comment your resource files.

To use the command simply use the command resource and the file containing the commands here you can see an example run:

meterpreter > resource /tmp/cmd.rc
[*] Reading /tmp/cmd.rc
[*] Running sysinfo
System Language : en_US
OS              : Windows 7 (Build 7600).
Computer        : INFIDEL01
Architecture    : x64 (Current Process is WOW64)
Meterpreter     : x86/win32
[*] Running getuid
Server username: Infidel01\Carlos

The contents of the file is as follows:

loki:trunk cperez$ cat /tmp/cmd.rc
sysinfo
getuid

Reader Comments (3)

Thanks

great addition as usual.

No more need for copy and paste on the shell!
March 18, 2011 | Unregistered Commenterjames
Is it possible to save the output of sysinfo, getuid and other commands to a file using a .rc?
December 1, 2011 | Unregistered CommenterAnony
Only of you use spool command to save all output to a file
December 7, 2011 | Registered CommenterCarlos Perez

PostPost a New Comment

Enter your information below to add a new comment.
Author Email (optional):
Author URL (optional):
Post:
 
All HTML will be escaped. Hyperlinks will be created for URLs automatically.