From e48031cf22c71475ec9447e804a777ed062b5ec6 Mon Sep 17 00:00:00 2001 From: Jonathan Cran Date: Thu, 22 Dec 2011 14:56:45 -0600 Subject: [PATCH] squashed lab upload commit --- lib/lab/driver/fog_driver.rb | 4 +- lib/lab/driver/remote_esx_driver.rb | 4 +- lib/lab/driver/remote_workstation_driver.rb | 27 ++-- lib/lab/driver/virtualbox_driver.rb | 4 +- lib/lab/driver/vm_driver.rb | 10 +- lib/lab/driver/workstation_driver.rb | 6 +- lib/lab/driver/workstation_vixr_driver.rb | 4 +- lib/lab/modifier/meterpreter_modifier.rb | 12 +- lib/lab/vm.rb | 26 +-- lib/lab/vm_controller.rb | 24 ++- plugins/lab.rb | 166 ++++++++++++++------ 11 files changed, 187 insertions(+), 100 deletions(-) diff --git a/lib/lab/driver/fog_driver.rb b/lib/lab/driver/fog_driver.rb index 9a4a61e6ba..424761aab7 100644 --- a/lib/lab/driver/fog_driver.rb +++ b/lib/lab/driver/fog_driver.rb @@ -134,11 +134,11 @@ class FogDriver < VmDriver end end - def copy_from(from, to) + def copy_from_guest(from, to) raise "unimplemented" end - def copy_to(from, to) + def copy_to_guest(from, to) raise "unimplemented" end diff --git a/lib/lab/driver/remote_esx_driver.rb b/lib/lab/driver/remote_esx_driver.rb index 8639d6a5d9..816b6d63e3 100644 --- a/lib/lab/driver/remote_esx_driver.rb +++ b/lib/lab/driver/remote_esx_driver.rb @@ -102,7 +102,7 @@ class RemoteEsxDriver < VmDriver raise "Not Implemented" end - def copy_from(from, to) + def copy_from_guest(from, to) if @os == "linux" scp_from(from, to) else @@ -110,7 +110,7 @@ class RemoteEsxDriver < VmDriver end end - def copy_to(from, to) + def copy_to_guest(from, to) if @os == "linux" scp_to(from, to) else diff --git a/lib/lab/driver/remote_workstation_driver.rb b/lib/lab/driver/remote_workstation_driver.rb index f7e8097931..c2a4e3dceb 100644 --- a/lib/lab/driver/remote_workstation_driver.rb +++ b/lib/lab/driver/remote_workstation_driver.rb @@ -116,7 +116,7 @@ class RemoteWorkstationDriver < VmDriver end end - def copy_from(from, to) + def copy_from_guest(from, to) from = filter_input(from) to = filter_input(to) @@ -133,7 +133,7 @@ class RemoteWorkstationDriver < VmDriver end end - def copy_to(from, to) + def copy_to_guest(from, to) from = filter_input(from) to = filter_input(to) @@ -165,9 +165,8 @@ class RemoteWorkstationDriver < VmDriver directory = filter_input(directory) if @tools - emote_system_command("ssh #{@user}@#{@host} vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " + + remote_system_command("ssh #{@user}@#{@host} vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " + "createDirectoryInGuest \'#{@location}\' \'#{directory}\' nogui") - system_command(vmrunstr) else raise "Not Implemented - Install VmWare Tools" end @@ -178,17 +177,21 @@ class RemoteWorkstationDriver < VmDriver end def running? - ## Get running VMs - running = `ssh #{@user}@#{@host} \"vmrun list nogui\"` - running_array = running.split("\n") - running_array.shift - running_array.each do |vmx| - if vmx.to_s == @location.to_s - return true + # Get running VMs + running = remote_system_command("vmrun list nogui") + + if running + running_array = running.split("\n") + running_array.shift + + running_array.each do |vmx| + if vmx.to_s == @location.to_s + return true + end end end - + false end diff --git a/lib/lab/driver/virtualbox_driver.rb b/lib/lab/driver/virtualbox_driver.rb index 847f73b193..a79ebf8f1b 100644 --- a/lib/lab/driver/virtualbox_driver.rb +++ b/lib/lab/driver/virtualbox_driver.rb @@ -98,14 +98,14 @@ module Drivers system_command(command) end - def copy_from(from, to) + def copy_from_guest(from, to) from = filter_input(from) to = filter_input(to) raise "Not supported by Virtual Box" end - def copy_to(from, to) + def copy_to_guest(from, to) from = filter_input(from) to = filter_input(to) diff --git a/lib/lab/driver/vm_driver.rb b/lib/lab/driver/vm_driver.rb index f3c60a976f..c3610456c0 100644 --- a/lib/lab/driver/vm_driver.rb +++ b/lib/lab/driver/vm_driver.rb @@ -24,6 +24,7 @@ class VmDriver @location = filter_command(config["location"]) @credentials = config["credentials"] || [] @tools = filter_input(config["tools"]) + @os = filter_input(config["os"]) @hostname = filter_input(config["hostname"]) || filter_input(config["vmid"].to_s) @@ -86,11 +87,11 @@ class VmDriver raise "Command not Implemented" end - def copy_from(from, to) + def copy_from_guest(from, to) raise "Command not Implemented" end - def copy_to(from, to) + def copy_to_guest(from, to) raise "Command not Implemented" end @@ -142,7 +143,7 @@ private def filter_input(string) return "" unless string # nil becomes empty string - return unless string.class == String # Allow other types unmodified + return string unless string.class == String # Allow other types unmodified unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/.match string raise "WARNING! Invalid character in: #{string}" @@ -166,8 +167,7 @@ private # the ability to still run clean (controlled entirely by us) # command lines. def system_command(command) - #puts "DEBUG: system command #{command}" - system(command) + `#{command}` end diff --git a/lib/lab/driver/workstation_driver.rb b/lib/lab/driver/workstation_driver.rb index f42e13473a..8e52b5a2db 100644 --- a/lib/lab/driver/workstation_driver.rb +++ b/lib/lab/driver/workstation_driver.rb @@ -107,7 +107,6 @@ class WorkstationDriver < VmDriver # Ghettohack! string = File.open(output_file,"r").read `rm #{output_file}` - else raise "zomgwtfbbqnotools" end @@ -115,7 +114,7 @@ class WorkstationDriver < VmDriver return string end - def copy_from(from, to) + def copy_from_guest(from, to) from = filter_input(from) to = filter_input(to) if @tools @@ -127,7 +126,8 @@ class WorkstationDriver < VmDriver system_command(vmrunstr) end - def copy_to(from, to) + def copy_to_guest(from, to) + from = filter_input(from) to = filter_input(to) if @tools diff --git a/lib/lab/driver/workstation_vixr_driver.rb b/lib/lab/driver/workstation_vixr_driver.rb index cb135b96ff..5e28fb4a6f 100644 --- a/lib/lab/driver/workstation_vixr_driver.rb +++ b/lib/lab/driver/workstation_vixr_driver.rb @@ -91,13 +91,13 @@ class WorkstationVixrDriver < VmDriver end end - def copy_from(from, to) + def copy_from_guest(from, to) from = filter_input(from) to = filter_input(to) cp_from_host(from,to) end - def copy_to(from, to) + def copy_to_guest(from, to) from = filter_input(from) to = filter_input(to) vm.cp_to_guest(from,to) diff --git a/lib/lab/modifier/meterpreter_modifier.rb b/lib/lab/modifier/meterpreter_modifier.rb index 680e0294be..2ca1263b32 100644 --- a/lib/lab/modifier/meterpreter_modifier.rb +++ b/lib/lab/modifier/meterpreter_modifier.rb @@ -1,19 +1,15 @@ $:.unshift(File.join(File.dirname(__FILE__), '..', '..')) -module Lab -module Modifier -module Meterpreter -end -end -end + # This allows us to override the default way of running commands # Currently useful for the esx controller module Lab -class Vm +module Modifier +module Meterpreter attr_accessor :framework attr_accessor :session @@ -165,3 +161,5 @@ class Vm end end +end + diff --git a/lib/lab/vm.rb b/lib/lab/vm.rb index f44752e158..789304037b 100644 --- a/lib/lab/vm.rb +++ b/lib/lab/vm.rb @@ -18,7 +18,9 @@ class Vm attr_accessor :host attr_accessor :os attr_accessor :arch - + attr_accessor :tags + attr_accessor :type + ## Initialize takes a vm configuration hash of the form ## - vmid (unique identifier) ## driver (vm technology) @@ -75,8 +77,6 @@ class Vm #Only fog systems need this @fog_config = config['fog_config'] - #puts "Passing driver config: #{config}" - # Process the correct driver if @driver_type == "workstation" @driver = Lab::Drivers::WorkstationDriver.new(config) @@ -101,8 +101,6 @@ class Vm # Load in a list of modifiers. These provide additional methods # Currently it is up to the user to verify that # modifiers are properly used with the correct VM image. - # - # If not, the results are likely to be disasterous. @modifiers = config['modifiers'] if @modifiers @@ -112,6 +110,14 @@ class Vm # modifier likely didn't exist end end + + # Consume all tags + @tags = config['tags'] + end + + def tagged?(tag_name) + return false unless @tags + return true if @tags.include?(tag_name) end def running? @@ -163,12 +169,12 @@ class Vm @driver.start end - def copy_to(from,to) - @driver.copy_to(from,to) + def copy_to_guest(from,to) + @driver.copy_to_guest(from,to) end - def copy_from(from,to) - @driver.copy_from(from,to) + def copy_from_guest(from,to) + @driver.copy_from_guest(from,to) end def run_command(command) @@ -196,7 +202,7 @@ class Vm end def to_s - return "#{@vmid}" + return "#{@hostname}" end def to_yaml diff --git a/lib/lab/vm_controller.rb b/lib/lab/vm_controller.rb index 66e9b65cb7..4cfc4a5891 100644 --- a/lib/lab/vm_controller.rb +++ b/lib/lab/vm_controller.rb @@ -50,19 +50,25 @@ module Controllers def [](x) # Support indexing by both names and number if x.class == String - find_by_vmid(x) + find_by_hostname(x) else return @vms[x] end end - def find_by_vmid(vmid) + def find_by_hostname(vmid) @vms.each do |vm| if (vm.hostname.to_s.downcase == vmid.to_s.downcase) return vm end end - return nil + return nil + end + + def find_by_tag(tag_name) + tagged_vms = [] + @vms.each { |vm| tagged_vms << vm if vm.tagged?(tag_name) } + return tagged_vms end def add_vm(vmid, location=nil, os=nil, tools=nil, credentials=nil, user=nil, host=nil) @@ -75,7 +81,7 @@ module Controllers end def remove_by_vmid(vmid) - @vms.delete(self.find_by_vmid(vmid)) + @vms.delete(self.find_by_hostname(vmid)) end def from_file(file) @@ -108,6 +114,14 @@ module Controllers false end + def includes_hostname?(hostname) + @vms.each do |vm| + return true if (vm.hostname == hostname) + end + false + end + + def build_from_dir(driver_type, dir, clear=false) if clear @@ -229,7 +243,7 @@ module Controllers def running?(vmid) if includes_vmid?(vmid) - return self.find_by_vmid(vmid).running? + return self.find_by_hostname(vmid).running? end return false end diff --git a/plugins/lab.rb b/plugins/lab.rb index 60e3f8b7ed..0c3e97838f 100644 --- a/plugins/lab.rb +++ b/plugins/lab.rb @@ -28,6 +28,9 @@ class Plugin::Lab < Msf::Plugin { "lab_help" => "lab_help - Show that command's description.", "lab_show" => "lab_show - show all vms in the lab.", + "lab_search" => "lab_search - search local vms in the lab.", + "lab_search_tags" => "lab_search_tag - search local vms in the lab.", + #"lab_search_remote" => "lab_search_remote - search remote vms in the lab.", "lab_show_running" => "lab_show_running - show running vms.", "lab_load" => "lab_load [file] - load a lab definition from disk.", "lab_save" => "lab_save [filename] - persist a lab definition in a file.", @@ -41,6 +44,7 @@ class Plugin::Lab < Msf::Plugin "lab_stop" => "lab_stop [vmid+|all] stop the specified vm.", "lab_revert" => "lab_revert [vmid+|all] [snapshot] revert the specified vm.", "lab_snapshot" => "lab_snapshot [vmid+|all] [snapshot] snapshot all targets for this exploit.", + "lab_upload" => "lab_upload [vmid] [local_path] [remote_path] upload a file.", "lab_run_command" => "lab_run_command [vmid+|all] [command] run a command on all targets.", "lab_browse_to" => "lab_browse_to [vmid+|all] [uri] use the default browser to browse to a uri." } @@ -103,16 +107,15 @@ class Plugin::Lab < Msf::Plugin ## ## Commands for dealing with a currently-loaded lab ## - def cmd_lab_show(*args) if args.empty? hlp_print_lab else - args.each do |vmid| - if @controller.includes_vmid? vmid - print_line @controller[vmid].to_yaml + args.each do |name| + if @controller.includes_hostname? name + print_line @controller[name].to_yaml else - print_error "Unknown vm '#{vmid}'" + print_error "Unknown vm '#{name}'" end end end @@ -122,27 +125,57 @@ class Plugin::Lab < Msf::Plugin hlp_print_lab_running end + + def cmd_lab_search(*args) + if args.empty? + hlp_print_lab + else + args.each do |arg| + print_line "Searching for vms with hostname matching #{arg}" + @controller.each do |vm| + print_line "checking to see #{vm.hostname} matches #{arg}" + print_line "#{vm.hostname} matched #{arg}" if vm.hostname =~ Regexp.new(arg) + end + end + end + end + + def cmd_lab_search_tags(*args) + if args.empty? + hlp_print_lab + else + args.each do |arg| + print_line "Searching for vms with tags matching #{arg}" + @controller.each do |vm| + print_line "checking to see #{vm.hostname} is tagged #{arg}" + print_line "#{vm.hostname} tagged #{arg}" if vm.tagged?(arg) + end + end + end + end + + def cmd_lab_start(*args) return lab_usage if args.empty? if args[0] == "all" @controller.each do |vm| - print_line "Starting lab vm #{vm.vmid}." + print_line "Starting lab vm #{vm.hostname}." if !vm.running? vm.start else - print_line "Lab vm #{vm.vmid} already running." + print_line "Lab vm #{vm.hostname} already running." end end else args.each do |arg| - if @controller.includes_vmid? arg - vm = @controller.find_by_vmid(arg) + if @controller.includes_hostname? arg + vm = @controller.find_by_hostname(arg) if !vm.running? - print_line "Starting lab vm #{vm.vmid}." + print_line "Starting lab vm #{vm.hostname}." vm.start else - print_line "Lab vm #{vm.vmid} already running." + print_line "Lab vm #{vm.hostname} already running." end end end @@ -154,22 +187,22 @@ class Plugin::Lab < Msf::Plugin if args[0] == "all" @controller.each do |vm| - print_line "Stopping lab vm #{vm.vmid}." + print_line "Stopping lab vm #{vm.hostname}." if vm.running? vm.stop else - print_line "Lab vm #{vm.vmid} not running." + print_line "Lab vm #{vm.hostname} not running." end end else args.each do |arg| - if @controller.includes_vmid? arg - vm = @controller.find_by_vmid(arg) + if @controller.includes_hostname? arg + vm = @controller.find_by_hostname(arg) if vm.running? - print_line "Stopping lab vm #{vm.vmid}." + print_line "Stopping lab vm #{vm.hostname}." vm.stop else - print_line "Lab vm #{vm.vmid} not running." + print_line "Lab vm #{vm.hostname} not running." end end end @@ -183,10 +216,10 @@ class Plugin::Lab < Msf::Plugin @controller.each{ |vm| vm.suspend } else args.each do |arg| - if @controller.includes_vmid? arg - if @controller.find_by_vmid(arg).running? + if @controller.includes_hostname? arg + if @controller.find_by_hostname(arg).running? print_line "Suspending lab vm #{arg}." - @controller.find_by_vmid(arg).suspend + @controller.find_by_hostname(arg).suspend end end end @@ -201,10 +234,10 @@ class Plugin::Lab < Msf::Plugin @controller.each{ |vm| vm.reset } else args.each do |arg| - if @controller.includes_vmid? arg - if @controller.find_by_vmid(arg).running? + if @controller.includes_hostname? arg + if @controller.find_by_hostname(arg).running? print_line "Resetting lab vm #{arg}." - @controller.find_by_vmid(arg).reset + @controller.find_by_hostname(arg).reset end end end @@ -220,10 +253,10 @@ class Plugin::Lab < Msf::Plugin print_line "Snapshotting all lab vms to snapshot: #{snapshot}." @controller.each{ |vm| vm.create_snapshot(snapshot) } else - args[0..-2].each do |vmid_arg| - next unless @controller.includes_vmid? vmid_arg - print_line "Snapshotting #{vmid_arg} to snapshot: #{snapshot}." - @controller[vmid_arg].create_snapshot(snapshot) + args[0..-2].each do |name_arg| + next unless @controller.includes_hostname? name_arg + print_line "Snapshotting #{name_arg} to snapshot: #{snapshot}." + @controller[name_arg].create_snapshot(snapshot) end end end @@ -237,10 +270,10 @@ class Plugin::Lab < Msf::Plugin print_line "Reverting all lab vms to snapshot: #{snapshot}." @controller.each{ |vm| vm.revert_snapshot(snapshot) } else - args[0..-2].each do |vmid_arg| - next unless @controller.includes_vmid? vmid_arg - print_line "Reverting #{vmid_arg} to snapshot: #{snapshot}." - @controller[vmid_arg].revert_snapshot(snapshot) + args[0..-2].each do |name_arg| + next unless @controller.includes_hostname? name_arg + print_line "Reverting #{name_arg} to snapshot: #{snapshot}." + @controller[name_arg].revert_snapshot(snapshot) end end end @@ -253,16 +286,48 @@ class Plugin::Lab < Msf::Plugin print_line "Running command #{command} on all vms." @controller.each do |vm| if vm.running? - print_line "#{vm.vmid} running command: #{command}." + print_line "#{vm.hostname} running command: #{command}." vm.run_command(command) end end + else + args[0..-2].each do |name_arg| + next unless @controller.includes_hostname? name_arg + if @controller[name_arg].running? + print_line "#{name_arg} running command: #{command}." + @controller[name_arg].run_command(command) + end + end + end + end + + # + # Command: lab_upload [vmids] [from] [to] + # + # Description: Uploads a file to the guest(s) + # + # Quirks: Pass "all" as a vmid to have it operate on all vms. + # + def cmd_lab_upload(*args) + return lab_usage if args.empty? + return lab_usage if args.count < 3 + + local_path = args[args.count-2] + vm_path = args[args.count-1] + + if args[0] == "all" + @controller.each do |vm| + if vm.running? + print_line "Copying from #{local_path} to #{vm_path} on #{vm.hostname}" + vm.copy_to_guest(local_path, vm_path) + end + end else args[0..-2].each do |vmid_arg| next unless @controller.includes_vmid? vmid_arg if @controller[vmid_arg].running? - print_line "#{vmid_arg} running command: #{command}." - @controller[vmid_arg].run_command(command) + print_line "Copying from #{local_path} to #{vm_path} on #{vmid_arg}" + @controller[vmid_arg].copy_to_guest(local_path, vm_path) end end end @@ -275,16 +340,16 @@ class Plugin::Lab < Msf::Plugin print_line "Opening: #{uri} on all vms." @controller.each do |vm| if vm.running? - print_line "#{vm.vmid} opening to uri: #{uri}." + print_line "#{vm.hostname} opening to uri: #{uri}." vm.open_uri(uri) end end else - args[0..-2].each do |vmid_arg| - next unless @controller.includes_vmid? vmid_arg - if @controller[vmid_arg].running? - print_line "#{vmid_arg} opening to uri: #{uri}." - @controller[vmid_arg].open_uri(uri) + args[0..-2].each do |name_arg| + next unless @controller.includes_hostname? name_arg + if @controller[name_arg].running? + print_line "#{name_arg} opening to uri: #{uri}." + @controller[name_arg].open_uri(uri) end end end @@ -347,14 +412,13 @@ class Plugin::Lab < Msf::Plugin tbl = Rex::Ui::Text::Table.new( 'Header' => 'Available Lab VMs', 'Indent' => indent.length, - 'Columns' => [ 'Vmid', 'Name', 'Location', "Power?" ] + 'Columns' => [ 'Hostname', 'Driver', 'Type' ] ) @controller.each do |vm| - tbl << [ vm.vmid, - vm.name, - vm.location, - vm.running?] + tbl << [ vm.hostname, + vm.driver.class, + vm.type] end print_line tbl.to_s @@ -366,14 +430,14 @@ class Plugin::Lab < Msf::Plugin tbl = Rex::Ui::Text::Table.new( 'Header' => 'Running Lab VMs', 'Indent' => indent.length, - 'Columns' => [ 'Vmid', 'Name', 'Location', 'Power?' ] + 'Columns' => [ 'Hostname', 'Driver', 'Type', 'Power?' ] ) @controller.each do |vm| if vm.running? - tbl << [ vm.vmid, - vm.name, - vm.location, + tbl << [ vm.hostname, + vm.driver.class, + vm.type, vm.running?] end end @@ -390,6 +454,8 @@ class Plugin::Lab < Msf::Plugin # inheriting from Msf::Plugin to ensure that the framework attribute on # their instance gets set. # + attr_accessor :controller + def initialize(framework, opts) super @@ -430,4 +496,4 @@ class Plugin::Lab < Msf::Plugin end end ## End Class -end ## End Module +end ## End Module