From 7a71d226253c95687bcb726750cce1a89e1dfe5c Mon Sep 17 00:00:00 2001 From: Jonathan Cran Date: Thu, 5 Jan 2012 23:09:05 -0600 Subject: [PATCH] Revert "make the esx driver dependent on meterpreter" This reverts commit eec70706d073503832fda61e9e28e24c5097c579. --- lib/lab/driver/remote_esx_driver.rb | 151 ++++------------------- lib/lab/driver/vm_driver.rb | 19 ++- lib/lab/modifier/meterpreter_modifier.rb | 140 +++++++++++---------- lib/lab/vm.rb | 19 ++- lib/lab/vm_controller.rb | 21 ++-- plugins/lab.rb | 4 +- 6 files changed, 138 insertions(+), 216 deletions(-) diff --git a/lib/lab/driver/remote_esx_driver.rb b/lib/lab/driver/remote_esx_driver.rb index 3beeb800f1..b928f6c1cc 100644 --- a/lib/lab/driver/remote_esx_driver.rb +++ b/lib/lab/driver/remote_esx_driver.rb @@ -97,6 +97,26 @@ class RemoteEsxDriver < VmDriver def delete_all_snapshots remote_system_command("vim-cmd vmsvc/snapshot.removeall #{@vmid}") end + + def run_command(command) + raise "Not Implemented" + end + + def copy_from_guest(from, to) + if @os == "linux" + scp_from(from, to) + else + raise "Unimplemented" + end + end + + def copy_to_guest(from, to) + if @os == "linux" + scp_to(from, to) + else + raise "Unimplemented" + end + end def check_file_exists(file) raise "Not Implemented" @@ -106,137 +126,16 @@ class RemoteEsxDriver < VmDriver raise "Not Implemented" end - def run_command(command, timeout=60) - - setup_session - #puts "Using session #{@session}" - - # TODO: pass the timeout down - - if @session - if @session.type == "shell" - #puts "Running command via shell: #{command}" - @session.shell_command_token(command, timeout) - elsif @session.type == "meterpreter" - #puts "Running command via meterpreter: #{command}" - @session.shell_command(command) - end - else - raise "No session" - end - end - - def copy_to_guest(local,remote) - setup_session - if @session.type == "meterpreter" - @session.run_cmd("upload #{local} #{remote}") - else - @driver.copy_to(local,remote) - end - end - - def copy_from_guest(local, remote) - setup_session - if @session.type == "meterpreter" - @session.run_cmd("download #{local} #{remote}") - else - @driver.copy_from(local,remote) - end - end - def cleanup + end def running? - power_status_string = `ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.getstate #{@vmid}\"` - return true if power_status_string =~ /Powered on/ + #power_status_string = `ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.getstate #{@vmid}\"` + #return true if power_status_string =~ /Powered on/ + true end -private - - def create_framework - return if @framework - @framework = Msf::Simple::Framework.create - end - - # perform the setup only once - def setup_session - return if @session - - # require the framework (assumes this sits in lib/lab/modifiers) - require 'msf/base' - - create_framework # TODO - this should use a single framework for all hosts, not one-per-host - - @session = nil - @session_input = Rex::Ui::Text::Input::Buffer.new - @session_output = Rex::Ui::Text::Output::Buffer.new - - if @os == "windows" - exploit_name = 'windows/smb/psexec' - - # TODO - check for x86, choose the appropriate payload - - payload_name = 'windows/meterpreter/bind_tcp' - options = { - "RHOST" => @hostname, - "SMBUser" => @vm_user, - "SMBPass" => @vm_pass} - - #puts "DEBUG: using options #{options}" - - # Initialize the exploit instance - exploit = @framework.exploits.create(exploit_name) - - begin - # Fire it off. - @session = exploit.exploit_simple( - 'Payload' => payload_name, - 'Options' => options, - 'LocalInput' => @session_input, - 'LocalOutput' => @session_output) - @session.load_stdapi - - #puts "DEBUG: Generated session: #{@session}" - - rescue Exception => e - #puts "DEBUG: Unable to exploit" - #puts e.to_s - end - else - module_name = 'scanner/ssh/ssh_login' - - # TODO - check for x86, choose the appropriate payload - - payload_name = 'linux/x86/shell_bind_tcp' - options = { "RHOSTS" => @hostname, - "USERNAME" => @vm_user, - "PASSWORD" => @vm_pass, - "BLANK_PASSWORDS" => false, - "USER_AS_PASS" => false, - "VERBOSE" => false} - - # Initialize the module instance - aux = @framework.auxiliary.create(module_name) - - #puts "DEBUG: created module: #{aux}" - - begin - # Fire it off. - aux.run_simple( - 'Payload' => payload_name, - 'Options' => options, - 'LocalInput' => @session_input, - 'LocalOutput' => @session_output) - - @session = @framework.sessions.first.last - rescue Exception => e - #puts "DEBUG: Unable to exploit" - #puts e.to_s - end - end - end - def get_snapshots # Command take the format: # vmware-vim-cmd vmsvc/snapshot.revert [vmid: int] [snapshotlevel: int] [snapshotindex: int] @@ -248,7 +147,7 @@ private # ... snapshots = [] - # Use these to keep track of the parsing... + # Use these to keep track of the parsing... current_tree = -1 current_num = 0 count = 0 diff --git a/lib/lab/driver/vm_driver.rb b/lib/lab/driver/vm_driver.rb index b25280ae3a..c3610456c0 100644 --- a/lib/lab/driver/vm_driver.rb +++ b/lib/lab/driver/vm_driver.rb @@ -86,11 +86,11 @@ class VmDriver def run_command(command) raise "Command not Implemented" end - + def copy_from_guest(from, to) raise "Command not Implemented" end - + def copy_to_guest(from, to) raise "Command not Implemented" end @@ -117,6 +117,7 @@ private #::Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp| # scp.upload!(from,to) #end + system_command("scp #{local} #{@vm_user}@#{@hostname}:#{remote}") end @@ -126,13 +127,17 @@ private #::Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp| # scp.download!(from,to) #end + system_command("scp #{@vm_user}@#{@hostname}:#{remote} #{local}") - end + end + def ssh_exec(command) + ::Net::SSH.start(@hostname, @vm_user, :password => @vm_pass) do |ssh| result = ssh.exec!(command) end + `scp #{@vm_user}@#{@hostname} from to` end @@ -143,6 +148,7 @@ private unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/.match string raise "WARNING! Invalid character in: #{string}" end + string end @@ -153,17 +159,18 @@ private unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\)]*$/.match string raise "WARNING! Invalid character in: #{string}" end + string end - + # The only reason we don't filter here is because we need # the ability to still run clean (controlled entirely by us) # command lines. def system_command(command) `#{command}` end - - + + def remote_system_command(command) system_command("ssh #{@user}@#{@host} \"#{command}\"") end diff --git a/lib/lab/modifier/meterpreter_modifier.rb b/lib/lab/modifier/meterpreter_modifier.rb index 94d89f44a2..3ccb8c535e 100644 --- a/lib/lab/modifier/meterpreter_modifier.rb +++ b/lib/lab/modifier/meterpreter_modifier.rb @@ -1,73 +1,26 @@ $:.unshift(File.join(File.dirname(__FILE__), '..', '..')) + + + + # This allows us to override the default way of running commands -# Currently useful for the remote esx driver +# Currently useful for the esx controller module Lab module Modifier module Meterpreter - + attr_accessor :framework attr_accessor :session attr_accessor :session_input attr_accessor :session_output - def meterpreter_run_command(command, timeout=60) - - setup_session - puts "Using session #{@session}" - - # TODO: pass the timeout down - - if @session - if @session.type == "shell" - puts "Running command via shell: #{command}" - @session.shell_command_token(command, timeout) - elsif @session.type == "meterpreter" - puts "Running command via meterpreter: #{command}" - @session.shell_command(command) #, timeout) - end - else - raise "No session" - end - end - - def meterpreter_copy_to_guest(local,remote) - puts "DEBUG: Meterpreter" - setup_session - if @session.type == "meterpreter" - @session.run_cmd("upload #{local} #{remote}") - else - @driver.copy_to(local,remote) - end - end - - def meterpreter_copy_from_guest(local, remote) - puts "DEBUG: Meterpreter" - setup_session - if @session.type == "meterpreter" - @session.run_cmd("download #{local} #{remote}") - else - @driver.copy_from(local,remote) - end - end - - # This isn't part of the normal API, but too good to pass up. - def meterpreter_run_script(script, options) - if @session.type == "meterpreter" - @session.execute_script(script, options) - else - raise "Unsupported on #{@session.type}" - end - end - -private - def create_framework return if @framework - @framework = Msf::Simple::Framework.create + @framework = Msf::Simple::Framework.create end - + # perform the setup only once def setup_session return if @session @@ -75,11 +28,12 @@ private # require the framework (assumes this sits in lib/lab/modifiers) require 'msf/base' - create_framework # TODO - this should use a single framework for all hosts, not one-per-host + create_framework ## TODO - this should use a single framework + ## for all hosts, not one-per-host - @session = nil - @session_input = Rex::Ui::Text::Input::Buffer.new - @session_output = Rex::Ui::Text::Output::Buffer.new + @session = nil + @session_input = Rex::Ui::Text::Input::Buffer.new + @session_output = Rex::Ui::Text::Output::Buffer.new if @os == "windows" exploit_name = 'windows/smb/psexec' @@ -87,12 +41,11 @@ private # TODO - check for x86, choose the appropriate payload payload_name = 'windows/meterpreter/bind_tcp' - options = { - "RHOST" => @hostname, - "SMBUser" => @vm_user, - "SMBPass" => @vm_pass} + options = { "RHOST" => @hostname, + "SMBUser" => @vm_user, + "SMBPass" => @vm_pass} - puts "DEBUG: using options #{options}" + puts "DEBUG: using options #{options}" # Initialize the exploit instance exploit = @framework.exploits.create(exploit_name) @@ -126,7 +79,7 @@ private "USER_AS_PASS" => false, "VERBOSE" => false} - puts "DEBUG: using options #{options}" + puts "DEBUG: using options #{options}" # Initialize the module instance aux = @framework.auxiliary.create(module_name) @@ -148,7 +101,64 @@ private puts e.to_s end end + + + end + + def run_command(command, timeout=60) + + setup_session + puts "Using session #{@session}" + + # TODO: pass the timeout down + + if @session + if @session.type == "shell" + puts "Running command via shell: #{command}" + @session.shell_command_token(command, timeout) + elsif @session.type == "meterpreter" + puts "Running command via meterpreter: #{command}" + @session.shell_command(command) #, timeout) + end + else + raise "No session" + end + end + + + # This isn't part of the normal API, but too good to pass up. + def run_script(script, options) + if @session.type == "meterpreter" + @session.execute_script(script, options) + else + raise "Unsupported on #{@session.type}" + end + end + + # For meterpreter API compatibility + #def execute_file(script,options) + # run_script(script,options) + #end + + def copy_to_guest(local,remote) + setup_session + if @session.type == "meterpreter" + @session.run_cmd("upload #{local} #{remote}") + else + @driver.copy_to(local,remote) + end + end + + def copy_from_guest(local, remote) + setup_session + if @session.type == "meterpreter" + @session.run_cmd("download #{local} #{remote}") + else + @driver.copy_from(local,remote) + end + end + end end end diff --git a/lib/lab/vm.rb b/lib/lab/vm.rb index 48f8018cf1..789304037b 100644 --- a/lib/lab/vm.rb +++ b/lib/lab/vm.rb @@ -103,15 +103,12 @@ class Vm # modifiers are properly used with the correct VM image. @modifiers = config['modifiers'] - if @modifiers - @modifiers.each do |modifier| - begin - self.class.send(:include, eval("Lab::Modifier::#{modifier}")) - rescue Exception => e - #puts "WARNING: Unable to load: #{modifier}" - #puts "Exception: #{e}" - end - end + if @modifiers + begin + @modifiers.each { |modifier| self.class.send(:include, eval("Lab::Modifier::#{modifier}"))} + rescue Exception => e + # modifier likely didn't exist + end end # Consume all tags @@ -209,9 +206,11 @@ class Vm end def to_yaml + + # TODO - push this down to the drivers. + # Standard configuration options out = " - vmid: #{@vmid}\n" - out = " hostname: #{@hostname}\n" out += " driver: #{@driver_type}\n" out += " location: #{@location}\n" out += " type: #{@type}\n" diff --git a/lib/lab/vm_controller.rb b/lib/lab/vm_controller.rb index abc82b4293..4cfc4a5891 100644 --- a/lib/lab/vm_controller.rb +++ b/lib/lab/vm_controller.rb @@ -158,12 +158,12 @@ module Controllers case driver_type.intern when :workstation vm_list = ::Lab::Controllers::WorkstationController::running_list - + vm_list.each do |item| - + ## Name the VM index = @vms.count + 1 - + ## Add it to the vm list @vms << Vm.new( { 'vmid' => "vm_#{index}", 'driver' => driver_type, @@ -171,6 +171,8 @@ module Controllers 'user' => user, 'host' => host } ) end + + when :virtualbox vm_list = ::Lab::Controllers::VirtualBoxController::running_list vm_list.each do |item| @@ -187,10 +189,10 @@ module Controllers vm_list = ::Lab::Controllers::RemoteWorkstationController::running_list(user, host) vm_list.each do |item| - + ## Name the VM index = @vms.count + 1 - + ## Add it to the vm list @vms << Vm.new( { 'vmid' => "vm_#{index}", 'driver' => driver_type, @@ -200,6 +202,7 @@ module Controllers end when :remote_esx vm_list = ::Lab::Controllers::RemoteEsxController::running_list(user,host) + vm_list.each do |item| @vms << Vm.new( { 'vmid' => "#{item[:id]}", 'name' => "#{item[:name]}", @@ -207,11 +210,12 @@ module Controllers 'user' => user, 'host' => host } ) end + else raise TypeError, "Unsupported VM Type" end - end + end def build_from_config(driver_type=nil, user=nil, host=nil, clear=false) if clear @@ -230,17 +234,18 @@ module Controllers 'user' => user, 'host' => host } ) end + else raise TypeError, "Unsupported VM Type" end - end + end def running?(vmid) if includes_vmid?(vmid) return self.find_by_hostname(vmid).running? end - return false + return false end end end diff --git a/plugins/lab.rb b/plugins/lab.rb index 18dab80373..f3099d9fc2 100644 --- a/plugins/lab.rb +++ b/plugins/lab.rb @@ -384,6 +384,8 @@ class Plugin::Lab < Msf::Plugin local_path = args[args.count-2] vm_path = args[args.count-1] + print_line "Copying from #{local_path} to #{vm_path} on #{args[0]}" + if args[0] == "all" @controller.each do |vm| if vm.running? @@ -393,7 +395,7 @@ class Plugin::Lab < Msf::Plugin end else args[0..-2].each do |vmid_arg| - next unless @controller.includes_hostname? vmid_arg + next unless @controller.includes_vmid? vmid_arg if @controller[vmid_arg].running? print_line "Copying from #{local_path} to #{vm_path} on #{vmid_arg}" @controller[vmid_arg].copy_to_guest(local_path, vm_path)